Mongoose Category模型添加关联Product虚拟字段报错及空结果问询
问题1报错修复
你出现TypeError: Cannot use 'in' operator to search for 'transform' in true的原因是Schema配置项中toJSON、toObject的取值错误,不能直接赋值为true,需要传入配置对象,若要虚拟字段正常序列化返回,还需要开启virtuals: true属性。
问题2关联查询无结果修复
你当前$lookup的关联字段写反,同时虚拟字段getter的实现逻辑存在三处错误:
- 不能直接调用Schema的
aggregate方法,需要调用Model的方法 - 关联逻辑颠倒:Category集合的
_id对应Product集合的category字段,所以localField应该是Category的_id,foreignField是Product的category - Mongoose虚拟字段默认不支持异步getter的结果序列化,如果你需要统计分类下的商品数量,更推荐使用Mongoose内置的虚拟关联配置实现,比手写聚合逻辑更稳定
修复后完整代码
// PRODUCT MODEL 无需修改 const productSchema = new mongoose.Schema( { category: { type: mongoose.Schema.Types.ObjectId, ref: "Category", }, name: { type: String, required: true, }, price: { type: Number, required: true, default: 0, }, colors: [ { type: mongoose.Schema.Types.ObjectId, ref: "Color", }, ], sizes: { type: Array, default: [ { id: 1, size: "XS" }, { id: 2, size: "S" }, { id: 3, size: "M" }, { id: 4, size: "L" }, { id: 5, size: "XL" }, { id: 6, size: "XXL" }, ], }, }, { timestamps: true } ); const Product = mongoose.model("Product", productSchema); export default Product; // CATEGORY MODEL 修复后代码 const CategorySchema = new mongoose.Schema( { name: String, }, { timestamps: true, // 修复toJSON/toObject配置,开启虚拟字段序列化 toJSON: { virtuals: true }, toObject: { virtuals: true } } ); // 配置count虚拟字段,直接返回对应分类的商品数量 CategorySchema.virtual("count", { ref: "Product", localField: "_id", foreignField: "category", count: true // 开启后直接返回匹配数量,不会返回完整商品列表 }); // 可选:配置items虚拟字段,返回对应分类的完整商品列表 CategorySchema.virtual("items", { ref: "Product", localField: "_id", foreignField: "category", }); const Category = mongoose.model("Category", CategorySchema); export default Category;
使用示例
查询时需要手动populate虚拟字段才能拿到对应值:
// 查询所有分类同时返回每个分类的商品数量 const categories = await Category.find().populate('count'); // 查询所有分类同时返回每个分类的商品列表+数量 const categoriesWithProducts = await Category.find().populate('count').populate('items');
内容的提问来源于stack exchange,提问作者john otor
相关产品推荐
相关产品推荐

