4.2 获取文档 (Get API) Elasticsearch 核心操作:文档管理 - 4.2 获取文档 (Get API) 详解 Get API 的基本概念与作用 Get API 的核心作用正如其名,就是获取 Elasticsearch 中存储的文档。当我们知道一个文档的唯一标识符(ID)时,可以使用 Get API 快速定位并获取该文档的完整 JSON 源文档,或者只获取文档的特定部分信息。 在文档管理领域,Get API 的应用场景非常广泛,例如: 数据详情展示: 在应用程序中,当用户需要查看某个具体的数据条目详情时,可以使用 Get API 根据文档 ID 获取数据并展示给用户。
Get API 的核心作用正如其名,就是获取 Elasticsearch 中存储的文档。当我们知道一个文档的唯一标识符(ID)时,可以使用 Get API 快速定位并获取该文档的完整 JSON 源文档,或者只获取文档的特定部分信息。
在文档管理领域,Get API 的应用场景非常广泛,例如:
数据详情展示: 在应用程序中,当用户需要查看某个具体的数据条目详情时,可以使用 Get API 根据文档 ID 获取数据并展示给用户。
数据验证与调试: 在数据索引或更新后,可以使用 Get API 立即验证数据是否正确写入 Elasticsearch,方便调试和问题排查。
数据分析的准备: 在进行更复杂的数据分析之前,可能需要先通过 Get API 获取一些关键文档,作为后续分析的输入数据。
构建实时应用: 对于需要实时响应的应用,Get API 的快速检索能力可以保证用户在极短时间内获取到所需的数据。
总而言之,Get API 是与 Elasticsearch 交互,进行文档检索的最基本也是最常用的 API 之一,理解和熟练掌握 Get API 的使用,是深入学习和应用 Elasticsearch 的基础。
Get API 的请求方法是 HTTP GET 请求,其基本请求路径结构如下:
GET <index>/_doc/<id> GET <index>/_doc/<id>?parameters
或者在旧版本 Elasticsearch 中,可能使用 _type:
GET <index>/<type>/<id> GET <index>/<type>/<id>?parameters
路径参数说明:
<index>: 必需参数,指定要从中检索文档的索引名称。
_doc 或 <type>: 必需参数,指定文档类型。在 Elasticsearch 7.0 及以后版本,官方推荐使用 _doc 作为默认类型,并逐步弱化 _type 的概念。在旧版本中,可能需要指定具体的 _type 名称。
<id>: 必需参数,指定要检索的文档的唯一 ID。
请求参数 (Query Parameters):
Get API 提供了丰富的可选请求参数,用于控制检索行为和返回结果,常用的参数包括:
_source: 控制是否返回 _source 字段。可以设置为 true (默认) 或 false。还可以指定要包含或排除的 _source 字段列表。
_source_includes: 指定要包含在 _source 中的字段列表,多个字段用逗号分隔。
_source_excludes: 指定要从 _source 中排除的字段列表,多个字段用逗号分隔。
stored_fields: 指定要返回的存储字段 (stored fields)。只有在 mapping 中显式设置为 store: true 的字段才能通过 stored_fields 返回。
realtime: 控制是否实时检索。默认为 true,表示实时检索,反映最新的文档状态。设置为 false 可以从更近的索引段中检索,可能更快,但可能不是最新的数据。
preference: 指定在哪个分片或节点上执行检索操作,用于控制检索的偏好。
routing: 指定路由值,用于在索引时使用了自定义路由的场景下,确保从正确的shard检索文档。
version: 指定期望的文档版本号,用于实现乐观并发控制。
version_type: 指定版本类型,配合 version 参数使用,控制版本检查的方式。
fields: 请求返回的字段列表,可以用来获取 _source 之外的字段,例如元数据字段或 stored fields。
refresh: 在检索之前强制刷新索引,确保检索到最新的数据。通常不建议在生产环境中使用,会影响性能。
接下来,我们将通过具体的代码示例,演示 Get API 的使用方法,并对各种常用参数进行详细解释。
代码示例 (curl):
假设我们有一个名为 products 的索引,其中有一个文档 ID 为 1,我们要获取这个文档的完整信息。
curl -X GET "localhost:9200/products/_doc/1"
预期响应 (成功 - 200 OK):
{ "_index" : "products", "_type" : "_doc", "_id" : "1", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true, "_source" : { "name" : "Elasticsearch Guide Book", "price" : 59.99, "description" : "A comprehensive guide to Elasticsearch." } }
响应字段详解:
_index: 文档所在的索引名称 (products)。
_type: 文档类型 (_doc)。
_id: 文档 ID (1)。
_version: 文档版本号 (1)。每次文档更新,版本号都会递增。
_seq_no: 文档的序列号,用于 Elasticsearch 的内部操作和并发控制。
_primary_term: 文档所在的主分片的主 term。
found: 布尔值,表示是否找到文档 (true 表示找到)。
_source: JSON 对象,包含文档的完整源数据。
Mermaid 图形 - 基本 Get API 请求流程:
代码示例 (Python - elasticsearch-py):
from elasticsearch import Elasticsearch es = Elasticsearch("http://localhost:9200") index_name = "products" doc_id = "1" try: response = es.get(index=index_name, id=doc_id) print(response) except Exception as e: print(f"Error: {e}")
这段 Python 代码使用了 elasticsearch-py 客户端库,连接到 Elasticsearch 集群,并使用 es.get() 方法发送 Get API 请求,获取指定索引和 ID 的文档。
_source 参数:控制源文档返回默认情况下,Get API 会返回完整的 _source 字段。我们可以使用 _source 参数来控制是否返回 _source,或者只返回 _source 的部分字段。
3.2.1 _source=false:只检查文档是否存在
如果我们只想检查文档是否存在,而不需要获取文档内容,可以将 _source 参数设置为 false。
代码示例 (curl):
curl -X GET "localhost:9200/products/_doc/1?_source=false"
预期响应 (成功 - 200 OK):
{ "_index" : "products", "_type" : "_doc", "_id" : "1", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true }
可以看到,响应中不再包含 _source 字段,但 found 字段仍然为 true,表明文档存在。如果文档不存在,found 字段将为 false,并且 HTTP 状态码为 404 Not Found。
3.2.2 _source_includes 和 _source_excludes:字段过滤
我们可以使用 _source_includes 参数指定要包含在 _source 中的字段列表,或者使用 _source_excludes 参数指定要从 _source 中排除的字段列表。
代码示例 (curl - _source_includes):
只返回 name 和 price 字段:
curl -X GET "localhost:9200/products/_doc/1?_source_includes=name,price"
预期响应:
{ "_index" : "products", "_type" : "_doc", "_id" : "1", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true, "_source" : { "name" : "Elasticsearch Guide Book", "price" : 59.99 } }
代码示例 (curl - _source_excludes):
排除 description 字段:
curl -X GET "localhost:9200/products/_doc/1?_source_excludes=description"
预期响应:
{ "_index" : "products", "_type" : "_doc", "_id" : "1", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true, "_source" : { "name" : "Elasticsearch Guide Book", "price" : 59.99 } }
Mermaid 图形 - _source 参数控制:
stored_fields 参数:获取存储字段默认情况下,Elasticsearch 只会将 _source 字段存储起来,用于文档检索。如果我们在 mapping 中将某些字段显式设置为 store: true,这些字段会被单独存储,称为 stored fields。我们可以使用 stored_fields 参数来获取这些存储字段的值。
注意: 通常情况下,不建议过度使用 stored fields,因为会增加存储开销。_source 字段已经包含了所有原始数据,通常足以满足需求。stored fields 主要用于优化特定场景下的性能,例如只需要获取少量字段,且这些字段访问频率非常高。
假设 mapping 中 name 字段被设置为 store: true:
PUT /products/_mapping { "properties": { "name": { "type": "text", "store": true }, "price": { "type": "double" }, "description": { "type": "text" } } }
代码示例 (curl - stored_fields):
curl -X GET "localhost:9200/products/_doc/1?stored_fields=name"
预期响应:
{ "_index" : "products", "_type" : "_doc", "_id" : "1", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true, "fields" : { "name" : [ "Elasticsearch Guide Book" ] } }
可以看到,存储字段的值被包含在响应的 fields 字段中。
realtime 参数:实时性控制Elasticsearch 是近实时 (Near Real-Time, NRT) 的搜索引擎。默认情况下,索引操作 (如 index, update, delete) 完成后,数据并不会立即对搜索可见,需要经过一个 refresh 操作才能变为可搜索。
Get API 默认情况下 (realtime=true) 是实时检索的,这意味着它会尝试从最新的数据段中检索文档,反映最新的文档状态。
realtime=false: 设置为 false 时,Get API 可以从更近的索引段中检索数据,这可能会更快,但返回的数据可能不是最新的,可能不包含最近索引或更新的文档,直到索引被刷新。
在大多数情况下,默认的 realtime=true 已经足够好,不需要显式设置 realtime 参数。 只有在对实时性要求不高,且对性能有极致追求的特定场景下,可以考虑使用 realtime=false。
代码示例 (curl - realtime=false):
curl -X GET "localhost:9200/products/_doc/1?realtime=false"
Mermaid 图形 - realtime 参数的影响:
_source=false 和 fields=_source如前所述,将 _source 参数设置为 false 可以只检查文档是否存在,而无需获取文档内容。这在某些场景下非常高效,例如,只需要判断某个文档 ID 是否已经被索引,而不需要实际的数据。
另一种高效的文档存在性检查方法是使用 fields=_source 参数,并结合 _source=false。 虽然看起来矛盾,但实际上,当 _source=false 且 fields=_source 时,Elasticsearch 会进行优化,只进行文档存在性检查,并不会真正去加载和返回 _source 字段。
代码示例 (curl - _source=false 和 fields=_source):
curl -X GET "localhost:9200/products/_doc/1?_source=false&fields=_source"
预期响应 (文档存在):
{ "_index" : "products", "_type" : "_doc", "_id" : "1", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true }
预期响应 (文档不存在):
{ "_index" : "products", "_type" : "_doc", "_id" : "non_existent_id", "found" : false }
version 和 version_type 参数Elasticsearch 使用版本号来管理文档的更新。每次文档被修改,其版本号都会递增。Get API 允许我们通过 version 和 version_type 参数进行版本控制,实现乐观并发控制。
version 参数: 我们可以指定期望的文档版本号。只有当文档的当前版本号与指定的 version 相匹配时,Get API 才会成功返回文档。否则,会返回 409 Conflict 错误。
version_type 参数: 控制版本检查的方式,常用的 version_type 包括:
internal (默认): 使用 Elasticsearch 内部的版本号进行比较,必须完全匹配。
external 或 external_gte: 用于外部系统管理版本号的场景。external 要求指定的 version 必须大于当前文档的版本号,external_gte 要求大于等于。 通常用于从外部数据库同步数据到 Elasticsearch,并保持版本一致性。
force: 强制获取指定版本的文档,即使该版本不是最新的。通常用于历史数据查询或调试,生产环境慎用。
代码示例 (curl - version 和 version_type=external_gte):
假设文档当前版本号为 2,我们期望获取版本号大于等于 2 的文档:
curl -X GET "localhost:9200/products/_doc/1?version=2&version_type=external_gte"
如果文档版本号确实大于等于 2,则成功返回文档。否则,返回 409 Conflict 错误。
Mermaid 图形 - 版本控制流程:
Get API 可能会返回以下常见的错误状态码:
200 OK: 成功获取文档。
404 Not Found: 文档不存在,或者指定的索引或类型不存在。
409 Conflict: 版本冲突,当使用 version 参数进行版本控制时,版本号不匹配会返回此错误。
在应用程序中,需要根据不同的错误状态码进行相应的处理。例如,当收到 404 Not Found 错误时,可以提示用户文档不存在,或者进行默认处理。
代码示例 (Python - elasticsearch-py 错误处理):
from elasticsearch import Elasticsearch from elasticsearch import NotFoundError es = Elasticsearch("http://localhost:9200") index_name = "products" doc_id = "non_existent_id" try: response = es.get(index=index_name, id=doc_id) print(response) except NotFoundError as e: print(f"Document not found: {e}") except Exception as e: print(f"Other error: {e}")
这段 Python 代码使用了 elasticsearch-py 的 NotFoundError 异常来捕获 404 错误,并进行专门处理。
避免频繁的 refresh=true: 强制刷新索引会影响性能,通常不建议在生产环境中使用。
合理使用 _source_includes 和 _source_excludes: 只获取需要的字段可以减少数据传输量,提升性能。
利用缓存: 在应用程序层面,可以对 Get API 的结果进行缓存,减少对 Elasticsearch 的重复请求。
索引设计优化: 合理的索引 mapping 和分片策略可以提升整体检索性能,包括 Get API 的性能。
监控与调优: 定期监控 Elasticsearch 集群的性能指标,根据实际情况进行调优,确保 Get API 的高效运行。
Get API 是 Elasticsearch 文档管理中不可或缺的组成部分。它提供了简单而强大的文档检索能力,通过丰富的参数可以灵活控制检索行为和返回结果。
在实际应用中,根据具体的业务场景和需求,灵活运用 Get API 的各种参数,并结合性能优化策略,才能充分发挥 Elasticsearch 的强大功能。