MongoDB聚合查询实现产品按子分类名称分组的方法
参考实现代码
首先先对齐你的模型定义,方便你对应字段修改:
// 子分类模型定义 const subcategorySchema = new mongoose.Schema({ subcategoryName: String }) const SubcategoryModel = mongoose.model('Subcategory', subcategorySchema) // 产品模型定义 const productSchema = new mongoose.Schema({ product_name: String, description: String, price: Number, subcategory: { type: mongoose.Schema.Types.ObjectId, ref: 'Subcategory' } }) const ProductModel = mongoose.model('Product', productSchema)
直接在ProductModel上调用如下聚合查询即可:
const result = await ProductModel.aggregate([ // 1. 关联子分类集合,等价于populate填充subcategory字段 { $lookup: { from: 'subcategories', // 注意此处填MongoDB实际存储的集合名,默认是模型名小写加复数,自定义集合名需对应修改 localField: 'subcategory', foreignField: '_id', as: 'subcategory' } }, // 2. 拆分lookup返回的数组,单个产品对应唯一子分类,拆后subcategory为对象格式 { $unwind: '$subcategory' }, // 3. 按子分类名称分组,同分类产品存入数组 { $group: { _id: '$subcategory.subcategoryName', products: { $push: { // 自定义需要返回的产品字段,直接写$$ROOT则返回完整产品对象 product_name: '$product_name', description: '$description', price: '$price' } } } }, // 4. 转换为【子分类名: 产品数组】的键值对结构 { $replaceRoot: { newRoot: { $arrayToObject: [ [ { k: '$_id', v: '$products' } ] ] } } }, // 可选追加:如果需要合并为单个大对象而不是数组,新增下面两个阶段 // { // $group: { // _id: null, // allCategories: { $mergeObjects: '$$ROOT' } // } // }, // { // $replaceRoot: { newRoot: '$allCategories' } // } ])
输出示例
默认返回结构:
[ { "手机配件": [/* 该分类下所有产品对象 */] }, { "电脑外设": [/* 该分类下所有产品对象 */] } ]
追加可选阶段后返回单对象结构:
{ "手机配件": [/* 该分类下所有产品对象 */], "电脑外设": [/* 该分类下所有产品对象 */] }
注意事项
- 若存在产品未关联子分类的场景,可在
$unwind阶段添加preserveNullAndEmptyArrays: true保留这些产品,否则会被自动过滤 - 不需要返回填充后的subcategory字段的话,在
$push阶段明确指定要返回的产品字段即可
内容的提问来源于stack exchange,提问作者Taher
相关产品推荐
相关产品推荐

