MongoDB 4.2.0中基于顺序条件的数据查询问题
MongoDB 4.2.0 查询实现方案
需求回顾
需要查询所有b=5的记录,要求同一a值下,比b=5小的最大b值对应的记录的c字段等于5。注意b可为可排序的非数值类型(如字符串、时间戳),且同一a下的b值唯一。
方案1:仅返回符合条件的b=5记录
通过聚合管道实现,步骤清晰且适配非数值类型的b:
db.collection.aggregate([ // 筛选b<=5的记录,缩小后续处理范围 { $match: { b: { $lte: 5 } } }, // 按a分组,将每组记录存入数组 { $group: { _id: "$a", records: { $push: "$$ROOT" } } }, // 对每组记录按b升序排序(适配非数值类型排序规则) { $addFields: { sortedRecords: { $sortArray: { input: "$records", sortBy: { b: 1 } } } } }, // 过滤出包含b=5且前一个最大b的c=5的分组 { $match: { $expr: { $and: [ { $eq: [{ $last: "$sortedRecords.b" }, 5] }, { $eq: [{ $arrayElemAt: ["$sortedRecords.c", -2] }, 5] } ] } } }, // 提取分组中的b=5记录 { $replaceRoot: { newRoot: { $last: "$sortedRecords" } } } ])
执行结果:
[ {a:4,b:5,c:1}, {a:5,b:5,c:1} ]
方案2:返回符合条件的a对应的相关记录(含前一个最大b记录)
如果需要同时返回同一a下的b=5记录及其前一个最大b的记录,调整管道如下:
db.collection.aggregate([ { $match: { b: { $lte: 5 } } }, { $group: { _id: "$a", records: { $push: "$$ROOT" } } }, { $addFields: { sortedRecords: { $sortArray: { input: "$records", sortBy: { b: 1 } } } } }, { $match: { $expr: { $and: [ { $eq: [{ $last: "$sortedRecords.b" }, 5] }, { $eq: [{ $arrayElemAt: ["$sortedRecords.c", -2] }, 5] } ] } } }, // 提取数组最后两个元素(前一个最大b和b=5的记录) { $addFields: { targetRecords: { $slice: ["$sortedRecords", -2] } } }, // 展开数组 { $unwind: "$targetRecords" }, // 切换为记录本身 { $replaceRoot: { newRoot: "$targetRecords" } } ])
执行结果:
[ {a:4,b:3,c:5}, {a:4,b:5,c:1}, {a:5,b:4,c:5}, {a:5,b:5,c:1} ]
关键说明
- 针对非数值类型的
b,$sortArray和$lte会遵循MongoDB对应类型的排序规则正常工作 - 同一
a下b值唯一的前提,保证了每组中b=5仅出现一次,无需处理重复逻辑
内容的提问来源于stack exchange,提问作者migs
相关产品推荐
相关产品推荐

