2013-12-08 22 views
35

Ich benutze Sequelize ORM; Alles ist großartig und sauber, aber ich hatte ein Problem, wenn ich es mit join Abfragen verwende. Ich habe zwei Modelle: Benutzer und Beiträge.Wie mache ich eine Query mit Sequelize in Nodejs

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

Ich möchte eine Abfrage, die mit einem Beitrag mit den Informationen des Benutzers, der es gemacht hat, antworten. In der rohen Abfrage, bekomme ich diese:

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

Meine Frage ist, wie kann ich den Code ändern, um den ORM-Stil statt die SQL-Abfrage zu verwenden?

Antwort

51
User.hasMany(Post, {foreignKey: 'user_id'}) 
Post.belongsTo(User, {foreignKey: 'user_id'}) 

Post.find({ where: { ...}, include: [User]}) 

die Ihnen

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`; 

Die Abfrage oben vielleicht ein bisschen kompliziert aussehen im Vergleich zu dem, was geschrieben Sie, aber was es tut, ist im Grunde Aliasing nur alle Spalten der Tabelle Benutzer sicherzustellen, dass sie wenn zurückgegeben werden, in das richtige Modell platziert und nicht mit dem Pfosten Modell gemischt

Anders als das Sie werden feststellen, dass es sich um eine aus zwei Tabellen statt der Auswahl beitritt, aber das Ergebnis sollte die gleiche

sein

Weiterführende Literatur:

+0

Dank Mann, die großen Werke. –

+6

Was ist, wenn ich nur Benutzern beitreten möchte, die 1984 geboren sind? In SQL würde ich tun: 'SELECT * FROM Beiträge JOIN Benutzer ON users.id = posts.user_id WHERE users.year_birth = 1984' – Iwazaru

+0

@Iwazaru Die Antwort wäre zu lang, um in einen Kommentar zu passen, bitte eine neue Frage zu öffnen –

0
Model1.belongsTo(Model2, { as: 'alias' }) 

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

Während die akzeptierte Antwort technisch nicht falsch ist, ist es nicht die ursprüngliche Frage beantworten, noch die Follow-up-Frage in den Kommentaren, nach denen ich hier suchte. Aber ich habe es herausgefunden, also hier.

Wenn Sie alle Beiträge finden, die Benutzer haben (und nur diejenigen, die Benutzer haben), wo die SQL würde wie folgt aussehen:

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

Welche semantisch das gleiche wie der ursprüngliche SQL des OP ist:

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

dann ist es das, was Sie wollen:

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

Rahmen tr erforderlich Es ist der Schlüssel zum Herstellen einer inneren Verbindung. Wenn Sie möchten, eine linke äußere Verknüpfung (wo Sie alle Beiträge zu erhalten, unabhängig davon, ob es ein Benutzer verknüpft), dann auf false erforderliche Änderung, oder lassen Sie es ab, da dies die Standard ist:

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

Wenn Sie alle finden wollen Beiträge zu Benutzern gehören, deren Geburtsjahr 1984 ist, dann würden Sie wollen:

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

Beachten Sie, dass, sobald der Standardeinstellung ist wahr erforderlich, wie Sie eine where-Klausel in hinzufügen.

Wenn Sie alle Beiträge wollen, unabhängig davon, ob ein Benutzer es angebracht, aber wenn es ein Benutzer dann ist nur die 1984 Geborenen, dann fügen Sie das gewünschte Feld zurück in:

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

Wenn Sie alle wollen Beiträge in dem der Name „Sunshine“ und nur, wenn es zu einem Benutzer gehört, die im Jahr 1984 geboren wurde, dann würden Sie dies tun:

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

wenn Sie alle Beiträge wollen, wo der Name „Sunshine“ ist und nur dann, wenn Es gehört zu einem Benutzer, der im selben Jahr geboren wurde, der mit dem post_year Attribut auf dem übereinstimmt Post, würden Sie dies tun:

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

Ich weiß, macht es keinen Sinn machen, dass jemand ein Post das Jahr würde sie geboren wurden, aber es ist nur ein Beispiel - mit ihm gehen. :)

Ich dachte, dies aus (meist) von dieser doc:

Verwandte Themen