Elasticsearch2.x Filter执行流程及缓存原理

Elasticsearch2.x Filter执行与缓存解析
本文详细介绍了Elasticsearch2.x中Filter的执行流程和缓存原理,包括Filter的Query和Filter Context,基本查询过程,位图(bitset)的创建和迭代,以及Filter Cache的工作机制。强调了Filter在非评分查询中的作用,以及如何通过位图优化查询效率和缓存策略。

一、基本概念

这里说的Filter非Post filter,关于Post filter这里不做介绍,我们主要关注的是在执行一个评分查询前执行的Filter。

在讲述ES Filter的执行流程和缓存原理之前,有几个概念我们必须要清楚。

Query and Filter context 

官网地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html

1. Query Context

所谓查询上下文,是指包含一个或多个查询条件的逻辑组合,QueryContext里包含的的单个查询表示的含义是“文档和该查询条件的匹配度有多大”,针对QueryContext里的每一个查询都会计算出一个_score来表示匹配度,整个QueryContext的匹配度评分等于其包含所有单个查询评分的总和,所以针对一个Query我们更多关注的是匹配度。

2.Filter Context

过滤器上下文和查询上下文类似,都是由1个或多个子查询(Query clause) 组成的。他们的区别在于Filter不会计算文档得分,它代表的含义是“文档和该查询条件是否匹配”,所以针对一个Filter我们更多关注的是能否可以过滤掉文档,返回的结果只能是可以或者不可以(true or false)。

二、基本查询

