Easysearch Java SDK 2.0.x 使用指南(三)

194 阅读7分钟

Easysearch Java SDK 2.0.x 使用指南(一) 中,我们介绍了 Easysearch Java SDK 2.0.2 的基本使用和批量操作功能。

Easysearch Java SDK 2.0.x 使用指南(二) 中,则详细介绍了索引管理相关的功能,包括索引的创建、删除、开关、刷新、滚动等操作,以及新版 SDK 提供的同步和异步两种调用方式。

本篇文章将继续向大家介绍 Easysearch Java SDK 2.0.2 的 Query 的使用。


1. QueryString:灵活的全文检索

QueryString 查询允许开发者以类似 Easysearch Query DSL 的语法执行全文检索,非常适合处理用户输入的复杂搜索条件。

基本概念

  • fields:指定要检索的字段列表。
  • query:查询字符串,支持布尔操作符(如 AND、OR、NOT)。
  • default_operator:当查询字符串中未明确操作符时使用的默认逻辑操作符。
  • analyze_wildcard:是否对通配符查询进行分析。

代码示例

以下示例展示了如何通过新版 Java 客户端构建一个 QueryString 查询,用于检索标题和内容中同时包含 easysearchjava 的文档:

@Test
public void testQueryString() {
    // 定义 JSON 查询字符串
    String jsonQuery = "{\n" +
        "  \"query_string\": {\n" +
        "    \"fields\": [\"title\", \"content\"],\n" +
        "    \"query\": \"easysearch AND java\",\n" +
        "    \"default_operator\": \"AND\",\n" +
        "    \"analyze_wildcard\": true\n" +
        "  }\n" +
        "}";

    // 使用 JacksonJsonpMapper 解析 JSON 字符串
    JacksonJsonpMapper mapper = new JacksonJsonpMapper();
    JsonParser parser = mapper.jsonProvider().createParser(new StringReader(jsonQuery));
    Query query = Query._DESERIALIZER.deserialize(parser, mapper);

    // 提取 QueryStringQuery 并构建最终查询
    QueryStringQuery queryStringQuery = query.queryString();
    Query finalQuery = Query.of(q -> q.queryString(queryStringQuery));

    // 输出最终查询对象
    System.out.println(finalQuery);
}

代码解析

  1. 构建 JSON 查询字符串:定义了 query_string 查询的核心参数,包括字段列表和查询条件。
  2. 解析 JSON:使用 JacksonJsonpMapper 将 JSON 字符串解析为 Java 对象。
  3. 提取 QueryStringQuery:从解析后的 Query 对象中获取 QueryStringQuery
  4. 封装最终查询:通过 Query.of 方法将 QueryStringQuery 封装为最终的 Query 对象。

使用场景

  • 用户输入的搜索条件需要支持布尔逻辑。
  • 需要在多个字段中进行全文检索。
  • 支持模糊搜索(如通配符)的场景。

2. Bool Query:构建复杂的多条件查询

Bool Query 可以将多个查询子句组合成一个高级查询。这些子句通过布尔逻辑组合在一起,用于查找结果中返回的匹配文档。

Bool Query 的核心子句

子句行为
must逻辑"与"运算符。结果必须匹配此子句中的所有查询。
must_not逻辑"非"运算符。所有匹配此子句中查询的文档都会从结果中排除。
should逻辑"或"运算符。结果必须匹配至少一个查询。匹配的 should 子句越多,文档的相关性得分越高。你可以使用 minimum_should_match 参数设置必须匹配的最小查询数量。如果查询包含 mustfilter 子句,则 minimum_should_match 的默认值为 0。否则,minimum_should_match 的默认值为 1。
filter逻辑"与"运算符,在应用其他查询之前首先应用,以减少数据集。filter 子句中的查询是一个是或否选项。如果文档匹配查询,则会将其返回到结果中;否则不会返回。filter 查询的结果通常会被缓存,以实现更快的返回。使用 filter 查询可根据精确匹配、范围、日期或数字来过滤结果。

基于 JSON 的代码示例

以下代码展示了如何通过 JSON 字符串构建一个复杂的 BoolQuery

@Test
public void testBoolQueryString() {
    // 定义 JSON 查询字符串
    String jsonQuery = "{\n" +
        "  \"bool\": {\n" +
        "    \"must\": [\n" +
        "      { \"match\": { \"title\": \"easysearch\" } },\n" +
        "      { \"match\": { \"content\": \"java programming\" } }\n" +
        "    ],\n" +
        "    \"should\": [\n" +
        "      { \"term\": { \"category\": \"technology\" } },\n" +
        "      { \"term\": { \"category\": \"programming\" } }\n" +
        "    ],\n" +
        "    \"must_not\": [\n" +
        "      { \"term\": { \"status\": \"draft\" } },\n" +
        "      { \"range\": { \"publish_date\": { \"lt\": \"2020-01-01\" } } }\n" +
        "    ],\n" +
        "    \"filter\": [\n" +
        "      { \"range\": { \"rating\": { \"gte\": 4 } } },\n" +
        "      { \"terms\": { \"tags\": [\"search\", \"database\"] } }\n" +
        "    ],\n" +
        "    \"minimum_should_match\": 1\n" +
        "  }\n" +
        "}";

    // 解析 JSON 并构建查询
    JacksonJsonpMapper mapper = new JacksonJsonpMapper();
    JsonParser parser = mapper.jsonProvider().createParser(new StringReader(jsonQuery));
    Query query = Query._DESERIALIZER.deserialize(parser, mapper);

    // 提取 BoolQuery 并构建最终查询
    BoolQuery boolQuery = query.bool();
    Query finalQuery = Query.of(q -> q.bool(boolQuery));

    // 输出最终查询对象
    System.out.println(finalQuery);
}

