如何对MongoDB嵌套文档执行聚合查询以计算各特征累计得分?
MongoDB多task嵌套特征聚合实现方案
固定结构适配版(匹配当前文档格式)
你当前的文档结构固定为3个task字段、每个task下包含Humor/Spirituality/Fairness三个特征,使用简化硬编码的聚合管道运行效率最高,核心逻辑为先在单文档内对同一特征跨task求和,再跨相同user的所有文档累加总得分。
聚合命令示例:
// 替换下方的your_collection为你实际的集合名称 db.your_collection.aggregate([ { $group: { // 以user字段为分组依据 _id: "$user", // 单文档内累加3个task的同特征值,跨文档自动求和 Humor: { $sum: { $add: ["$task1.Humor", "$task2.Humor", "$task3.Humor"] } }, Spirituality: { $sum: { $add: ["$task1.Spirituality", "$task2.Spirituality", "$task3.Spirituality"] } }, Fairness: { $sum: { $add: ["$task1.Fairness", "$task2.Fairness", "$task3.Fairness"] } } } }, { // 调整输出结构,去掉默认分组生成的_id字段,映射为要求的user字段 $project: { _id: 0, user: "$_id", Humor: 1, Spirituality: 1, Fairness: 1 } } ])
运行上述命令得到的输出和你期望的格式完全一致:
{ "user" : 123, "Humor" : 0, "Spirituality" : 6, "Fairness" : 0 }
动态扩展适配版
如果后续会新增更多task(如task4、task5)或者每个task下新增其他特征,不需要修改管道代码,使用动态字段解析的方式完成聚合,适配结构变化的场景。
聚合命令示例:
db.your_collection.aggregate([ // 筛选出所有以task开头的字段,排除_id/user这类无关字段 { $project: { user: 1, taskList: { $filter: { input: { $objectToArray: "$$ROOT" }, cond: { $regexMatch: { input: "$$this.k", regex: /^task\d+$/ } } } } } }, // 展开所有task条目,为后续逐特征计算做准备 { $unwind: "$taskList" }, // 将每个task下的嵌套特征对象转换为键值对列表 { $project: { user: 1, featureList: { $objectToArray: "$taskList.v" } } }, // 展开所有特征条目 { $unwind: "$featureList" }, // 按user+特征名分组,累加所有匹配条目的得分 { $group: { _id: { user: "$user", featureName: "$featureList.k" }, totalScore: { $sum: "$featureList.v" } } }, // 按user重新聚合,将每个特征的得分整理为键值对格式 { $group: { _id: "$_id.user", featureKV: { $push: { k: "$_id.featureName", v: "$totalScore" } } } }, // 合并为最终要求的输出结构 { $replaceRoot: { newRoot: { $mergeObjects: [ { user: "$_id" }, { $arrayToObject: "$featureKV" } ] } } } ])
内容的提问来源于stack exchange,提问作者Moeed Lodhi
相关产品推荐
相关产品推荐

