如何在MongoDB中实现指定SQL查询的等效语句?
嘿,我来帮你把这段SQL转换成MongoDB的等效查询~先理清楚原SQL的逻辑:它是要找出所有和用户ID=1互为好友的人,不管是用户1发起的好友请求,还是收到的请求,最后合并结果并自动去重。下面给你两种实现方式,根据你的MongoDB版本选就行:
方法一:通用聚合管道(适合所有MongoDB版本)
这种方法用聚合管道一步完成筛选、关联、去重的操作,兼容性最好:
db.friendships.aggregate([ // 第一步:筛选出所有和用户1相关的好友关系记录 { $match: { $or: [ { requestee: 1 }, { requester: 1 } ] }}, // 第二步:根据关系类型,标记出对应的好友ID { $addFields: { friendId: { $cond: { if: { $eq: ["$requestee", 1] }, then: "$requester", else: "$requestee" } } }}, // 第三步:关联person集合,获取好友的详细信息 { $lookup: { from: "person", localField: "friendId", foreignField: "id", as: "friend" }}, // 第四步:把关联返回的数组展开成单个文档 { $unwind: "$friend" }, // 第五步:提取需要的字段,和原SQL输出格式对齐 { $project: { _id: 0, id: "$friend.id", firstName: "$friend.firstName", lastName: "$friend.lastName" }}, // 第六步:去重,确保每个好友只出现一次(对应SQL的UNION) { $group: { _id: "$id", firstName: { $first: "$firstName" }, lastName: { $first: "$lastName" } }}, // 第七步:重新调整字段格式,去掉分组用的_id { $project: { _id: 0, id: "$_id", firstName: 1, lastName: 1 }} ])
方法二:用$unionWith贴近原SQL结构(MongoDB 4.4+支持)
如果你用的是MongoDB 4.4及以上版本,可以用$unionWith直接模拟SQL的UNION逻辑,结构上和原SQL更相似:
db.friendships.aggregate([ // 对应原SQL第一个SELECT:requestee=1时,取requester的信息 { $match: { requestee: 1 }}, { $lookup: { from: "person", localField: "requester", foreignField: "id", as: "friend" }}, { $unwind: "$friend" }, { $project: { _id: 0, id: "$friend.id", firstName: "$friend.firstName", lastName: "$friend.lastName" }} ]).unionWith({ coll: "friendships", pipeline: [ // 对应原SQL第二个SELECT:requester=1时,取requestee的信息 { $match: { requester: 1 }}, { $lookup: { from: "person", localField: "requestee", foreignField: "id", as: "friend" }}, { $unwind: "$friend" }, { $project: { _id: 0, id: "$friend.id", firstName: "$friend.firstName", lastName: "$friend.lastName" }} ] })
注意事项
- 要确保
person集合里的id字段,和friendships集合里的requester、requestee字段类型一致(比如都是数字1或者字符串"1"),不然关联会匹配不到数据。 - 如果不需要去重(对应SQL的UNION ALL),可以去掉方法一里的
$group和最后一步$project;方法二若要保留重复项,需要用$concatArrays结合两个聚合结果,不过这种场景在好友关系里很少见。
内容的提问来源于stack exchange,提问作者Sebastian
相关产品推荐
相关产品推荐

