如何在ElasticsearchRepository中用NativeSearchQueryBuilder按嵌套字段id查询
问题根因
- 之前
termQuery不生效:大概率是status.id字段在Elasticsearch中为text类型会被分词,termQuery是精确匹配分词后的词条,和你传入的完整statusId无法匹配导致结果为空。 - Criteria API报错:因为你使用了带空格的文本做通配符查询,Criteria API不支持这种写法,所以抛出构造查询错误。
最优实现方案
你调整后的bool查询逻辑是正确的,不过更推荐将statusId的筛选放到filter节点,不会参与相关性评分,能提升查询性能,完整代码如下:
import org.elasticsearch.index.query.Operator; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.domain.Pageable; import java.util.List; public List<Sample> getAll(String statusId, String text, Pageable pageable) { // status.id如果是keyword类型(精确匹配)用termQuery,text类型用matchQuery QueryBuilder statusFilter = QueryBuilders.termQuery("status.id.keyword", statusId); // 若status.id没有keyword子字段,改用下面的match写法 // QueryBuilder statusFilter = QueryBuilders.matchQuery("status.id", statusId).operator(Operator.AND); QueryBuilder nameMatchQuery = QueryBuilders.multiMatchQuery(text) .field("name") .type(MatchQueryBuilder.Type.PHRASE_PREFIX); NativeSearchQuery query = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.boolQuery() .filter(statusFilter) .must(nameMatchQuery) ) .withPageable(pageable) .build(); // 执行查询,使用你注入的ElasticsearchRestTemplate/ElasticsearchOperations实例 return elasticsearchRestTemplate.queryForList(query, Sample.class); }
注意事项
- 优先使用
status.id.keyword做筛选,前提是你的索引映射中该字段配置了keyword类型的子字段,能保证精确匹配不会因为分词漏查 - 如果需要返回带总条数、总页数的分页结果,改用
elasticsearchRestTemplate.searchForPage()方法即可
内容的提问来源于stack exchange,提问作者H Athukorala
相关产品推荐
相关产品推荐

