这是我的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: '$_idpany', model: '$_id.model', prosTag: '$pros' }, prosTagCount: { $sum: 1 } }}); aggParams.push({$group: { _id: { company:'$_idpany', 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匹配的内容返回到 $sum 聚合累加器.
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跨不同文档的两个数组中的项目总计计数?
发布评论