MongoDB按日期和值分组并仅返回值发生变化记录的实现方法
实现方案
你可以使用MongoDB 5.0及以上版本提供的$setWindowFields窗口运算符实现相邻记录的字段比对,完整聚合语句如下:
let history = await History.aggregate([ // 原有匹配逻辑 { $match: { address: "123456", token_to_index: "1" } }, // 原有按日期+价格分组逻辑 { $group: { _id : { date: "$date", floor_price: "$stats.floor_price" }, count: { $sum: 1 } } }, // 原有按日期升序排序逻辑 { $sort: { "_id.date": 1 } }, // 新增:获取上一条记录的floor_price { $setWindowFields: { partitionBy: null, // 不需要分区,所有记录属于同一窗口 sortBy: { "_id.date": 1 }, output: { prev_floor_price: { $shift: { output: "$_id.floor_price", by: -1, // 取当前行的上一行数据 default: null // 第一条记录的上一行默认为null } } } } }, // 新增:过滤掉价格和上一条相同的记录 { $match: { $or: [ { prev_floor_price: null }, // 保留第一条记录 { $expr: { $ne: [ "$prev_floor_price", "$_id.floor_price" ] } } // 保留价格变动的记录 ] } }, // 可选:不需要prev_floor_price字段可通过下面的阶段移除 { $unset: "prev_floor_price" } ]);
$setWindowFields阶段会在排序后的结果集上开全局窗口,给每一条记录附加prev_floor_price字段存储上一条记录的floor_price值,第一条记录的该字段值为null- 后续的
$match阶段直接过滤出第一条或者价格和上一条不一致的记录,完全等价于你写的JS过滤逻辑
如果使用的MongoDB版本低于5.0,不支持
$setWindowFields运算符,无法在聚合层直接实现该逻辑,仍需要查询后通过JS代码过滤。
内容的提问来源于stack exchange,提问作者Lucas Veiga
相关产品推荐
相关产品推荐

