目录
1 Elasticsearch搜索基础概述
Elasticsearch作为一款开源的分布式搜索和分析引擎,其核心功能之一就是提供高效、灵活的数据检索能力。在Elasticsearch中,检索操作主要涉及两个核心概念:查询(Query)和过滤器(Filter)。理解这两者的区别对于构建高效搜索系统至关重要。
Elasticsearch的搜索请求通常由查询DSL(领域特定语言)构成,这是一种基于JSON的查询语言。在DSL中,查询和过滤器可以单独使用,也可以组合使用,以满足不同的搜索需求。
2 ES过滤器(Filter)详解
2.1 过滤器的基本概念
过滤器(Filter)是Elasticsearch中用于筛选文档的一种机制,它的主要特点是 只关心文档是否匹配条件,而不关心匹配的相关性程度。过滤器就像一个二进制开关,文档要么匹配(返回true),要么不匹配(返回false),没有中间状态。
{
"query": {
"bool": {
"filter": [
{ "term": { "status": "published" } },
{ "range": { "publish_date": { "gte": "2025-06-01" } } }
]
}
}
}
2.2 过滤器的工作原理
- 过滤器的执行过程

- 缓存检查:Elasticsearch首先检查过滤器缓存,看是否有可用的缓存结果
- 执行过滤:如果缓存未命中,则执行实际的过滤操作
- 构建位图:系统会为匹配的文档构建一个位图(BitSet),其中每一位代表一个文档是否匹配
- 缓存结果:过滤结果会被缓存以便后续查询使用
- 返回结果:最终返回匹配的文档集合
2.3 过滤器的核心特性
- 二进制判断:只返回是/否的二元结果,不计算相关性分数
- 可缓存性:过滤结果会被自动缓存,提高重复查询性能
- 高效执行:避免了相关性分数计算的开销
- 位图操作:使用高效的位运算进行多过滤器组合
3 ES查询(Query)详解
3.1 查询的基本概念
查询(Query)是Elasticsearch中用于查找匹配文档并计算其相关性分数的机制。与过滤器不同,查询不仅关心文档是否匹配,还关心 匹配的程度如何,并据此计算相关性分数(_score)。
{
"query": {
"match": {
"title": {
"query": "elasticsearch filter",
"operator": "and"
}
}
}
}
3.2 查询的工作原理
- 查询的执行过程

- 解析查询:解析查询DSL,确定查询类型和参数
- 文档遍历:根据查询条件找出潜在匹配的文档
- 分数计算:为每个匹配文档计算相关性分数(_score)
- 结果排序:根据分数对文档进行降序排列
- 返回结果:返回排序后的文档列表
3.3 查询的核心特性
- 相关性评分:计算并返回每个匹配文档的相关性分数
- 不可缓存:由于涉及分数计算,结果通常不被缓存
- 功能丰富:支持全文搜索、模糊匹配等复杂场景
- 性能开销:比过滤器有更大的性能开销
4 过滤器与查询的核心区别
4.1 功能差异对比
特性 | 过滤器(Filter) | 查询(Query) |
相关性评分 | 不计算分数 | 计算相关性分数 |
缓存机制 | 结果自动缓存 | 通常不被缓存 |
使用场景 | 精确匹配、结构化数据筛选 | 全文搜索、相关性排序 |
性能 | 高效,适合频繁使用的条件 | 相对较慢,适合复杂搜索 |
二进制判断 | 是/否判断 | 有程度判断 |
排序影响 | 不影响排序 | 直接影响排序 |
4.2 性能差异分析
过滤器的性能优势主要来自三个方面:
- 缓存机制:过滤结果被缓存后,后续相同过滤可以直接使用缓存结果
- 避免评分计算:省去了相关性分数计算的开销
- 位图操作:多个过滤条件可以通过高效的位运算组合
查询由于需要计算相关性分数,且无法有效缓存结果,因此在性能上通常不如过滤器高效。
4.3 使用场景对比
适合使用过滤器的场景:
- 精确值匹配(status="published")
- 范围查询(date >= "2025-06-01")
- 是否存在的判断(exists field)
- 频繁使用的筛选条件
适合使用查询的场景:
- 全文搜索
- 需要相关性排序的结果
- 模糊匹配
- 同义词处理
5 过滤器与查询的联合使用
在实际应用中,过滤器与查询经常组合使用,以实现既高效又相关的搜索体验。最常见的组合方式是通过布尔查询(bool query)将两者结合起来。
5.1 组合使用架构

