web-dev-qa-db-ja.com

Sequelize-where句のサブクエリ

Expressアプリで 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()を試してみましたが、機能しますが、 "proper"のwhere句でサブクエリを実行する方法であるかどうかはわかりません私はそれに慣れていないので続編。

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

私はSequelize.query()を使用できることも知っていますが、それを見極める必要があるのか​​、またはliteral()がすぐに見逃しているかのように感じるので、本当にわかりません。

"proper"の方法でSequelizeを使用してWHERE句でサブクエリを実行する方法を知りたいです。

フィードバックをお寄せいただきありがとうございます!

19
hungerstar

プロジェクトで同様の問題が発生しました。それを実装することを選択する方法は、2つの理由で少し異なります。

  1. ある時点でSequelizeがサブクエリを実装することを決定した場合、構文は準備ができています。
  2. SQLインジェクションに対してSequelize保護を使用します。

これが私のコードスニペットです。

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変数を使用せずに、find構造内にSQLを構築することを選択するかもしれません(おそらくヘルパーメソッドを使用していますか?)

ほとんど同じ構文を使用しているため、これがsequelizeのサブクエリ拡張機能の基礎になると私は思います。

22
Shahar Hadas