如何在Java中为Elasticsearch实现支持正则的MultiMatch多字段查询
后缀匹配多字段查询实现方案
错误点说明
- 之前的查询用
must拼接两个正则查询,逻辑为两个字段同时匹配后缀,不符合需求中「任意一个字段匹配即可」的要求 MultiMatchQuery属于全文检索类查询,不会解析输入内容中的正则语法,只会将.*xxx当做普通字符串进行匹配,无法实现正则效果- 如果
numberId1、numberId2是数值类型(int/long),正则查询天然不支持数值类型字段,必然匹配失败
实现方案
场景1:字段为字符串/keyword类型
直接用Bool查询的should逻辑包裹两个正则查询即可:
BoolQueryBuilder suffixMatchQuery = QueryBuilders.boolQuery(); String suffixRegex = ".*" + searchParameter; // 两个字段任意一个匹配即可 suffixMatchQuery.should(QueryBuilders.regexpQuery("numberId1", suffixRegex)); suffixMatchQuery.should(QueryBuilders.regexpQuery("numberId2", suffixRegex)); // 要求至少满足1个should条件 suffixMatchQuery.minimumShouldMatch(1); // 将该查询加入你的主查询逻辑 yourMainQuery.must(suffixMatchQuery);
场景2:字段为数值类型
如果不方便修改字段映射为字符串类型,可以用Painless脚本做字段值转换后匹配,性能比正则查询更好:
Script suffixMatchScript = new Script( ScriptType.INLINE, "painless", // 转成字符串后直接匹配后缀 "doc['numberId1'].value.toString().endsWith(params.suffix) || doc['numberId2'].value.toString().endsWith(params.suffix)", Collections.singletonMap("suffix", searchParameter) ); QueryBuilder suffixMatchQuery = QueryBuilders.scriptQuery(suffixMatchScript); // 将该查询加入你的主查询逻辑 yourMainQuery.must(suffixMatchQuery);
性能优化建议
如果数据量较大,推荐提前将两个字段的末尾四位预计算为单独的short类型字段存储,查询时直接做精确匹配,性能比正则、脚本查询高一个数量级。
内容的提问来源于stack exchange,提问作者rolo
相关产品推荐
相关产品推荐

