繁体   English   中英

MongoDB $ sort聚合

[英]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.

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