MongoDB聚合,按子对象键分组

时间:2016-05-16 11:27:40

标签: mongodb aggregation-framework

我有一个mongo集合,其架构如下所示:

_id: ObjectId(),
segments: {
  activity: 'value1',
  activation: 'value2',
  plan: 'value3'
}

我正在尝试使用聚合框架来查明我的文档有多少具有该段活动的value1。

问题在于,如果可能的话,我想为同一个请求中的每个细分执行此操作,并且我不知道我将拥有多少个细分,甚至是他们的名字。

基本上这就是我想做的事情:

如果我有这两个文件:

{ _id: 1, segments: { activity: 'active', activation: 'inactive', plan: 'free' }
{ _id: 2, segments: { activity: 'inactive', activation: 'inactive', plan: 'free' }

我希望能够看到其中两个激活段处于非活动状态和免费计划,该活动有1个非活动值和1个活动值。这是我想要的:

{ 
  activity: {
    active: 1,
    inactive: 1
  },
  activation: {
    inactive: 2
  },
  plan: {
    free: 2
  }
}

所以基本上,如果按键只能$group,那就太好了!像这样:

{
  $group: {
    _id: { $concat: [ '$segments.$key', '-', '$segments.$key.$value' ],
    count: { $sum: 1 }
  }
}

或者,如果我可以在每个键上放松......

2 个答案:

答案 0 :(得分:4)

要获取计数,请利用$cond管道步骤中的$group运算符来根据子文档值评估计数,如下所示:

<meta>

答案 1 :(得分:0)

可能存在这个问题的通用解决方案,但可能需要稍微后处理:

获得输出类似于此:

{
    "_id" : {
        "activity" : "active",
        "activation" : "inactive"
    },
    "plan" : [{
            "type" : "free",
            "total" : 1
        }, {
            "type" : "paid",
            "total" : 1
        }
    ]
}, {
    "_id" : {
        "activity" : "inactive",
        "activation" : "inactive"
    },
    "plan" : [{
            "type" : "free",
            "total" : 1
        }
    ]
}, {
    "_id" : {
        "activity" : "inactive",
        "activation" : "active"
    },
    "plan" : [{
            "type" : "paid",
            "total" : 3
        }, {
            "type" : "free",
            "total" : 6
        }
    ]
}
  

使用类似的查询:

db.collection.aggregate([{
            $group : {
                _id : {
                    activity : "$segments.activity",
                    activation : "$segments.activation",
                    plan : "$segments.plan"
                },
                total : {
                    $sum : 1
                }
            }
        }, {
            $group : {
                _id : {
                    activity : "$_id.activity",
                    activation : "$_id.activation"
                },
                plan : {
                    $push : {
                        type : "$_id.plan",
                        total : "$total"
                    }
                }
            }
        },

    ])