使用 Builder 模式构建 BoolQuery

新版 Java 客户端还提供了类型安全的 Builder 模式,简化了复杂查询的构建过程:

@Test
public void testBooleanQuery() throws IOException {
    // 构建 BoolQuery
    BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder();

    // 添加 must 子句
    boolQueryBuilder.must(new MatchQuery.Builder().field("title").query("easysearch").build()._toQuery());
    boolQueryBuilder.must(new MatchQuery.Builder().field("content").query("java programming").build()._toQuery());

    // 添加 should 子句
    boolQueryBuilder.should(new TermQuery.Builder().field("category").value("technology").build()._toQuery());
    boolQueryBuilder.should(new TermQuery.Builder().field("category").value("programming").build()._toQuery());

    // 添加 must_not 子句
    boolQueryBuilder.mustNot(new TermQuery.Builder().field("status").value("draft").build()._toQuery());

    // 添加 filter 子句
    boolQueryBuilder.filter(new RangeQuery.Builder().field("rating").gte("4").build()._toQuery());

    // 构建查询
    Query query = new Query(boolQueryBuilder.build());
    System.out.println(query);
}

使用场景

  • 构建复杂的多条件查询。
  • 满足高级搜索需求,例如结合全文检索和精确匹配。
  • 实现复杂的逻辑,如过滤无关数据、优先特定条件。

3. Constant score query:统一评分的过滤查询

Constant score 查询用于包装一个 filter 查询,并为所有匹配的文档分配一个统一的相关性分数。这种查询方式不考虑词频 (TF) 和逆文档频率 (IDF),适合那些只关心文档是否匹配而不关心相关度排序的场景。

基本概念

constant_score 的参数

  • filter

    • (必需) 您希望运行的过滤查询。任何返回的文档都必须匹配此查询。
    • 过滤查询不计算相关性得分。为了提高性能,Easysearch 会自动缓存常用的过滤查询。
  • boost

    • (可选) 用作每个匹配过滤查询的文档的常量相关性得分的浮点数。默认为 1.0。

基于 JSON 的代码示例

@Test
public void testConstantScoreQuery() {
    // 定义 JSON 查询字符串
    String jsonQuery = "{\n" +
        "  \"constant_score\": {\n" +
        "    \"filter\": {\n" +
        "      \"term\": { \"status\": \"published\" }\n" +
        "    },\n" +
        "    \"boost\": 1.2\n" +
        "  }\n" +
        "}";

    // 解析 JSON 并构建查询
    JacksonJsonpMapper mapper = new JacksonJsonpMapper();
    JsonParser parser = mapper.jsonProvider().createParser(new StringReader(jsonQuery));
    Query query = Query._DESERIALIZER.deserialize(parser, mapper);

    // 提取 ConstantScoreQuery 并构建最终查询
    ConstantScoreQuery constantScoreQuery = query.constantScore();
    Query finalQuery = Query.of(q -> q.constantScore(constantScoreQuery));

    System.out.println(finalQuery);
}

使用 Builder 模式构建 ConstantScoreQuery

@Test
public void testConstantScoreQueryBuilder() {
    // 使用 Builder 构建 ConstantScoreQuery
    ConstantScoreQuery.Builder constantScoreBuilder = new ConstantScoreQuery.Builder();

    // 创建 filter 查询
    TermQuery termQuery = new TermQuery.Builder()
        .field("status")
        .value("published")
        .build();

    // 设置 filter 和 boost
    constantScoreBuilder
        .filter(termQuery._toQuery())
        .boost(1.2f);

    // 构建最终查询
    Query query = Query.of(q -> q.constantScore(constantScoreBuilder.build()));

    System.out.println(query);
}

使用场景

  1. 精确匹配过滤
  • 查找特定状态的文档
  • 不需要考虑相关度排序
  1. 性能优化
  • 过滤查询会被缓存
  • 不计算相关性分数,查询更快
  1. 自定义评分
  • 需要给所有匹配文档统一分数
  • 覆盖默认的相关性评分
  1. 布尔查询的组件
  • 作为 bool 查询的一部分
  • 用于预过滤或调整特定文档集的分数

通过使用 Constant score 查询,我们可以在需要简单过滤和统一评分的场景中获得更好的性能和更简单的实现。这种查询方式特别适合那些不需要复杂相关性计算的应用场景。


总结

本文介绍了 Easysearch Java SDK 2.0.2 中的三种核心查询:Query String、Bool Query 和 Constant Score。

Query String 擅长灵活处理用户输入的全文检索,支持布尔逻辑和通配符。Bool Query 则通过组合 must、must_not、should 和 filter 等子句,满足复杂的多条件查询需求。Constant Score 则专注于高效过滤和统一评分,适用于不需要排序的场景。


想要了解更多?

大家有啥问题或者建议,也欢迎随时反馈!

关于 Easysearch

INFINI Easysearch 是一个分布式的搜索型数据库,实现非结构化数据检索、全文检索、向量检索、地理位置信息查询、组合索引查询、多语种支持、聚合分析等。Easysearch 可以完美替代 Elasticsearch,同时添加和完善多项企业级功能。Easysearch 助您拥有简洁、高效、易用的搜索体验。

官网文档:infinilabs.cn/docs/latest…

作者:张磊,极限科技(INFINI Labs)搜索引擎研发负责人,对 Elasticsearch 和 Lucene 源码比较熟悉,目前主要负责公司的 Easysearch 产品的研发以及客户服务工作。