在我的应用程序中,我有两个模型user
和userdetail
。 user
详细信息只是一个包含唯一ID的表格,userdetail
在(user_id, version)
上有唯一键。当我想获取最新的用户数据时,我运行类似于以下的SQL:
SELECT userdetail1.password_hash FROM user
JOIN userdetail userdetail1 ON userdetail1.user_id = user.id
JOIN (
SELECT user_id, MAX(version) version
FROM userdetail
GROUP BY user_id
) userdetail2 ON userdetail2.user_id = userdetail1.user_id AND userdetail2.version = userdetail1.version
WHERE user.id = 1;
我正在处理的数据库只允许INSERT,因此我只能更新'通过在userdetail
中插入新行来记录。
我在Sequelize中定义了两个模型:
var UserDetail = sequelize.define('userdetail', {
id: {
type: DataTypes.INTEGER(10),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
user_id: {
type: DataTypes.INTEGER(10),
allowNull: false,
references: {
model: 'user',
key: 'id'
}
},
version: {
type: DataTypes.INTEGER(10),
allowNull: false
},
password_hash: {
type: DataTypes.STRING,
allowNull: false
}
}, {
timestamps: false,
tableName: 'userdetail'
});
var User = sequelize.define('user', {
id: {
type: DataTypes.INTEGER(10),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
created: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
}
}, {
timestamps: false,
tableName: 'user'
});
User.hasMany(UserDetail.getModel(), {
foreignKey: "user_id"
});
UserDetail.getModel().belongsTo(User, {
foreignKey: "user_id"
});
我希望使用findAll()方法找到最新记录。这是我遇到问题的地方。我知道我需要加入三次(User< - > UserDetail< - > UserDetail),所以我有以下内容:
return this.model.findAll({
include: [{
model: this.UserDetail.getModel()
}, {
model: this.UserDetail.getModel(),
as: "userdetail2"
}]
但是,这会产生错误userdetail (userdetail2) is not associated to user!
,所以我不确定如何两次加入同一个表?
此外,我需要第二个连接在其userdetail.version
子句中的ON
上有一个条件 - 这可能在Sequelize中吗?
答案 0 :(得分:1)
你也应该做两次关联:
User.hasMany(UserDetail.getModel(), {
foreignKey: "user_id"
});
User.hasMany(UserDetail.getModel(), {
as: "userdetail2",
foreignKey: "user_id"
});
UserDetail.getModel().belongsTo(User, {
foreignKey: "user_id"
});
UserDetail.getModel().belongsTo(User, {
as: "userdetail2",
foreignKey: "user_id"
});
答案 1 :(得分:1)
上述答案的另一种形式:
合并为文字语句这是使用T-SQL。想法是您加入,但只能使用version字段的最大结果。
db.user.findAll({
include: [
{
model: db.userDetail,
as: 'userdetail_a',
where: {
userId: userId,
[Op.and]: [ Sequelize.literal(' version = (
Select MAX(version)
FROM tbluserDetail
WHERE
userId = [user].[userId])')
],
}
}
],
});
您必须将'userdetail_a'的关联设置为hasOne,即使有很多情况,否则您的联接最终会成为数组中的一个值
答案 2 :(得分:0)
如果有人正在寻找答案,我在这个GitHub问题中回答了这个问题:https://github.com/sequelize/sequelize/issues/8600
第一步是按照@Adam的建议,两次声明一对多关联。
然后查询将如下所示:
db.user.findAll({
include: [
{
model: db.userDetail,
required: false, // forces left join
duplicating: false // prevents sub-queries
},
{
model: db.userDetail,
as: 'userdetail2',
required: false, // forces left join
duplicating: false, // prevents sub-queries
on: {
'$user.id$': { $col: 'user->userdetail2.userId' },
'$user->userdetail.version$': { $col: 'user->userdetail2.version' }
}
}
],
where: {
'$user->membership_2.id$': { $eq: null }
}
});