[英]Use AND operation with many to many relationship in Sequelize
简而言之,我的问题是:我想在联接表中使用 AND 操作。 我认为这是现实生活中非常普遍的用例,但我还没有找到任何相关的文章、博客或问题。 (我认为我的坏处:D)
让我描述一个例子来说明我的意思:我想创建一个网上商店,我有一个手机和一个功能 model,它们之间存在多对多关系。 该功能有一个多选过滤器(在我的网站上),我想列出那些具有选定功能的手机。 (例如:A和B和C...)我想我不能创建一个查询,因为列不能同时是 A 和 B,但我不确定。 例子:
const mobiles = await models.mobile.findAll({
where: '???',
attributes: ['id', 'name'],
include: [
{
model: models.feature,
where: '???',
attributes: ['id', 'name],
through: {
attributes: [],
},
},
],
});
我也对 Sequelize 和 SQL 解决方案感兴趣。
示例模型和预期结果:
const Mobile = sequelize.define('Mobile', {
id: {
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER,
},
name: {
type: DataTypes.STRING
}
}, {});
const Feature = sequelize.define('Feature', {
id: {
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER,
},
name: {
type: DataTypes.STRING
}
}, {});
Mobile.belongsToMany(Feature, { through: 'MobileFeature' });
Feature.belongsToMany(Mobile, { through: 'MobileFeature' });
// Example Data in DB (from mobile context)
const exampleData = [
{
"id": 1,
"name": "Mobile1",
"features": [
{
"id": 1,
"name": "A",
},
{
"id": 2,
"name": "B",
},
{
"id": 3,
"name": "C",
},
],
},
{
"id": 2,
"name": "Mobile2",
"features": [],
},
{
"id": 3,
"name": "Mobile3",
"features": [
{
"id": 1,
"name": "A",
},
]
}
];
// Expected result
// Scenario: I want to list those mobiles which have A and C feature
const result = [
{
"id": 1,
"name": "Mobile1",
"features": [
{
"id": 1,
"name": "A",
},
{
"id": 2,
"name": "B",
},
{
"id": 3,
"name": "C",
},
]
},
];
我认为这里的查询将比where
更复杂。
能否提供适合您问题的SQL查询? 我想您将需要使用 GROUP BY、COUNT 和 HAVING(但这只是一个假设,按您的方式行事;))
如果我理解你的问题是正确的:加入移动和功能表。 然后在结果上使用where
WHERE: {
name: { [Op.or]: [A,B,C] } // here we pass array of selected feature names to where. It returns mobiles only with this features. But we are looking for mobile with ALL features passed in array)
}
按 Mobile.name 对其进行分组,计算每个手机中的功能,然后使用具有功能编号 = 用户选择的功能的手机(因此具有我们正在寻找的所有功能的手机)。
当然最后会是一个sequelize语句。
更新:在对此答案的评论中回答您的问题:
首先,您需要计算功能。 所以我们将使用COUNT
并将 output 存储在CountedFeatures
列中:
attributes: ['id', 'name', [sequelize.fn('COUNT', 'table.fieldToCount'), 'CountedFeatures']],
然后您需要使用 group 对其进行group
。 使用示例:
group: ["table.name, table.id"]
然后您enter code here
having
使用之前创建countedFeatures
列:
having: sequelize.where(sequelize.fn('COUNT', 'countedFeatures'), '=', searchedFeaturesArray.length)
所以代码结构看起来像这样:
(...).findAll({
attributes: [...],
include : [
(...)
],
group: [...],
having: [...]
})
您还可以打开 SQL 语句日志记录到控制台,看看下面到底发生了什么。 为此,在findAll
function 中添加logging: console.log
作为属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.