请教:this.query与this.query.find()的区别(MERN电商场景)
我正在跟随MERN教程搭建完整电商应用,以下是用于查询的FeaturesApi类及调用它的getallProducts控制器代码:
// FeaturesApi类 constructor(query, querystr) { this.query = query; this.querystr = querystr; console.log(this.querystr.keyword); } search() { const keyword = this.querystr.keyword ? { name: { $regex: this.querystr.keyword, $options: "i", }, } : {}; this.query = this.query.find({ ...keyword }); return this; } export default FeaturesApi;
// getallProducts控制器 export const getallProducts = catchAsyncerror(async (req, res, next) => { const apifeature = new FeaturesApi(Product.find(), req.query).search(); const products = await FeaturesApi.query; if (!products) { return next(CustomError.noProducts); } res.status(200).json({ message: "Products found", products }); return next(CustomError); });
我的疑问是:this.query传入的是Product.find(),那this.query.find()是否等同于Product.find().find()?想请教二者的区别及我的理解误区。
解答
是的,this.query.find()在这里确实等同于Product.find().find(),但背后的逻辑需要理清:
Query对象的本质
Product.find()返回的是一个未执行的MongoDB Query实例,它不会立刻向数据库发送请求,只是用来构建查询条件。Query对象的所有方法(包括find())都会返回自身实例,以此支持链式调用。多次
find()的作用
当你在一个Query实例上再次调用find(additionalConditions)时,MongoDB会把新传入的条件和已有的查询条件做逻辑与(AND)合并,而不是重新发起查询或者覆盖原有条件。比如:// 这两行代码的最终查询效果完全一致 Product.find().find({name: {$regex: "shirt", $options: "i"}}) Product.find({name: {$regex: "shirt", $options: "i"}})你的理解误区
你可能误以为多次调用find()会重复执行数据库查询,但实际上Query是延迟执行的——只有当你通过await、exec()等方法触发时,才会真正向数据库发送请求,链式调用的find()只是在不断叠加查询规则。
另外,你的控制器代码存在一处错误:const products = await FeaturesApi.query;应该改为const products = await apifeature.query;,因为FeaturesApi是类本身,apifeature才是你创建的实例,你现在访问的是类的静态属性,而非实例的query属性,这会导致获取不到正确的查询结果。
内容的提问来源于stack exchange,提问作者Vaikruta

