【问题标题】:MongoDb aggregate and group by two fields depending on valuesMongoDb 根据值聚合和分组两个字段
【发布时间】:2014-10-21 21:54:28
【问题描述】:

我想聚合一个给定类型的集合。如果类型是 foo 我想按字段 author 分组,如果类型是 bar 我想按 user。

所有这些都应该发生在一个查询中。

示例数据:

{
   "_id": 1,
   "author": {
     "someField": "abc",
  },
   "type": "foo" 
}

{
   "_id": 2,
   "author": {
     "someField": "abc",
  },
   "type": "foo" 
}

{
   "_id": 3,
   "user": {
     "someField": "abc",
  },
   "type": "bar" 
}

仅当类型为 bar 时,此用户字段才存在。

所以基本上是这样的......试图用$or来表达它。

function () { 
var results = db.vote.aggregate( [ 
   { $or: [ {

      { $match : { type : "foo" } },
      { $group :    { _id : "$author", sumAuthor : {$sum : 1} } } },

      { { $match : { type : "bar" } },
      { $group : { _id : "$user", sumUser : {$sum : 1} } } 
   } ] }
] );
return results;
}

有人对此有好的解决方案吗?

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    我觉得可以

    db.c.aggregate([{
        $group : {
            _id : {
                $cond : [{
                    $eq : [ "$type", "foo"]
                }, "author", "user"]
            },
            sum : {
                $sum : 1
            }
        }
    }]);
    

    【讨论】:

      【解决方案2】:

      下面的解决方法可以稍微清理一下...

      对于“bar”(注意:对于“foo”,你必须稍微改变一下)

          db.vote.aggregate(
              {
                  $project:{
                      user:{ $ifNull: ["$user", "notbar"]},
                      type:1
                  }
              },
              {
                  $group:{
                      _id:{_id:"$user.someField"},
                      sumUser:{$sum:1}
                  }
              }
          )
      

      另请注意:在您的最终答案中,任何不属于“bar”类型的内容都将具有 _id=null

      【讨论】:

        【解决方案3】:

        这里需要的是$cond 运算符,它是一个三元运算符,在条件为真或假时返回特定值。

        db.vote.aggregate([
            { "$group": {
                "_id": null,
                "sumUser": { 
                    "$sum": {
                        "$cond": [ { "$eq": [ "$type", "user" ] }, 1, 0 ]
                    }
                },
                "sumAuhtor": { 
                    "$sum": {
                        "$cond": [ { "$eq": [ "$type", "auhtor" ] }, 1, 0 ]
                    }
                }
            }}
        ])
        

        这基本上测试了当前文档的“类型”,并决定是否将10 传递给$sum 操作。

        如果“用户”和“作者”字段包含与您的示例中相同的值,这也可以避免错误的分组。最终结果是一个包含两种类型计数的文档。

        【讨论】:

        • 不是我需要的。我需要为每个作者提供一份文件。用户及其总和
        • @koengsen 够公平的。我主要是查看您的样本,根据所提供的数据,这只会产生一份文件。那你似乎在询问总数。
        猜你喜欢
        • 2018-04-05
        • 2013-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-10
        • 1970-01-01
        • 1970-01-01
        • 2020-04-25
        相关资源
        最近更新 更多