[英]Iterating through array produced by MongoDB aggregation query
Good afternoon all, 大家下午好
I am having a really tough time working with aggregation queries in MongoDB 3.4. 我在MongoDB 3.4中处理聚合查询时非常艰难。 I have a problem that is asking me to do push the results of my aggregation query into an empty array called
categories
which I have been able to do successfully using this code: 我有一个问题,要求我将聚合查询的结果推送到一个名为
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
looks like this: 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 } ]
Next I have the following task: 接下来,我有以下任务:
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.
The problem is that it seems like inside my .toArray()
method the data
parameter sometimes acts like an array and sometimes not. 问题在于,似乎在我的
.toArray()
方法内部, data
参数有时像数组,有时却像数组。 For example if I wanted to add perhaps just the value of the num
key to the categories
array like so: categories.push(...data["num"])
I get an error stating undefined is not iterable
. 例如,如果我想将
num
键的值仅添加到categories
数组中,例如: categories.push(...data["num"])
我收到一条错误消息,指出undefined is not iterable
。
Since I cannot iterate over each data.num
key I cannot extract it's value and add it to a running total of all data.num
values. 由于无法遍历每个
data.num
键,因此无法提取其值并将其添加到所有data.num
值的运行总计中。
What am I not understanding about what is going on here? 我对这里发生的事情不了解什么?
You don't need to use application logic to group data, mongoDB aggregation is made for this task. 您无需使用应用程序逻辑来对数据进行分组,此任务进行了mongoDB聚合。 Add another
$group
to your query with a new field All
that $sum
your $num
field and $push
all documents to a new field called categories
: 使用新字段将另一个
$group
添加到您的查询中, All
$sum
将您的$num
字段和$push
所有文档$push
到一个名为categories
的新字段中:
db.item.aggregate([{
$group: {
_id: "$category",
num: { $sum: 1 }
}
}, { $sort: { _id: 1 } }, {
$group: {
_id: 1,
All: { $sum: "$num" },
categories: {
$push: {
_id: "$_id",
num: "$num"
}
}
}
}])
It gives : 它给 :
{
"_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
}]
}
For consuming the output, data
is an array , to access the first element use data[0]
: 为了使用输出,
data
是一个数组 ,使用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);
}
})
What I wanted to achieve was pushing or unshifting as we'll see in a moment an object that looked like this into my categories
array: 我想要实现的是推动或保持不变,我们稍后将看到一个类似以下内容的对象进入我的
categories
数组:
var allCategory = {
_id: "All",
num: [sum of all data.num values]
}
I ended up messing with .reduce()
method and used it on the categories
array. 我最终
.reduce()
方法弄乱了,并在categories
数组上使用了它。 I got lucky through some console.log
-ing and ended up making this: 我很幸运通过一些
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);
})
First I use a spread operator to push all the objects from data
into categories
. 首先,我使用散布运算符将
data
所有对象推入categories
。 Then declare sum
which runs .reduce()
on categories
returning the accumulation of val["num"]
which is really data.num
(console log is life). 然后声明对
categories
运行.reduce()
sum
,返回真正是data.num
的val["num"]
data.num
(控制台日志就是生命)。 I create the allCategory
document/object then use .unshift
to place it at the beginning of my categories
array (this placement was a requirement) then use my callback. 我创建了
allCategory
文档/对象,然后使用.unshift
将其放在我的categories
数组的开头(此位置是.unshift
),然后使用回调。
I think it's a hacky way of accomplishing my goal and I had to go through some trial and error as to the correct order of methods and variables in my .toArray()
. 我认为这是实现目标的一种简单方法,我必须对
.toArray()
中方法和变量的正确顺序进行一些试验和错误。 Yet it worked and I learned something. 然而它奏效了,我学到了一些东西。 Thanks for the help @Bertrand Martel .
感谢@Bertrand Martel的帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.