Elasticsearch如何实现文档字段值被包含在搜索短语的精确匹配?
实现文档字段值被搜索短语完整包含的精确匹配(Elasticsearch)
索引结构
示例文档的_source结构如下:
"_source": { "iD": "378", "containsTerms": [ { "containsTerm": "search term to match" }, { "containsTerm": "another search term to match" }, { "containsTerm": "etcetera" } ], "startdate": "2022-09-08T14:07:00", "enddate": "2022-09-30T14:07:00" }
字段映射
该索引的映射配置:
"mappings":{ "properties":{ "containsTerms":{ "properties":{ "containsTerm":{ "type":"text", "fields":{ "keyword":{ "type":"keyword", "ignore_above":256 } } } } }, "enddate":{ "type":"date" }, "startdate":{ "type":"date" } } }
原有查询的局限性
之前使用的match查询会返回包含搜索短语部分内容(如"search"、"search term")或更长匹配短语的文档:
{ "query":{ "bool":{ "must":[ { "match":{ "containsTerms.containsTerm":{ "query":"search term to match" } } }, { "range":{ "startdate":{ "lte":"2022-09-22T14:43:38" } } }, { "range":{ "enddate":{ "gte":"2022-09-22T15:43:38" } } } ] } } }
若改用keyword类型的精确匹配,则仅当搜索内容与字段值完全一致时才返回结果,无法满足搜索短语完整包含文档字段值即匹配的需求(例如搜索"blah blah search term to match blah blah"需返回文档,而"blah blah search term to blah blah"则不返回)。
可行的解决方案
可以通过以下两种方式实现需求:
方法1:Script查询
通过脚本遍历文档中的containsTerm.keyword值,判断是否存在被搜索短语包含的项:
{ "query": { "bool": { "must": [ { "script": { "script": { "source": """ def searchPhrase = params.searchPhrase; for (def term : doc['containsTerms.containsTerm.keyword']) { if (searchPhrase.contains(term.value)) { return true; } } return false; """, "params": { "searchPhrase": "blah blah search term to match blah blah" } } } }, { "range": { "startdate": { "lte": "2022-09-22T14:43:38" } } }, { "range": { "enddate": { "gte": "2022-09-22T15:43:38" } } } ] } } }
该脚本会逐一检查文档中所有containsTerm的精确值,只要有一个值被搜索短语包含,就会匹配该文档。
方法2:Wildcard查询
将搜索短语作为通配符模式的中间部分,匹配字段值是否为搜索短语的子串:
{ "query": { "bool": { "must": [ { "wildcard": { "containsTerms.containsTerm.keyword": { "value": "*blah blah search term to match blah blah*" } } }, { "range": { "startdate": { "lte": "2022-09-22T14:43:38" } } }, { "range": { "enddate": { "gte": "2022-09-22T15:43:38" } } } ] } } }
注意:如果通配符模式以*开头,会导致查询性能下降,数据量较大时优先选择Script查询。
内容的提问来源于stack exchange,提问作者DaveSav
相关产品推荐
相关产品推荐

