MongoDB 3.4.1单查询更新users集合指定条件数组字段求助
针对MongoDB 3.4.1的批量数组更新方案
你的需求是在users集合中,批量更新符合特定过滤条件的文档里,userPreferences数组中不同pData.name对应的value值,正好MongoDB 3.4.1支持用聚合管道结合更新操作来实现这个需求,具体方案如下:
核心思路
我们需要同时完成两个目标:精准过滤需要更新的文档,以及对数组内的元素按条件分别修改。利用$map遍历数组元素,配合$cond做条件判断,再用$mergeObjects保留原字段的同时更新目标值,这样就能在单个查询里完成所有操作。
完整更新代码
db.users.update( // 过滤条件:匹配指定userId,且userPreferences包含指定pId的文档 { userId: { $in: ["00UPQAARGT7", "02UPQAARST7"] }, "userPreferences.pId": { $in: ["59SDS64675A00096D48CB","59SDS64675A00096D59DB"] } }, // 更新逻辑:用聚合管道处理数组元素 [ { $set: { userPreferences: { $map: { input: "$userPreferences", as: "prefItem", in: { // 合并原元素的所有字段,只修改pData部分 $mergeObjects: [ "$$prefItem", { pData: { // 嵌套判断,分别处理FORMAT和LAN的情况 $cond: [ { $eq: ["$$prefItem.pData.name", "FORMAT"] }, { name: "FORMAT", value: "TAB" }, { $cond: [ { $eq: ["$$prefItem.pData.name", "LAN"] }, { name: "LAN", value: "FRN" }, // 其他情况保留原pData不变 "$$prefItem.pData" ] } ] } } ] } } } } } ], // 确保更新所有符合条件的文档,而不只是第一个 { multi: true } )
细节解释
- 过滤条件部分:
userId: { $in: [...] }精准匹配你指定的用户ID列表"userPreferences.pId": { $in: [...] }确保只更新包含指定pId的偏好项的文档
- 数组更新部分:
$map遍历userPreferences数组的每一项,用$$prefItem指代当前元素$mergeObjects非常关键:它会保留原元素的所有原有字段(比如pId等),只替换我们需要修改的pData对象- 嵌套的
$cond实现了分支逻辑:先判断是否是"FORMAT",再判断是否是"LAN",其他情况完全保留原数据,不会破坏其他偏好项
multi: true参数:必须加上这个参数,否则默认只会更新第一个匹配到的文档,达不到批量更新的效果
特殊情况说明
如果你的userPreferences不是数组,而是单个对象(比如每个用户只有一组偏好),那可以简化代码,去掉$map,直接针对userPreferences.pData做判断:
db.users.update( { userId: { $in: ["00UPQAARGT7", "02UPQAARST7"] }, "userPreferences.pId": { $in: ["59SDS64675A00096D48CB","59SDS64675A00096D59DB"] } }, [ { $set: { "userPreferences.pData": { $cond: [ { $eq: ["$userPreferences.pData.name", "FORMAT"] }, { name: "FORMAT", value: "TAB" }, { $cond: [ { $eq: ["$userPreferences.pData.name", "LAN"] }, { name: "LAN", value: "FRN" }, "$userPreferences.pData" ] } ] } } } ], { multi: true } )
内容的提问来源于stack exchange,提问作者Dev
相关产品推荐
相关产品推荐

