查询
match all(匹配所有文档)
_sourcefromsizesort
精确匹配
Term-level 查询直接处理原始输入值,不进行分词。
Term-level 查询不会对字段进行分词或分析,因此字段值必须与索引中的词项(term)完全一致才能匹配。
Term-level 查询直接对倒排索引的词项进行精确匹配,不做分析,适合结构化数据。
如果字段类型是 keyword 或未经过 lowercase 分析器(归一化器)处理,则 term 查询是大小写敏感的。
如果字段是 keyword 类型,并配置了 normalizer,在索引和查询阶段,都会对值进行归一化处理(如小写转换、去除空格等)。
term: 单字段精确匹配查询terms: 多值精确匹配range: 范围查询exists: 查询可以用于筛选出指定字段存在的文档(无论字段的值是什么,只要字段存在就会被匹配)。如果字段不存在或字段值为null(取决于映射配置),则不会匹配。ids: 根据一组_id查询prefix:前缀匹配查询,遍历查询字段对应的倒排索引,并比较每个词项(term)是否以所搜索的前缀开头wildcard:通配符匹配,原理同prefix,性能更低 (? 一个字符 * 0个或多个字符 )regexp:正则匹配查询,原理同prefix,性能更低fuzzy: 模糊查询terms_set:用于匹配文档字段(通常是数组字段)是否满足包含一个或多个指定值的查询
terms_set
terms_set 查询是一个用于匹配文档字段(通常是数组字段)是否满足包含一个或多个指定值的查询。与 terms 查询不同,它可以控制匹配的最小数量,更灵活。
基本语法
1 | { |
参数说明
- terms: 要匹配的词项列表。例如,[“apple”, “banana”, “orange”]。
- minimum_should_match_field: 指定一个字段名,该字段的值决定需要匹配的最小词项数量。例如,文档中某个字段 required_matches 值为 2,则需要匹配 terms 中至少 2 个词项。
- minimum_should_match_script: 替代 minimum_should_match_field,通过脚本动态计算最小匹配数量。例如,”source”: “doc[‘required_matches’].value”。
- field: 要查询的字段名,必须是精确值字段(如 keyword 类型)。
示例
1 | //文档 |
原理说明
terms_set针对的是数组字段;terms是输入的一组值,代表“用户感兴趣”的关键词;- Elasticsearch 会取交集:文档的
tags和terms的 - 然后通过
minimum_should_match来判断匹配程度; - 如果满足设定的
minimum_should_match条件,就返回文档。
这使得terms_set非常适合做用户画像、标签匹配、兴趣推荐系统等功能。
1 | // 最少2个 |
mo
fuzzy
Fuzzy 查询(模糊查询)是一种用于处理拼写错误或近似匹配的搜索机制,其核心原理基于编辑距离(Edit Distance,又称 Levenshtein Distance)。
1.编辑距离
- 定义:编辑距离是将一个字符串转换为另一个字符串所需的最小单字符编辑操作次数。允许的操作包括:
- 插入(Insertion): 添加一个字符(如
bat→boat)。 - 删除(Deletion): 删除一个字符(如
black→back)。 - 替换(Substitution): 替换一个字符(如
cat→cap)。 - 交换(Transposition): 交换相邻字符(如
form→from,仅当fuzziness = 2时支持)。
- 插入(Insertion): 添加一个字符(如
- Fuzziness 参数:指定允许的最大编辑距离(默认
AUTO,根据词项长度动态调整)。
2. Fuzzy 查询的工作流程***
当执行 Fuzzy 查询时,Elasticsearch 按以下步骤处理:
- 词项分析与归一化
- 输入的关键词会经过分词器处理(如转为小写),生成基础词项。
- 例如:搜索
"bule"会被归一化为"bule"(假设未进一步分词)。
- 生成候选词项变体
- 基于编辑距离,生成所有满足
编辑距离 ≤ fuzziness的词项变体。 - 例如:
"bule"的fuzziness=1的变体可能包括"blue"、"bule"(自身)、"bulge"、"rule"等。
- 基于编辑距离,生成所有满足
- 倒排索引匹配
- 在倒排索引中查找所有候选词项,收集包含这些词项的文档。
- 例如:若文档中存在
"blue",则匹配成功。
- 相关性评分
- 原始词项和候选词项的编辑距离越短,匹配文档的评分越高(更相关)。
3. 关键参数
fuzziness- 允许的最大编辑距离。可选值:
0、1、2:直接指定距离。AUTO:根据词项长度动态调整(如长度3-5允许1次编辑,长度>5允许2次)。
- 示例:
{"fuzziness": "AUTO"}。
- 允许的最大编辑距离。可选值:
prefix_length- 要求前 N 个字符必须完全匹配,减少生成的候选词项数量,提升性能。
- 例如:
prefix_length=2时,输入"apple"只匹配前两个字符"ap"相同的词项(如"apply"、"apples")。
max_expansions- 限制生成的候选词项数量,防止内存溢出(默认
50)。 - 示例:
{"max_expansions": 100}。
- 限制生成的候选词项数量,防止内存溢出(默认
范围查找
- range
全文检索
Full text queries
- intervals
- match
- match_bool_prefix
- match_phrase
- match_phrase_prefix
- multi_match
- combined_fields
- query_string
- simple_query_string
组合查询
- bool
- must
- should
- filter
- must_not
高亮显示
地理位置空间位置查询
向量检索
相关性评分
boost: 调整字段权重negative_boost: 降低相关性function_socre自定义评分rescore: 查询后二次打分
| 方法 | 适用场景 | 性能影响 | 灵活性 |
|---|---|---|---|
boost |
简单调整字段或子查询权重 | 低 | 低 |
negative_boost |
软性排除文档,不直接过滤 | 低 | 中 |
function_score |
复杂业务逻辑(如销量、时间、距离) | 高(尤其含脚本时) | 极高 |
rescore |
对少量结果优化(如精确匹配、短语查询) | 中(取决于窗口大小) | 中 |
多字段评分
dis_max:Disjunction Max Query将多个字段的匹配结果中得分最高的那个作为最终得分,而不是将所有字段的得分相加。- 在多字段查询中,取所有字段中 最高得分 作为文档的最终得分(而非字段得分的总和),同时通过
tie_breaker参数调整其他字段得分的贡献。 - 最终得分 = 最高字段得分 +
tie_breaker× 其他字段得分之和1
2
3
4
5
6
7
8
9
10
11
12GET /products/_search
{
"query": {
"dis_max": {
"queries": [
{ "match": { "title": "智能手机" } },
{ "match": { "description": "智能手机" } }
],
"tie_breaker": 0.3 // 其他字段得分按30%计入总分
}
}
}
- 在多字段查询中,取所有字段中 最高得分 作为文档的最终得分(而非字段得分的总和),同时通过
multi_matchbest_fields: 默认行为与dis_max一致,取所有字段中最高得分。 可结合tie_breaker调整其他字段的贡献。most_fields:将多个字段的得分 累加,最终得分为所有字段匹配得分的总和。cross_fields:跨字段联合搜索
1 | GET address/_search |
| 类型 | 评分逻辑 | 适用场景 | 性能 |
|---|---|---|---|
dis_max |
取最高分 + 其他字段辅助 | 强调单字段最佳匹配(如标题搜索) | 高 |
best_fields |
同 dis_max |
同 dis_max,简化语法 |
高 |
most_fields |
累加所有字段得分 | 多字段内容相似(如多语言字段) | 中 |
cross_fields |
全局统计词项分布,跨字段匹配 | 字段高度相关(如姓名、地址拆分字段) | 中 |
聚合
桶聚合(Bucket Aggregations)
- terms
- range
- data_range
- ip_rang
- histogram:
interval - date_histogram :
calendar_interval,fixed_interval - filters :将文档分组为多个桶,每个桶对应一组过滤条件。
桶数据的分页排序
1 | GET /sales/_search |
取桶内指定数量的文档
1 | GET /products/_search |
指标聚合(Metrics Aggregations)
- min
- max
- sum
- avg
- value_count
- stats : 按字段汇总统计该字段的总数、最大值、最小值、平均值、总和
管道聚合(Pipeline Aggregations)
管道聚合特点:
- 输入数据:依赖其他聚合的输出结果(如某个桶的统计值)。
- 功能:对已有的聚合结果进行二次计算(如求多个桶的平均值)。
- 语法位置:通常与父聚合 同级 或 嵌套在父聚合内部,需通过
buckets_path指定依赖路径。
1 | GET /sales/_search |
同级管道聚合(Sibling Pipeline Aggregations)
avg_bucket / sum_bucket:计算多个桶的平均值/总和1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23GET /sales/_search //统计所有月份的销售额平均值。
{
"size": 0,
"aggs": {
"sales_by_month": {
"date_histogram": {
"field": "date",
"calendar_interval": "month"
},
"aggs": { "monthly_sales": { "sum": { "field": "amount" } } } // 按月份统计销售额总和
},
"avg_monthly_sales": {
"avg_bucket": {
"buckets_path": "sales_by_month>monthly_sales" // 计算所有月份的平均销售额
}
},
"total_sales": {
"sum_bucket": {
"buckets_path": "sales_by_month>monthly_sales" // 所有月份的总和
}
}
}
}max_bucket/min_bucket:找出最大/最小的桶1
2
3
4
5
6
7
8
9
10{
"aggs": {
"sales_by_month": { ... }, // 同上
"max_month": {
"max_bucket": {
"buckets_path": "sales_by_month>monthly_sales" // 返回销售额最大的月份
}
}
}
}-
stats_bucket:返回多个桶的统计值(均值、总和等)
父级管道聚合(Parent Pipeline Aggregations)
对父聚合的桶内数据进行连续计算。
cumulative_sum:计算累积和。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20GET /sales/_search //计算销售额的年度累积值。
{
"size": 0,
"aggs": {
"sales_by_day": {
"date_histogram": {
"field": "date",
"calendar_interval": "day"
},
"aggs": {
"daily_sales": { "sum": { "field": "amount" } }, // 每日销售额
"cumulative_sales": {
"cumulative_sum": { // 累积和
"buckets_path": "daily_sales" // 依赖父聚合的子聚合结果
}
}
}
}
}
}derivative:计算相邻桶的差值(导数)moving_avg:计算移动平均值- …
总结
| 管道聚合类型 | 核心功能 | 典型场景 |
|---|---|---|
avg_bucket |
计算多个桶的平均值 | 月度平均销售额 |
cumulative_sum |
累积和 | 年度累计销售额 |
derivative |
计算相邻桶差值 | 日销售额变化率 |
moving_avg |
移动平均 | 7天销售额趋势 |
max_bucket/min_bucket |
找出最大/最小的桶 | 全年最高销售额月份 |
serial_diff |
序列差分(环比/同比) | 月度销售额 |
其他聚合
top_hits:返回每个桶内相关性最高的文档(如每类最新文章)。percentilespercentile_rankadjacency_matric: 邻接矩阵1
2
3
4
5
6
7PUT movies/_bulk?refresh
{"index":{"_id":1}}
{"name":"爱情片","accounts":["朋友的妈妈","霸王别姬"]}
{"index":{"_id":2}}
{"name":"动作片","accounts":["朋友的妈妈","道士下山"]}
{"index":{"_id":3}}
{"name":"恐怖片","accounts":["午夜凶铃","道士下山"]}
1 | GET movies/_search?filter_path=aggregations |
1 | { |
嵌套聚合
- 子聚合, 二次聚合、嵌套聚合、下钻聚合
按商品分类(category)分桶,并计算每个分类的最高价格。
1 | "aggs": { |
脚本聚合
过滤器筛选器
聚合前过滤数据
- filter
全局过滤
- 全局query查询中过滤
global
解除某个聚合的全局query限制
post_filter
1 | { |
| 对比项 | 普通 filter(查询上下文) |
post_filter |
|---|---|---|
| 执行阶段 | 在查询阶段生效,影响聚合和搜索结果。 | 在查询和聚合完成后生效,仅影响搜索结果。 |
| 对聚合的影响 | 聚合基于过滤后的文档计算。 | 聚合基于原始查询结果计算,不受过滤影响。 |
| 适用场景 | 需要同时过滤聚合和搜索结果的场景。 | 需要保持聚合完整,但过滤搜索结果的场景。 |
doc_values和fielddata
| 特性 | fielddata | doc_values |
|---|---|---|
| 适用字段 | text 类型的字段(需手动启用) |
keyword、numeric、date、boolean 等非分词字段(默认启用) |
| 核心用途 | 对分词后的文本字段进行排序、聚合、脚本操作 | 对非分词字段进行排序、聚合、脚本操作 |
| 存储位置 | 内存(按需加载) | 磁盘(列式存储,查询时部分加载到内存) |
| 特性 | fielddata | doc_values |
|---|---|---|
| 存储结构 | 行式存储(Row-based):按文档存储词项,适合快速访问单个文档的字段值。 | 列式存储(Column-based):按字段值连续存储,适合聚合和排序等批量操作。 |
| 加载时机 | 按需加载:首次对字段执行聚合/排序时动态构建到内存,可能阻塞查询。 | 索引时构建:数据在文档写入时生成并持久化到磁盘,查询时按需部分加载到内存。 |
| 内存占用 | 高:需将所有词项加载到内存,高基数(Cardinality)字段易引发内存问题。 | 低:数据主要存储在磁盘,查询时仅加载必要部分到内存,内存占用可控。 |
| 性能影响 | 潜在性能风险:频繁更新索引或高基数字段可能导致内存压力,甚至节点 OOM。 | 高效稳定:列式存储优化了聚合和排序性能,对内存压力小,适合大规模数据分析。 |
默认情况下,text 类型的字段会被分词(例如,"Elasticsearch Guide" 会被拆分为 ["elasticsearch", "guide"]),原始文本不会直接存储。因此:
- 如果要对
text字段进行排序或聚合,Elasticsearch 需要知道字段的 完整词项列表。 fielddata通过将分词后的词项(倒排索引中的词项)加载到内存中,形成一个 词项到文档的映射,从而支持这类操作。
向量搜索
dense vector
sparse vector
semantic_text
配置_inference_id
elser、e5
alibaba
https://opensearch.console.aliyun.com/cn-shanghai/rag/server-market
1 | PUT _inference/text_embedding/aliyun_text-embedding-v1 |