sql - 如何按包含的实体搜索/选择,但将所有相关实体包含到结果集中
问题描述
在我的应用程序中,我使用的是 sequelize ORM。有几个实体: ATool
可以有Tags
和Categories
。
现在我想搜索所有Tool
具有特定 s 的 s Tag
,但我想包括Tag
该工具的所有相关 s(不仅仅是特定的)。如果我现在将一条where
语句放入包含中,则只有指定Tag
的 s 会包含在结果集中(请参阅 参考资料[2]
)。我试图限制Tag
外部 where 语句中的 s(请参阅 参考资料[1]
),但这也无济于事。
例子
工具A
有标签t1
,t2
和t3
。现在我想搜索所有具有 Tag 的工具t3
,但结果集应包含所有三个标签。
预期结果:
Tool A
\
- Tag t1
- Tag t2
- Tag t3
db.Tool.scope('published').findAll({
where: { '$tool.tag.name$': filter.tag }, // [1] Does not work
include: [
{
model: db.User,
attributes: ['id', 'username']
},
{
model: db.Tag,
attributes: ['name'],
through: { attributes: [] },
// [2] Would limit the result specified tag
// where: {
// name: {
// [Op.and]: filter.tag
// }
// }
},
{
model: db.Category,
attributes: ['id', 'name', 'views'],
through: { attributes: ['relevance'] },
where: {
id: {
[Op.and]: filter.category
}
}
}
],
where: {
title: {
[Op.like]: `%${filter.term}%`,
}
},
attributes: ['id', 'title', 'description', 'slug', 'docLink', 'vendor', 'vendorLink', 'views', 'status', 'createdAt'],
order: [['title', 'ASC'], [db.Tag, 'name', 'ASC']]
})
我知道我可以通过首先通过标签执行选择来执行此操作(db.Tag.findAll()
而不是db.Tool.findAll()
;我已经在项目的其他地方完成了此操作),但同时我也希望能够通过另一个实体进行过滤(Category
) 一样的方法。所以Tool.findAll()
应该是起点。
任何帮助表示赞赏!
解决方案
首先,您的顶级查询中有两个 where 子句:
where: { '$tool.tag.name$': filter.tag }, // [1] Does not work
// ...
where: {
title: {
[Op.like]: `%${filter.term}%`,
}
},
我认为您最好的方法是literal
在 WHERE 子句中使用子查询。基本上,我们想要找到所有具有正确标签且包含filter.term
.
WHERE 的子查询部分看起来像......
SELECT ToolId FROM ToolTags WHERE TagId='t2';
受到这篇文章Sequelize - where 子句中的子查询的子查询解决方案的启发
// assuming your join table is named 'ToolTags' in the database--we need the real table name not the model name
const tempSQL = sequelize.dialect.QueryGenerator.selectQuery('ToolTags',{
attributes: ['ToolId'],
where: {
TagId: filter.tag
}})
.slice(0,-1); // to remove the ';' from the end of the SQL
db.Tool.scope('published').findAll({
where: {
title: {
[Op.like]: `%${filter.term}%`,
},
id: {
[Op.In]: sequelize.literal(`(${tempSQL})`)
}
},
include: [
{
model: db.User,
attributes: ['id', 'username']
},
{
model: db.Tag,
attributes: ['name'],
through: { attributes: [] },
},
// {
// model: db.Category,
// attributes: ['id', 'name', 'views'],
// through: { attributes: ['relevance'] },
// where: {
// id: {
// [Op.and]: filter.category
// }
// }
// }
],
attributes: ['id', 'title', 'description', 'slug', 'docLink', 'vendor', 'vendorLink', 'views', 'status', 'createdAt'],
order: [['title', 'ASC'], [db.Tag, 'name', 'ASC']]
})
我现在评论了你的类别加入。我认为您应该在向查询中添加更多内容之前尝试隔离标签的解决方案。
推荐阅读
- swift - 在 SwiftUI 中的 ForEach 中绑定
- python-3.x - Powerpoint通过python中的COM更改图表数据标签中一个字符的颜色
- reactjs - 反应日期选择器处理空日期和时间值
- python - 在 tkinter 中同时运行多个函数
- cython - Cython:如何转换包含赋值的 C 宏
- c# - Linq - Sql 日期时间溢出
- flutter - 在 Flutter 中更新对象不起作用
- c - 为什么 GCC 不优化这个循环?
- generics - Swift 5 - 泛型 - RangeReplaceableCollection
- python - python import fastparquet 出现“双重免费或损坏(顶部)”错误