MongoDB聚合查询:获取符合条件的关联随机Status文档
MongoDB聚合查询:获取符合条件的随机Status文档
需求说明
现有三个集合:User、Credit、Status,关联规则为:每个User对应1条Credit数据,对应多条Status数据。需要实现查询:
- 从
Status中随机返回1条文档 - 满足两个条件:
- 该
Status的userId不等于当前查询用户的_id - 当前用户的
Credit数值 ≥ 该Status的useCredit
- 该
集合结构
User集合
[ { "_id": ObjectId("669fbce1704d41e9040cbb41"), "Name": "First User" }, { "_id": ObjectId("669fbce1704d41e9040cbb42"), "Name": "Second User" }, { "_id": ObjectId("669fbce1704d41e9040cbb43"), "Name": "Third User" } ]
Credit集合
[ { "_id": ObjectId("669fbce1704d41e9040cbb44"), "userId": ObjectId("669fbce1704d41e9040cbb41"), "credit": 100 }, { "_id": ObjectId("669fbce1704d41e9040cbb45"), "userId": ObjectId("669fbce1704d41e9040cbb42"), "credit": 10 }, { "_id": ObjectId("669fbce1704d41e9040cbb46"), "userId": ObjectId("669fbce1704d41e9040cbb43"), "credit": 100 } ]
Status集合
[ { "_id": ObjectId("669fbce1704d41e9040cbb47"), "userId": ObjectId("669fbce1704d41e9040cbb41"), "status": "First User Status", "useCredit": 1 }, { "_id": ObjectId("669fbce1704d41e9040cbb48"), "userId": ObjectId("669fbce1704d41e9040cbb42"), "status": "Second User Status", "useCredit": 20 }, { "_id": ObjectId("669fbce1704d41e9040cbb49"), "userId": ObjectId("669fbce1704d41e9040cbb42"), "status": "Second User Status", "useCredit": 10 }, { "_id": ObjectId("669fbce1704d41e9040cbb4a"), "userId": ObjectId("669fbce1704d41e9040cbb43"), "status": "Third User Status", "useCredit": 3 }, { "_id": ObjectId("669fbdac704d41e9040cbb4c"), "userId": ObjectId("669fbce1704d41e9040cbb43"), "status": "Third User Status", "useCredit": 4 }, { "_id": ObjectId("669fbdac704d41e9040cbb4d"), "userId": ObjectId("669fbce1704d41e9040cbb43"), "status": "Third User Status", "useCredit": 2 }, { "_id": ObjectId("669fbdac704d41e9040cbb50"), "userId": ObjectId("669fbce1704d41e9040cbb43"), "status": "Third User Status", "useCredit": 2 } ]
聚合查询实现
以First User(_id: ObjectId("669fbce1704d41e9040cbb41"))发起查询为例,聚合管道如下:
db.Credit.aggregate([ // 1. 匹配当前用户的信用记录 { $match: { userId: ObjectId("669fbce1704d41e9040cbb41") } }, // 2. 关联Status集合,筛选符合条件的记录 { $lookup: { from: "Status", let: { currentUserId: "$userId", userCredit: "$credit" }, pipeline: [ { $match: { $expr: { $and: [ { $ne: ["$userId", "$$currentUserId"] }, // 排除当前用户自己的Status { $lte: ["$useCredit", "$$userCredit"] } // 确保用户信用足够支付该Status的useCredit ] } } } ], as: "validStatuses" } }, // 3. 将符合条件的Status数组展开为单个文档 { $unwind: "$validStatuses" }, // 4. 随机抽取1条文档 { $sample: { size: 1 } }, // 5. 将结果格式化为Status文档的结构 { $replaceRoot: { newRoot: "$validStatuses" } } ])
代码说明
- $match:定位当前用户的信用记录,获取其
credit数值和userId。 - $lookup:使用子管道关联
Status集合,通过$expr引用当前用户的变量,筛选出符合条件的Status文档。 - $unwind:把筛选得到的
validStatuses数组拆分为独立文档,方便后续随机抽取。 - $sample:从符合条件的文档中随机选取1条,实现随机返回的需求。
- $replaceRoot:将结果的根节点替换为
validStatuses的内容,直接返回标准的Status文档结构。
示例验证
对于First User的查询:
- 排除自身的Status文档(
_id: 669fbce1704d41e9040cbb47) - 由于First User信用为100,所有其他Status的
useCredit均≤100,因此符合条件的文档为剩余6条,查询会从中随机返回1条。
(注:原示例中提到排除_id:669fbce1704d41e9040cbb48,该文档useCredit=20,First User信用足够支付,推测是示例描述有误;若为Second User发起查询,其信用为10,才会排除该文档)
内容的提问来源于stack exchange,提问作者Afdal
相关产品推荐
相关产品推荐

