如何在MongoDB聚合中实现评分分组计数?技术求助
解决MongoDB聚合统计产品评分数量的问题
我来帮你调整聚合管道,实现你想要的按评分值统计数量的输出格式:
完整的聚合管道
[ // 关联stores集合,获取店铺信息 { $lookup: { from: "stores", localField: "store", foreignField: "_id", as: "store" } }, // 将store数组转换为单个对象(每个产品对应唯一店铺) { $addFields: { store: { $first: "$store" } } }, // 关联products_comment集合,获取所有关联评论 { $lookup: { from: "products_comment", localField: "comment", foreignField: "_id", as: "comment" } }, // 展开评论数组,同时保留无评论的产品 { $unwind: { path: "$comment", preserveNullAndEmptyArrays: true } }, // 按产品分组,统计每个评分的出现次数 { $group: { _id: "$_id", media: { $first: "$media" }, store: { $first: "$store" }, meta: { $first: { title: "$meta.title", price: "$meta.price" } }, // 收集评分对应的键值对,格式为{k: "x_rating", v: 1} ratingEntries: { $push: { k: { $concat: [ { $toString: "$comment.rating" }, "_rating" ] }, v: 1 } } } }, // 将评分条目转为对象,并补全1-5星的默认值(0) { $addFields: { comment: { $mergeObjects: [ { "1_rating": 0, "2_rating": 0, "3_rating": 0, "4_rating": 0, "5_rating": 0 }, { $arrayToObject: { $filter: { input: "$ratingEntries", cond: { $ne: [ "$$this.k", "_rating" ] } } } } ] } } }, // 整理最终输出字段,移除临时数据 { $project: { media: 1, store: { type: 1, "profile.address.city": 1 }, meta: 1, comment: 1 } } ]
关键步骤说明
- 处理店铺关联结果:用
$first把lookup返回的店铺数组转成单个对象,匹配你期望的store结构。 - 兼容无评论场景:
$unwind添加preserveNullAndEmptyArrays: true,确保没有评论的产品不会被过滤掉。 - 收集评分统计条目:在分组阶段把每个评论的评分转换为
x_rating的键名,为后续转对象做准备。 - 补全缺失评分:用
$mergeObjects将统计结果和包含1-5星默认值(0)的对象合并,避免出现评分字段缺失的情况。 - 过滤无效数据:如果产品无评论,
$unwind会产生空值,用$filter过滤掉键为_rating的无效条目。
输出示例
基于你提供的测试数据,运行管道后会得到类似结果:
{ "_id": "5cc570257631a313d489ba4a", "media": [ "httpsdssd", "dfdfd" ], "store": { "type": "craft", "profile": { "address": { "city": "Padang" } } }, "meta": { "title": "Traveling Sumbar", "price": "150000" }, "comment": { "1_rating": 0, "2_rating": 0, "3_rating": 1, "4_rating": 2, "5_rating": 0 } }
内容的提问来源于stack exchange,提问作者Ardy Febriansyah
相关产品推荐
相关产品推荐

