MongoDB如何按ID匹配合并两个数组的对应字段值
问题原因
你之前写的聚合语句无法生效,核心问题有4个:
- 字段名写错:你操作的
licenses.activities字段在现有文档中不存在,实际需要修改的是users数组下的内容 - 缺少关联匹配逻辑:直接引用
$activeUsersLookup.users.activities只会返回嵌套的全量活动数二维数组,不会按照用户_id做一一对应匹配 - 没有默认值处理:不会给无活动记录的用户自动填充
activities: 0 - 没有冗余字段清理、活动数求和的相关逻辑
正确聚合管道
以下管道可以实现你要的全部效果,默认输出规范结构(sumOfActivities放在文档顶层):
db.你的实际集合名.aggregate([ // 1. 提取和当前文档_id匹配的lookup结果,去掉外层无用数组包装 { $addFields: { activeUserData: { $arrayElemAt: [ { $filter: { input: "$activeUsersLookup", cond: { $eq: ["$$this._id", "$_id"] } } }, 0 ] } } }, // 2. 遍历顶层users数组,给每个用户合并匹配到的activities字段,无匹配记录则默认设为0 { $addFields: { users: { $map: { input: "$users", as: "user", in: { $mergeObjects: [ "$$user", { activities: { $let: { vars: { matchedUser: { $arrayElemAt: [ { $filter: { input: "$activeUserData.users", cond: { $eq: ["$$this._id", "$$user._id"] } } }, 0 ] } }, in: { $ifNull: ["$$matchedUser.activities", 0] } } } } ] } } } } }, // 3. 对所有用户的activities值求和得到总活动数 { $addFields: { sumOfActivities: { $sum: "$users.activities" } } }, // 4. 删除冗余的临时字段和原lookup字段 { $unset: ["activeUsersLookup", "activeUserData"] } ])
特殊结构调整说明
你给出的期望示例里把sumOfActivities放在了users数组内部,这个结构不推荐(数组内混合存储用户对象和统计值,会提升后续查询、更新的复杂度),如果确实需要输出该结构,把上面第3步的stage替换为以下代码即可:
{ $addFields: { users: { $concatArrays: [ "$users", [{ sumOfActivities: { $sum: "$users.activities" } }] ] } } }
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

