3

我有一个包含如下文档的集合:{

ipAddr: '1.2.3.4',
"results" : [
             {
                     "Test" : "Sight",
                     "Score" : "FAIL",
                     "Reason" : "S1002"
             },
             {
                     "Test" : "Speed",
                     "Score" : "FAIL",
                     "Reason" : "85"
             },
             {
                     "Test" : "Sound",
                     "Score" : "FAIL",
                     "Reason" : "A1001"
             }
     ],
     "finalGrade" : "FAILED"

}

这是我正在尝试编写的聚合查询,我想要做的(见注释掉的部分)是创建一个分组字段,每个 ipAddr,“原因/错误”代码,但前提是原因代码以一个特定的字母,并且只添加一次代码,我尝试了以下方法:

 db.aggregate([
   {$group: 
        {  _id: "$ipAddr", 
         attempts: {$sum:1}, 
         results: {$push: "$finalGrade"},    
        // errorCodes: {$addToSet: {$cond: ["$results.Reason": /[A|B|S|N.*/, "$results.Reason", ""]}},                                                              
        finalResult: {$last: "$finalGrade"} } 
   }
]);

一切正常,不包括注释掉的“errorCodes”行。我试图创建的逻辑是:“添加错误代码设置结果的值。如果它以 A、B、S 或 N 开头,则原因代码,否则没有可添加的内容”。

对于上面的记录,errorCodes 集包含:
... errorCodes: [S1002,A1001], ...

4

2 回答 2

5

$group不能采用条件表达式,这就是该行不起作用的原因。$project是您可以基于$condional 表达式(除其他外)转换原始文档的阶段。

您需要先在聚合管道中执行两个步骤$group- 首先您需要$unwind结果数组,然后您需要$match过滤掉您不关心的结果。

这将做一件简单的事情,只需将结果与您不关心保留的错误代码一起丢弃,但听起来您想计算包括所有错误代码在内的失败总数,然后只将特定错误代码添加到输出中大批?没有直接的方法可以做到这一点,您必须$group $unwind在管道中进行两次传递。

类似的事情会做到这一点:

db.aggregate([
   {$unwind : "$results"},
   {$group:
        { _id: "$ipAddr",
          attempts: {$sum:1},
          results: {$push : "$results"},
          finalGrade: {$last : "$finalGrade" } 
        } 
   },
   {$unwind: "$results"},
   {$match: {"results.Reason":/yourMatchExpression/} },
   {$group: 
        {  _id: "$ipAddr", 
         attempts: {$last:"$attempts"},    
         errorCodes: {$addToSet: "$results.Reason"},                                                              
        finalResult: {$last: "$finalGrade"}
   }
]);

如果您只想计算具有匹配错误代码的尝试,那么您可以使用单个来执行此$group操作 - 您需要这样做$unwind,$match$group. 您可以像以前一样使用 $project $cond,但是您的 errorCodes 数组将有一个空字符串条目以及所有正确的错误代码。

于 2013-01-12T03:57:03.803 回答
0

从 Mongo 2.4 开始,$regex 可用于模式匹配,但不能作为返回布尔值的表达式,这是 $cond 所要求的

然后,您可以使用 $match 运算符来使用 $regex 关键字:

http://mongotry.herokuapp.com/#?bookmarkId=52fb39e207fc4c02006fcfed

[
{
    "$unwind": "$results"
},
{
    "$match": {
        "results.Reason": {
            "$regex": "[SA].*"
        }
    }
},
{
    "$group": {
        "_id": "$ipAddr",
        "attempts": {
            "$sum": 1
        },
        "results": {
            "$push": "$finalGrade"
        },
        "undefined": {
            "$last": "$finalGrade"
        },
        "errorCodes": {
            "$addToSet": "$results.Reason"
        }
    }
}
]

或者您可以使用 $substr 因为您的模式匹配非常简单 http://mongotry.herokuapp.com/index.html#?bookmarkId=52fb47bc7f295802001baa38

[
{
    "$unwind": "$results"
},
{
    "$group": {
        "_id": "$ipAddr",
        "errorCodes": {
            "$addToSet": {
                "$cond": [
                    {
                        "$or": [
                            {
                                "$eq": [
                                    {
                                        "$substr": [
                                            "$results.Reason",
                                            0,
                                            1
                                        ]
                                    },
                                    "A"
                                ]
                            },
                            {
                                "$eq": [
                                    {
                                        "$substr": [
                                            "$results.Reason",
                                            0,
                                            1
                                        ]
                                    },
                                    "S"
                                ]
                            }
                        ]
                    },
                    "$results.Reason",
                    "null"
                ]
            }
        }
    }
}
]
于 2014-02-12T11:00:32.740 回答