在写基本查询前我们先创建一个索引(my_store)和一个类型(products)并插入4条product数据 <
<think>我们正在使用Elasticsearch 8.x的Java API客户端。在Elasticsearch中,布尔查询(bool query)是一种组合查询,它可以将多个查询组合在一起,使用布尔逻辑(must, should, must_not, filter)来构建复杂的查询条件。 根据Elasticsearch 8.x的官方Java API客户端文档,创建布尔查询的步骤如下: 1. 构建布尔查询的各个部分(must, should, must_not, filter),这些部分都是查询(Query)对象。 2. 使用`BoolQuery.of(b -> b.must(...).should(...).mustNot(...).filter(...))`来构建布尔查询。 3. 将构建好的布尔查询作为搜索请求的一部分。 注意:在Elasticsearch 8.x中,Java API客户端使用了全新的构建器模式,该模式是强类型的,并且利用了Java的函数式编程特性。 下面是一个具体的示例,展示如何创建一个布尔查询: 假设我们想要查询满足以下条件的文档: - 必须(must)包含字段"title"中包含"Elasticsearch"的文档(使用match查询) - 必须(must)包含字段"content"中包含"Java"的文档(使用match查询) - 应该(should)包含字段"tags"中包含"latest"的文档(使用term查询),并且满足至少一个should条件(这里只有一个,所以满足即可) - 必须不(must_not)包含字段"status"为"inactive"的文档(使用term查询) - 过滤(filter)条件:字段"create_time"在2023年之后(使用range查询) 以下是使用Elasticsearch 8.x Java API客户端创建该布尔查询的代码: ```java import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery; import co.elastic.clients.elasticsearch._types.query_dsl.Query; import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery; import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery; import co.elastic.clients.elasticsearch._types.query_dsl.RangeQuery; import co.elastic.clients.util.ObjectBuilder; import java.io.IOException; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; public class BoolQueryExample { public static void main(String[] args) throws IOException { // 构建布尔查询 Query boolQuery = BoolQuery.of(b -> b .must(Query.of(q -> q .match(MatchQuery.of(m -> m .field("title") .query("Elasticsearch") )) )) .must(Query.of(q -> q .match(MatchQuery.of(m -> m .field("content") .query("Java") )) )) .should(Query.of(q -> q .term(TermQuery.of(t -> t .field("tags") .value("latest") )) )) .mustNot(Query.of(q -> q .term(TermQuery.of(t -> t .field("status") .value("inactive") )) )) .filter(Query.of(q -> q .range(RangeQuery.of(r -> r .field("create_time") .gte(JsonData.of("2023-01-01T00:00:00Z")) )) )) )._toQuery(); // 然后,我们可以将这个查询用于搜索请求 // 例如:SearchRequest request = SearchRequest.of(s -> s.index("your_index").query(boolQuery)); // 然后使用client.search(request, YourDocumentClass.class)执行查询 } } ``` 注意: - 每个子查询(must, should等)都是一个`Query`对象,我们可以通过`Query.of`方法并传入一个函数来构建具体的查询(如match、term等)。 - 在构建range查询时,我们使用了`JsonData`来表示日期值,因为日期在Elasticsearch中需要特定的格式。这里我们使用了ISO格式的日期字符串,并假设字段"create_time"是日期类型。 - 最后,我们通过调用`_toQuery()`方法将`BoolQuery`对象转换为`Query`对象。 另外,关于布尔查询中各个部分的作用: - `must`:必须满足的条件,相当于AND,并且参与算分。 - `should`:应该满足的条件,相当于OR,在bool查询中,如果没有must或filter,那么至少需要满足一个should条件。如果同时存在must或filter,则should条件变为增加相关性的条件(即满足的should条件越多,文档的相关性得分越高)。可以通过`minimumShouldMatch`参数设置至少满足的should条件数量。 - `must_not`:必须不满足的条件,相当于NOT,不参与算分。 - `filter`:过滤条件,必须满足,但不参与算分,通常用于结构化数据过滤(如范围、状态等)。 在构建布尔查询时,我们还可以设置一些参数,比如`minimum_should_match`。例如,如果我们有多个should条件,我们可以设置至少满足2个: ```java BoolQuery.of(b -> b .should(...) // 多个should条件 .minimumShouldMatch("2") // 至少满足2... // 其他部分 ) ``` 以上就是在Elasticsearch 8.x中使用Java API客户端创建布尔查询的方法。 §§相关问题§§ 1. 在布尔查询中,must和filter有什么区别? 2. 如何设置布尔查询中的minimum_should_match参数? 3.Elasticsearch 8.x中,除了布尔查询,还有哪些常用的复合查询? 4. 如何执行这个布尔查询并处理返回结果?</think>### 在 Elasticsearch 8.x 中使用 Java API 创建布尔查询 (boolQuery) 在 Elasticsearch 8.x 中,使用新的 Java API 客户端创建布尔查询的步骤如下(基于强类型构建器模式): #### 1. **基础 boolQuery 结构** ```java import co.elastic.clients.elasticsearch._types.query_dsl.*; // 创建布尔查询构建器 BoolQuery boolQuery = QueryBuilders.bool() .must(/* must 子句 */) .should(/* should 子句 */) .mustNot(/* must_not 子句 */) .filter(/* filter 子句 */) .build(); // 组合到搜索请求 SearchRequest request = new SearchRequest.Builder() .index("your_index") .query(new Query.Builder().bool(boolQuery).build()) .build(); ``` #### 2. **完整示例:组合多条件查询** ```java import co.elastic.clients.elasticsearch.core.SearchRequest; import co.elastic.clients.elasticsearch.core.SearchResponse; import co.elastic.clients.elasticsearch._types.query_dsl.*; // 构建 boolQuery Query boolQuery = Query.of(q -> q .bool(b -> b .must( // AND 条件 QueryBuilders.match(m -> m.field("title").query("Elasticsearch")), QueryBuilders.range(r -> r.field("price").gte(JsonData.of(100))) ) .should( // OR 条件 QueryBuilders.term(t -> t.field("category").value("book")), QueryBuilders.term(t -> t.field("category").value("ebook")) ) .mustNot( // NOT 条件 QueryBuilders.term(t -> t.field("status").value("out_of_stock")) ) .filter( // 不参与评分的高效过滤 QueryBuilders.term(t -> t.field("in_store").value(true)) ) ) ); // 执行搜索 SearchResponse<YourDocumentClass> response = esClient.search( request -> request.index("products").query(boolQuery), YourDocumentClass.class ); ``` #### 关键参数说明: | **子句类型** | **作用** | **是否影响评分** | |--------------|-----------------------------------|------------------| | `must` | 所有条件必须满足 (AND) | ✅ 是 | | `should` | 至少满足一个条件 (OR) | ✅ 是 | | `mustNot` | 必须不满足的条件 (NOT) | ❌ 否 | | `filter` | 高效过滤,不参与相关性评分 | ❌ 否 | #### 3. **高级用法** **a. 设置最小 should 匹配数** ```java boolQuery(b -> b .should(/* 多个 should 条件 */) .minimumShouldMatch("2") // 至少满足 2 个 should 条件 ) ``` **b. 嵌套布尔查询** ```java boolQuery(b -> b .must(Query.of(q -> q .bool(b2 -> b2 // 嵌套 bool 查询 .must(/* 内部条件 */) ) )) ) ``` #### 注意事项: 1. **字段类型匹配**:确保查询字段的映射类型与查询类型兼容(如 `text` 字段用 `match`,`keyword` 用 `term`)[^3] 2. **性能优化**:将不参与评分的过滤条件放入 `filter` 子句,可利用缓存提升性能[^1] 3. **空值处理**:使用 `existsQuery` 过滤空字段: ```java .filter(QueryBuilders.exists(e -> e.field("stock_count"))) ``` > **最佳实践**:对于需要中文分词的字段(如商品描述),在映射中配置 `"ik_max_word"` 分词器[^3],查询时使用 `match` 而非 `term`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值