如何在Elasticsearch中实现类似MongoDB $lookup的跨索引关联查询
Elasticsearch 实现类似MongoDB $lookup关联查询的方案
Elasticsearch 原生支持该类关联查询需求,针对你的场景有三种常用落地方案,可根据你的业务特性选择:
方案1:查询侧二次查询组装(最简单,适合中小数据量、实时性要求高的场景)
不需要修改现有索引结构,分两步查询后在应用侧组装结果即可:
- 第一步全量查询index1,拿到所有
doc_id列表和对应index1文档的基础信息 - 第二步用terms查询拉取所有关联的index2文档:
GET /index2/_search { "query": { "terms": { "index1_id": ["A1", "A2", "A3"] // 替换为第一步拿到的所有index1的doc_id } }, "size": 10000 // 可根据关联数据量级调整 }
- 应用侧将查询到的index2文档按
index1_id字段分组,拼接到对应index1文档的index2_docs字段,同时统计total_index2_count即可,无关联数据的字段填充空数组和0。
方案2:Enrich处理器预关联(适合查询性能要求高、实时性要求低的场景)
原理是提前将index2的关联数据预聚合后写入index1的字段中,查询时直接读取index1就能得到目标结构,无需二次处理:
- 创建enrich关联策略,配置匹配规则:
PUT /_enrich/policy/index2_lookup_policy { "match": { "indices": "index2", "match_field": "index1_id", "enrich_fields": ["doc_id", "class"] } }
- 执行策略初始化,生成关联快照:
POST /_enrich/policy/index2_lookup_policy/_execute
- 为index1配置摄入管道,写入/更新index1文档时自动关联index2的数据,聚合为
index2_docs数组并计算total_index2_count存储。
注:如果index2的数据有更新,需要重新执行策略执行命令同步快照数据。
方案3:父子文档模型(适合关联关系固定、实时性要求高的场景)
将两个索引合并为同一个索引的父子文档结构,查询时直接通过inner_hits拿到关联数据:
- 合并后的索引mapping配置join字段,将index1文档设为父类型,index2文档设为子类型,子文档写入时指定
parent字段为对应index1的doc_id - 查询时用以下请求直接拿到目标结果:
GET /merged_index/_search { "query": { "term": { "join_field": "index1_doc" } }, "inner_hits": { "index2_docs": { "type": "index2_doc", "size": 100 } }, "aggs": { "to_children": { "children": { "type": "index2_doc" }, "aggs": { "total_index2_count": { "value_count": { "field": "_id" } } } } } }
注:该方案要求父子文档必须落在同一分片,写入子文档时需要指定父文档id作为路由参数,灵活性相对较低。
内容的提问来源于stack exchange,提问作者drake1994
相关产品推荐
相关产品推荐

