您可以$sort 并使用$last 作为项目,并将分组键四舍五入到每一天:
db.collection.aggregate([
{ "$sort": { "timestamp": 1 } },
{ "$group": {
"_id": {
"$add": [
{ "$subtract": [
{ "$subtract": [ "$timestamp", new Date(0) ] },
{ "$mod": [
{ "$subtract": [ "$timestamp", new Date(0) ] },
1000 * 60 * 60 * 24
]}
]},
new Date(0)
]
},
"lastDoc": { "$last": "$$ROOT" }
}}
])
因此排序使事物按顺序显示,然后分组_id 每天通过一些日期数学进行四舍五入。您从当前日期中减去纪元日期以使其成为一个数字。使用模数舍入到一天,然后将纪元日期添加到数字以返回 Date。
因此,通过数学计算,我们从$subract 行的日期中获取时间戳值。我们这样做了几次:
{ "$subtract": [ "$timestamp", new Date(0) ] }
// Is roughly internally like
ISODate("2017-06-06T10:44:37.627Z") - ISODate("1970-01-01T00:00:00Z")
1496745877627
然后是 $mod 的模数,当应用于数值时会返回差值。 1000 毫秒 * 60 秒 * 60 * 分钟 * 24 小时给出了另一个参数:
{ "$mod": [
{ "$subtract": [ "$timestamp", new Date(0) ] },
1000 * 60 * 60 * 24
]}
// Equivalent to
1496745877627 % (1000 * 60 * 60 * 24)
38677627
然后是两个数字的包装$subtract:
{ "$subtract": [
{ "$subtract": [ "$timestamp", new Date(0) ] },
{ "$mod": [
{ "$subtract": [ "$timestamp", new Date(0) ] },
1000 * 60 * 60 * 24
]}
]}
// Subtract "difference" of the modulo to a day
// from the milliseconds value of the current date
1496745877627 - 38677627
1496707200000
然后添加回纪元日期值以创建一个四舍五入到当前日期的日期,这对于聚合管道来说基本上看起来像向构造函数提供毫秒值:
new Date(1496707200000)
ISODate("2017-06-06T00:00:00Z")
它采用时间戳值并减去除数与“一天”的差异,并在“一天开始”的时间结束。
这里只使用$$ROOT 来表示整个文档。但是这里提供给$last 的任何文档路径都会提供结果。