简体   繁体   English

MongoDB $ sort聚合

[英]MongoDB $sort aggregation

I have data base with user's activities and I'd like to count active users and number of activities that they made for each month, then sort result first by year, and each year sort by month! 我有关于用户活动的数据库,我想计算活跃用户及其每月进行的活动数量,然后先按年份对结果进行排序,然后再按月对每年进行排序!

I've got query: 我有查询:

query = {
        "activities": {
            "$exists": 1
        },
        "activities.started": {
            "$exists": 1,
            "$type": MONGODB_DATE_TYPE,
            "$gte": datetime(2011, 6, 1),
            "$lte": datetime(2013, 10, 1)
        }
    }

Then, I made pipeline like this: 然后,我做了这样的管道:

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", [])

But, this $sort operation doesn't work good, It did not sort by _id.y and _id.m , only by _id.m ! 但是,此$ sort操作效果不佳,它没有按_id.y_id.m进行排序,仅按_id.m进行了排序

I've been following this link for mongodb $sort and there is a example that shows that's possible to sort by two values there . 我一直在关注mongodb $ sort的链接,并且有一个示例显示可以在其中按两个值进行排序。

So, my question is : How can I order result first by year, then each year by month? 因此,我的问题是:如何首先按年份排序结果,然后每年按顺序排序?

EDIT 编辑

For example when I put pdb below result variable and type function: 例如,当我将pdb放在result变量下面并键入函数时:

for res in results : print res["_id"]

I got this results : 我得到了这个结果:

{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}

Like @JohnnyHK mentioned in the comments python dictionaries (unlike js objects) are unordered. 就像注释中提到的@JohnnyHK一样,python字典(与js对象不同)是无序的。 If you want to use sorting on curosr you would use something like this db.foo.find().sort([("foo", 1), ("bar": 1)])) but this syntax is not supported in aggregation $sort . 如果要在curosr上使用排序,则可以使用类似db.foo.find().sort([("foo", 1), ("bar": 1)]))但是此语法不受支持聚合$sort You can use bson.son.SON object or collections.OrderedDict instead: 您可以使用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)
        ])}
    ]

EDIT 编辑

Actually I think that in your case this should be enough: 实际上,我认为您的情况就足够了:

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}}
   ]

If sort filed is document MonogoDB seems to perform sorting field by field. 如果排序文件是文档,则MonogoDB似乎逐字段执行排序。 Order of the fields in a document can change during updates and in the general case it wouldn't work. 在更新期间,文档中字段的顺序可能会更改,通常情况下将不起作用。 Here however order of fields is defined in the $group phase and document are not modified after that so it shouldn't be a problem. 但是,这里的字段顺序是在$group阶段定义的,此后不会对文档进行修改,因此这不是问题。

Sorting by embedded document - shell example: 按嵌入式文档排序-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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM