Elasticsearch QueryBuilders 初级使用教程

59 阅读4分钟

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. 注意事项

  1. 版本兼容性:不同版本的 Elasticsearch 中 QueryBuilders 的方法可能有所不同,请根据实际使用的版本查阅官方文档。

  2. 性能优化

    • termQuery 比 matchQuery 性能更好,因为不涉及分词
    • wildcardQuery 特别是以通配符开头的查询性能较差,尽量避免
    • 合理使用 filter 上下文(不计算评分)可以提高性能
  3. 查询精度:根据字段类型和查询需求选择合适的查询类型,例如精确值使用 termQuery,全文搜索使用 matchQuery。

  4. 索引设计:良好的索引设计(如合适的分词器、字段类型)对查询效果至关重要。

通过合理组合使用这些查询方法,可以满足各种复杂的搜索需求。在实际应用中,建议根据具体业务场景选择最合适的查询方式。