如何在 Node.js 上使用 Sequelize 进行连接查询

我正在使用 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 查询?

282828 次浏览
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`;

上面的查询与您发布的内容相比可能看起来有点复杂,但它所做的基本上只是对用户表中的所有列进行别名,以确保它们在返回时被放置到正确的模型中,而不会与发布模型混淆

除此之外,您会注意到它执行了一个 JOIN,而不是从两个表中进行选择,但是结果应该是相同的

进一步阅读:

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


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

虽然接受的答案在技术上并没有错,但它并没有回答原来的问题,也没有回答评论中的后续问题,这正是我来这里寻找的。但我想明白了,所以开始吧。

如果你想找到所有有用户的帖子(只有那些有用户的帖子) ,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 => {
/* ... */
});

设置为 true 是生成内部连接的关键。如果你想要一个左外部连接(无论是否有用户链接,你都可以得到所有的帖子) ,那么需要将其改为 false,或者将其关闭,因为这是默认值:

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 => {
/* ... */
});

如果你想要所有名字为“ Sunshine”的帖子,并且只有当它属于一个1984年出生的用户时,你可以这样做:

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

如果您希望所有名称为“ Sunshine”的帖子,并且只有当它属于与该帖子的 post _ year 属性相匹配的同一年出生的用户时,才需要执行以下操作:

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

我知道,有人在他们出生的那一年发帖子是没有道理的,但这只是一个例子——顺其自然吧。:)

我(大部分时间)是通过这个文档得出这个结论的:

在我的情况下,我做了下面的事情。在 UserMaster 中 UserId是 PK,在 UserAccessUserId中是 UserMaster 的 FK

UserAccess.belongsTo(UserMaster,{foreignKey: 'userId'});
UserMaster.hasMany(UserAccess,{foreignKey : 'userId'});
var userData = await UserMaster.findAll({include: [UserAccess]});