MongoDB跨不同文档的两个数组中的项目总计计数? [英] MongoDB aggregate count of items in two arrays across different documents?
问题描述
这是我的MongoDB收集模式:
Here is my MongoDB collection schema:
company: String
model: String
cons: [String] // array of tags that were marked as "cons"
pros: [String] // array of tags that were marked as "pros"
我需要对其进行汇总,以便获得以下输出:
I need to aggregate it so I get the following output:
[{
"_id": {
"company": "Lenovo",
"model": "T400"
},
"tags": {
tag: "SomeTag"
pros: 124 // number of times, "SomeTag" tag was found in "pros" array in `Lenovo T400`
cons: 345 // number of times, "SomeTag" tag was found in "cons" array in `Lenovo T400`
}
}...]
我尝试执行以下操作:
var aggParams = {};
aggParams.push({ $unwind: '$cons' });
aggParams.push({ $unwind: '$pros' });
aggParams.push({$group: {
_id: {
company: '$company',
model: '$model',
consTag: '$cons'
},
consTagCount: { $sum: 1 }
}});
aggParams.push({$group: {
_id: {
company: '$_id.company',
model: '$_id.model',
prosTag: '$pros'
},
prosTagCount: { $sum: 1 }
}});
aggParams.push({$group: {
_id: {
company:'$_id.company',
model: '$_id.model'
},
tags: { $push: { tag: { $or: ['$_id.consTag', '$_id.prosTag'] }, cons: '$consTagCount', pros: '$prosTagCount'} }
}});
但是我得到了以下结果:
But I got the following result:
{
"_id": {
"company": "Lenovo",
"model": "T400"
},
"tags": [
{
"tag": false,
"pros": 7
}
]
}
用aggregation
执行此操作的正确方法是什么?
What is the right way to do this with aggregation
?
推荐答案
是的,考虑到存在多个数组,这会有点困难,如果同时尝试这两个数组,则会遇到笛卡尔条件",其中一个arrray将另一个的内容相乘.
Yes this is a bit harder considering that there are multiple arrays, and if you try both at the same time you end up with a "cartesian condition" where one arrray multiplies the contents of the other.
因此,只需在开始时合并数组内容,这可能表明您首先应该如何存储数据:
Therefore, just combine the array content at the beginning, which probably indicates how you should be storing the data in the first place:
Model.aggregate(
[
{ "$project": {
"company": 1,
"model": 1,
"data": {
"$setUnion": [
{ "$map": {
"input": "$pros",
"as": "pro",
"in": {
"type": { "$literal": "pro" },
"value": "$$pro"
}
}},
{ "$map": {
"input": "$cons",
"as": "con",
"in": {
"type": { "$literal": "con" },
"value": "$$con"
}
}}
]
}
}},
{ "$unwind": "$data" }
{ "$group": {
"_id": {
"company": "$company",
"model": "$model",
"tag": "$data.value"
},
"pros": {
"$sum": {
"$cond": [
{ "$eq": [ "$data.type", "pro" ] },
1,
0
]
}
},
"cons": {
"$sum": {
"$cond": [
{ "$eq": [ "$data.type", "con" ] },
1,
0
]
}
}
}
],
function(err,result) {
}
)
因此,通过第一个 $project
阶段 $map
运算符会将类型"值添加到每个数组的每个项目中.并不是说这里真的很重要,因为所有项目无论如何都应该处理唯一", $setUnion
运算符将每个数组污染"为单个数组.
So via the first $project
stage the $map
operators are adding the "type" value to each item of each array. Not that it really matters here as all items should process "unique" anyway, the $setUnion
operator "contatenates" each array into a singular array.
如前所述,您可能应该首先以这种方式存储.
As mentioned earlier, you probably should be storing in this way in the first place.
然后执行 $unwind
后跟 $group
,然后通过 1
或0
分别与true/false
匹配的内容返回到
Then process $unwind
followed by $group
, wherein each "pros" and "cons" is then evaluated via $cond
to for it's matching "type", either returning 1
or 0
where the match is respectively true/false
to the $sum
aggregation accumulator.
这为您提供了逻辑匹配",可以根据指定的分组键对聚合操作中的每个类型"进行计数.
This gives you a "logical match" to count each respective "type" within the aggregation operation as per the grouping keys specified.
这篇关于MongoDB跨不同文档的两个数组中的项目总计计数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!