Node.js MongoDB跨不同文档在两个数组中的项目聚合计数?
以下是我的MongoDB集合模式:Node.js MongoDB跨不同文档在两个数组中的项目聚合计数?,node.js,mongodb,mongoose,mongodb-query,aggregation-framework,Node.js,Mongodb,Mongoose,Mongodb Query,Aggregation Framework,以下是我的MongoDB集合模式: company: String model: String cons: [String] // array of tags that were marked as "cons" pros: [String] // array of tags that were marked as "pros" 我需要对其进行聚合,以便获得以下输出: [{ "_id": { "company": "Lenovo", "model": "T400" },
company: String
model: String
cons: [String] // array of tags that were marked as "cons"
pros: [String] // array of tags that were marked as "pros"
我需要对其进行聚合,以便获得以下输出:
[{
"_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'} }
}});
但我得到了以下结果:
{
"_id": {
"company": "Lenovo",
"model": "T400"
},
"tags": [
{
"tag": false,
"pros": 7
}
]
}
聚合的正确方法是什么?是的,考虑到存在多个数组,这有点困难,如果同时尝试这两个数组,最终会出现一个“笛卡尔条件”,其中一个数组乘以另一个数组的内容 因此,只需在开始时组合数组内容,这可能表明您首先应该如何存储数据:
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) {
}
)
因此,通过第一阶段,操作符将“type”值添加到每个数组的每个项中。这并不重要,因为所有项都应该处理“唯一的”,无论如何,操作符将每个数组“重叠”为一个单数数组
如前所述,您可能首先应该以这种方式存储
然后处理,其中每个“赞成”和“反对”然后通过to评估其匹配的“类型”,返回1
或0
,其中匹配分别为true/false
,并返回到聚合累加器
这为您提供了一个“逻辑匹配”,可以根据指定的分组键对聚合操作中的每个“类型”进行计数。在此,我们是否可以假定“赞成”或“反对”中的“标记”在任一数组中都是唯一的,或者实际上在两个数组中都是唯一的?当然是每个文档。正确,每个文档的标记都是唯一的(“两个数组中都是唯一的”),所以要完全清楚。“SomeTag”只会在每个文档中出现一次,比如说“赞成”,而不是“反对”?@BlakesSeven不,一个标记可能会同时出现在“赞成”和“反对”中,如果它可以同时出现在两个文档中,这是可以的。这里的关键元素是,它从来不会在say“pros”中出现超过一次。下面是输出:
{u id:{“company”:“Lenovo”,“model”:“T400”,“tag”:“Quality”},“pros”:132,“cons”:324}
@MikeVayvala So?重点是什么?这应该是您想要的,尽管您的“所需输出”不再是真正理想的。每个“赞成”和“反对”都按分组键计数。这就是你所要求的。