2014-10-21 75 views
0

我想聚合一个给定类型的集合。如果类型为我想组由现场笔者,如果类型为酒吧我想按用户MongoDb聚合和根据值取决于两个字段的组

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

实施例的数据:如果类型为酒吧

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

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

{ 
    "_id": 3, 
    "user": { 
    "someField": "abc", 
    }, 
    "type": "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; 
} 

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

回答

1

我认为它可以通过

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

下面的解决方案可以清理有点...

为“条”(注:“富”,你必须改变一点)

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

还要注意:在你最终的答案,任何类型为“栏”不将有一个_id = NULL

0
完成

这里你想要的是$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操作。

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

+0

不是我所需要的。我需要每个作者的文档。用户与他们的总和 – koengsen 2014-10-22 06:45:59

+0

@koengsen足够。我主要是看你的样本,根据所提供的数据只能得到一份文件。这和你似乎在要求总数。 – 2014-10-22 08:24:24