汇总与真实

时间:2015-07-25 16:24:37

标签: mongodb mongodb-query aggregation-framework

我正在努力与mongodb中的聚合。我有以下类型的文件:

{
    "_id": "xxxx",
    "workHome": true,
    "commute": true,
    "tel": false,
    "weekend": true,
    "age":39
},
{
    "_id": "yyyy",
    "workHome": false, 
    "commute": true, 
    "tel": false, 
    "weekend": true,
    "age":32
},
{
    "_id": "zzzz",
    "workHome": false,
    "commute": false,
    "tel": false,
    "weekend": false,
    "age":27
}

除此之外,我想通过文档中“true”的字段总数生成聚合。文档中总共有4个布尔字段,因此我希望查询将它们组合在一起以生成以下输出(例如,总共包含100个文档的集合中的示例):

0:20
1:30
2:10
3:20
4:20

这意味着:100个文件中有100个“全部为假”,30个文档“1x为真”,10个文档“2x为真”等等,总共“全部4个为真”。

有没有办法用$ aggregate语句执行此操作?现在我试图通过'真'值的$ sum来$ group,但是找不到让条件查询起作用的方法。

1 个答案:

答案 0 :(得分:1)

因此,假设数据与“workHome”,“commute”,“tel”和“weekend”等所有相同的字段一致,那么您将继续进行“逻辑”评估,例如:

db.collection.aggregate([
  { "$project": {
    "mapped": { "$map": {
      "input": ["A","B","C","D"],
      "as": "el",
      "in": { "$cond": [
        { "$eq": [ "$$el", "A" ] },
        "$workHome",
        { "$cond": [
          { "$eq": [ "$$el", "B" ] },
          "$commute",
          { "$cond": [
            { "$eq": [ "$$el", "C" ] },
            "$tel",
            "$weekend"
          ]}
        ]}
      ]}
    }}
  }},
  { "$unwind": "$mapped" },
  { "$group": {
    "_id": "$_id",
    "size": { "$sum": { "$cond": [ "$mapped", 1, 0 ] } }
  }},
  { "$group": {
      "_id": "$size",
      "count": { "$sum": 1 }
  }},
  { "$sort": { "_id": 1 } }
])

从简单的样本中可以看出:

{ "_id" : 0, "count" : 1 }
{ "_id" : 2, "count" : 1 }
{ "_id" : 3, "count" : 1 }

为了解决这个问题,首先$map运算符首先将字段的值转换为与字段本身相同长度的数组。这样做是通过$cond将“输入”的每个元素与预期值进行比较,并将true条件返回到匹配位置,或者转移到{{1}中嵌入的下一个条件这个"ternary"运算符的一部分。完成此操作直到满足所有逻辑匹配,并为第一个文档生成类似字段的值数组:

false

下一步是$unwind数组元素以进行进一步比较。这会将每个数组元素的“反规范化”分离为单独的文档,并且在处理数组时通常需要在聚合管道中使用。

完成此操作后,将调用$group管道阶段,以评估具有[true,true,false,true] 值的元素的“总数”。相同的true三元组用于将逻辑$cond条件转换为数值,并将其传送到$sum累加器以进行添加。

由于true/false_id中提供的“分组键”是原始文档$group值,因此当前总计是_id字段的每个文档。为了获得整个集合(或选择)上“计数”的总计,然后调用更进一步的true阶段,其中分组键是每个匹配的$group结果的返回“大小”文档。

在那里使用的true累加器只为分组键上的每个匹配添加$sum,从而“计算”每个匹配计数的出现次数。

最后$sort匹配“key”的数量,以便为结果生成一些顺序。

为了记录,对于即将发布的MongoDB(写作时),这包括1运算符,这是非常好的:

$filter

所以现在只有“两个”管道阶段与MongoDB 2.6及以上版本的原始语句做同样的事情。

因此,如果您自己的应用程序本身处于“开发”阶段,或者您对此感到好奇,那么请查看现在可以使用此功能的Development Branch releases