如何在MongoDB中筛选含active和renew状态的用户并去重数组元素
MongoDB 筛选同时拥有指定状态的用户并对数组去重
问题说明
需要筛选出Keys数组中同时包含keyStatus为active和renew的用户,并且返回结果时对Keys数组按keyType+keyStatus组合去重,去除重复条目。
注意:原过滤器{keys: {$elemMatch: {status: {$in: ["active", "renew"] }}}}仅能匹配数组中存在任意一种状态的用户,无法确保同时拥有两种状态,需先修正筛选条件。
解决方案:使用聚合管道实现筛选+去重
方法一:内存中直接处理数组去重(适合数组元素较少的场景)
通过$match筛选符合条件的用户,再用$reduce对Keys数组去重:
db.users.aggregate([ // 筛选同时拥有active和renew状态的用户 { $match: { $and: [ {"Keys.keyStatus": "active"}, {"Keys.keyStatus": "renew"} ] } }, // 对Keys数组按keyType+keyStatus组合去重 { $addFields: { Keys: { $reduce: { input: "$Keys", initialValue: [], in: { $concatArrays: [ "$$value", { $cond: [ { $not: { $in: [ {keyType: "$$this.keyType", keyStatus: "$$this.keyStatus"}, "$$value" ] } }, ["$$this"], [] ] } ] } } } } } ])
方法二:通过展开+分组实现去重(适合数组元素较多的场景)
利用$unwind展开数组,再通过两次$group分别去重和重组数组:
db.users.aggregate([ // 筛选同时拥有active和renew状态的用户 { $match: { $and: [ {"Keys.keyStatus": "active"}, {"Keys.keyStatus": "renew"} ] } }, // 展开Keys数组 { $unwind: "$Keys" }, // 按用户ID+keyType+keyStatus分组,去除重复条目 { $group: { _id: { userId: "$_id", keyType: "$Keys.keyType", keyStatus: "$Keys.keyStatus" }, // 保留用户其他字段,示例为name,可根据实际需求添加 name: { $first: "$name" }, keyInfo: { $first: "$Keys" } } }, // 按用户ID重新分组,聚合去重后的Keys数组 { $group: { _id: "$_id.userId", name: { $first: "$name" }, Keys: { $push: "$keyInfo" } } } ])
说明
- 两种方法都会先筛选出同时拥有
active和renew状态的用户,再对Keys数组去重; - 方法一无需展开数组,内存处理更快,但数组过大时可能性能下降;
- 方法二通过分组去重,适合大数据量场景,但需要处理用户其他字段的保留逻辑。
内容的提问来源于stack exchange,提问作者Jin
相关产品推荐
相关产品推荐

