繁体   English   中英

在 Sequelize 中使用具有多对多关系的 AND 操作

[英]Use AND operation with many to many relationship in Sequelize

简而言之,我的问题是:我想在联接表中使用 AND 操作。 我认为这是现实生活中非常普遍的用例,但我还没有找到任何相关的文章、博客或问题。 (我认为我的坏处:D)

让我描述一个例子来说明我的意思:我想创建一个网上商店,我有一个手机和一个功能 model,它们之间存在多对多关系。 该功能有一个多选过滤器(在我的网站上),我想列出那些具有选定功能的手机。 (例如:ABC...)我想我不能创建一个查询,因为列不能同时是 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM