sequelize.js - 在 Sequelize 中,如何按项目的多对多关联值过滤项目,并显示它们的所有关联值?
问题描述
在 Sequelize 中,如何按项目的多对多关联值过滤项目,并且仍然显示它们的所有关联值,而不仅仅是过滤后的关联值?
考虑这些模式(我使用 sequelize-typescript 但几乎相同)。我在 Item 和 Tag 之间有一个多态的 nm 关联。nm 关联用 EntityTag 模型/表表示;这个关联有一个额外的“值”,代表标签值。
标签只是一个键(词),但是当它与实体(例如:项目)链接时,这个键(词)可能具有关联的值。这正是 Amazon Web Services 对其资源所做的事情。
@Table
export class Item extends Model<Interaction> {
@Column
description: string;
@BelongsToMany(() => Tag, {
through: {
model: () => EntityTag,
scope: { entityType: 2 }, // For the polymorphic association
unique: false
},
foreignKey: 'entityId'
})
tags: Tag[];
}
@Table
export class Tag extends Model<Tag> {
@PrimaryKey
@Column
id: string;
}
@Table
export class EntityTag extends Model<EntityTag> {
@PrimaryKey
@Column
entityId: number;
@PrimaryKey
@Column
entityType: number;
@PrimaryKey
@ForeignKey(() => Tag)
@Column
tagId: string;
@Column
value: string;
}
现在,理想情况下,我希望能够执行类似“给我所有与具有以下值的以下标签相关联的项目:('TagA' = 'Foo', 'TagB' = 'Bar')”的查询.
我知道这有点太复杂了,所以现在我只考虑一个更简单的查询,例如:“给我与以下单个标签相关联的所有项目,并具有以下特定值:('TagA' = 'Foo' )”,其中 'TagA' 是 tagId, 'Foo' 是值。
考虑以下数据库
标签
+------+
| id |
+------+
| TagA |
| TagB |
+------+
物品
+------+-------------+
| id | description |
+------+-------------+
| 1000 | NULL |
+------+-------------+
实体标签
+------------+----------+-------+-------+
| entityType | entityId | tagId | value |
+------------+----------+-------+-------+
| 2 | 1000 | TagA | Foo |
+------------+----------+-------+-------+
| 2 | 1000 | TagB | Bar |
+------------+----------+-------+-------+
我希望 Sequelize 自动生成的 SQL 查询是这样的(我自己手动编写的):
SELECT * FROM
(SELECT Item.*
FROM Item
JOIN EntityTag
ON EntityTag.entityId = Item.id AND EntityTag.entityType = 2
WHERE EntityTag.tagId = "TagA" AND EntityTag.value = "Foo")
AS I
JOIN EntityTag
ON EntityTag.entityType = 2 AND EntityTag.entityId = I.id;
我的查询结果如下:
+------+-------------+------------+----------+-------+-------+
| id | description | entityType | entityId | tagId | value |
+------+-------------+------------+----------+-------+-------+
| 1000 | NULL | 2 | 1000 | TagA | Foo |
+------+-------------+------------+----------+-------+-------+
| 1000 | NULL | 2 | 1000 | TagB | Bar |
+------+-------------+------------+----------+-------+-------+
不幸的是,当我尝试使用 Sequelize 获得相同的结果时,我发现了一些困难。我试过这个:
let items = await Item.findAll({
include: [{
model: Tag,
through: {
where: {
"tagId": "TagA",
"value": "Foo"
}
}
}]
});
生成以下查询:
SELECT
`Item`.*,
`tags`.`id` AS `tags.id`,
`tags->EntityTag`.`entityId` AS `tags.EntityTag.entityId`,
`tags->EntityTag`.`entityType` AS `tags.EntityTag.entityType`,
`tags->EntityTag`.`tagId` AS `tags.EntityTag.tagId`,
`tags->EntityTag`.`value` AS `tags.EntityTag.value`
FROM
(SELECT
`Item`.`id`,
`Item`.`description`
FROM
`Item` AS `Item`
) AS `Item`
LEFT OUTER JOIN
(`EntityTag` AS `tags->EntityTag`
INNER JOIN `Tag` AS `tags` ON `tags`.`id` = `tags->EntityTag`.`tagId`
AND ((`tags->EntityTag`.`tagId` = 'TagA'
AND `tags->EntityTag`.`value` = 'Foo')
AND `tags->EntityTag`.`entityType` = 2)) ON `Item`.`id` = `tags->EntityTag`.`entityId`;
但是我从这个查询中得到的是只填充了匹配标签的项目。它缺少与同一项目关联的所有其他标签。
[
{
"id": 1000,
"description": null,
"tags": [
{
"id": "TagA",
"EntityTag": {
"entityId": 1000,
"entityType": 2,
"tagId": "TagA",
"value": "Foo"
}
}
]
}
]
这是原始查询结果。
+------+-------------+------------+----------+-------+-------+
| id | description | entityType | entityId | tagId | value |
+------+-------------+------------+----------+-------+-------+
| 1000 | NULL | 2 | 1000 | TagA | Foo |
+------+-------------+------------+----------+-------+-------+
如您所见,它缺少值为“Bar”的“TagB”。我对 Sequelize 自动生成的所有子查询感到很困惑。我怎样才能用 Sequelize 解决这个问题?
提前致谢。
解决方案
推荐阅读
- python-3.x - 基于属性着色节点
- hive - 无法使 Apache Superset 连接到 Presto DB(此 PrestoDB 连接到 Apache Pinot)
- reactjs - 在排序列表和原始列表 React.js 之间切换
- css - 按顺序做动画| CSS动画
- powershell - "|| exit /b" 和 "|| exit /b !errorlevel!" 之间的区别
- java - A obj = new A(new B); 是什么意思?
- amazon-web-services - 创建内联策略以通过 terraform 附加到 IAM 用户
- spring - 带有 JdbcTemplate 自动装配的 SimpleJdbcCall 的 Junit
- c++ - 如何在 C++ 中将二叉树序列化为文件
- python - ValueError:传递的项目数错误