2015-08-16 71 views
1

我收集將看看這個,MongoDB的合計數 - (多場數)

{ 
    "_id" : ObjectId("55c8bd1d85b83e06dc54c0eb"), 
    "name" : "xxx", 
    "salary" : 10000, 
    "type" : "type1" 
} 
{ 
    "_id" : ObjectId("55c8bd1d85b83e06dc54c0eb"), 
    "name" : "aaa", 
    "salary" : 10000, 
    "type" : "type2" 
} 
{ 
    "_id" : ObjectId("55c8bd1d85b83e06dc54c0eb"), 
    "name" : "ccc", 
    "salary" : 10000, 
    "type" : "type2" 
} 

我的查詢參數會來的,

{工​​資= 10000,類型= TYPE2}

所以基於該查詢我需要獲取上述查詢的計PARAMS

結果應該是這樣的

{類: 'TYPE1',計數:500} {類別: '2型',計數:200} {類別: '姓名',數:100}

現在我通過點擊三個不同的查詢並構造結果(或)服務器端迭代我可以得到結果來計數。

任何人都可以建議或給我提供很好的方式來獲得上述結果

+0

你會更好地展示你目前在做什麼。你的解釋目前還不清楚,因爲你的「參數」與你所要的輸出的關係。 –

+0

@布萊克斯,我的標準將是或條件(例如薪水> 10000,姓名= xxx)在這個標準中,我需要得到通過這個標準的工資數和曾經有過相同名字的人數。 –

回答

4

你quesstion不是非常清晰,但似乎什麼你想在這裏做的是計數字段中的數據的發生,可選地通過匹配標準的值來過濾這些字段。

這裏$cond運營商允許您將logical condition等轉換成數值:

db.collection.aggregate([ 
    { "$group": { 
     "_id": null, 
     "name": { "$sum": 1 }, 
     "salary": { 
      "$sum": { 
       "$cond": [ 
        { "$gte": [ "$salary", 1000 ] }, 
        1, 
        0 
       ] 
      } 
     }, 
     "type": { 
      "$sum": { 
       "$cond": [ 
        { "$eq": [ "$type", "type2" ] }, 
        1, 
        0 
       ] 
      } 
     } 
    }} 
]) 

的所有值均在同一文件中,並沒有真正使任何意義,他們在這裏分手了,因爲這是額外的正在籌備中。

{ "_id" : null, "name" : 3, "salary" : 3, "type" : 2 } 

否則在長期的形式,這是不是很高性能由於需要使每個文檔的副本,每一個鍵看起來像這樣:

db.collection.aggregate([ 
    { "$project": { 
    "name": 1, 
    "salary": 1, 
    "type": 1, 
    "category": { "$literal": ["name","salary","type"] } 
    }}, 
    { "$unwind": "$category" }, 
    { "$group": { 
    "_id": "$category", 
    "count": { 
     "$sum": { 
     "$cond": [ 
      { "$and": [ 
      { "$eq": [ "$category", "name"] }, 
      { "$ifNull": [ "$name", false ] } 
      ]}, 
      1, 
      { "$cond": [ 
      { "$and": [ 
       { "$eq": [ "$category", "salary" ] }, 
       { "$gte": [ "$salary", 1000 ] } 
      ]}, 
      1, 
      { "$cond": [ 
       { "$and": [ 
       { "$eq": [ "$category", "type" ] }, 
       { "$eq": [ "$type", "type2" ] } 
       ]}, 
       1, 
       0 
      ]} 
      ]} 
     ] 
     } 
    } 
    }} 
]) 

而且它的輸出:

{ "_id" : "type", "count" : 2 } 
{ "_id" : "salary", "count" : 3 } 
{ "_id" : "name", "count" : 3 } 

如果您的文檔沒有統一的密鑰名稱,或者無法在管道條件中指定每個密鑰,請使用mapReduce代替:

db.collection.mapReduce(
    function() { 
     var doc = this; 
     delete doc._id; 

     Object.keys(this).forEach(function(key) { 
      var value = ((key == "salary") && (doc[key] < 1000)) 
       ? 0 
       : ((key == "type") && (doc[key] != "type2")) 
       ? 0 
       : 1; 

      emit(key,value); 
     }); 
    }, 
    function(key,values) { 
     return Array.sum(values); 
    }, 
    { 
     "out": { "inline": 1 } 
    } 
); 

而且它的輸出:

"results" : [ 
      { 
        "_id" : "name", 
        "value" : 3 
      }, 
      { 
        "_id" : "salary", 
        "value" : 3 
      }, 
      { 
        "_id" : "type", 
        "value" : 2 
      } 
    ] 

這基本上是一個有條件的計數同樣的事情,但你只指定了「反向」的狀況下,你想,只爲要到田間地頭過濾條件。當然,這種輸出格式很容易作爲單獨的文檔發佈。

同樣的方法適用於在條件滿足的條件下測試滿足條件的條件並返回1滿足條件的條件或0不適用於總計計數的條件。

+0

感謝您的明確解釋,它確實幫助了我很多並且澄清了一些問題,如何在兩個標準中都使用「like」條件而不是「equals」 ** mapReduce **和**聚合**功能。 –

+0

@ venkat.s聚合框架沒有用於邏輯比較的操作符。 mapReduce是JavaScript,因此您可以使用正則表達式作爲邏輯比較。 –

+0

非常感謝 –

0

可以使用aggregation爲以下查詢:

db.collection.aggregate({ 
     $match: { 
      salary: 10000, 
      //add any other condition here 
     } 
    }, { 
     $group: { 
      _id: "$type", 
      "count": { 
       $sum: 1 
      } 
     } 
    }, { 
     $project: { 
      "category": "$_id", 
      "count": 1, 
      _id: 0 
     } 
    } 
+0

我嘗試使用聚合函數,但我可以得到任何一個標準的計數。我希望每個標準字段的計數(例如,工資標準計數,類型標準計數) –