点路径索引仅加速精确匹配子文档字段的查询,不支持嵌套文档全等匹配;多层数组路径会触发多键索引,禁用唯一约束;复合索引须遵循ESR原则;null和缺失字段默认被索引,sparse可排除缺失值。

直接用 db.collection.createIndex({ "a.b.c": 1 }) 就行,但必须清楚它只加速「精确匹配整个子文档路径」的查询,不是万能的。
点路径索引只对字段级查询生效,不支持子文档整体匹配
比如有文档 { _id: 1, user: { profile: { name: "Alice", age: 27 } } },建了 db.users.createIndex({ "user.profile.name": 1 }) 后:
-
db.users.find({ "user.profile.name": "Alice" })能走索引 ✅ -
db.users.find({ user: { profile: { name: "Alice", age: 27 } } })不能走索引 ❌(这是嵌套文档全等匹配,需建{ user: 1 }索引) -
db.users.find({ "user.profile": { name: "Alice" } })也不能走索引 ❌(user.profile是对象,不是点路径)
多层嵌套数组里的点路径索引会自动变成多键索引
当点路径最终指向数组元素(如 comments.replies.author),MongoDB 会隐式创建多键索引(multikey: true),这带来两个关键影响:
- 索引条目数 = 所有匹配文档中该路径下所有数组元素总数,可能远超文档数
- 无法在该字段上再建唯一索引(
unique: true会被拒绝) - 执行
explain()时注意"stage": "IXSCAN"下是否出现"multiKeyPaths"字段,确认是否触发多键行为
复合索引中点路径字段顺序必须严格遵循 ESR 原则
例如想加速 find({ "meta.status": "active", "meta.updatedAt": { $gt: ISODate(...) } }, { sort: { "meta.score": -1 } }),索引必须是:
db.items.createIndex({ "meta.status": 1, "meta.updatedAt": 1, "meta.score": -1 })
不能把 "meta.score" 放前面,也不能把范围条件 "meta.updatedAt" 放在等值条件 "meta.status" 前面 —— 否则排序或范围部分无法被索引覆盖。
空值、缺失字段和 null 值在点路径索引中的行为容易被忽略
如果文档里压根没有 user.profile.name 字段,或它的值是 null,MongoDB 仍会在索引中存一条 null 条目(除非显式加 sparse: true):
- 这意味着
find({ "user.profile.name": null })也能命中索引 - 但
find({ "user.profile.name": { $exists: false } })不走索引,因为$exists不使用点路径索引 - 若只想索引非空值,加
{ sparse: true }选项,但要注意:稀疏索引不包含缺失字段的文档,查询结果可能不完整











