2013-12-08 67 views
35

我使用了sequelize ORM;一切都很好,很乾淨,但是當我在join查詢中使用它時,我遇到了問題。 我有兩種模式:用戶和帖子。如何使用nodejs中的sequelize製作連接查詢

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查詢?

回答

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

上面的查詢可能看起來有點複雜,比你貼什麼,但它所做的工作基本上就是混疊users表中的所有列,以確保它們在返回時放入正確的模型中,並且不與帖子模型混合

除此之外,您會注意到它會執行JOIN而不是從兩個表中進行選擇,但結果應該相同

延伸閱讀:

+0

感謝的人,是偉大工程。 –

+6

如果我只想加入1984年出生的用戶,該怎麼辦?在SQL我會做:'選擇* FROM職位JOIN用戶ON users.id = posts.user_id WHERE users.year_birth = 1984' – Iwazaru

+0

@Iwazaru答案將太長,以適應一個評論,請打開一個新問題 –

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

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

雖然接受的答案是不是技術上的錯誤,它沒有回答原來的問題,也不是在評論中跟進問題,這是我來這裏尋找的。但我明白了,所以這裏就是了。

如果你想找到有用戶(僅具有用戶的那些),其中SQL就像這一切帖子:

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

這是語義上是同樣的事情OP的原始SQL:

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

那麼這就是你想要的東西:需要

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

設置到TR ue是產生內連接的關鍵。如果你想有一個左外連接(你在哪裏得到的所有帖子,無論是否有鏈接的用戶),然後更改所需的假,或將其關閉,因爲這是默認的:

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

如果你想找到所有屬於用戶,其出生年份是1984年的帖子,你會想:

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

注意,要求只要你在添加一個WHERE子句默認爲true。

如果你希望所有的帖子,無論是否有附加一個用戶,但如果有一個用戶則只有1984年出生的操作,然後添加所需的字段回:

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

如果你希望所有如果你希望所有的帖子,其中名爲「陽光」,只有當

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

:帖子,其中名爲「陽光」,只有當它屬於這是1984年出生的用戶,你可以這樣做它屬於同一年出生的用戶,該用戶匹配的是該post_year屬性後,你可以這樣做:

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

我知道,這是沒有意義的,有人會讓他們出生一年後,但它只是一個例子 - 去用它。 :)

我從此doc想通了這一點(主要):