Elasticsearch MatchQuery禁用模糊匹配 获取text类型referenceId精确匹配结果
问题根源
你遇到的问题和Fuzziness配置无关,是text类型的分词逻辑和matchQuery默认匹配规则导致的:
- text类型字段默认会经过分词器处理,
106-0638778-542266这类带横杠的字符串会被标准分词器拆分为106、0638778、542266三个独立分词 - matchQuery默认的
operator为OR,只要文档的分词结果和查询词的分词结果有任意一个匹配就会命中,你返回的结果里的referenceId都包含前两个相同的分词,所以就算最后一位不同也会被检索到
解决方案
根据你的索引配置不同,有两种可行方案:
方案1:使用keyword子字段做TermQuery(最优推荐)
ES默认创建的索引中,text类型字段会自动附带一个.keyword后缀的子字段,类型为keyword,不会做分词,直接存储原始值,完全适配精确匹配场景,代码修改如下:
// 字段名加.keyword后缀,用termQuery直接匹配原始完整值 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder() .query(QueryBuilders.termQuery(key + ".keyword", val)) .timeout(TIMEOUT_SECONDS); SearchRequest searchRequest = new SearchRequest().indices(index).source(searchSourceBuilder); return restHighLevelClient.search(searchRequest);
你可以调用GET 索引名/_mapping查看索引结构,确认referenceId下是否存在.keyword子字段即可,绝大多数默认创建的索引都自带该配置。
方案2:修改matchQuery匹配规则(无keyword子字段时备选)
如果你的索引确实没有配置keyword子字段,必须用text字段检索的话,需要同时修改两个匹配参数:
- 将
operator设置为AND,要求查询词拆分后的所有分词都在文档中命中 - 增加
minimum_should_match为100%,确保所有分词全部匹配
代码如下:
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder() .query(QueryBuilders.matchQuery(key, val) .fuzziness(Fuzziness.ZERO) .operator(Operator.AND) .minimumShouldMatch("100%")) .timeout(TIMEOUT_SECONDS); SearchRequest searchRequest = new SearchRequest().indices(index).source(searchSourceBuilder); return restHighLevelClient.search(searchRequest);
注意该方案只能保证分词全部匹配,无法区分长度不同但前缀分词完全一致的场景,比如查询a-b-c和文档a-b-c-d的前三个分词完全一致,仍然会命中,因此优先推荐使用方案1。
内容的提问来源于stack exchange,提问作者Reid C
相关产品推荐
相关产品推荐

