5.1 搜索 API (Search API)


文档摘要

5.1 搜索 API (Search API) Elasticsearch 核心操作:搜索与查询 - 5.1 搜索 API (Search API) 详解 在 Elasticsearch 的世界里,搜索是其核心价值所在。用户将海量数据存储在 Elasticsearch 中,最终目的都是为了能够快速、准确地从中检索出所需信息。而 搜索 API (Search API) 正是 Elasticsearch 提供的最重要、最核心的 API 之一,它是连接用户与 Elasticsearch 强大搜索能力的桥梁。 搜索 API 的基本概念 搜索 API (Search API) 允许用户通过 HTTP 请求向 Elasticsearch 发送搜索请求,并接收包含匹配文档的结果。

5.1 搜索 API (Search API)

Elasticsearch 核心操作:搜索与查询 - 5.1 搜索 API (Search API) 详解

在 Elasticsearch 的世界里,搜索是其核心价值所在。用户将海量数据存储在 Elasticsearch 中,最终目的都是为了能够快速、准确地从中检索出所需信息。而 搜索 API (Search API) 正是 Elasticsearch 提供的最重要、最核心的 API 之一,它是连接用户与 Elasticsearch 强大搜索能力的桥梁。

1. 搜索 API 的基本概念

搜索 API (Search API) 允许用户通过 HTTP 请求向 Elasticsearch 发送搜索请求,并接收包含匹配文档的结果。它基于 RESTful 风格,使用 JSON 作为数据交换格式,易于理解和使用。

核心功能:

  • 全文搜索: 基于文本内容进行关键词匹配,支持多种分词器和分析器,实现高效的全文检索。

  • 结构化搜索: 基于文档的结构化字段进行精确匹配、范围查询、布尔查询等,满足各种复杂查询需求。

  • 组合查询: 可以将全文搜索和结构化搜索灵活组合,构建更精细、更强大的查询条件。

  • 结果控制: 可以对搜索结果进行排序、分页、高亮显示、字段过滤等操作,提升用户体验。

  • 聚合分析: 可以对搜索结果进行统计分析,例如计算平均值、最大值、最小值、词频统计等,为数据分析提供支持。

请求方式:

搜索 API 主要通过 GETPOST 请求方式访问。

  • GET: 适用于简单的查询场景,查询参数直接附加在 URL 中。

  • POST: 适用于复杂的查询场景,查询参数以 JSON 格式放在请求体中,更加灵活和安全,也更适合处理较长的查询语句。

请求路径:

搜索 API 的基本请求路径格式如下:

/[index]/_search /[index1],[index2]/_search /_search
  • [index]: 指定要搜索的索引名称。

  • [index1],[index2]: 指定要搜索的多个索引名称,用逗号分隔。

  • _search: 固定路径,表示搜索操作。

  • /_search: 搜索所有索引。

2. 简单的搜索实践:match_all 查询

我们先从最简单的搜索开始,使用 match_all 查询,它会返回指定索引下的所有文档。

代码示例 (使用 curl 命令):

假设我们有一个名为 products 的索引,包含商品数据。

curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} } } '

代码详解:

  • curl -X GET "localhost:9200/products/_search?pretty": 使用 GET 请求访问 Elasticsearch 的搜索 API,指定索引为 products,并添加 pretty 参数,使返回的 JSON 结果更易读。

  • -H 'Content-Type: application/json': 设置请求头,表明请求体是 JSON 格式。

  • -d' ... ': 指定请求体,包含 JSON 格式的查询语句。

  • "query": { ... }: query 字段是搜索请求的核心,定义了查询条件。

  • "match_all": {}: match_all 查询类型,表示匹配所有文档, {} 表示没有任何参数。

返回结果 (部分示例):

{ "took" : 2, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 3, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "products", "_type" : "_doc", "_id" : "1", "_score" : 1.0, "_source" : { "name" : "Elasticsearch Guide Book", "description" : "A comprehensive guide to Elasticsearch.", "price" : 49.99, "category" : "Books" } }, // ... 更多文档 ] } }

