同_id不同_routing值文档存同一分片为何仅返回一个?
问题解析:同ID不同Routing的文档落入同分片后仅返回一个的原因
核心原因
Elasticsearch的分片内部是通过_id来唯一标识文档的——即便_routing不同,只要同一分片内的文档_id重复,后写入的文档会直接覆盖先写入的。这是分片级别的文档处理逻辑,和_routing的分片路由规则是两个独立机制:
_routing仅负责计算文档要落入哪个分片;- 分片内部则以
_id作为主键,重复_id的写入操作会被当作对原有文档的更新(默认op_type为index,会直接覆盖)。
结合你的场景分析
你计算得出两个文档都落入分片1,此时:
- 先写入的
_id相同、_routing=user1的文档会被存储在分片1; - 后写入的
_id相同、_routing=user2的文档,因同样落入分片1且_id重复,会直接覆盖分片1中已有的同_id文档; - 最终分片1中仅保留最后写入的
_routing=user2的文档,所以查询只会返回这一个结果。
验证方式
可通过指定_routing查询验证:
- 查询时指定
routing=user1,Elasticsearch会路由到分片1,但分片1中已无_routing=user1的文档(已被覆盖),返回空结果; - 查询时指定
routing=user2,会正常返回目标文档; - 不指定
routing查询时,Elasticsearch会广播查询到所有分片,最终也只会返回分片1中保留的那一个文档。
如何保留同ID不同Routing的文档
若需保留多个_id相同但_routing不同的文档,需确保文档标识在分片内唯一,可通过以下方式实现:
- 自定义
_id:将_id设置为原ID + _routing的组合(如docId-user1、docId-user2),保证分片内_id不重复; - 隔离索引:将不同
_routing的文档写入不同索引,从索引层面实现隔离。
内容的提问来源于stack exchange,提问作者Bilal Munawar
相关产品推荐
相关产品推荐

