DSL
song

查询

match all(匹配所有文档)

  • _source
  • from size
  • sort

精确匹配

 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
2
3
4
5
6
7
8
9
10
11
12
13
{
"query": {
"term_set": {
"<field>": {
"terms": ["term1", "term2", "term3"],
"minimum_should_match_field": "<field_name>",
"minimum_should_match_script": {
"source": "<script>"
}
}
}
}
}

参数说明

  • 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//文档
{
"id": 1,
"tags": ["sports", "news", "tech"]
}
//查询
{
"query": {
"terms_set": {
"tags": {
"terms": ["sports", "finance", "news"],
"minimum_should_match_script": {
"source": "2" //查询包含我们感兴趣标签中的 **至少两个** 的文档
}
}
}
}
}

原理说明

  1. terms_set 针对的是数组字段
  2. terms 是输入的一组值,代表“用户感兴趣”的关键词;
  3. Elasticsearch 会取交集:文档的 tagsterms
  4. 然后通过 minimum_should_match 来判断匹配程度;
  5. 如果满足设定的 minimum_should_match 条件,就返回文档。
    这使得 terms_set 非常适合做用户画像、标签匹配、兴趣推荐系统等功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
// 最少2个 
{
"minimum_should_match_script":{"source":2}
}
//required_matches 字段中包含了最少匹配的数量
{
"minimum_should_match_field": "required_matches"
}
//动态计算
{
"minimum_should_match_script":{"source":"doc[tags_count].value*0.3"} //0.1 ~1
}
//

mo

fuzzy

 Fuzzy 查询(模糊查询)是一种用于处理拼写错误或近似匹配的搜索机制,其核心原理基于编辑距离(Edit Distance,又称 Levenshtein Distance)。

1.编辑距离

  • 定义:编辑距离是将一个字符串转换为另一个字符串所需的最小单字符编辑操作次数。允许的操作包括:
    • 插入(Insertion): 添加一个字符(如 bat → boat)。
    • 删除(Deletion): 删除一个字符(如 black → back)。
    • 替换(Substitution): 替换一个字符(如 cat → cap)。
    • 交换(Transposition): 交换相邻字符(如 form → from,仅当 fuzziness = 2 时支持)。
  • Fuzziness 参数:指定允许的最大编辑距离(默认 AUTO,根据词项长度动态调整)。

2. Fuzzy 查询的工作流程***

当执行 Fuzzy 查询时,Elasticsearch 按以下步骤处理:

  1. 词项分析与归一化
    • 输入的关键词会经过分词器处理(如转为小写),生成基础词项。
    • 例如:搜索 "bule" 会被归一化为 "bule"(假设未进一步分词)。
  2. 生成候选词项变体
    • 基于编辑距离,生成所有满足 编辑距离 ≤ fuzziness 的词项变体。
    • 例如:"bule" 的 fuzziness=1 的变体可能包括 "blue""bule"(自身)、"bulge""rule" 等。
  3. 倒排索引匹配
    • 在倒排索引中查找所有候选词项,收集包含这些词项的文档。
    • 例如:若文档中存在 "blue",则匹配成功。
  4. 相关性评分
    • 原始词项和候选词项的编辑距离越短,匹配文档的评分越高(更相关)。

3. 关键参数

  • fuzziness
    • 允许的最大编辑距离。可选值:
      • 012:直接指定距离。
      • 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_maxDisjunction Max Query 将多个字段的匹配结果中得分最高的那个作为最终得分,而不是将所有字段的得分相加。
    • 在多字段查询中,取所有字段中 最高得分 作为文档的最终得分(而非字段得分的总和),同时通过 tie_breaker 参数调整其他字段得分的贡献。
    • 最终得分 = 最高字段得分 + tie_breaker × 其他字段得分之和
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      GET /products/_search
      {
      "query": {
      "dis_max": {
      "queries": [
      { "match": { "title": "智能手机" } },
      { "match": { "description": "智能手机" } }
      ],
      "tie_breaker": 0.3 // 其他字段得分按30%计入总分
      }
      }
      }
  • multi_match
    • best_fields: 默认行为与 dis_max 一致,取所有字段中最高得分。 可结合 tie_breaker 调整其他字段的贡献。
    • most_fields:将多个字段的得分 累加,最终得分为所有字段匹配得分的总和。
    • cross_fields跨字段联合搜索
1
2
3
4
5
6
7
8
9
10
11
GET address/_search
{
    "query": {
        "multi_match": {
            "query": "北京市 海淀区",
            "fields": ["province","city","district" ],
            "type": "cross_fields",
            "operator": "and" //控制词项间的逻辑关系:`and`(必须全部匹配)或 `or`(至少匹配一个)
        }
    }
}
类型 评分逻辑 适用场景 性能
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
GET /sales/_search
{
"size": 0,
"aggs": {
"categories": {
"terms": {
"field": "category.keyword",
"size": 1000, // 需覆盖总分页范围,性能风险高!
"order": { "_count": "desc" } // 按桶中文档数降序排序
},
"aggs": {
"paged_buckets": {
"bucket_sort": {
"sort": [ { "sales": { "order": "desc" } } ], // 二次排序
"size": 5, // 每页大小
"from": 10 // 分页偏移量
}
},
"sales": { "sum": { "field": "amount" } } // 子聚合用于排序
}
}
}
}