结果解析:

  • took: 查询耗时,单位毫秒。

  • timed_out: 是否超时。

  • _shards: 分片信息,包括总分片数、成功分片数、跳过分片数、失败分片数。

  • hits: 搜索结果的核心部分。

    • total: 匹配到的文档总数。

      • value: 文档总数。

      • relation: 文档总数关系,eq 表示精确匹配。

    • max_score: 最高得分。

    • hits: 匹配到的文档列表,每个文档包含以下信息:

      • _index: 文档所属索引。

      • _type: 文档类型 (在 Elasticsearch 版本后默认为 _doc)。

      • _id: 文档 ID。

      • _score: 文档得分,相关性越高得分越高。

      • _source: 文档的原始 JSON 数据。

Mermaid Graph TD 图示:

3. 基于关键词的全文搜索:match 查询

match_all 查询虽然简单,但在实际应用中很少直接使用。更常见的需求是根据关键词进行全文搜索。match 查询是 Elasticsearch 中最常用的全文搜索查询类型。

代码示例 (搜索商品描述中包含 "guide" 的商品):

curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "match": { "description": "guide" } } } '

代码详解:

  • "match": { "description": "guide" }: 使用 match 查询类型,指定要查询的字段为 description,关键词为 "guide"

返回结果 (部分示例):

