MongoDB:聚合,按几个字段分组

时间:2014-01-09 14:31:47

标签: node.js mongodb aggregation-framework

我有一个包含该结构文件的集合

{
  type: 'a',
  date: '2014-01-04'
},
{
  type: 'b',
  date: '2014-01-04'
},
{
  type: 'b',
  date: '2014-01-04
},
{
  type: 'c',
  date: '2014-01-03'
},
{
  type: 'a',
  date: '2014-01-03'
}

我希望按日期和类型(按日期分组和按类型计算)聚合该数据:

{
  date: '2014-01-04': {
    'a': 1,
    'b': 2
  },

  date: '2014-01'03': {
    'a': 1,
    'c': 1
  }
}

我有聚合功能,就像这个

db.items.aggregate([
    {
        $match: { user: user },
    },
    {
        $group: { _id: {date: '$date'}, count: {$sum: 1}, services: {$push: '$type'}}
    }
], function (err, results) {

但是这样做我仍然需要reduce服务结果。

这可以通过一个聚合查询完成吗?

2 个答案:

答案 0 :(得分:3)

您当然可以按多个字段进行分组:

{ $group: { _id: { date: '$date', services: '$services' } }

但这不是你想要的。您不能轻易地将数据转换为密钥,除非您可以手动完成所有操作。以下查询将是一个选项:

db.test.aggregate( [
    { $group: {
        '_id' : { date: '$date' },
        a: { $sum: { 
            $cond: [ { $eq: [ '$type', 'a' ] }, 1, 0 ]  
        } },
        b: { $sum: { 
            $cond: [ { $eq: [ '$type', 'b' ] }, 1, 0 ]
        } },
        c: { $sum: { 
            $cond: [ { $eq: [ '$type', 'c' ] }, 1, 0 ] 
        } },
    } },
    { $project: {
        _id: 0,
        date: '$_id.date',
        a: '$a',
        b: '$b',
        c: '$c',
    } }
] );

您需要为每种新类型手动添加一行。

答案 1 :(得分:0)

假设您有固定数量的类型,您可以按如下方式解决:

db.collection.aggregate(
{$group : {_id : "$date", 
           a:{$sum:{$cond:[{$eq:['$type','a']},1,0]}},
           b:{$sum:{$cond:[{$eq:['$type','b']},1,0]}},
           c:{$sum:{$cond:[{$eq:['$type','c']},1,0]}}
}},
{$project : {_id : 0, date : "$_id", a: "$a", b : "$b", c : "$c"}}
)