我有包含用户事件的数据库,我想计算活跃用户和他们每个月进行的事件数量,然后首先按年份对结果进行排序,每年按月排序!
我有一个疑问:
query = {
"activities": {
"$exists": 1
},
"activities.started": {
"$exists": 1,
"$type": MONGODB_DATE_TYPE,
"$gte": datetime(2011, 6, 1),
"$lte": datetime(2013, 10, 1)
}
}
然后,我制作了这样的管道:
pipeline = [
{'$project': {
'_id': 1,
'activities': 1
}},
{'$unwind': "$activities"},
{'$match': query},
{'$group': {
'_id': {"y": {"$year": "$activities.started"},
"m": {"$month": "$activities.started"}},
'users': {'$addToSet': "$_id"},
'activities_count': {"$sum": 1},
}},
{"$sort": {
"_id.y": 1,
"_id.m": 1,
}}
]
results = col.aggregate(pipeline)
results = results.get("result", [])
但是,这个$sort操作效果不好,它没有按照_id.y和_id.m排序,只是作者:_id.m!
我一直在关注这个link for mongodb $sort并且有一个示例表明可以按两个值进行排序。
所以,我的问题是:如何先按年排序结果,然后每年按月排序?
编辑
例如,当我将 pdb
放在 result
变量和类型函数下面时:
for res in results : print res["_id"]
我得到了这个结果:
{u'y': 2012, u'm': 1}
{u'y': 2013, u'm': 1}
{u'y': 2012, u'm': 2}
{u'y': 2013, u'm': 2}
{u'y': 2012, u'm': 3}
{u'y': 2013, u'm': 3}
{u'y': 2012, u'm': 4}
{u'y': 2013, u'm': 4}
{u'y': 2012, u'm': 5}
{u'y': 2013, u'm': 5}
{u'y': 2011, u'm': 6}
{u'y': 2012, u'm': 6}
{u'y': 2013, u'm': 6}
{u'y': 2011, u'm': 7}
{u'y': 2012, u'm': 7}
{u'y': 2013, u'm': 7}
{u'y': 2011, u'm': 8}
{u'y': 2012, u'm': 8}
{u'y': 2013, u'm': 8}
{u'y': 2011, u'm': 9}
{u'y': 2012, u'm': 9}
{u'y': 2013, u'm': 9}
{u'y': 2011, u'm': 10}
{u'y': 2012, u'm': 10}
{u'y': 2011, u'm': 11}
{u'y': 2012, u'm': 11}
{u'y': 2011, u'm': 12}
{u'y': 2012, u'm': 12}
最佳答案
就像 @JohnnyHK 在评论中提到的那样,Python 字典(与 js 对象不同)是无序的。如果你想在 curosr 上使用排序,你可以使用类似这样的 db.foo.find().sort([("foo", 1), ("bar": 1)]))
但聚合 $sort
不支持此语法。您可以使用bson.son.SON
对象或 collections.OrderedDict
相反:
from bson.son import SON
pipeline = [
{'$project': {
'_id': 1,
'activities': 1
}},
{'$unwind': "$activities"},
{'$match': query},
{'$group': {
'_id': {"y": {"$year": "$activities.started"},
"m": {"$month": "$activities.started"}},
'users': {'$addToSet': "$_id"},
'activities_count': {"$sum": 1},
}},
{"$sort": SON([
("_id.y", 1),
("_id.m", 1)
])}
]
编辑
实际上我认为对于你的情况来说这应该足够了:
pipeline = [
{'$project': {
'_id': 1,
'activities': 1
}},
{'$unwind': "$activities"},
{'$match': query},
{'$group': {
'_id': {"y": {"$year": "$activities.started"},
"m": {"$month": "$activities.started"}},
'users': {'$addToSet': "$_id"},
'activities_count': {"$sum": 1},
}},
{"$sort": {"_id": 1}}
]
如果排序归档是文档,MonogoDB 似乎会逐个字段执行排序。文档中字段的顺序在更新期间可能会发生变化,并且在一般情况下它不起作用。然而,这里字段的顺序是在 $group
阶段定义的,之后文档不会被修改,所以这应该不是问题。
按嵌入文档排序 - shell 示例:
> db.bar.insert({foobar: {foo: 2012, bar: 1}})
> db.bar.insert({foobar: {foo: 2012, bar: 5}})
> db.bar.insert({foobar: {foo: 2012, bar: 3}})
> db.bar.insert({foobar: {foo: 2010, bar: 5}})
> db.bar.insert({foobar: {foo: 2010, bar: 1}})
> db.bar.insert({foobar: {foo: 2013, bar: 5}})
> db.bar.insert({foobar: {foo: 2013, bar: 3}})
> db.bar.find({}, {_id: 0}).sort({foobar: 1})
{ "foobar" : { "foo" : 2010, "bar" : 1 } }
{ "foobar" : { "foo" : 2010, "bar" : 5 } }
{ "foobar" : { "foo" : 2012, "bar" : 1 } }
{ "foobar" : { "foo" : 2012, "bar" : 3 } }
{ "foobar" : { "foo" : 2012, "bar" : 5 } }
{ "foobar" : { "foo" : 2013, "bar" : 3 } }
{ "foobar" : { "foo" : 2013, "bar" : 5 } }
关于javascript - MongoDB $sort 聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19866149/