Mongoose价格筛选时出现Query was already executed错误如何解决?
错误原因
该报错是Mongoose v6+ 版本的特性限制导致的:同一个Mongoose Query实例仅允许被执行一次,你在代码中对同一个查询实例做了两次执行操作:
- 调用
search()、filter()构造完查询条件后,你直接执行await apiFeatures.query,此时查询请求已经发送到MongoDB执行,该Query实例被标记为已完成状态 - 后续你又调用
pagination()方法修改了同一个Query实例的配置,再次执行await apiFeatures.query,就触发了「查询已被执行」的报错。
另外你提供的后端代码还存在一个语法问题:getProducts方法内使用了await关键字,但函数没有声明async,也会导致运行异常。
解决方案
最合理的修复方式是克隆查询实例用来统计过滤后的商品数量,避免修改主查询的状态,同时优化统计逻辑的性能,修改后的代码如下:
// 补充async关键字 exports.getProducts = async (req, res, next) => { const resPerPage = 4; const productsCount = await Product.countDocuments(); const apiFeatures = new APIFeatures(Product.find(), req.query) .search() .filter(); // 克隆独立的查询实例统计过滤后的总数,不影响主查询 const countQuery = apiFeatures.query.clone(); const filteredProductsCount = await countQuery.countDocuments(); // 主查询添加分页规则后仅执行一次 apiFeatures.pagination(resPerPage); const products = await apiFeatures.query; res.status(200).json({ success: true, productsCount, resPerPage, filteredProductsCount, products, }); };
优化说明
- 用
clone()方法复制未执行的查询实例,两个实例独立运行互不干扰 - 用
countDocuments()统计数量替代查询全量数据后取length,大幅降低大数量级下的接口性能损耗 - 补充了函数缺失的
async关键字,修复语法错误
内容的提问来源于stack exchange,提问作者Shankar Ghimire
相关产品推荐
相关产品推荐