{ // ... 其他结果信息 "hits" : { // ... "hits" : [ { "_index" : "products", "_type" : "_doc", "_id" : "1", "_score" : 0.2876821, "_source" : { "name" : "Elasticsearch Guide Book", "description" : "A comprehensive guide to Elasticsearch.", "price" : 49.99, "category" : "Books" } } // ... ] } }

结果解析:

  • 只有商品描述中包含 "guide" 关键词的文档被匹配到。

  • _score 值反映了文档与关键词的相关性,match 查询会根据关键词在文档中的出现频率、位置等因素计算得分。

match 查询的分析过程:

match 查询会先对输入的关键词进行分析 (analysis),例如分词、停用词处理、大小写转换等,然后将分析后的词项与索引中的倒排索引进行匹配。

可以通过 analyzer 参数指定分析器:

{ "query": { "match": { "description": { "query": "guide books", "analyzer": "standard" // 使用 standard 分析器 } } } }

如果不指定 analyzer,则默认使用字段映射中定义的分析器,或者索引的默认分析器。

match 查询的操作符 (operator):

match 查询可以通过 operator 参数控制关键词之间的匹配关系:

  • or (默认): 关键词之间是 OR 关系,只要文档包含任意一个关键词就匹配。

  • and: 关键词之间是 AND 关系,文档必须包含所有关键词才匹配。

示例 (搜索商品描述中同时包含 "guide" 和 "comprehensive" 的商品):

{ "query": { "match": { "description": { "query": "guide comprehensive", "operator": "and" } } } }

match 查询的最小匹配度 (minimum_should_match):

minimum_should_match 参数用于控制 should 子句 (OR 关系) 的最小匹配词项数量,可以更精细地控制匹配度。

示例 (搜索商品描述中至少包含 "guide", "comprehensive", "elasticsearch" 中的两个关键词):

{ "query": { "match": { "description": { "query": "guide comprehensive elasticsearch", "minimum_should_match": "2" } } } }

4. 精确匹配查询:term 查询

term 查询用于精确匹配某个字段的值,它不会对查询关键词进行分析,直接按照原始值进行匹配。

代码示例 (搜索 category 字段为 "Books" 的商品):

curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "term": { "category": "Books" } } } '

代码详解:

  • "term": { "category": "Books" }: 使用 term 查询类型,指定要查询的字段为 category,精确匹配值为 "Books"

返回结果 (部分示例):

{ // ... 其他结果信息 "hits" : { // ... "hits" : [ { "_index" : "products", "_type" : "_doc", "_id" : "1", "_score" : 1.0, "_source" : { "name" : "Elasticsearch Guide Book", "description" : "A comprehensive guide to Elasticsearch.", "price" : 49.99, "category" : "Books" } } // ... ] } }

term 查询的应用场景:

  • 枚举值字段: 例如商品分类、订单状态等,需要精确匹配特定值。

  • ID 字段: 根据文档 ID 进行精确查找。

  • 不需要分词的字段: 例如数字、日期、keyword 类型字段。

注意: term 查询对文本字段进行精确匹配时,需要确保查询的关键词与索引中的词项完全一致,包括大小写。如果文本字段使用了分词器,term 查询可能无法匹配到原始文本,因为分词器会将文本拆分成多个词项。

5. 范围查询:range 查询

range 查询用于查询某个字段值在指定范围内的文档。

代码示例 (搜索价格在 40 到 60 之间的商品):

curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "range": { "price": { "gte": 40, // 大于等于 40 "lte": 60 // 小于等于 60 } } } } '

代码详解:

  • "range": { "price": { ... } }: 使用 range 查询类型,指定要查询的字段为 price

  • "gte": 40: gte (greater-than-or-equal) 参数,表示价格大于等于 40。

  • "lte": 60: lte (less-than-or-equal) 参数,表示价格小于等于 60。

range 查询支持的范围操作符:

  • gte: 大于等于 (>=)

  • gt: 大于 (>)

  • lte: 小于等于 (<=)

  • lt: 小于 (<)

  • from: 范围起始值 (包含)

  • to: 范围结束值 (包含)

  • include_lower: 是否包含下界,默认为 true

  • include_upper: 是否包含上界,默认为 true

range 查询的应用场景:

  • 价格范围: 例如搜索指定价格区间的商品。

  • 日期范围: 例如搜索指定时间段内的订单。

  • 年龄范围: 例如搜索指定年龄段的用户。

6. 复合查询:bool 查询

bool 查询是 Elasticsearch 中最强大的复合查询类型,它可以将多个查询条件组合在一起,构建复杂的查询逻辑。

bool 查询包含四个子句:

  • must (必须): 文档必须满足 must 子句中的所有条件,类似于 AND 关系。

  • should (应该): 文档应该满足 should 子句中的至少一个条件,类似于 OR 关系。满足的 should 子句越多,文档得分越高。

  • must_not (必须不): 文档不能满足 must_not 子句中的任何条件,用于排除特定文档。

  • filter (过滤): 类似于 must,文档必须满足 filter 子句中的所有条件,但不计算相关性得分,性能更高,常用于过滤场景。

代码示例 (搜索分类为 "Books" 且描述中包含 "guide" 的商品):

curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "bool": { "must": [ { "term": { "category": "Books" } }, { "match": { "description": "guide" } } ] } } } '

代码详解:

  • "bool": { ... }: 使用 bool 查询类型。

  • "must": [ ... ]: must 子句,包含两个查询条件:

    • { "term": { "category": "Books" } }: term 查询,分类必须为 "Books"。

    • { "match": { "description": "guide" } }: match 查询,描述中必须包含 "guide"。

Mermaid Graph TD 图示:

bool 查询的灵活组合:

bool 查询的子句可以灵活组合,构建各种复杂的查询逻辑。例如:

  • shouldminimum_should_match 结合: 实现 "至少匹配 N 个条件" 的逻辑。

  • must_not 排除特定条件: 例如搜索 "不是 Books 分类的商品"。

  • filter 进行高效过滤: 例如先用 filter 过滤出指定价格范围的商品,再用 match 进行全文搜索。

  • 嵌套 bool 查询: 可以在 bool 查询中嵌套其他 bool 查询,构建更复杂的查询树。

7. 结果排序:sort

默认情况下,搜索结果按照相关性得分 _score 降序排列。可以使用 sort 参数自定义排序规则。

代码示例 (按照价格升序排列商品):

curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} }, "sort": [ { "price": { "order": "asc" } } // 价格升序 ] } '

代码详解:

  • "sort": [ ... ]: sort 参数,定义排序规则,可以是一个数组,支持多字段排序。

  • { "price": { "order": "asc" } }: 按照 price 字段排序,order: "asc" 表示升序 (ascending),order: "desc" 表示降序 (descending)。

支持的排序类型:

  • 数值型字段: 例如 price, age

  • 日期型字段: 例如 create_time, update_time

  • 字符串字段: 默认按照字典顺序排序。

  • 地理位置字段: 可以按照距离排序。

多字段排序:

"sort": [ { "category": { "order": "asc" } }, // 先按照分类升序 { "price": { "order": "desc" } } // 再按照价格降序 ]

8. 分页查询:fromsize

当搜索结果数量很大时,需要进行分页显示。可以使用 fromsize 参数控制分页。

  • size: 指定每页返回的文档数量,默认值为 10。

  • from: 指定从第几条文档开始返回,默认值为 0,表示从第一条文档开始。

代码示例 (查询第二页,每页显示 2 条文档):

curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} }, "from": 2, // 从第 3 条文档开始 (索引从 0 开始) "size": 2 // 每页显示 2 条文档 } '

分页计算公式:

  • 当前页码 (page): 假设页码从 1 开始。

  • from 值: (page - 1) * size

深分页问题:

from 值很大时,例如查询第 10000 页之后的数据,会发生深分页问题,导致性能下降甚至超时。因为 Elasticsearch 需要从各个分片收集大量数据,并进行排序和截取。

避免深分页的方法:

  • 避免使用过大的 from 值: 尽量限制分页深度。

  • 使用 scroll API: 适用于需要遍历所有结果的场景,例如数据导出。

  • 使用 search_after: 适用于实时分页场景,基于上一页最后一条文档的排序值进行分页,避免了深分页问题。

9. 源文档过滤:_source

默认情况下,搜索结果会返回完整的源文档 (_source 字段)。可以使用 _source 参数控制返回的字段。

代码示例 (只返回商品名称和价格):

curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} }, "_source": ["name", "price"] // 指定返回的字段 } '

