Sequelize - подзапрос в where where

Я использую Sequelize в своем экспресс-приложении. Мне нужно сгенерировать запрос с подзапросом в предложении WHERE.

SELECT *
  FROM MyTable
 WHERE id NOT IN (
       SELECT fkey
         FROM MyOtherTable
        WHERE field1 = 1
          AND field2 = 2
          AND field3 = 3
       )

Я сначала пробовал отношения/ассоциации через свои модели, но не мог заставить его работать. Что-то вроде:

MyTable.find( {
    where: {
        id: {
            $notIn: // <= what goes here? Can I somehow reference my include model?
        }
    },
    include: [ {
        model: MyOtherTable,
        where: {
            field1: 1,
            field2: 2,
            field3: 3
    } ]
} );

Затем я попытался использовать Sequelize.where(), вам не повезло.

Затем я попробовал Sequelize.literal(), и это работает, но не уверен, что это "правильный" способ сделать подзапрос в предложении where в Sequelize, поскольку я новичок в нем.

MyTable.find( {
    where: {
        id: {
            $notIn: sequelize.literal( 
                '( SELECT fkey ' +
                    'FROM MyOtherTable ' +
                   'WHERE field1 = ' + field1 +
                    ' AND field2 = ' + field2 +
                    ' AND field3 = ' + field3 + 
                ')'
        }
    } 
} );

Я также знаю, что я мог бы использовать Sequelize.query(), но на самом деле не знаю, следует ли мне это сделать или если literal() сразу, так как я чувствую, что там что-то не замечаю.

Мне бы очень хотелось знать, как выполнить подзапрос в предложении WHERE с Sequelize "правильный" способ.

Спасибо за отзыв!

Ответ 1

Я столкнулся с аналогичной проблемой в своем проекте. Способ, которым я его реализую, несколько отличается по двум причинам:

  • Если в какой-то момент времени Sequelize решает реализовать вспомогательные запросы - синтаксис готов.
  • Использовать защиту Sequelize снова для SQL-инъекций.

Вот мой фрагмент кода, надеюсь, что это поможет.

const tempSQL = sequelize.dialect.QueryGenerator.selectQuery('MyOtherTable',{
    attributes: ['fkey'],
    where: {
         field1: 1,
         field2: 2,
         field3: 3
    }})
    .slice(0,-1); // to remove the ';' from the end of the SQL

MyTable.find( {
    where: {
        id: {
             $notIn: sequelize.literal('(' + tempSQL + ')'),
        }
    } 
} );

Некоторые люди могут отказаться от использования переменной tempSQL и просто построить SQL внутри структуры поиска (возможно, используя вспомогательный метод?)

Я также думаю, что это может послужить основой для расширения подзапросов для sequelize, поскольку он использует тот же синтаксис почти.