MongoDB中使用$addToSet+$each时如何按UserId避免数组对象重复
MongoDB批量嵌套数组元素按UserId去重方案
直接使用$addToSet配合$each时,MongoDB会将整个对象作为判断重复的依据,导致UserId相同但其他字段不同的元素仍会被添加到数组中,无法满足按UserId唯一的需求。以下是两种实用解决方案:
方案一:跳过已存在UserId的元素
通过更新管道(MongoDB 4.2+支持),先过滤掉待添加列表中已存在UserId的元素,再合并到原数组:
db.Chats.updateOne( { _id: ObjectId("63d244175c4c7b3fe7a01818") }, [ { $set: { Members: { $concatArrays: [ "$Members", { $filter: { input: [ { "UserId": 123, "IsActive": false }, { "UserId": 123, "IsActive": true }, { "UserId": 456, "IsActive": true } ], cond: { $not: { $in: ["$$this.UserId", "$Members.UserId"] } } } } ] } } } ] )
逻辑说明:
$filter遍历待添加的元素数组,只保留UserId不在原Members.UserId集合中的元素$concatArrays将原Members数组与过滤后的新元素数组合并,实现无重复添加
方案二:替换已存在UserId的元素
如果需要用新元素覆盖原数组中相同UserId的记录,可先移除已存在的元素,再批量添加:
db.Chats.updateOne( { _id: ObjectId("63d244175c4c7b3fe7a01818") }, [ { $set: { // 移除原数组中所有UserId在待添加列表中的元素 Members: { $filter: { input: "$Members", cond: { $not: { $in: ["$$this.UserId", [123, 456]] } } } } } }, { // 批量添加所有待添加元素(此时无重复UserId) $addToSet: { Members: { $each: [ { "UserId": 123, "IsActive": false }, { "UserId": 456, "IsActive": true } ] } } } ] )
逻辑说明:
- 第一步过滤原
Members数组,删除所有UserId与待添加列表重复的元素 - 第二步用
$addToSet+$each添加所有待添加元素,确保最终数组中UserId唯一,且新元素覆盖旧记录
内容的提问来源于stack exchange,提问作者RussianPupok Pupok
相关产品推荐
相关产品推荐

