MongoDB集合嵌套数组的条件更新查询需求
处理MongoDB嵌套动态键数组的更新需求
原始User集合数据
[ { "_id": "000-0000-0001", "Roles": { "0000-0000-0011": ["0000-0000-0111", "0000-0000-0112", "0000-0000-3333"], "0000-0000-0012": ["0000-0000-0121", "0000-0000-0112"] } }, { "_id": "000-0000-0002", "Roles": { "0000-0000-0021": ["0000-0000-0222", "0000-0000-0112"], "0000-0000-0022": ["0000-0000-0121", "0000-0000-0112"], "0000-0000-0022": ["0000-0000-0121", "0000-0000-0112", "0000-0000-3333"] } } ]
需求说明
针对Roles对象下的每个动态键(EngagementId)对应的RoleId数组,如果数组同时包含0000-0000-3333和0000-0000-0112,则移除其中的0000-0000-3333。
预期结果
[ { "_id": "000-0000-0001", "Roles": { "0000-0000-0011": ["0000-0000-0111", "0000-0000-0112"], "0000-0000-0012": ["0000-0000-0121", "0000-0000-0112"] } }, { "_id": "000-0000-0002", "Roles": { "0000-0000-0021": ["0000-0000-0222", "0000-0000-0112"], "0000-0000-0022": ["0000-0000-0121", "0000-0000-0112"], "0000-0000-0022": ["0000-0000-0121", "0000-0000-0112"] } } ]
解决方案
由于Roles的键是动态的(每个文档的EngagementId不固定),无法直接用普通的$pull操作,必须通过聚合管道来遍历处理每个动态键对应的数组:
db.User.updateMany( {}, [ { $set: { Roles: { $arrayToObject: { $map: { input: { $objectToArray: "$Roles" }, as: "roleEntry", in: { k: "$$roleEntry.k", v: { $cond: [ { $and: [ { $in: ["0000-0000-3333", "$$roleEntry.v"] }, { $in: ["0000-0000-0112", "$$roleEntry.v"] } ] }, { $pull: ["$$roleEntry.v", "0000-0000-3333"] }, "$$roleEntry.v" ] } } } } } } } ] )
代码解释
$objectToArray: "$Roles":把Roles对象转换成[{k: "EngagementId", v: ["RoleId1", ...]}]格式的数组,方便遍历处理每个动态键。$map:遍历转换后的数组,对每个键值对做判断和处理:- 用
$and和$in判断当前数组是否同时包含两个目标RoleId。 - 如果满足条件,用
$pull移除0000-0000-3333;否则保留原数组。
- 用
$arrayToObject:把处理后的键值对数组转回原来的对象结构,赋值给Roles字段。updateMany({}, [...]):对集合中所有文档执行这个更新操作。
内容的提问来源于stack exchange,提问作者ANURAG
相关产品推荐
相关产品推荐

