如何用Elasticsearch查询用户订阅节目下的所有剧集?
解决方案
Elasticsearch完全支持单次查询实现这个需求,不需要拆分多次请求,以下是两种可行方案,适配不同的索引结构:
方案1:平级索引下的Terms Lookup查询
如果所有数据都是平级存储在同一索引中(无父子/嵌套关系),可以用Terms Lookup查询实现类似SQL IN子查询的效果——它能动态从匹配的Subscription文档中提取showId,再用这些ID过滤Episode文档。
假设你的索引名为media_index,且每个文档都有doc_type字段标识类型(比如doc_type: "episode"/"subscription"),查询语句如下:
{ "query": { "bool": { "filter": [ // 只匹配剧集类型的文档 { "term": { "doc_type": "episode" } }, // 动态获取目标用户订阅的节目ID,并用这些ID过滤剧集 { "terms": { "showId": { "index": "media_index", "query": { "bool": { "filter": [ { "term": { "doc_type": "subscription" } }, { "term": { "userId": "user-1" } } ] } }, "path": "showId" } } } ] } } }
注意:该功能需要Elasticsearch 7.10+版本支持,且要确保索引的search_enabled参数为true。
方案2:使用Join数据类型(更高效的关联查询)
如果可以调整索引结构,推荐使用Elasticsearch的Join数据类型定义文档间的父子关系,这是官方推荐的关联数据处理方式,性能更优:
给索引添加Join字段,定义两组父子关系:
media_relation:parent: "show",child: "episode"(节目是剧集的父文档)user_sub_relation:parent: "user",child: "subscription"(用户是订阅记录的父文档)
单次查询语句如下:
{ "query": { "bool": { "must": [ // 找到所有属于目标用户订阅节目的剧集 { "has_parent": { "parent_type": "show", "query": { "bool": { "must": [ { "has_child": { "child_type": "subscription", "query": { "term": { "userId": "user-1" } } } } ] } } } } ] } } }
总结
两种方案都能实现单次查询的需求:如果不想改动现有索引结构,用Terms Lookup查询;如果追求更规范、高效的关联处理,优先选择Join数据类型。
内容的提问来源于stack exchange,提问作者luickx
相关产品推荐
相关产品推荐

