如何在mongo聚合中使用$ in或$ nin $ group $ cond

时间:2015-11-16 12:02:44

标签: mongodb mongodb-query aggregation-framework

我希望通过使用$或on property来获得$ cond的$ sum:

db.collectionName.aggregate(
{
   "$group": {
     "_id":'$created_at',
     "count": {"$sum": 1},
     "count_failure": {
         "$sum": {
           "$cond": [
               {
                 "$id":
                  { "$in": [ 0,100,101,102,103,104,105 ] }
               }, 
               1,
               0
              ] 
           }
         }
    }  
 }
)

但错误说:Invalid operator "$id"

语法有什么问题?或者我错误地写了查询。

目前我通过以下方式实现这一目标:

db.collectionName.aggregate(
{
   "$group": {
     "_id":'$created_at',
     "count": {"$sum": 1},
     "count_failure": {
         "$sum": {
           "$cond": [
               {
                 "$or":[
                  { "$eq": [ "$id", 0 ] },
                  { "$eq": [ "$id", 100 ]},
                  { "$eq": [ "$id", 101 ]},
                  { "$eq": [ "$id", 102 ]},
                  { "$eq": [ "$id", 103 ]},
                  { "$eq": [ "$id", 104 ]},
                  { "$eq": [ "$id", 105 ]}
                 ]
               }, 
               1,
               0
              ] 
           }
         }
   }  
 }
)

3 个答案:

答案 0 :(得分:10)

$setIsSubset上的比较比您正在使用的$or条件更短,但它仍然基本上可以正常执行您的工作。

$setIsSubset的唯一问题是每个参数都是一个数组,因此您需要将单个元素转换为单个元素数组。使用$map

这很容易
db.collectionName.aggregate([
    { "$group": {
        "_id": "$createdAt",
        "count": { "$sum": 1 },
        "count_failure": {
            "$sum": {
                "$cond": [
                    { "$setIsSubset": [
                        { "$map": {
                            "input": ["A"],
                            "as": "el",
                            "in": "$id"
                        }},
                        [ 0,100,101,102,103,104,105 ],
                    ]},
                    1,
                    0
                ]
            }
        }
    }}    
])

或者,如果您愿意,则使用$anyElementTrue来匹配奇异值的参数数组:

db.collectionName.aggregate([
    { "$group": {
        "_id": "$createdAt",
        "count": { "$sum": 1 },
        "count_failure": {
            "$sum": {
                "$cond": [
                    { "$anyElementTrue": { "$map": {
                        "input": [ 0,100,101,102,103,104,105 ],
                        "as": "el",
                        "in": { "$eq": [ "$$el", "$id" ] }
                    }}},
                    1,
                    0
                ]
            }
        }
    }}
])

$map正在遍历参数以匹配单数而不是将单数形式强制转换为数组。

当然,由于任何一种表单基本上都会向true/false提供$cond,因此您可以在必要时使用$not来反转逻辑:

db.collectionName.aggregate([
    { "$group": {
        "_id": "$createdAt",
        "count": { "$sum": 1 },
        "count_failure": {
            "$sum": {
                "$cond": [
                    { "$not": [{ "$anyElementTrue": { "$map": {
                        "input": [ 0,100,101,102,103,104,105 ],
                        "as": "el",
                        "in": { "$eq": [ "$$el", "$id" ] }
                    }}}]},
                    1,
                    0
                ]
            }
        }
    }}
])

这实际上取决于你如何看待它,但仅仅作为提供的参数,你就不会在$or的原始形式上获得任何东西。它可能看起来更清洁,更容易键入"但通常我不会"键入"这样的逻辑直接进入聚合管道,而是首先基于普通列表生成结构的那部分:

var failList = [ 0,100,101,102,103,104,105 ];

var orCondition = failList.map(function(el) { 
    return { "$eq": [ "$id", el ] }
})

然后只使用管道定义中重新映射的数组内容:

    { "$group": {
        "_id": "$createdAt",
        "count": { "$sum": 1 },
        "count_failure": {
            "$sum": {
                "$cond": [
                    { "$or": orCondition },
                    1,
                    0
                ]
            }
        }
    }}
])

无论你如何看待它,请记住它只是数据结构而且你有基本的操作过程。管道处理内部以及管道构造本身。

答案 1 :(得分:0)

我认为$ in不是聚合管道运营商。

答案 2 :(得分:0)

首先,您应该在项目中使用$map创建$id列表,然后在群组中使用setIsSubset,如下所示:

db.collectionName.aggregate([{
  "$project": {
    "idsArray": {
      "$map": {
        "input": ["A"],
        "as": "el",
        "in": {
          "$cond": [{
              "$eq": ["$$el", "A"]
            }, "$id",
            null
          ]
        }
      }
    }
  }
}, {
  "$group": {
    "_id": "$created_at",
    "count": {
      "$sum": 1
    },
    "count_failure": {
      "$sum": {
        "$cond": [{
            "$setIsSubset": ["$idsArray", [
              0,
              100,
              101,
              102,
              103,
              104,
              105
            ]]
          },
          1,
          0
        ]
      }
    }
  }
}])