5月29日 01:08
Mongoose 查询构建器的链式方法和性能优化有哪些?
Mongoose 查询构建器支持两种写法:对象语法 User.find({ age: { $gte: 18 } }) 和链式语法 User.find().where('age').gte(18)。链式方法包括 .where() 设置字段、.gt()/.lt()/.gte()/.lte() 范围筛选、.in() 匹配数组、.sort() 排序、.limit().skip() 分页、.select() 投影字段、.populate() 关联填充。性能优化关键三点:.lean() 跳过文档封装返回纯 JS 对象,查询速度提升约 30%;.select() 只取必要字段减少传输量;确保查询字段有索引。链式调用时方法顺序不影响查询结果,但可读性上建议先筛选再排序分页。
追问
链式查询和对象查询能混用吗? 可以,两者等价,Mongoose 内部会将链式调用合并为同一个查询条件对象。但混用时不建议对同一字段既用对象又用链式,容易产生冲突。
lean() 返回的对象为什么不能调用 save()? lean() 跳过了 Mongoose 文档实例化,返回的是普通对象,没有 $__ 内部状态和实例方法。需要修改再保存时应去掉 lean()。
populate() 的性能问题怎么解决? populate 本质是额外查询,N 个文档关联会产生 N+1 次查询。替代方案:用 $lookup 聚合在数据库端完成关联,或手动批量查询减少往返次数。
如何调试慢查询? 开启 mongoose.set('debug', true) 打印实际查询语句,或对查询链调用 .explain('executionStats') 查看索引命中和扫描行数。
写段代码
javascriptconst users = await User.find({ status: 'active' }) .where('age').gte(18).lte(60) .sort({ createdAt: -1 }) .select('name email age') .populate('department', 'name') .lean() .limit(20);