mongoose 6.x 中 index: true 仅记录索引定义,不会自动创建;需显式调用 syncindexes() 才能落地,且要求连接已建立、集合已存在。

为什么 index: true 在 Mongoose 6.x 中可能没生效
默认情况下,Mongoose 不会自动在 MongoDB 中创建索引,即使你在 Schema 字段上写了 index: true。它只是把索引定义“记下来”,真正建索引要靠显式调用 mongoose.connect() 后的 await mongoose.connection.db.collection(...).createIndex(),或者更常用的方式:触发 ensureIndexes()(已弃用)或改用 syncIndexes()。
常见错误现象是:查询依然慢、explain() 显示 stage: "COLLSCAN"、MongoDB Compass 里看不到对应索引。
-
index: true只影响该字段的单字段升序索引;复合索引必须用schema.index({ fieldA: 1, fieldB: -1 }) - Mongoose 6.0+ 已移除
ensureIndexes()的自动调用,也不会在connect()后静默创建 - 如果连接时数据库不存在,索引创建会失败——得等集合首次写入后才能建(因为 MongoDB 要求集合存在)
如何让 Schema 中的 index 配置真正落地
最稳妥的做法是在应用启动完成连接后,主动同步索引。Mongoose 6.1+ 推荐使用 syncIndexes(),它会比对 Schema 定义和 DB 实际索引,只创建缺失的、删除多余的(需开启 dropDups 配置)。
示例代码:
await mongoose.connect('mongodb://localhost:27017/myapp');
// 确保所有 model 的 index 定义被加载(比如 require('./models/User'))
await User.syncIndexes(); // 返回 { nIndexesWas: X, nIndexes: Y }
- 必须在
connect()成功之后调用,否则报Connection is not yet open - 如果多个 model 共享同名索引(如都定义了
{ email: 1 }),syncIndexes()会去重,但不保证哪个 model 的选项(如unique)最终生效 - 生产环境建议加
try/catch并记录日志,索引创建失败不会中断服务,但会影响后续查询性能
background: true 和 unique: true 的实际影响
在字段上写 index: { unique: true, background: true } 看似合理,但要注意:Mongoose 会把整个对象当索引选项透传给 MongoDB,而 background 是创建索引时的行为控制,不是索引结构的一部分;unique 则直接影响数据写入逻辑。
-
background: true能避免建索引阻塞读写,但会延长创建时间;线上集合数据量大时务必加,否则syncIndexes()可能卡住几秒到几分钟 -
unique: true会让 MongoDB 拒绝重复值插入,但注意:已有重复数据的集合上调用syncIndexes()会直接失败,报E11000 duplicate key error - 稀疏索引(
sparse: true)适合有大量null或缺失字段的场景,能减小索引体积,但查询时{ field: null }不会命中稀疏索引
验证索引是否生效的三个关键动作
光看 Schema 写了 index 不算数,必须确认 MongoDB 层面真实存在且被查询计划采用。
- 在 MongoDB Shell 或 Compass 中运行
db.users.getIndexes(),检查输出里是否有你定义的键和选项(如{ email: 1 }) - 用
db.users.find({ email: 'a@b.c' }).explain('executionStats'),确认executionStages.stage === 'IXSCAN'且nReturned接近预期 - 如果用了聚合管道,注意
$lookup或$facet可能无法利用外层定义的索引——得在$match阶段前置,且字段需在 pipeline 起始就可用
最容易被忽略的是:开发时用 dropDatabase() 清库后,忘记重新 syncIndexes();或者用 mongoose.model('User', schema, 'users') 指定了 collection 名,但索引定义在另一个 model 上——Mongoose 不会跨 model 合并索引。











