pymongo按日期时间分组
问题内容:
我正在尝试搜索集合并按日期字段将记录分组,该日期字段是日期时间。我知道pymongo在后台将那些转换为正确的类型(ISODate或类似的东西)。
问题是,由于datetime对象具有日期,时间,时区..我如何告诉组操作员仅使用日期部分?因为否则我无法获得所需的分组,因为时间阻止了将同一天,月,年的记录分组在一起。
db.test.aggregate([
{"$group": {
"_id": "$date",
"count": {"$sum": 1}
}},
{"$limit": 10}])
结果:
{u'ok': 1.0,
u'result': [
{u'_id': datetime.datetime(2014, 2, 15, 18, 49, 9, tzinfo=<bson.tz_util.FixedOffset object at 0x318f210>),
u'count': 1},
{u'_id': datetime.datetime(2014, 2, 15, 18, 36, 38, tzinfo=<bson.tz_util.FixedOffset object at 0x318f210>),
u'count': 1},
{u'_id': datetime.datetime(2014, 2, 15, 18, 23, 56, tzinfo=<bson.tz_util.FixedOffset object at 0x318f210>),
u'count': 1}]}
控制用于分组的日期时间信息会很好,
- 仅按日期分组
- 按日期和小时分组
- 按日期,小时和分钟分组
- 等等
是否有类似的东西:(或某种告诉使用日期的方式)
db.test.aggregate([
{"$group": {
"_id": "$date.date()",
"count": {"$sum": 1}
}},
{"$sort": "_id"}
])
或者,也许还有另一种处理方式,任何想法?谢谢。
问题答案:
是。您可以将日期运算符与$
substr
和$
concat
结合使用。
db.test.aggregate([
{"$group": {
"_id" : { "$concat": [
{"$substr": [{"$year": "$date"}, 0, 4 ]},
"-",
{"$substr": [{"$month": "$date"}, 0, 2 ]},
"-",
{"$substr": [{"$dayOfMonth": "$date"}, 0, 2 ]},
]},
"count": {"$sum": 1 }
}},
{"$sort": { "_id": 1 }}
])
您可以只使用日期运算符,并按以下步骤制作文档:
"day": {
"year": {"$year": "$date" },
"month": {"$month": "$date"},
"day": {"$dayOfYear": "$date"}
}
效果也一样。但这为您提供了一个不错的字符串。这利用了$substr
将从整数转换为字符串的事实。如果有的话,添加到文档中。
请查看日期运算符文档,以了解可用于日期的其他时分的用法。
更好的是,使用日期数学来返回BSON日期:
import datetime
db.test.aggregate([
{ "$group": {
"_id": {
"$add": [
{ "$subtract": [
{ "$subtract": [ "$date", datetime.datetime.utcfromtimestamp(0) ] },
{ "$mod": [
{ "$subtract": [ "$date", datetime.datetime.utcfromtimestamp(0) ] },
1000 * 60 * 60 * 24
]}
]},
datetime.datetime.utcfromtimestamp(0)
]
},
"count": { "$sum": 1 }
}},
{ "$sort": { "_id": 1 } }
])
这datetime.datetime.utcfromtimestamp(0)
将作为代表“时代”的BSON日期送入管道。当您将$subtract
一个BSON日期与另一个日期分开时,将返回以毫秒为单位的差异。这样,您就可以通过再次减去$mod
结果以将日期“舍入”为当前日期,从而获得一天中剩余的毫秒差。
将$add
BSON日期“添加”到数字值将导致BSON日期的情况也是如此。