我有一个Node web应用程序,它使用mongodb来存储数据。我有一个类似于:
的Messages集合[
{
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut",
"pubDate": "2014-01-16T14:15:33.792Z",
"pubTimezone": "America/Tijuana"
"id": "a9baa2f0-7eb8-11e3-b732-0b0c79e81098"
},
{
"message": "labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco",
"pubDate": "2014-01-16T14:01:24.198Z",
"pubTimezone": "America/Tijuana"
"id": "af550860-7eb6-11e3-b732-0b0c79e81098"
},
{
"message": "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in",
"pubDate": "2014-01-17T01:12:27.277Z",
"pubTimezone": "America/Tijuana"
"id": "6dff53d0-7f14-11e3-b732-0b0c79e81098"
},
{
"message": "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat",
"pubDate": "2014-01-17T01:10:17.249Z",
"pubTimezone": "America/Tijuana"
"id": "207ea110-7f14-11e3-b732-0b0c79e81098"
}
...
]
我想根据pubDate时间戳运行一个按日分组的查询,从而产生输出:
[
{
"items":[
{
"message":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut",
"pubDate":"2014-01-16T14:15:33.792Z",
"pubTimezone": "America/Tijuana"
"id":"a9baa2f0-7eb8-11e3-b732-0b0c79e81098"
},
{
"message":"labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco",
"pubDate":"2014-01-16T14:01:24.198Z",
"pubTimezone": "America/Tijuana"
"id":"af550860-7eb6-11e3-b732-0b0c79e81098"
}
],
"day":"2014-01-16T00:00:00.000Z"
},
{
"items":[
{
"message":"laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in",
"pubDate":"2014-01-17T01:12:27.277Z",
"pubTimezone": "America/Tijuana"
"id":"6dff53d0-7f14-11e3-b732-0b0c79e81098"
},
{
"message":"voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat",
"pubDate":"2014-01-17T01:10:17.249Z",
"pubTimezone": "America/Tijuana"
"id":"207ea110-7f14-11e3-b732-0b0c79e81098"
}
],
"day":"2014-01-17T00:00:00.000Z"
}
...
]
订购逆向日期订单,必须使用时区来计算日期。 结果每页50页 请注意,有些日期没有创建项目,pubDates在db中都是ISODate格式。
我已经阅读了一些关于分组的帖子但是他们似乎都在进行求和/计数任务,而不是按照我想要的输出格式将所有结果按日分组。我还阅读了关于聚合框架的一些博客posts和map reduce,但没有取得多大进展。
如果可以将total_messages和total_days作为同一查询的一部分,那将会很棒,但是当我得到结果时,我总是可以在代码中执行此操作。
我的网络应用程序工作的方式,它按日期desc顺序提取所有消息然后在代码中按天排序,性能非常糟糕,所以我希望找到一种方法来进行数字处理数据来自数据库。
任何指导和/或帮助都非常感激。
答案 0 :(得分:0)
如果您的日期是ISODate格式,则应将其保存为数据库中的此类型。以下行显示该类型是一个字符串:
"pubDate": "2014-01-16T14:15:33.792Z",
看起来应该是这样的:
{
"message" : "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut",
"pubDate" : ISODate("2014-01-16T14:15:33.792Z"),
"pubTimezone" : "America/Tijuana",
"id" : "a9baa2f0-7eb8-11e3-b732-0b0c79e81098"
}
在第一个提案中,我们假设您可以将字符串更改为ISODate类型。 然后,您可以使用聚合框架函数来提取有关日期的信息。 MongoDB将返回与GMT-0值对应的年,月和日的值。我想这就是你想要的,但如果没有,请看第二个解决方案。
然后,运行聚合查询应该可以提供您想要的内容:
db.mycollection.aggregate([{"$project":{year:{"$year":"$pubDate"},month:{"$month":"$pubDate"},day:{"$dayOfMonth":"$pubDate"},"item":{"message":"$message","pubDate":"$pubDate","pubTimezone":"$pubTimezone","id":"$id"}}},{"$group":{"_id":{"year":"$year","month":"$month","day":"$day"},"items":{"$push":"$item"},"count":{"$sum":1}}}]).result
[
{
"_id" : {
"year" : 2014,
"month" : 1,
"day" : 17
},
"items" : [
{
"message" : "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in",
"pubDate" : ISODate("2014-01-17T01:12:27.277Z"),
"pubTimezone" : "America/Tijuana",
"id" : "6dff53d0-7f14-11e3-b732-0b0c79e81098"
},
{
"message" : "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat",
"pubDate" : ISODate("2014-01-17T01:10:17.249Z"),
"pubTimezone" : "America/Tijuana",
"id" : "207ea110-7f14-11e3-b732-0b0c79e81098"
}
],
"count" : 2
},
{
"_id" : {
"year" : 2014,
"month" : 1,
"day" : 16
},
"items" : [
{
"message" : "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut",
"pubDate" : ISODate("2014-01-16T14:15:33.792Z"),
"pubTimezone" : "America/Tijuana",
"id" : "a9baa2f0-7eb8-11e3-b732-0b0c79e81098"
},
{
"message" : "labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco",
"pubDate" : ISODate("2014-01-16T14:01:24.198Z"),
"pubTimezone" : "America/Tijuana",
"id" : "af550860-7eb6-11e3-b732-0b0c79e81098"
}
],
"count" : 2
}
]
请注意,您只能在一个字段列表中进行分组。这意味着,您可以获取每天的文档数量,使用聚合返回的文档数量作为天数,但是您需要计算应用程序中的消息总数,迭代文档。
针对您无法使用ISODate类型或者您希望在非GMT时间内存储数据的情况的第二种解决方案。 在该解决方案中,计算一个附加字段,该字段表示要聚合的日期。例如,您将使用其他“日期”字段创建文档:
{
"message" : "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut",
"pubDate" :"2014-01-16T14:15:33.792Z",
"pubTimezone" : "America/Tijuana",
"date" : "2014-01-16"),
"id" : "a9baa2f0-7eb8-11e3-b732-0b0c79e81098"
}
然后编写类似的聚合查询,但在$ group子句中使用'date'作为'_id'。 预先计算的字段聚合的优点是它会更快,但它也会让你做一个简单的
find({"date":"2014-01-16"})
查询以在需要时检索文档的子集。 使用简单的find()命令与聚合框架的优点是后者需要在返回结果之前完成所有处理。 find()命令将开始批量返回结果,因此如果您打算将结果分页给用户,则会更快。