Как сделать запросы соединения с помощью Sequelize на узле.js


Я использую sequelize ORM; все отлично и чисто, но у меня была проблема, когда я использую его с join запросы. У меня есть две модели: пользователи и сообщения.

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

Я хочу запрос, который отвечает с сообщением с информацией пользователя, который сделал это. В необработанном запросе я получаю следующее:

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

мой вопрос в том, как я могу изменить код, чтобы использовать стиль ORM вместо SQL-запроса?

3   51   2013-12-09 02:54:21

3 ответа:

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

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

который даст вам

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

запрос выше может выглядеть немного сложным по сравнению с тем, что вы опубликовали, но то, что он делает, в основном просто сглаживает все столбцы таблицы пользователей, чтобы убедиться, что они помещены в правильную модель при возврате и не смешиваются с моделью сообщений

кроме этого вы заметите, что он делает соединение вместо выбора из двух таблиц, но результат должен быть одинаковым

далее чтение:

в то время как принятый ответ не является технически неправильным, он не отвечает на исходный вопрос или последующий вопрос в комментариях, который был тем, что я искал здесь. Но я понял это, так что поехали.

если вы хотите найти все сообщения, которые имеют пользователей (и только те, которые имеют пользователей), где SQL будет выглядеть так:

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

что семантически то же самое, что и исходный SQL OP:

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

тогда это то, что вы хочу:

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

установка значения true является ключом к созданию внутреннего соединения. Если вы хотите левое внешнее соединение (где вы получаете все сообщения, независимо от того, связан ли пользователь), то измените обязательное значение на false или оставьте его, так как это значение по умолчанию:

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

если вы хотите найти все сообщения, принадлежащие пользователям, чей год рождения в 1984, вы хотите:

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

обратите внимание, что required имеет значение true по умолчанию, как только вы добавляете предложение where в.

если вы хотите, чтобы все сообщения, независимо от того, есть ли пользователь прикреплен, но если есть пользователь, то только те, кто родился в 1984 году, а затем добавить необходимое поле обратно в:

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

если вы хотите, чтобы все сообщения, где имя "Sunshine" и только если он принадлежит пользователю, который родился в 1984 году, вы бы сделали это:

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

если вы хотите, чтобы все сообщения, где имя "солнечный свет" и только если он принадлежит пользователю, который родился в том же году, который соответствует атрибут post_year на посту, вы бы сделали это:

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

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

я понял это (в основном) из этого документа:

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

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