Javascript MongoDB$排序聚合
我有关于用户活动的数据库,我想统计每个月的活跃用户和活动数量,然后先按年对结果排序,然后每年按月排序 我有个疑问:Javascript MongoDB$排序聚合,javascript,python,mongodb,sorting,Javascript,Python,Mongodb,Sorting,我有关于用户活动的数据库,我想统计每个月的活跃用户和活动数量,然后先按年对结果排序,然后每年按月排序 我有个疑问: query = { "activities": { "$exists": 1 }, "activities.started": { "$exists": 1, "$type": MONGODB_DATE_TYPE, "$gte": date
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操作不起作用,它没有按\u id.y和\u id.m排序,只按\u id.m排序
我一直在关注这一点,有一个例子表明可以按两个值进行排序
所以,我的问题是:我怎样才能先按年份排序结果,然后再按月份排序结果
编辑
例如,当我将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}
就像注释中提到的@johnyhk一样,python字典(与js对象不同)是无序的。如果您想在curosr上使用排序,您可以使用类似以下内容的
db.foo.find().sort([(“foo”,1),(“bar”:1)])
,但聚合$sort
中不支持此语法。您可以使用对象,也可以使用:
编辑
事实上,我认为在你的情况下,这应该足够了:
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 } }
就像注释中提到的@johnyhk一样,python字典(与js对象不同)是无序的。如果您想在curosr上使用排序,您可以使用类似以下内容的
db.foo.find().sort([(“foo”,1),(“bar”:1)])
,但聚合$sort
中不支持此语法。您可以使用对象,也可以使用:
编辑
事实上,我认为在你的情况下,这应该足够了:
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 } }
你有一些游离的尾随逗号,但除此之外,它看起来是正确的。你能更新你的问题,提供几个重现问题的样本文档吗?我更新了,你能找出问题吗?它只是按月份排序!我敢肯定,问题在于您使用的Python不能维护dicts中字段的顺序。试着用一个像这样的
$sort
值:[(“\u id.y”,1),(“\u id.m”,1)]
我得到了这个错误:TypeError:unhable type:'list'。。但是,正如您所看到的那样,这个输出是在mongodb内部执行的。。我自己制作了聚合到mongodb中,而不是使用python!如果你从你的收藏中加载了一个示例文档,这会很有帮助,因为@johnnykyou有一些散乱的尾随逗号,但除此之外,它看起来是正确的。你能更新你的问题,提供几个重现问题的样本文档吗?我更新了,你能找出问题吗?它只是按月份排序!我敢肯定,问题在于您使用的Python不能维护dicts中字段的顺序。试着用一个像这样的$sort
值:[(“\u id.y”,1),(“\u id.m”,1)]
我得到了这个错误:TypeError:unhable type:'list'。。但正如您所看到的,这个输出是在mongodb内部执行的。。我自己制作了聚合到mongodb中,而不是使用python!如果您从您的收藏中加载了一个示例文档,这将非常有帮助。per@JohnnyHKI已经尝试由SON解决它,但没有成功!结果也一样!你能发布一些示例文档吗?例如,bson.json_util import dumps的输出;dumps(col.find(query.limit(5))
我已经尝试过用SON解决它,但没有成功!结果也一样!你能发布一些示例文档吗?例如,bson.json_util import dumps的输出;转储(列查找(查询).limit(5))