2015-11-16 13 views
5

我想實現與$ COND $總和:

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

回答

8

$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 
       ] 
      } 
     } 
    }} 
]) 

你看它無論什麼方式,記住這一切都只是數據結構和你有基本過程操縱。無論是在管道處理還是在管道建設本身。

+0

第一種方式有點難。第二個很簡單。雖然應該有簡單的$或$組?希望mongo發佈此功能。 –

+0

@SomnathMuluk考慮到所示的三種方法,我認爲你的意思是「第三種方式」,而對於像我這樣做的所有代碼的記錄都是這樣做的,因爲這是合乎邏輯的方法。如果你的意思是你想要一個'$ in'子句,那麼考慮你首先要求這個提供給'$ cond',那麼這樣一個操作的語法究竟是什麼?你在哪裏指定你想比較的領域?歡迎您以任何此類建議發佈[JIRA](https://jira.mongodb.org/secure/Dashboard.jspa)。 –

+1

是的,我的意思是第二和第三個很容易。並已有建議作爲https://jira.mongodb.org/browse/SERVER-6146 –

0

我認爲,在$不是一個聚合管道運營商。

+0

如何使用「$ setIsSubset」而不是「$ In」? –

+0

語法:'{$ setIsSubset:[]}'。 你需要把你的元素「id」放在一個矩陣中。但是再想一想,我認爲這不是最好的解決方案。 – hecnabae

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