Elasticsearch QueryBuilders 使用教程
QueryBuilders 是 Elasticsearch Java API 中用于构建查询条件的工具类,它提供了丰富的静态方法来创建各种类型的查询。下面详细介绍常用的查询方法及其使用方式。
1. 基础查询
1.1 matchAllQuery - 匹配所有文档
// 匹配所有文档
QueryBuilder query = QueryBuilders.matchAllQuery();
1.2 termQuery - 精确匹配查询
适用于精确值匹配,不会对查询值进行分词。
// 精确匹配 status 字段值为 "active"
QueryBuilder query = QueryBuilders.termQuery("status", "active");
// 适用于关键词、数字、日期等精确值查询
QueryBuilder query = QueryBuilders.termQuery("price", 100);
1.3 matchQuery - 全文搜索查询
对查询值进行分词后匹配,适用于文本字段的全文搜索。
// 在 name 字段中搜索包含指定关键词的文档
QueryBuilder query = QueryBuilders.matchQuery("name", "华为 Mate10");
// 查询会对 "华为 Mate10" 进行分词,只要文档包含任一分词就会被匹配
2. 短语查询
2.1 matchPhraseQuery - 短语匹配
要求查询的词语必须以相同的顺序出现,且相邻。
// 匹配 supplierName 字段中包含完整短语 "华为技术有限公司" 的文档
QueryBuilder query = QueryBuilders.matchPhraseQuery("supplierName", "华为技术有限公司");
2.2 matchPhrasePrefixQuery - 前缀短语匹配
与短语匹配类似,但最后一个词可以是前缀。
// 匹配以 "华为" 开头的短语
QueryBuilder query = QueryBuilders.matchPhrasePrefixQuery("supplierName", "华为");
3. 模糊查询
3.1 wildcardQuery - 通配符查询
支持 *(匹配任意多个字符)和 ?(匹配单个字符)。
// 匹配 supplierName 字段中包含 "华" 的文档
QueryBuilder query = QueryBuilders.wildcardQuery("supplierName", "*华*");
// 匹配以 "华" 开头的文档
QueryBuilder query = QueryBuilders.wildcardQuery("supplierName", "华*");
3.2 fuzzyQuery - 模糊查询
允许一定的编辑距离,用于拼写错误容错。
// 允许最多2个字符的编辑距离
QueryBuilder query = QueryBuilders.fuzzyQuery("productName", "huawei").fuzziness(Fuzziness.TWO);
4. 范围查询
4.1 rangeQuery - 范围查询
用于数值、日期等范围匹配。
// 匹配 price 字段在 5000 到 10000 之间的文档
QueryBuilder query = QueryBuilders.rangeQuery("price").from(5000).to(10000);
// 不包含边界值
QueryBuilder query = QueryBuilders.rangeQuery("price").gt(5000).lt(10000);
// 日期范围查询
QueryBuilder query = QueryBuilders.rangeQuery("createTime").from("2023-01-01").to("2023-12-31");
5. 复合查询
5.1 boolQuery - 布尔查询
组合多个查询条件,使用 must、should、mustNot 等逻辑关系。
// 组合多个查询条件
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 必须满足的条件(AND)
boolQuery.must(QueryBuilders.termQuery("brand", "Apple"));
boolQuery.must(QueryBuilders.rangeQuery("price").from(5000).to(10000));
// 应该满足的条件(OR),至少满足一个
boolQuery.should(QueryBuilders.termQuery("color", "black"));
boolQuery.should(QueryBuilders.termQuery("color", "white"));
// 必须不满足的条件(NOT)
boolQuery.mustNot(QueryBuilders.termQuery("status", "inactive"));
5.2 multiMatchQuery - 多字段匹配
在多个字段中搜索相同的查询条件。
// 在 title 和 description 字段中搜索 "elasticsearch"
QueryBuilder query = QueryBuilders.multiMatchQuery("elasticsearch", "title", "description");
// 指定匹配类型
QueryBuilder query = QueryBuilders.multiMatchQuery("elasticsearch", "title", "description")
.type(MultiMatchQueryBuilder.Type.BEST_FIELDS);
6. 高级查询
6.1 queryStringQuery - 查询字符串查询
支持更复杂的查询语法,如字段指定、布尔操作符等。
// 支持 Lucene 查询语法
QueryBuilder query = QueryBuilders.queryStringQuery("brand:Apple AND price:[5000 TO 10000]");
// 指定默认字段
QueryBuilder query = QueryBuilders.queryStringQuery("华为手机").defaultField("name");
6.2 nestedQuery - 嵌套查询
用于查询嵌套文档。
// 查询嵌套字段中的数据
QueryBuilder nestedQuery = QueryBuilders.nestedQuery(
"comments", // 嵌套字段名
QueryBuilders.termQuery("comments.user", "张三"),
ScoreMode.None // 评分模式
);
7. 实际使用示例
7.1 结合 ElasticsearchRestTemplate 使用
@Service
public class ProductService {
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
// 基础查询示例
public List<Product> searchProducts(String keyword) {
QueryBuilder query = QueryBuilders.matchQuery("name", keyword);
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(query)
.withPageable(PageRequest.of(0, 10))
.build();
return elasticsearchRestTemplate.search(searchQuery, Product.class)
.stream()
.map(SearchHit::getContent)
.collect(Collectors.toList());
}
// 复杂条件查询
public List<Product> searchProductsByConditions(String brand, Integer minPrice, Integer maxPrice) {
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
if (StringUtils.hasText(brand)) {
boolQuery.must(QueryBuilders.termQuery("brand", brand));
}
if (minPrice != null && maxPrice != null) {
boolQuery.filter(QueryBuilders.rangeQuery("price").from(minPrice).to(maxPrice));
}
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(boolQuery)
.withSort(SortBuilders.fieldSort("price").order(SortOrder.ASC))
.withPageable(PageRequest.of(0, 20))
.build();
return elasticsearchRestTemplate.search(searchQuery, Product.class)
.stream()
.map(SearchHit::getContent)
.collect(Collectors.toList());
}
}
8. 注意事项
-
版本兼容性:不同版本的 Elasticsearch 中 QueryBuilders 的方法可能有所不同,请根据实际使用的版本查阅官方文档。
-
性能优化:
- termQuery 比 matchQuery 性能更好,因为不涉及分词
- wildcardQuery 特别是以通配符开头的查询性能较差,尽量避免
- 合理使用 filter 上下文(不计算评分)可以提高性能
-
查询精度:根据字段类型和查询需求选择合适的查询类型,例如精确值使用 termQuery,全文搜索使用 matchQuery。
-
索引设计:良好的索引设计(如合适的分词器、字段类型)对查询效果至关重要。
通过合理组合使用这些查询方法,可以满足各种复杂的搜索需求。在实际应用中,建议根据具体业务场景选择最合适的查询方式。