5.2 典型组合示例
{
"query": {
"bool": {
"must": [
{
"match": {
"content": "elasticsearch"
}
}
],
"filter": [
{
"term": {
"status": "published"
}
},
{
"range": {
"publish_date": {
"gte": "2025-06-01"
}
}
}
]
}
}
}
此查询表示:
- must:文档内容(content)必须包含"elasticsearch"(计算相关性分数)
- filter:文档状态(status)必须是"published",且发布日期(publish_date)不早于2025年6月1日(不计算分数)
5.3 组合使用的最佳实践
- 先过滤后查询:先用过滤器缩小文档范围,再在结果集上执行查询
- 频繁条件过滤化:将频繁使用的条件放在filter子句中利用缓存
- 静态条件过滤化:将不依赖相关性评分的静态条件作为过滤器
- 动态条件查询化:将需要相关性排序的条件放在must/should子句中
6 过滤器缓存机制深度解析
6.1 过滤器缓存工作原理
- Elasticsearch的过滤器缓存是基于分片(Shard)级别的,其架构如下:

6.2 缓存关键特性
- 自动缓存:ES自动决定哪些过滤器需要缓存
- LRU策略:使用最近最少使用策略管理缓存
- 分片级别:每个分片维护自己的过滤器缓存
- 内存管理:可通过indices.queries.cache.size配置缓存大小
6.3 影响缓存效率的因素
- 过滤器重复度:重复使用的过滤器更能受益于缓存
- 过滤选择性:高选择性的过滤器(匹配少量文档)缓存效果更好
- 分片大小:较小的分片意味着更小的位图,缓存效率更高
- 文档变化频率:频繁变化的索引会降低缓存命中率
7 性能优化建议
7.1 查询性能优化策略
- 合理使用过滤器:将不关心相关性评分的条件放在filter中
- 避免昂贵的查询:如通配符查询、正则表达式查询等
- 限制查询范围:通过index/type限制搜索范围
- 分页控制:合理设置from/size参数
7.2 过滤器优化技巧
- 顺序安排:将高选择性的过滤器放在前面
- 避免过度过滤:不必要的过滤条件会增加开销
- 缓存友好:设计可重复使用的过滤条件
- 监控缓存命中率:通过_stats接口监控过滤器缓存效率
7.3 监控与调优指标

8 常见问题解答
Q1:什么时候应该使用过滤器而不是查询?
当以下条件满足时,优先使用过滤器:
- 需要进行精确匹配(如状态、标签、分类等)
- 不需要相关性评分
- 条件会被频繁重复使用
- 处理结构化数据而非全文内容
Q2:过滤器缓存是如何失效的?
过滤器缓存在以下情况下会失效:
- 索引的文档发生变化(新增、修改、删除)
- 过滤器缓存达到配置大小限制,部分缓存被LRU淘汰
- 集群重启或分片重分配
Q3:过滤器能否处理全文搜索?
过滤器主要用于精确匹配,不适合全文搜索场景。全文搜索应该使用查询(query)而不是过滤器(filter)。不过,某些过滤器如terms过滤器可以处理分词后的结果。
9 总结
Elasticsearch中的过滤器(Filter)和查询(Query)是两种不同的文档检索机制,各有其特点和适用场景:过滤器:
- 适合精确匹配和结构化数据筛选
- 不计算相关性分数,性能更高
- 结果可缓存,适合频繁使用的条件
- 使用二进制判断(是/否匹配)
查询:
- 适合全文搜索和相关性排序
- 计算相关性分数,功能更丰富
- 结果通常不被缓存
- 有程度判断(匹配好坏)
在实际应用中,最佳实践是将两者结合使用:
- 用过滤器处理结构化数据的精确匹配
- 用查询处理全文搜索和相关性排序
- 通过布尔查询将两者有机结合
理解过滤器与查询的区别及其适用场景,对于构建高效、相关的搜索体验至关重要。合理使用过滤器可以显著提高搜索性能,特别是在处理大量数据和频繁查询的场景下。