Comment faire des requêtes de jointure en utilisant Sequelize sur Node.js

J’utilise Sequelize ORM; tout est super et propre, mais j’ai eu un problème quand je l’utilise avec des requêtes de join . J’ai deux modèles: utilisateurs et messages.

 var User = db.seq.define('User',{ username: { type: db.Sequelize.STRING}, email: { type: db.Sequelize.STRING}, password: { type: db.Sequelize.STRING}, sex : { type: db.Sequelize.INTEGER}, day_birth: { type: db.Sequelize.INTEGER}, month_birth: { type: db.Sequelize.INTEGER}, year_birth: { type: db.Sequelize.INTEGER} }); User.sync().success(function(){ console.log("table created") }).error(function(error){ console.log(err); }) var Post = db.seq.define("Post",{ body: { type: db.Sequelize.TEXT }, user_id: { type: db.Sequelize.INTEGER}, likes: { type: db.Sequelize.INTEGER, defaultValue: 0 }, }); Post.sync().success(function(){ console.log("table created") }).error(function(error){ console.log(err); }) 

Je veux une requête qui répond avec un message avec les informations de l’utilisateur qui l’a créé. Dans la requête brute, je reçois ceci:

 db.seq.query('SELECT * FROM posts, users WHERE posts.user_id = users.id ').success(function(rows){ res.json(rows); }); 

Ma question est la suivante: comment puis-je modifier le code pour utiliser le style ORM au lieu de la requête SQL?

 User.hasMany(Post, {foreignKey: 'user_id'}) Post.belongsTo(User, {foreignKey: 'user_id'}) Post.find({ where: { ...}, include: [User]}) 

Qui vous donnera

 SELECT `posts`.*, `users`.`username` AS `users.username`, `users`.`email` AS `users.email`, `users`.`password` AS `users.password`, `users`.`sex` AS `users.sex`, `users`.`day_birth` AS `users.day_birth`, `users`.`month_birth` AS `users.month_birth`, `users`.`year_birth` AS `users.year_birth`, `users`.`id` AS `users.id`, `users`.`createdAt` AS `users.createdAt`, `users`.`updatedAt` AS `users.updatedAt` FROM `posts` LEFT OUTER JOIN `users` AS `users` ON `users`.`id` = `posts`.`user_id`; 

La requête ci-dessus peut sembler un peu compliquée comparée à ce que vous avez publié, mais ce qu’elle fait est simplement d’aliaser toutes les colonnes de la table des utilisateurs pour s’assurer qu’elles sont placées dans le bon modèle

En dehors de cela, vous remarquerez qu’il effectue une JOIN au lieu de sélectionner deux tables, mais le résultat devrait être le même.

Lectures complémentaires:

Bien que la réponse acceptée ne soit pas techniquement incorrecte, elle ne répond pas à la question initiale ni à la question de suivi dans les commentaires, ce que je recherchais ici. Mais j’ai compris, alors voilà.

Si vous souhaitez trouver tous les messages contenant des utilisateurs (et uniquement ceux qui ont des utilisateurs) dans lesquels le SQL ressemblerait à ceci:

 SELECT * FROM posts INNER JOIN users ON posts.user_id = users.id 

Ce qui est sémantiquement la même chose que le SQL original de l’OP:

 SELECT * FROM posts, users WHERE posts.user_id = users.id 

alors c’est ce que vous voulez:

 Posts.findAll({ include: [{ model: User, required: true }] }).then(posts => { /* ... */ }); 

La définition requirejse pour true est la clé pour produire une jointure interne. Si vous souhaitez une jointure externe gauche (où vous obtenez tous les messages, qu’il y ait un lien utilisateur ou non), modifiez la valeur sur false ou désactivez-la, car c’est la valeur par défaut:

 Posts.findAll({ include: [{ model: User, // required: false }] }).then(posts => { /* ... */ }); 

Si vous voulez trouver tous les articles appartenant aux utilisateurs dont l’année de naissance est en 1984, vous voudrez:

 Posts.findAll({ include: [{ model: User, where: {year_birth: 1984} }] }).then(posts => { /* ... */ }); 

Notez que requirejs est vrai par défaut dès que vous ajoutez une clause where dans.

Si vous voulez tous les messages, qu’il y ait un utilisateur ou non, mais s’il y a un utilisateur seulement ceux nés en 1984, ajoutez le champ requirejs dans:

 Posts.findAll({ include: [{ model: User, where: {year_birth: 1984} required: false, }] }).then(posts => { /* ... */ }); 

Si vous voulez tous les messages dont le nom est “Sunshine” et seulement s’ils appartiennent à un utilisateur né en 1984, procédez comme suit:

 Posts.findAll({ where: {name: "Sunshine"}, include: [{ model: User, where: {year_birth: 1984} }] }).then(posts => { /* ... */ }); 

Si vous voulez tous les messages dont le nom est “Sunshine” et uniquement s’ils appartiennent à un utilisateur né la même année que l’atsortingbut post_year de la publication, procédez comme suit:

 Posts.findAll({ where: {name: "Sunshine"}, include: [{ model: User, where: ["year_birth = post_year"] }] }).then(posts => { /* ... */ }); 

Je sais, cela n’a pas de sens que quelqu’un fasse un post l’année de sa naissance, mais c’est juste un exemple – allez-y. 🙂

Je l’ai compris (surtout) à partir de ce document:

 Model1.belongsTo(Model2, { as: 'alias' }) Model1.findAll({include: [{model: Model2 , as: 'alias' }]},{raw: true}).success(onSuccess).error(onError);