2013-01-11 100 views
2

我有一個文檔的集合,如下所示: {

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" 

}

這裏是聚集查詢我試着寫,我想do(請參見注釋掉的部分)是爲每個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'一行。我試圖創建的邏輯是: 「添加errorCodes設置結果的值。原因碼如果它以A,B,S或N開頭,否則不需要添加任何內容」。

爲了記錄上述情況,ErrorCode的設置包含:
... ErrorCode的:S1002,A1001], ...

回答

4

$group爲什麼不能把條件表達式,這是該行不管用。 $project是您可以基於$cond itional表達式(等等)轉換原始文檔的階段。

你之前,你可以$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。您可以像使用$cond一樣使用$ project,但是那麼您的errorCodes數組將具有空字符串條目以及所有正確的錯誤代碼。

0

由於蒙戈2.4,$正則表達式可用於模式匹配,而不是作爲一個表達式返回一個布爾值,它是什麼了$ COND需要

然後,您可以使用一個$匹配運營商使用在$正則表達式關鍵字:

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" 
       ] 
      } 
     } 
    } 
} 
]