我在Sequelize中重新创建以下查询时遇到问题。我已经坐了几个小时,试图弄清楚这一点。
我使用的是camelCase而不是snake_case,所以我无法重用相同的查询。
如果我将所有snake_cased变量交换为查询中的camelCase,则该查询将不起作用。我回来“关系\“ directmessages \”不存在”。我无法使用TABLE directmessages访问psql中的directmessages表; -但我知道它应该在那里。
我也不知道如何用续集进行相同的查询。
基本上,我需要获取当前用户已经直接发送消息的每个用户。作为发送者或接收者。
models.sequelize.query(
'select distinct on (u.id) u.id, u.username from users as u join direct_messages as dm on (u.id = dm.sender_id) or (u.id = dm.receiver_id) where (:currentUserId = dm.sender_id or :currentUserId = dm.receiver_id) and dm.team_id = :teamId',
{
replacements: { currentUserId: user.id, teamId: id },
model: models.User,
raw: true,
},
这些是与此查询相关的模型:
用户模型:
User.associate = (models) => {
User.belongsToMany(models.Team, {
through: models.Member,
foreignKey: 'userId',
})
User.belongsToMany(models.Channel, {
through: 'channel_member',
foreignKey: 'userId',
})
}
DirectMessage模型:
DirectMessage.associate = (models) => {
DirectMessage.belongsTo(models.Team, {
foreignKey: 'teamId',
})
DirectMessage.belongsTo(models.User, {
foreignKey: 'receiverId',
})
DirectMessage.belongsTo(models.User, {
foreignKey: 'senderId',
})
}
我尝试使用以下续集创建查询:
models.User.findAll({
include:[{
model: models.DirectMessage,
where: {
teamId,
[models.sequelize.Op.or]: [{senderId: user.id}, {receiverId: user.id}]
}
}]
}, { raw: true })
我得到“ message”:“ directMessage与用户无关!”,我认为这是因为DirectMessage与User相关联,而不是相反。
有人对我如何重构此查询有任何提示吗?
答案 0 :(得分:0)
我认为这是因为DirectMessage是与User相关联的,而不是与User相关联的。
我也想这样。从用户关联到DirectMessage很容易(两次):
User.hasMany(models.DirectMessage, {foreignKey: 'receiverId', as: 'receivers'});
User.hasMany(models.DirectMessage, {foreignKey: 'senderId', as: 'senders'});
然后查询还不错。请注意,“ as”值告诉Sequelizer使用哪个FK,因此请确保hasMany与查询的包含模型匹配
models.Users.findAll({
include: [
{
model: models.DirectMessage, as: 'receivers',
attributes: [[Sequelize.fn('count', 'id'), 'number_received']]
},
{
model: models.DirectMessage, as: 'senders',
attributes: [[Sequelize.fn('count', 'id'), 'number_sent']]
}
],
where : {id : user.id}, // parameter
group : ['id']
})
然后,您必须验证“ senders.number_sent”或“ receivers.number_received”不是非零且> 0。从理论上讲,您可以使用HAVING子句来执行此操作,但是恕我直言,这在Sequelize中实现得不太好。...
答案 1 :(得分:0)
这里有几件事。首先,当您使用belongsToMany
时,您需要在两个模型上进行关联,因为这是M:N关系,如下所示:
另外,您在关联上有错误的foreignKey
。应该是这样的:
User.associate = (models) => {
User.belongsToMany(models.Team, {
through: models.Member,
foreignKey: 'user_id',
})
models.Team.belongsToMany(User, {
through: models.Member,
foreignKey: 'team_id',
})
// ----------------------------------
User.belongsToMany(models.Channel, {
through: 'channel_member',
foreignKey: 'user_id',
})
models.Channel.belongsToMany(user, {
through: 'channel_member',
foreignKey: 'channel_id',
})
}
现在可以在javascript上使用camelCase名称并在sql上进行续集和保留snake_case,您可以执行以下操作:
module.exports = (sequelize, DataTypes) => {
const Member = sequelize.define('Member', {
// here goes your regular fields
userId: { //now you can use this property on sequelize
field: 'user_id', //and is linked yo the foreignKey
type: DataTypes.INTEGER
},
teamId: {
field: 'team_id',
type: DataTypes.INTEGER
}
}
}
与include有关的最后一个问题是,因为您必须指定要调用的关联,并且正如您所说,您需要
以另一种方式从User
到DirectMessage
声明关联:
User.hasMany(models.DirectMessage, { //there is also hasOne()
as: 'Sender', // this is important because you have two association from User to DirectMessage
foreignKey: 'sender_id',
})
User.hasMany(models.DirectMessage, { //there is also hasOne()
as: 'Receiver', // this is important because you have two association from User to DirectMessage
foreignKey: 'user_id',
})
现在您可以进行查询
models.User.findAll({
include:[{
model: models.DirectMessage,
as: 'Sender'
where: {
teamId,
}
}]
}, { raw: true })
我对此查询有疑问,因为实际上您正在调用所有DirectMessages
,因此senderId
和receiverId
过滤器没有多大意义。
无论如何,希望对此有个更好的主意。