![](/img/trans.png)
[英]How to sort Arrays of Object using aggregation in mongoDB
[英]MongoDB $sort aggregation
我有關於用戶活動的數據庫,我想計算活躍用戶及其每月進行的活動數量,然后先按年份對結果進行排序,然后再按月對每年進行排序!
我有查詢:
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進行了排序 !
我一直在關注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 } }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.