MongoDB聚合,按子对象键分组

Jul*_*lhé 5 mongodb aggregation-framework

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

_id: ObjectId(),
segments: {
  activity: 'value1',
  activation: 'value2',
  plan: 'value3'
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用聚合框架来找出我的多少文档具有细分活动的value1。

问题是,如果可能的话,我想针对同一请求中的每个细分进行此操作,而且我不知道我将拥有多少个细分,甚至不知道它们的名称。

基本上,这就是我想要做的:

如果我有这两个文件:

{ _id: 1, segments: { activity: 'active', activation: 'inactive', plan: 'free' }
{ _id: 2, segments: { activity: 'inactive', activation: 'inactive', plan: 'free' }
Run Code Online (Sandbox Code Playgroud)

我希望能够看到其中两个将激活段设为非激活和免费计划,并且该活动具有1个非激活值和1个激活值。这是我想要得到的:

{ 
  activity: {
    active: 1,
    inactive: 1
  },
  activation: {
    inactive: 2
  },
  plan: {
    free: 2
  }
}
Run Code Online (Sandbox Code Playgroud)

因此,基本上,如果您只需要$group按键就可以了!像这样:

{
  $group: {
    _id: { $concat: [ '$segments.$key', '-', '$segments.$key.$value' ],
    count: { $sum: 1 }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

chr*_*dam 5

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

db.collection.aggregate([    
    { 
        "$group": { 
            "_id": "$_id",             
            "activity_active": {
                "$sum": {
                    "$cond": [ { "$eq": [ "$segment.activity", "active" ] }, 1, 0 ]
                }
            },
            "activity_inactive": {
                "$sum": {
                    "$cond": [ { "$eq": [ "$segment.activity", "inactive" ] }, 1, 0 ]
                }
            },
            "activation_active": {
                "$sum": {
                    "$cond": [ { "$eq": [ "$segment.activation", "active" ] }, 1, 0 ]
                }
            },
            "activation_inactive": {
                "$sum": {
                    "$cond": [ { "$eq": [ "$segment.activity", "inactive" ] }, 1, 0 ]
                }
            },
            "plan_free": {
                "$sum": {
                    "$cond": [ { "$eq": [ "$segment.plan", "free" ] }, 1, 0 ]
                }
            } 
        }  
    },
    {
        "$project": {
            "_id": 0,            
            "activity": {
                "active": "$activity_active",
                "inactive": "$activity_inactive"
            },
            "activation": {
                "active": "$activation_active",
                "inactive": "$activation_inactive"
            },
            "plan": {
                "free": "$plan_free"
            }
        }
    }
])
Run Code Online (Sandbox Code Playgroud)