javascript - MongoDB $sort 聚合

标签 javascript python mongodb sorting

我有包含用户事件的数据库,我想计算活跃用户和他们每个月进行的事件数量,然后首先按年份对结果进行排序,每年按月排序!

我有一个疑问:

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/

相关文章:

javascript - 在javascript中搜索对象内的对象数组

javascript - 按回车后的目标位置

javascript - @font-face 套件预加载器

python - Streamfield 中的 Wagtail SnippetChooserBlock

mongodb - nodejs - mongodb - 如何删除记录

javascript - 解析 Node Express 路由中带有特殊字符的 URL

python - wxGlade GUI行为问题

python - 如何从字典列表中创建三个单独的值列表,其中每个字典都有三个键

javascript - 如何从 mongo shell 中的 Date 值创建 ObjectId?

javascript - 复合索引覆盖以前的文档