【问题标题】:MongoDB: Aggregation, group by several fieldsMongoDB:聚合,按几个字段分组
【发布时间】:2014-01-09 14:31:46
【问题描述】:

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

{
  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 结果。

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

【问题讨论】:

    标签: node.js mongodb aggregation-framework


    【解决方案1】:

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

    { $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',
        } }
    ] );
    

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

    【讨论】:

    • 这是不正确的。 "$_id.a"、"$_id.b" 和 "$_id.c" 不会返回任何结果。在组部分 _id 对象不包含 a,b,c 字段。
    • 是的,我有固定数量的类型 - 所以你的查询看起来很有趣。我不知道 $project 可以追求 $group。会尽快尝试的。
    【解决方案2】:

    假设你有固定数量的类型,你可以解决它:

    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"}}
    )
    

    【讨论】:

    • 在我看来这与@Derick 的答案非常接近。假设他的答案是经过编辑的..
    • 您可以查看答案的时间。我之前比德里克回答过。
    猜你喜欢
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 2018-08-04
    • 2014-02-27
    • 1970-01-01
    相关资源
    最近更新 更多