Elasticsearch:如何让match_phrase查询匹配marble floor与floor marble?
Elasticsearch 搜索解决方案
要匹配文档1(marble floor)和文档2(floor marble),同时排除文档3(marble floor light),提供三种可行方案:
方案一:精准匹配双词文档
用match查询确保两个关键词都存在,再通过脚本过滤分词后词数为2的文档:
{ "_source": ["title"], "size": 10, "query": { "bool": { "must": [ { "match": { "title": { "query": "marble floor", "operator": "and" } } } ], "filter": [ { "script": { "script": { "source": "doc['title'].length == 2", "lang": "painless" } } } ] } } }
match的operator: "and"确保marble和floor两个词都出现在标题中- 脚本过滤直接排除词数超过2的文档(比如文档3)
方案二:枚举短语组合+精确匹配
直接把两种顺序的短语加入查询,同时用terms精确匹配目标文档:
{ "_source": ["title"], "size": 10, "query": { "bool": { "should": [ { "match_phrase": { "title": "marble floor" } }, { "match_phrase": { "title": "floor marble" } } ], "minimum_should_match": 1, "filter": [ { "terms": { "title.keyword": ["marble floor", "floor marble"] } } ] } } }
should里的两个短语匹配保证相关性评分terms查询title.keyword直接精准命中目标文档,避免多余结果
方案三:自定义分词器(需修改索引映射)
如果允许调整索引配置,给title字段添加带shingle过滤器的分词器,生成双词组合,后续查询无需关心词序:
索引映射设置
{ "settings": { "analysis": { "filter": { "shingle_filter": { "type": "shingle", "min_shingle_size": 2, "max_shingle_size": 2 } }, "analyzer": { "shingle_analyzer": { "tokenizer": "standard", "filter": ["lowercase", "shingle_filter"] } } } }, "mappings": { "properties": { "title": { "type": "text", "analyzer": "shingle_analyzer", "fields": { "keyword": { "type": "keyword" } } } } } }
查询语句
{ "_source": ["title"], "size": 10, "query": { "bool": { "must": [ { "match": { "title": "marble floor" } } ], "filter": [ { "script": { "script": { "source": "doc['title'].length == 2", "lang": "painless" } } } ] } } }
- 分词器会为文档1生成
marble floor,为文档2生成floor marble,两种组合都能被查询匹配 - 同样用脚本过滤词数为2的文档,排除文档3
内容的提问来源于stack exchange,提问作者Mohan T
相关产品推荐
相关产品推荐

