如何在sequelize中查询多对多关系
How to query many to many relation in sequelize
我一直在通过 sequelize 在 postgres 数据库上使用 feathersjs/nodejs。在我的数据库中,我有用户 table 和事件 table。他们有两次关系:
events.belongsTo(models.users, {
foreignKey: {
name: 'creatorId',
allowNull: false
},
onDelete: 'CASCADE',
as: 'creator'
});
events.belongsToMany(models.users, {
through: 'event_participants',
as: 'participants',
foreignKey: 'eventId',
otherKey: 'userId'
});
models.users.belongsToMany(events, {
through: 'event_participants',
as: 'events'
});
一切正常,table 已创建,并且包含即时消息让用户作为参与者参与到活动中。问题是通过关联查询。我正在尝试为当前用户获取事件,因此我需要创建者是当前用户的事件以及参与者之一是当前用户的事件。问题是第二部分'querying where current user is one of participants'。我期待这样的事情
'api/events?$or[0][creatorId]=currUserId&$or[1][participants][$contains]=currUserId'
但它不起作用,因为没有包含 'participants' 这样的列,所以我无法查询它。所以现在我只是获取所有事件并在 after hooks 中为当前用户过滤它们,但这似乎是错误的。这样做的正确方法是什么?
是的,我知道我可以通过将用户作为参与者之一包含在用户中并获取他来获取事件,但问题是我无法对所有数据进行排序,它是单独排序的,另一个问题是分页在前端。
查询嵌套关联不是 Feathers 通用查询语法的一部分。在 Sequelize 的情况下,应根据您的需要使用 params.sequelize and includes as shown in the feathers-sequelize associations documentation:
组装查询
// GET /my-service?name=John&include=1
function (context) {
if (context.params.query.include) {
const AssociatedModel = context.app.services.fooservice.Model;
context.params.sequelize = {
include: [{
model: AssociatedModel
// normal Sequelize where query here
}]
};
// delete any special query params so they are not used
// in the WHERE clause in the db query.
delete context.params.query.include;
}
return Promise.resolve(context);
}
在@daff 的回答的帮助下,我找到了这样的解决方案...可以找到我遇到的错误 here。
const { authenticate } = require('@feathersjs/authentication').hooks;
function includeBefore(hook) {
currUserId = hook.params.user.id;
userModel = hook.app.services.users.Model
hook.params.sequelize = {
where: {
$or: [
{
creatorId: currUserId
},
{
'$participants.id$': currUserId //no idea what are '$$' for but it made it work
}
]
},
include: [
{
model: userModel,
as: 'creator',
}, {
model: userModel,
as: 'participants',
duplicating: false //fixed error that I was getting
}
],
}
return hook;
}
module.exports = {
before: {
all: [
authenticate('jwt'),
hook => includeBefore(hook)
],
.........
我一直在通过 sequelize 在 postgres 数据库上使用 feathersjs/nodejs。在我的数据库中,我有用户 table 和事件 table。他们有两次关系:
events.belongsTo(models.users, {
foreignKey: {
name: 'creatorId',
allowNull: false
},
onDelete: 'CASCADE',
as: 'creator'
});
events.belongsToMany(models.users, {
through: 'event_participants',
as: 'participants',
foreignKey: 'eventId',
otherKey: 'userId'
});
models.users.belongsToMany(events, {
through: 'event_participants',
as: 'events'
});
一切正常,table 已创建,并且包含即时消息让用户作为参与者参与到活动中。问题是通过关联查询。我正在尝试为当前用户获取事件,因此我需要创建者是当前用户的事件以及参与者之一是当前用户的事件。问题是第二部分'querying where current user is one of participants'。我期待这样的事情
'api/events?$or[0][creatorId]=currUserId&$or[1][participants][$contains]=currUserId'
但它不起作用,因为没有包含 'participants' 这样的列,所以我无法查询它。所以现在我只是获取所有事件并在 after hooks 中为当前用户过滤它们,但这似乎是错误的。这样做的正确方法是什么?
是的,我知道我可以通过将用户作为参与者之一包含在用户中并获取他来获取事件,但问题是我无法对所有数据进行排序,它是单独排序的,另一个问题是分页在前端。
查询嵌套关联不是 Feathers 通用查询语法的一部分。在 Sequelize 的情况下,应根据您的需要使用 params.sequelize and includes as shown in the feathers-sequelize associations documentation:
组装查询 // GET /my-service?name=John&include=1
function (context) {
if (context.params.query.include) {
const AssociatedModel = context.app.services.fooservice.Model;
context.params.sequelize = {
include: [{
model: AssociatedModel
// normal Sequelize where query here
}]
};
// delete any special query params so they are not used
// in the WHERE clause in the db query.
delete context.params.query.include;
}
return Promise.resolve(context);
}
在@daff 的回答的帮助下,我找到了这样的解决方案...可以找到我遇到的错误 here。
const { authenticate } = require('@feathersjs/authentication').hooks;
function includeBefore(hook) {
currUserId = hook.params.user.id;
userModel = hook.app.services.users.Model
hook.params.sequelize = {
where: {
$or: [
{
creatorId: currUserId
},
{
'$participants.id$': currUserId //no idea what are '$$' for but it made it work
}
]
},
include: [
{
model: userModel,
as: 'creator',
}, {
model: userModel,
as: 'participants',
duplicating: false //fixed error that I was getting
}
],
}
return hook;
}
module.exports = {
before: {
all: [
authenticate('jwt'),
hook => includeBefore(hook)
],
.........