Mongoose查询后先await调用map与链式调用map的差异问题
Mongoose两种查询写法差异原因
核心差异来自运算符优先级和Mongoose查询对象的特殊设计两方面:
- Mongoose的
find()、populate()都不属于真正执行查询的方法,调用后返回的是Mongoose Query(查询构建器实例),而非查询结果数组。只有对这个实例执行await或调用.exec()时,才会真正发起数据库请求,返回最终的文档数组。 - JavaScript中成员访问运算符(
.)的优先级远高于await,两种写法的执行顺序完全不同:
正常写法的执行逻辑
let responses = await Response.find({ responder_id: req.user._id, }).populate({ path: "query_id", select: ["query_type", "content"] }); responses = responses.map((response) => { return response.query_id; });
await作用于整个find+populate查询链,等待查询执行完成后,拿到填充后的普通文档数组赋值给responses- 对已经拿到的数组调用JS原生
Array.map()方法遍历提取属性,结果符合预期。
异常写法的执行逻辑
let responses = await Response.find({ responder_id: req.user._id, }) .populate({ path: "query_id", select: ["query_type", "content"] }) .map((response) => { return response.query_id; });
- 因为
.优先级更高,会先依次执行find()、populate(),拿到Query实例后,直接在Query实例上调用map(),而非在查询结果数组上调用 - 低版本Mongoose没有提供
Query.prototype.map方法,此时会直接抛出map is not a function的类型错误;即使是高版本支持该方法,Query的map是用来给查询注册全局转换逻辑的内置方法,和原生数组map的行为完全不同,自然得不到你预期的结果。
最佳实践
涉及查询结果的转换操作,统一先await拿到完整的结果数组后再处理,避免和Mongoose查询构建器的链式方法产生混淆。
内容的提问来源于stack exchange,提问作者Bear Bile Farming is Torture
相关产品推荐
相关产品推荐

