【问题标题】:Get last inserted item per day每天获取最后插入的项目
【发布时间】:2017-06-06 19:01:58
【问题描述】:

mongodb 中有一个功能可以用来获取每天最后插入的项目吗?我有一个集合,我需要每天获取最后插入的项目,数据按小时分组,如下面的结构所示​​。

{
   timestamp: 2017-05-04T09:00:00.000+0000,
   data: {}
},
{
   timestamp: 2017-05-04T10:00:00.000+0000,
   data: {}
}

我考虑过使用投影,但我不太确定如何做到这一点。

编辑:另外,由于 mongodb 以 UTC 存储数据,我也想考虑偏移量。

【问题讨论】:

  • 首先,按时间戳对数据进行排序(从最旧到最新)。然后,按天对文档进行分组(在 $group 阶段)并使用 $last 保留最后一个 data

标签: mongodb aggregation-framework


【解决方案1】:

您可以$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 的任何文档路径都会提供结果。

【讨论】:

  • 谢谢,您能再解释一下分组过程吗?顺便说一句,在我用一个数字替换所有数字后,它成功了
  • @Bazinga777 真的应该没什么区别。在 JavaScript 中对我来说效果很好,我一直都在这样做。数学是如何将其四舍五入为您需要比当前解释更好地理解的“一天”?
  • 问题是我需要为每个时区添加一个偏移量。我在我的问题中错过了这个
  • 没错,我想知道数学
  • @Bazinga777 好的。这大约是我能做到的冗长的,听起来不像是演讲。希望你能学到一些东西。因此,您的时区偏移量应该放在您将当前时间戳从Date BSON 类型转换为“数字”类型的位置。因此,在与使用重复的$subtract 语句的位置相同的行中。也一直这样做。
猜你喜欢
  • 1970-01-01
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
  • 2015-09-29
  • 2021-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多