上一篇【第13篇】 Elasticsearch索引API深度解析下一篇【第15篇】 Elasticsearch删除与更新API摘要文档检索是Elasticsearch中最频繁的操作之一。本文详细介绍了Elasticsearch文档检索API的完整用法包括GET API基本用法与响应结构深入解析_index、_id、_version、_source等关键字段、实时性配置realtime参数控制是否立即刷新可见、字段选择策略_source的includes/excludes过滤与stored_fields指定存储字段、直接获取_source轻量级文档源数据读取、路由参数与preference参数副本选择与本地化读取优化以及MGet批量获取多文档批量读取的高效模式。掌握这些内容能帮助你在实际应用中灵活选择最优的数据读取方式兼顾功能需求与性能开销。一、GET API基本用法1.1 基本读取GET API允许根据文档ID从索引中获取JSON文档。这是最简单的文档读取方式GETtwitter/_doc/1响应结构如下{_index:twitter,_type:_doc,_id:1,_version:1,_seq_no:0,_primary_term:1,found:true,_source:{user:kimchy,post_date:2009-11-15T14:12:12,message:Trying out Elasticsearch}}响应中关键字段的含义字段说明_index文档所属的索引名称_type文档类型7.x后固定为_doc_id文档唯一标识符_version文档版本号每次更新递增_seq_no操作序列号用于乐观并发控制_primary_term主分片任期号与_seq_no配合使用found是否找到文档true/false_source文档的原始JSON内容1.2 检查文档是否存在使用HEAD方法可以高效地检查文档是否存在不返回文档内容HEADtwitter/_doc/1如果文档存在返回HTTP 200不存在则返回404。这种方式比GET API更轻量适用于只需确认文档存在性的场景。1.3 文档不存在时的响应当请求的文档ID不存在时{_index:twitter,_type:_doc,_id:999,found:false}二、实时性配置2.1 默认实时读取默认情况下GET API是实时的realtimetrue不受索引刷新频率的影响。如果文档已更新但尚未刷新refreshGET API会在适当时机发出刷新调用使文档可见。这意味着即使在1秒的默认刷新间隔内GET API也能获取到最新数据。这种实时性也使得上次刷新后更改的其他文档一并可见。2.2 禁用实时读取如果不需要实时读取可以将realtime参数设置为falseGETtwitter/_doc/1?realtimefalse禁用实时性后GET API只返回已刷新的数据可能无法获取最新写入的文档。这适用于对数据实时性要求不高但对读取性能要求较高的场景。2.3 实时性参数对比realtime值行为适用场景true默认即时可见必要时触发刷新需要读取最新数据false仅返回已刷新的数据批量处理、报表生成注意将refresh参数设置为true可以在GET操作之前强制刷新相关分片。但应慎重考虑因为这可能导致系统负载过重并减慢索引速度。三、字段选择策略3.1 关闭_source返回默认情况下GET API返回_source的完整内容。对于大文档或不需完整内容的场景可以关闭_source检索GETtwitter/_doc/1?_sourcefalse响应将不包含_source字段只返回元数据信息{_index:twitter,_type:_doc,_id:1,_version:1,found:true}3.2 _source字段过滤includes/excludes如果只需要完整_source中的部分字段可以使用_source_includes和_source_excludes参数包含特定字段GETtwitter/_doc/1?_source_includes*.id,retweeted排除特定字段GETtwitter/_doc/1?_source_excludesentities组合使用GETtwitter/_doc/1?_source_includes*.id_source_excludesentities两个参数都支持逗号分隔的字段列表和通配符表达式。简写形式如果只需要指定 include可以使用较短的_source参数GETtwitter/_doc/1?_source*.id,retweeted3.3 stored_fields指定存储字段对于映射中设置了store: true的字段可以通过stored_fields参数指定返回这些存储字段首先建立映射PUTtwitter{mappings:{properties:{counter:{type:integer,store:true},tags:{type:keyword,store:true}}}}索引数据后检索指定的存储字段GETtwitter/_doc/1?stored_fieldstags,counter响应如下{_index:twitter,_type:_doc,_id:1,_version:1,found:true,fields:{counter:[1],tags:[red]}}注意只有叶字段可以通过stored_fields返回不能返回对象字段。3.4 字段选择方式对比方式参数适用场景性能完整_source无参数需要全部文档内容低传输量大_source过滤_source_includes/_source_excludes只需部分字段中关闭_source_sourcefalse只需元数据高存储字段stored_fields需要store字段不加载_source高四、直接获取_source4.1 基本用法可以使用/_source/端点仅获取文档的源数据而不返回任何元数据GETtwitter/_source/1响应直接返回文档的JSON内容{user:kimchy,post_date:2009-11-15T14:12:12,message:Trying out Elasticsearch}4.2 结合源过滤同样可以使用_source_includes和_source_excludes来控制返回的内容GETtwitter/_source/1?_source_includes*.id_source_excludesentities4.3 检查_source是否存在使用HEAD方法可以高效地检查文档的_source是否存在HEADtwitter/_source/1如果映射中禁用了_source该文档将没有_sourceHEAD请求将返回404。4.4 GET API vs 直接获取_source特性GET /index/_doc/idGET /index/_source/id返回内容完整元数据 _source仅_source包含_version是否包含_seq_no是否网络开销较大较小适用场景需要版本信息仅需文档数据五、路由参数5.1 路由参数的使用如果在索引文档时使用了自定义路由参数读取时也应指定相同的路由值。虽然不指定也能读取到数据但会降低性能因为Elasticsearch需要在所有分片上搜索。GETtwitter/_doc/2?routinguser1指定路由后GET请求会直接路由到包含该文档的分片避免在全部分片上进行广播查找显著提高读取效率。5.2 路由对性能的影响操作方式搜索范围性能指定路由仅目标分片高不指定路由所有分片低六、preference参数6.1 参数说明preference参数控制优先从哪个分片副本获取数据。默认情况下Elasticsearch使用自适应副本选择机制综合考虑以下因素选择最佳副本协调节点与数据节点之间的响应时间节点上执行过去搜索请求的时间节点上搜索线程池的队列大小6.2 常用配置值GETtwitter/_doc/1?preference_localpreference值行为适用场景默认不指定自适应副本选择通用场景_local优先选择本地分片减少网络开销_only_local仅在本地节点分片执行严格本地化_prefer_nodes:abc,xyz优先在指定节点执行节点亲和性_shards:2,3限制到指定分片分片级别调试最佳实践生产环境中最常用的是_local它可以减少不必要的网络传输提升读取性能。七、MGet批量获取7.1 基本用法MGet API_mget允许在单次请求中获取多个文档避免多次网络往返。它基于索引、ID可能还有路由返回多个文档。GET_mget{docs:[{_index:twitter,_id:1},{_index:twitter,_id:2}]}响应包含一个docs数组每个元素对应一个文档的获取结果包括成功的文档和失败的错误信息{docs:[{_index:twitter,_type:_doc,_id:1,_version:1,_seq_no:0,_primary_term:1,found:true,_source:{user:kimchy,message:Trying out Elasticsearch}},{_index:twitter,_type:_doc,_id:2,found:false}]}7.2 指定索引后简化请求如果所有文档都在同一个索引中可以在URL中指定索引GETtwitter/_mget{docs:[{_id:1},{_id:2}]}7.3 使用ids简写如果不需要为每个文档单独设置参数可以使用ids进一步简化GETtwitter/_mget{ids:[1,2]}7.4 MGet的_source过滤与GET API类似MGet也支持_source过滤可以全局设置或为每个文档单独设置全局设置GETtwitter/_mget{_source:[user,message],ids:[1,2]}为每个文档单独设置GET_mget{docs:[{_index:twitter,_id:1,_source:[user]},{_index:twitter,_id:2,_source:{includes:[message],excludes:[entities]}}]}7.5 MGet的stored_fields可以为每个文档指定检索特定的存储字段GETtwitter/_mget{docs:[{_id:1,stored_fields:[tags,counter]},{_id:2,stored_fields:[tags]}]}也可以在查询字符串中设置默认值应用于所有文档GETtwitter/_mget?stored_fieldstags,counter{ids:[1,2]}7.6 MGet的路由参数可以为每个文档指定路由值GET_mget{docs:[{_index:test,_id:1,routing:key1},{_index:test,_id:2,routing:key2}]}7.7 GET vs MGet性能对比特性GET APIMGet API获取文档数单个多个网络往返次数N次1次请求开销较高多次连接较低单次连接适用场景获取单个文档批量获取多个文档错误隔离请求级别文档级别互不影响八、总结与最佳实践8.1 核心要点回顾GET API是单文档读取的基础接口响应包含完整的元数据和文档内容实时性默认开启保证数据读取的一致性非实时场景可关闭以提升性能字段选择是优化读取性能的关键手段_source过滤比完整传输更高效直接获取_source适用于不需要元数据、只需文档数据的轻量级场景路由参数可以将读取直接定向到目标分片显著提升带路由文档的读取性能MGet是批量获取的最佳选择将N次GET请求合并为一次大幅减少网络开销8.2 生产环境最佳实践字段过滤优先始终使用_source_includes只返回需要的字段避免传输大文档的完整内容批量操作优先需要获取多个文档时优先使用MGet而非多次GET善用路由如果索引时使用了自定义路由读取时务必指定路由以提升性能prefference_local在读取密集型场景中设置_local减少网络传输避免stored_fields除非有特殊需求否则优先使用_source过滤而非stored_fields因为store: true会增加索引体积上一篇【第13篇】 Elasticsearch索引API深度解析下一篇【第15篇】 Elasticsearch删除与更新API