MongoDB聚合分组获取同类型房间最低价完整文档
嘿,这个需求很常见,我来帮你搞定!你现在的问题是$group只能拿到最低价的数值,但没法直接关联到对应的完整文档——毕竟$first/$last只是取分组后文档的位置,不是按价格排序后的结果。
给你两种实用的方案,按需选择:
方案一:先排序再分组(高效推荐)
核心思路是先把同房间的文档按价格升序排列,这样每个房间组里的第一个文档就是最低价的那个,再用$first直接取完整文档:
db.consolidation.aggregate([ // 先按房间ID分组排序,再按price.pvp升序,确保同房间最低价文档排在最前面 { $sort: { "room.id": 1, "price.pvp": 1 } }, // 按房间ID分组,取每组的第一个文档(也就是该房间最低价的完整文档) { $group: { _id: "$room.id", cheapestDoc: { $first: "$$ROOT" } } }, // 将获取到的完整文档替换为根文档,输出格式完全符合你的预期 { $replaceRoot: { newRoot: "$cheapestDoc" } } ])
方案二:先获取最低价再关联原文档(逻辑更直观)
如果觉得排序的方式不够直观,可以先拿到每个房间的最低价,再通过$lookup关联回原集合,筛选出对应价格的文档:
db.consolidation.aggregate([ // 第一步:统计每个房间的最低pvp价格 { $group: { _id: "$room.id", minPvp: { $min: "$price.pvp" } } }, // 第二步:关联原集合,匹配房间ID和对应最低价的文档 { $lookup: { from: "consolidation", let: { roomId: "$_id", targetPvp: "$minPvp" }, pipeline: [ { $match: { $expr: { $and: [ { $eq: ["$room.id", "$$roomId"] }, { $eq: ["$price.pvp", "$$targetPvp"] } ] } } } ], as: "cheapestDocs" } }, // 展开匹配到的文档数组 { $unwind: "$cheapestDocs" }, // 替换为根文档,得到最终结果 { $replaceRoot: { newRoot: "$cheapestDocs" } } ])
两种方案对比
- 方案一性能更好:只需要一次遍历+排序,适合数据量较大的场景;
- 方案二逻辑更清晰:分步操作容易理解,但需要额外的关联查询,数据量大时性能略逊。
运行任意一种方案,都能得到你想要的每个房间类型最低价的完整文档啦!
内容的提问来源于stack exchange,提问作者JSGarcia
相关产品推荐
相关产品推荐

