Elasticsearch 5:如何按符合条件的Speaker重复返回对应事件文档
针对Elasticsearch 5实现按数组元素重复返回文档的方案
临时方案:查询+应用层处理(无需修改索引)
Elasticsearch 5本身不会自动让一个文档因数组内多个匹配元素重复返回,你可以先查询出符合条件的文档,再在应用层做重复输出:
- 先过滤出包含目标gender speaker的文档
- 用脚本统计每个文档中符合条件的speaker数量
- 在应用代码里根据统计数,把对应文档重复输出对应次数
示例查询DSL
根据你的speakers字段类型选择对应的脚本:
- 如果
speakers是普通对象数组(未设nested类型):
{ "query": { "term": { "speakers.gender": "x" } }, "script_fields": { "matched_speaker_count": { "script": { "inline": "int count = 0; for (sp in doc['speakers.gender']) { if (sp == params.gender) count++; } return count;", "params": { "gender": "x" } } } }, "_source": true }
- 如果
speakers是nested类型:
{ "query": { "nested": { "path": "speakers", "query": { "term": { "speakers.gender": "x" } } } }, "script_fields": { "matched_speaker_count": { "script": { "inline": "int count = 0; for (sp in _source.speakers) { if (sp.gender == params.gender) count++; } return count;", "params": { "gender": "x" } } } }, "_source": true }
注意:Elasticsearch 5默认允许inline脚本,需确保配置中
script.inline: on已开启。
长期方案:重构索引结构(更高效)
如果这类查询很频繁或数据量较大,建议重新构建索引,把每个speaker拆成独立文档:
- 原结构示例:
{ "event_id": "evt_123", "event_name": "Tech Conference", "speakers": [ {"gender": "x", "name": "A"}, {"gender": "y", "name": "B"}, {"gender": "x", "name": "C"} ] }
- 重构后单speaker对应单文档:
{ "event_id": "evt_123", "event_name": "Tech Conference", "speaker_gender": "x", "speaker_name": "A" } { "event_id": "evt_123", "event_name": "Tech Conference", "speaker_gender": "y", "speaker_name": "B" } { "event_id": "evt_123", "event_name": "Tech Conference", "speaker_gender": "x", "speaker_name": "C" }
之后直接用term查询speaker_gender: x,就能直接得到两条对应事件的文档,完全匹配需求,且查询效率更高。
版本支持说明
Elasticsearch 5本身不支持直接让单文档因数组匹配元素重复返回,所以只能通过上述两种方式实现,考虑到版本已停止维护,不建议升级,这两个方案是最贴合你场景的选择。
内容的提问来源于stack exchange,提问作者magdastone
相关产品推荐
相关产品推荐