代码详解:

  • "_source": ["name", "price"]: _source 参数,指定一个数组,包含要返回的字段名称。

_source 参数的用法:

  • _source: false: 不返回源文档,只返回元数据 (_index, _type, _id, _score 等)。

  • _source: true (默认): 返回完整源文档。

  • _source: ["field1", "field2"]: 返回指定字段。

  • _source: { "includes": ["field*"], "excludes": ["field_exclude"] }: 使用 includesexcludes 进行更精细的字段过滤,支持通配符。

10. 高亮显示:highlight

高亮显示可以将搜索关键词在文档内容中突出显示,提升用户体验。

代码示例 (高亮显示商品描述中的 "guide" 关键词):

curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "match": { "description": "guide" } }, "highlight": { "fields": { "description": {} // 对 description 字段进行高亮 } } } '

代码详解:

  • "highlight": { ... }: highlight 参数,定义高亮配置。

  • "fields": { "description": {} }: 指定要进行高亮的字段为 description{} 表示使用默认高亮配置。

返回结果 (部分示例):

{ // ... 其他结果信息 "hits" : { // ... "hits" : [ { "_index" : "products", "_type" : "_doc", "_id" : "1", "_score" : 0.2876821, "_source" : { "name" : "Elasticsearch Guide Book", "description" : "A comprehensive guide to Elasticsearch.", "price" : 49.99, "category" : "Books" }, "highlight" : { "description" : [ "A comprehensive <em>guide</em> to Elasticsearch." // 高亮显示 ] } } // ... ] } }

结果解析:

  • hits 数组的每个文档中,会多出一个 highlight 字段,其中包含了高亮显示的字段和内容。

  • 默认使用 <em></em> 标签进行高亮显示,可以通过 pre_tagspost_tags 参数自定义高亮标签。

自定义高亮标签:

"highlight": { "pre_tags": ["<span style='color:red'>"], // 前缀标签 "post_tags": ["</span>"], // 后缀标签 "fields": { "description": {} } }

11. 总结与展望

本文详细介绍了 Elasticsearch 的 搜索 API (Search API) 的核心功能和常用查询类型,并通过代码示例演示了其基本用法。掌握搜索 API 是使用 Elasticsearch 的基础和关键。

核心要点回顾:

  • 搜索 API 的基本概念和请求方式。

  • match_all 查询:匹配所有文档。

  • match 查询:全文搜索,支持多种操作符和分析器。

  • term 查询:精确匹配。

  • range 查询:范围查询。

  • bool 查询:复合查询,灵活组合多个查询条件。

  • sort:结果排序。

  • fromsize:分页查询。

  • _source:源文档过滤。

  • highlight:高亮显示。

未来展望:

  • 更丰富的查询类型: Elasticsearch 提供了更多高级查询类型,例如 nested 查询、geo 查询、script 查询等,可以满足更复杂的搜索需求。

  • 性能优化: 在实际应用中,需要关注搜索性能,例如合理设计索引结构、选择合适的查询类型、优化查询语句、使用缓存等。

  • 与客户端集成: 可以使用 Elasticsearch 提供的各种客户端库 (例如 Java, Python, JavaScript 等) 更方便地与搜索 API 进行交互,构建强大的搜索应用。


发布者: 作者: 转发
评论区 (0)
U