web-dev-qa-db-fra.com

Sequelize - sous-requête dans la clause where

J'utilise Sequelize dans mon application Express. J'ai besoin de générer une requête qui a une sous-requête dans la clause WHERE.

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

J'ai d'abord essayé les relations/associations à travers mes modèles mais je n'ai pas réussi à le faire fonctionner. Quelque chose comme:

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
    } ]
} );

Ensuite, j'ai essayé d'utiliser Sequelize.where(), pas de chance là-bas.

Ensuite, j'ai essayé Sequelize.literal() et cela fonctionne mais je ne sais pas si c'est une manière "correcte" de faire une sous-requête dans une clause where dans Sequelize que je suis nouveau.

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

Je sais aussi que je pourrais utiliser Sequelize.query() mais je ne sais pas vraiment si je devrais l'atteindre ou si literal() est tout de suite, car j'ai l'impression qu'il y a quelque chose que j'oublie.

Je voudrais vraiment savoir comment effectuer une sous-requête dans une clause WHERE avec Sequelize de la manière "appropriée" .

Merci pour les commentaires!

19
hungerstar

J'ai rencontré un problème similaire dans mon projet. La façon dont je choisis de l'implémenter est un peu différente pour deux raisons:

  1. Si à un moment donné Sequelize décide d'implémenter des sous-requêtes - la syntaxe est prête.
  2. Utilisez la protection Sequelize contre l'injection SQL.

Voici mon extrait de code, j'espère que cela vous aidera.

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 + ')'),
        }
    } 
} );

Certaines personnes pourraient choisir de ne pas utiliser la variable tempSQL et simplement construire le SQL à l'intérieur de la structure de recherche (peut-être en utilisant une méthode d'assistance?)

Je pense également que cela pourrait être la base d'une extension de sous-requêtes pour sequelize car elle utilise presque la même syntaxe.

22
Shahar Hadas