2017-02-23 99 views
1

大家下午好,MongoDB聚合查詢生成的數組迭代

我在MongoDB 3.4中使用聚合查詢的時間非常艱難。我有一個要我做我的聚集查詢的結果推到一個名爲categories空數組,我已經能夠使用此代碼成功地做了一個問題:

var categories = []; 

    database.collection("item").aggregate([{ 
     $group : { 
      _id : "$category", 
      num : {$sum : 1} 
     }}, 
     {$sort:{_id:1}}]).toArray(function(err, data){ 

      categories.push(...data); 
      callback(categories); 
      console.log(categories); 
     }) 

    } 

categories看起來是這樣的:

[ { _id: 'Apparel', num: 6 }, 
{ _id: 'Books', num: 3 }, 
{ _id: 'Electronics', num: 3 }, 
{ _id: 'Kitchen', num: 3 }, 
{ _id: 'Office', num: 2 }, 
{ _id: 'Stickers', num: 2 }, 
{ _id: 'Swag', num: 2 }, 
{ _id: 'Umbrellas', num: 2 } ] 

接下來,我有以下任務:

 In addition to the categories created by your aggregation query, 
    include a document for category "All" in the array of categories 
    passed to the callback. The "All" category should contain the total 
    number of items across all categories as its value for "num". The 
    most efficient way to calculate this value is to iterate through 
    the array of categories produced by your aggregation query, summing   
    counts of items in each category. 

問題是,它看起來像在我的.toArray()方法中,data參數有時像一個數組,有時不起作用。例如,如果我想將num鍵的值添加到categories陣列中,如下所示:categories.push(...data["num"])我收到一條錯誤消息,提示undefined is not iterable

由於我無法迭代每個data.num密鑰,我無法提取它的值並將其添加到所有data.num值的運行總計中。

我不理解這裏發生了什麼?

回答

3

您不需要使用應用程序邏輯來對數據進行分組,mongoDB聚合是針對此任務進行的。

db.item.aggregate([{ 
    $group: { 
     _id: "$category", 
     num: { $sum: 1 } 
    } 
}, { $sort: { _id: 1 } }, { 
    $group: { 
     _id: 1, 
     All: { $sum: "$num" }, 
     categories: { 
      $push: { 
       _id: "$_id", 
       num: "$num" 
      } 
     } 
    } 
}]) 

它提供了:另外$group一個新的領域All$sum$num場和$push所有文件到一個新的領域被稱爲categories添加到您的查詢

{ 
    "_id": 1, 
    "All": 23, 
    "categories": [{ 
     "_id": "Swag", 
     "num": 2 
    }, { 
     "_id": "Office", 
     "num": 2 
    }, { 
     "_id": "Stickers", 
     "num": 2 
    }, { 
     "_id": "Apparel", 
     "num": 6 
    }, { 
     "_id": "Umbrellas", 
     "num": 2 
    }, { 
     "_id": "Kitchen", 
     "num": 3 
    }, { 
     "_id": "Books", 
     "num": 3 
    }, { 
     "_id": "Electronics", 
     "num": 3 
    }] 
} 

供消費的輸出,dataarray,要訪問第一個元素請使用data[0]

var categories = []; 

database.collection("item").aggregate([{ 
    $group: { 
     _id: "$category", 
     num: { $sum: 1 } 
    } 
}, { $sort: { _id: 1 } }, { 
    $group: { 
     _id: 1, 
     All: { $sum: "$num" }, 
     categories: { 
      $push: { 
       _id: "$_id", 
       num: "$num" 
      } 
     } 
    } 
}]).toArray(function(err, data) { 

    var totalCount = data[0]["All"]; 
    console.log("total count is " + totalCount); 

    categories = data[0]["categories"]; 

    for (var i = 0; i < categories.length; i++) { 
     console.log("category : " + categories[i]._id + " | count : " + categories[i].num); 
    } 
}) 
+0

您的解決方案與我正在尋找的內容非常接近,我感謝您的回覆。我認爲,在你的意見之後,我更好地理解了我正在處理的事情。我唯一不清楚的就是需要在'data'數組中創建新的'{category:'All}'文檔部分,我會在你的下面發佈我的答案,這樣你就可以看到我要做什麼了。 – m00saca

0

我想實現推擠或unshifting正如我們將在某一時刻看到這個樣子categories數組的對象是什麼:

var allCategory = { 
     _id: "All", 
     num: [sum of all data.num values] 
} 

我結束了.reduce()方法搞亂,並用它在categories陣列上。我通過一些console.log -ing幸運的,最終作出這樣的:

var categories = []; 

    database.collection("item").aggregate([{ 
     $group : { 
      _id : "$category", 
      num : {$sum : 1} 
     }}, 
     {$sort:{_id:1}}]).toArray(function(err, data){ 
      categories.push(...data); 
      var sum = categories.reduce(function(acc, val){ 
       // console.log(acc, val["num"]) 
       return acc + val["num"] 
      },0); 

      var allCategory = { 
       _id: "All", 
       num: sum 
      } 
      categories.unshift(allCategory) 
      callback(categories); 
     }) 

首先,我用一個傳播運營商的所有對象從推入datacategories。然後聲明sum其中運行.reduce()categories返回val["num"]這是真的data.num(控制檯日誌是生活)的積累。我創建allCategory文檔/對象,然後使用.unshift將其放置在我的categories數組的開頭(此位置是必需的),然後使用我的回調。

我認爲這是一種蠻幹的方式來完成我的目標,我必須經過一些試驗和錯誤的方法和變量在我的.toArray()正確的順序。然而,它工作,我學到了一些東西。感謝@Bertrand Martel的幫助。