如何在Elasticsearch搜索结果中添加命中关键词列表字段
如何在Elasticsearch搜索结果中添加命中关键词列表字段
索引Mapping
"result": { "properties": { "duration": { "type": "float" }, "endTime": { "type": "float" }, "results": { "properties": { "offsets": { "type": "long" }, "output": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } }, "startTime": { "type": "float" } } }, "timestamp": { "type": "date" }
原搜索请求
{ "query": { "bool": { "must": [ { "range": { "timestamp": { "gte": "now-5d" } } } ], "filter": [ { "terms": { "result.results.output": [ "keyword-1", "keyword-2" ] } } ] } } }
需求
在搜索结果的_source中新增found_keywords字段,展示当前文档命中的关键词列表,无需高亮文本,要求通过搜索时动态字段实现。
解决方案
使用Elasticsearch的runtime mappings定义动态字段,将匹配的关键词列表注入到_source中,具体请求如下:
{ "query": { "bool": { "must": [ { "range": { "timestamp": { "gte": "now-5d" } } } ], "filter": [ { "terms": { "result.results.output": [ "keyword-1", "keyword-2" ] } } ] } }, "runtime_mappings": { "found_keywords": { "type": "keyword", "script": { "source": """ List keywords = params.keywords; List matched = new ArrayList(); // 使用keyword子字段进行精确匹配检查 if (doc.containsKey('result.results.output.keyword')) { String content = doc['result.results.output.keyword'].value; for (def kw : keywords) { if (content.contains(kw)) { matched.add(kw); } } } emit(matched); """, "params": { "keywords": ["keyword-1", "keyword-2"] } }, "include_in_source": true } } }
说明
runtime_mappings用于在搜索时动态定义字段,不会修改索引的原始mappinginclude_in_source: true确保found_keywords字段会被包含在_source中,符合期望的输出格式- 脚本中使用
result.results.output.keyword子字段进行匹配,避免text字段分词带来的匹配偏差 - 遍历传入的关键词列表,检查文档内容是否包含该关键词,收集所有匹配项并返回
内容的提问来源于stack exchange,提问作者shahin
相关产品推荐
相关产品推荐