取桶内指定数量的文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
GET /products/_search
{
"size": 0, // 不返回原始文档,仅返回聚合结果
"aggs": {
"group_by_category": {
"terms": {
"field": "category.keyword", // 分桶字段
"size": 100 // 最多返回 100 个分类
},
"aggs": {
"top_products": {
"top_hits": {
"size": 10, // 每个分类取前 10 条
"sort": [{"sales": {"order": "desc"}}], // 按销量降序
"_source": ["title", "price", "sales"] // 返回指定字段
}
}
}
}
}
}

指标聚合(Metrics Aggregations)

  • min
  • max
  • sum
  • avg
  • value_count
  • stats : 按字段汇总统计该字段的总数、最大值、最小值、平均值、总和

管道聚合(Pipeline Aggregations)

管道聚合特点:

  • 输入数据:依赖其他聚合的输出结果(如某个桶的统计值)。
  • 功能:对已有的聚合结果进行二次计算(如求多个桶的平均值)。
  • 语法位置:通常与父聚合 同级 或 嵌套在父聚合内部,需通过 buckets_path 指定依赖路径。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
GET /sales/_search
{
    "size": 0,
    "aggs": {
        "group_by_month": {
            "date_histogram": {
                "field": "date",
                "calendar_interval": "month" // 按月份分桶
            },
            "aggs": {
                "monthly_sales": {
                    "sum": {
                        "field": "amount" //指标聚合(每月销售额总和)
                    }
                }
            }
        },
        "max_monthly_sales": {
            "max_bucket": { // 管道聚合(统计所有月份中的最大销售额)
                "buckets_path": "group_by_month>monthly_sales" //依赖其他聚合结果
            }
        }
    }
}

同级管道聚合(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
    23
    GET /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
    20
    GET /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:返回每个桶内相关性最高的文档(如每类最新文章)。
  • percentiles
  • percentile_rank
  • adjacency_matric: 邻接矩阵
    1
    2
    3
    4
    5
    6
    7
    PUT movies/_bulk?refresh
    {"index":{"_id":1}}
    {"name":"爱情片","accounts":["朋友的妈妈","霸王别姬"]}
    {"index":{"_id":2}}
    {"name":"动作片","accounts":["朋友的妈妈","道士下山"]}
    {"index":{"_id":3}}
    {"name":"恐怖片","accounts":["午夜凶铃","道士下山"]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GET movies/_search?filter_path=aggregations
{
  "size": 0,
  "aggs": {
    "interactions": {
      "adjacency_matrix": {
        "filters": {
          "张飞":{"terms":{"accounts.keyword":["朋友的妈妈","苹果"]}},
          "刘备":{"terms":{"accounts.keyword":["道士下山","阿甘正传"]}},
          "关羽":{"terms":{"accounts.keyword":["午夜凶铃","霸王别姬"]}}
        }
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
  "aggregations": {
    "interactions": {
      "buckets": [
        {
          "key": "关羽",
          "doc_count": 2
        },

        {
          "key": "关羽&刘备",
          "doc_count": 1
        },
        {
          "key": "关羽&张飞",
          "doc_count": 1
        },
        {
          "key": "刘备",
          "doc_count": 2
        },
        {
          "key": "刘备&张飞",
          "doc_count": 1
        },
        {
          "key": "张飞",
          "doc_count": 2
        }
      ]
    }
  }
}

嵌套聚合

  • 子聚合, 二次聚合、嵌套聚合、下钻聚合

按商品分类(category)分桶,并计算每个分类的最高价格。

1
2
3
4
5
6
"aggs": {
"group_by_category": {
"terms": { "field": "category.keyword" },
"aggs": { "max_price": { "max": { "field": "price" } } } // 直接统计原始字段
}
}

脚本聚合

过滤器筛选器

聚合前过滤数据

  • filter

全局过滤

  • 全局query查询中过滤

global

解除某个聚合的全局query限制

post_filter

1
2
3
4
5
{
"query":{}, //首先执行,全局数据过滤,会影响agg中聚合结果
"agg":{}, //第二执行, 以query过滤后的结果为准进行聚合
"post_filter":{} // 第三执行,不影响聚合,仅过滤返回的搜索结果。在检索+聚合之后,对已有数据再次进行的过滤
}
对比项 普通 filter(查询上下文) post_filter
执行阶段 在查询阶段生效,影响聚合和搜索结果。 在查询和聚合完成后生效,仅影响搜索结果。
对聚合的影响 聚合基于过滤后的文档计算。 聚合基于原始查询结果计算,不受过滤影响。
适用场景 需要同时过滤聚合和搜索结果的场景。 需要保持聚合完整,但过滤搜索结果的场景。

doc_values和fielddata

特性 fielddata doc_values
适用字段 text 类型的字段(需手动启用) keywordnumericdateboolean 等非分词字段(默认启用)
核心用途 对分词后的文本字段进行排序、聚合、脚本操作 对非分词字段进行排序、聚合、脚本操作
存储位置 内存(按需加载) 磁盘(列式存储,查询时部分加载到内存)
特性 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
2
3
4
5
6
7
8
9
10
PUT _inference/text_embedding/aliyun_text-embedding-v1
{
    "service": "alibabacloud-ai-search",
    "service_settings": {
        "host" : "default-3jix.platform-cn-shanghai.opensearch.aliyuncs.com",
        "api_key": "key",
        "service_id": "ops-text-embedding-001",
        "workspace" : "default"
    }
}
由 Hexo 驱动 & 主题 Keep