MongoDB含$elemMatch的子文档数组查询是否使用复合索引全部深度及判断依据
MongoDB含$elemMatch的子文档数组查询是否使用复合索引全部深度及判断依据
嘿,这个问题我来给你捋清楚~ 结论先放前面:你的这个查询确实用到了复合索引的全部字段(tar.a和tar.b),并非只使用第一个字段。
下面给你拆解判断的关键依据,都来自你提供的explain()输出:
1. 索引扫描阶段的indexBounds字段
看winningPlan.inputStage.indexBounds这部分:
"indexBounds": { "tar.a": ["[3.0, 3.0]"], "tar.b": ["[1.0, 1.0]"] }
这里明确显示,MongoDB在执行索引扫描(IXSCAN阶段)时,同时对tar.a和tar.b两个字段设置了精确匹配的范围(都是等于指定值的闭区间)。这就意味着索引的两个字段都被用来缩小扫描范围,而不是只靠tar.a过滤后再在内存里筛选tar.b。
2. 解析后的查询条件parsedQuery
再看queryPlanner.parsedQuery:
"parsedQuery": { "tar": { "$elemMatch": { "$and": [ { "a": { "$eq": 3 } }, { "b": { "$eq": 1 } } ] } } }
这里查询解析器正确识别了$elemMatch需要同一个子文档同时满足a=3和b=1的条件,这种情况下复合索引的多字段能够被有效利用——因为MongoDB的复合索引针对数组子文档的设计,支持匹配同一子文档的多字段条件。
3. 执行计划的阶段结构
整个winningPlan的流程是IXSCAN(索引扫描)→ FETCH(获取文档),而且FETCH阶段的过滤器只是再次确认$elemMatch的条件(因为索引已经精准匹配了两个字段,这个过滤的开销极低)。如果只用到了索引的第一个字段,indexBounds里只会出现tar.a的范围,tar.b不会有精确的区间限制,后续可能需要在FETCH阶段做大量过滤。
总结一下:只要indexBounds里列出了复合索引的所有字段的有效范围,就说明整个复合索引的深度都被利用上了。
内容来源于stack exchange
相关产品推荐
相关产品推荐

