connection.useDb 复用现有连接池,仅切换逻辑数据库上下文;需配合 db.model() 重绑定模型、合理缓存租户 db 实例,并确保主连接含正确 authSource,否则易导致数据写入错误库或认证失败。
connection.useDb 不会新建 TCP 连接,而是复用底层 Mongoose 实例已建立的连接池,只切换逻辑数据库上下文。这意味着它轻量、快速,但前提是目标数据库在同一个 MongoDB 实例上——跨实例或带认证差异时无效。
常见错误现象:调用 useDb 后模型操作仍写入原库,或抛出 Authentication failed。原因通常是目标库启用了独立用户权限,而原始连接没带对应 authSource 或凭据。
?authSource=admin(或对应鉴权库)useDb 时传 { useCache: true, auth: { user, pass } }
useDb 并立刻丢弃返回的 db 对象,容易导致缓存膨胀多租户场景下,useDb 是常用手段,但必须配合缓存和生命周期管理,否则会泄漏数据库引用、耗尽内存。
使用场景:SaaS 应用中,每个租户一个数据库,路由中间件根据 tenantId 动态绑定模型。
db 实例,键为租户 ID,避免重复 useDb 调用useDb 结果赋给全局 mongoose.connection,这会污染所有后续操作db.model() 显式创建(或重载),不能复用默认连接上的模型const tenantDb = mongoose.connection.useDb(tenantId, { useCache: true });<br>const TenantUser = tenantDb.model('User', userSchema);
可以,useDb 返回的是标准 MongoDB Node.js Driver 的 Db 实例,支持 db.collection().findOne()、db.adminCommand() 等原生操作,但要注意它不继承 Mongoose 中间件(如 pre-save 钩子)。
性能影响:原生命令绕过 Mongoose 封装,更快;但失去 schema 校验、类型转换、中间件等能力,适合批量导入、诊断查询等场景。
db.s.databaseName 是否为目标库名,防止误操作db.command({ listCollections: 1 }) 可验证当前上下文是否生效useDb 和原生命令——Mongoose 事务不跨 Db 实例最常见原因是模型未绑定到正确的 db,仍在用默认连接的模型实例。Mongoose 模型与连接强绑定,useDb 不会自动迁移已有模型。
容易被忽略的地方:开发者常以为“切换了 connection 就等于切换了所有模型”,其实不是。
useDb 后,必须用返回的 db 重新获取或定义模型:db.model('Post', postSchema)
schema.pre('save') 等钩子只在该 db.model() 实例上注册Model.db.name 和 Model.collection.db.s.databaseName,确认一致db 实例。漏掉一次 db.model() 重绑定,就可能让数据悄悄写进错误的库。