如何在MongoDB中查询唯一用户配对(去重双向配对)
问题与解决方案
问题描述
我往MongoDB的users集合插入了以下文档(注:实际user1和user2为ObjectId,此处用单个字符简化说明):
db.users.insert({user1: 'a',user2: 'b'}); db.users.insert({user1: 'b',user2: 'a'}); db.users.insert({user1: 'c',user2: 'd'}); db.users.insert({user1: 'd',user2: 'c'});
需要筛选出唯一的用户配对记录——互为配对的两条记录视为同一组,最终期望得到2组唯一配对,例如:
[ {user1: 'A',user2: 'B'}, {user1: 'C',user2: 'D'} ]
或者以下格式也可接受:
[ {user1: 'B',user2: 'A'}, {user1: 'D',user2: 'C'} ]
询问是否可直接在MongoDB中实现该需求,还是必须通过JavaScript代码处理。
解决方案:MongoDB聚合管道直接实现
完全可以在MongoDB内通过聚合管道完成,无需额外编写JavaScript算法。核心思路是为每对用户生成唯一分组标识(与配对顺序无关),再基于该标识去重。
具体聚合查询
db.users.aggregate([ // 生成排序后的用户数组,统一配对顺序 { $addFields: { sortedUsers: { $sortArray: { input: ["$user1", "$user2"], sortBy: 1 } } } }, // 以排序后的数组为分组key,每组保留第一条记录 { $group: { _id: "$sortedUsers", pair: { $first: { user1: "$user1", user2: "$user2" } } } }, // 调整输出格式,仅保留配对数据 { $replaceRoot: { newRoot: "$pair" } } ])
步骤解释
- $sortArray 阶段:将每个文档的
user1和user2存入数组并排序,例如{user1:'b',user2:'a'}会生成sortedUsers: ['a','b'],与{user1:'a',user2:'b'}的标识完全一致,实现同一组配对的统一标记。 - $group 阶段:以
sortedUsers作为分组ID,每组仅保留第一条记录($first),自动去除互为配对的重复记录。 - $replaceRoot 阶段:将分组后的
pair字段提升为根文档,输出符合要求的格式。
执行该聚合后,会随机返回两种可接受格式中的一种(取决于分组时取到的原始记录),完全满足需求。
内容的提问来源于stack exchange,提问作者oderfla
相关产品推荐
相关产品推荐

