2017-02-23 8 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と呼ばれる空の配列に私の集計クエリの結果を押す行うために私を求めている問題を抱えています

 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. 
[ { _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 } ] 

次は、私は、次のタスクを持っています0

問題は、.toArray()メソッドdataのパラメータが配列のように動作することがあり、時にはそうでないように見えるということです。たとえば、numキーの値をcategoriesの配列に追加する場合は、categories.push(...data["num"])と入力してください。undefined is not iterableというエラーが表示されます。

私は各data.numキーを反復処理できないので、値を抽出してそれを実行中のすべてのdata.num値に加算することはできません。

ここで何が起こっているのか理解できません。

答えて

3

データをグループ化するためにアプリケーションロジックを使用する必要はありません。このタスクでは、mongoDB集約が行われます。 、data出力を消費するために

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

:それが与える

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

:新しいフィールドへ$sum$numフィールドと$pushすべての文書がcategoriesと呼ばれることAll新しいフィールドを使用してクエリに別の$groupを追加arrayであり、最初の要素へのアクセスに使用します。data[0]

+0

あなたのソリューションは私が探していたものに近く、あなたの応答に感謝します。私はあなたの入力後に全体的に私が扱っていることをよりよく理解していると思います。私が明確にしていなかったのは、新しい '{category:" All} '文書を' data'配列の一部にする必要があったことです。私はあなたの下に自分の答えを掲載します。 – m00saca

0

私は何を達成したかっ押したりunshiftingた私たちは一瞬で表示されますようにこののように私のcategories配列に見えたオブジェクト:

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

は私が.reduce()方法をいじり終わったし、それを使用配列categoriesにあります。私はいくつかの-ing console.logを通じて幸運とこれを作ることになった:

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

まず私はcategoriesdataからすべてのオブジェクトをプッシュするスプレッド演算子を使用します。次にsum.reduce()がのval["num"]の累積を返していると宣言します。これは実際にはdata.num(コンソールログは寿命です)です。 allCategoryドキュメント/オブジェクトを作成し、.unshiftを使用して配列の先頭に配置します(この配置は必須です)。次にコールバックを使用します。

私の目標を達成するためのハッキーな方法だと思うし、私は.toArray()のメソッドと変数の正しい順序について試行錯誤しなければならなかった。しかし、それは働いて、私は何かを学びました。 @Bertrand Martel助けてくれてありがとう。

関連する問題