MongoDB聚合阶段如何按颜色名称去重生成唯一颜色数组?
MongoDB聚合按颜色名称去重实现方案
当然可以实现按颜色名称唯一保留的颜色集合。由于$combinations.color是包含name和value的对象,直接用$addToSet会按整个对象内容去重,而你需要按name字段去重,这里提供两种可行方案:
方案一:先展开数组再分组去重
适合数据量不大的场景,步骤清晰:
- 先用
$unwind展开combinations数组,让每个颜色对象单独成为一条记录 - 按颜色的
name字段分组,保留唯一的颜色对象(用$first取第一个出现的即可,假设同名称颜色的value一致) - 最后全局分组汇总所有需要的字段
[ // 展开combinations数组 { $unwind: "$combinations" }, // 按颜色name分组,去重颜色并收集其他字段 { $group: { _id: "$combinations.color.name", color: { $first: "$combinations.color" }, sizes: { $addToSet: "$combinations.size" }, brands: { $addToSet: { $cond: [{ $eq: ["$brand", ""] }, "$$REMOVE", "$brand"] } }, prices: { $push: `$price.${req.query.reg || 'aud'}` } } }, // 全局分组汇总所有字段 { $group: { _id: null, sizes: { $addToSet: "$sizes" }, colors: { $push: "$color" }, brands: { $addToSet: "$brands" }, topPrice: { $max: { $max: "$prices" } }, bottomPrice: { $min: { $min: "$prices" } } } }, // 展开sizes和brands的嵌套数组 { $addFields: { sizes: { $reduce: { input: "$sizes", initialValue: [], in: { $setUnion: ["$$value", "$$this"] } } }, brands: { $reduce: { input: "$brands", initialValue: [], in: { $setUnion: ["$$value", "$$this"] } } } } } ]
方案二:原分组后处理数组去重
更简洁,无需调整原有分组结构,利用对象键的唯一性自动去重:
- 保留原
$group阶段的逻辑,用$push收集所有颜色对象 - 新增
$addFields阶段,将颜色数组转换为以name为键的对象,再转回数组,自动实现按name去重
[ { $group: { _id: null, sizes: { $addToSet: "$combinations.size" }, colors: { $push: "$combinations.color" }, brands: { $addToSet: { $cond: [{ $eq: ["$brand", ""] }, "$$REMOVE", "$brand"] } }, topPrice: { $max: `$price.${req.query.reg || 'aud'}` }, bottomPrice: { $min: `$price.${req.query.reg || 'aud'}` } } }, { $addFields: { colors: { $map: { input: { $objectToArray: { $arrayToObject: { $map: { input: "$colors", as: "c", in: { k: "$$c.name", v: "$$c" } } } } }, as: "item", in: "$$item.v" } } } } ]
注意:如果同一个name对应不同的value,方案二会保留最后一个出现的颜色对象,你可以根据需求调整$arrayToObject前的处理逻辑(比如用$first取第一个匹配项)。
内容的提问来源于stack exchange,提问作者Omar Bahutair
相关产品推荐
相关产品推荐

