使用aggregate或map / reduce的新功能。我希望所有文档中名为“tags”的数组字段中的项目数。我正在使用猫鼬。谢谢!
示例:
doc 1
tags: ['A', 'B', 'C', 'D']
doc 2
tags: ['A', 'B']
doc 3
tags: ['D']
结果:{A: 2, B: 2, C: 1, D: 2}
还要计算总数组项数,以便计算百分比(例如,A = 2/7)
答案 0 :(得分:1)
尽我所能,我可以做到这样的事情:
db.getCollection('tags').aggregate([
{ "$unwind": "$tags" },
{ "$group": {
"_id": "$tags",
"count": { "$sum": 1 }
}},
{ "$sort": { "_id": 1 } },
{ "$group": {
"_id": null,
"tags": { "$push": { "k": "$_id", "v": "$count" } }
}},
{ "$replaceRoot": {
"newRoot": {
"$mergeObjects": [
{ "$arrayToObject": "$tags" },
{ "total": { "$sum": "$tags.v" } }
]
}
}}
])
如果你没有MongoDB 3.6功能,你可以简单地转换输出:
db.getCollection('tags').aggregate([
{ "$unwind": "$tags" },
{ "$group": {
"_id": "$tags",
"count": { "$sum": 1 }
}},
{ "$sort": { "_id": 1 } },
{ "$group": {
"_id": null,
"tags": { "$push": { "k": "$_id", "v": "$count" } }
}}
]).map( d =>
Object.assign(
d.tags.reduce((acc,curr) => Object.assign(acc, { [curr.k]: curr.v }), {}),
{ total: d.tags.reduce((acc,curr) => acc + curr.v, 0) }
)
)
无论哪种方式都会产生:
{
"A" : 2.0,
"B" : 2.0,
"C" : 1.0,
"D" : 2.0,
"total" : 7.0
}
如果你想要"百分比"在那里,您可以发布处理输出,因为所有数字已经存在,或者只是改变处理。
对于MongoDB 3.6
db.getCollection('tags').aggregate([
{ "$unwind": "$tags" },
{ "$group": {
"_id": "$tags",
"count": { "$sum": 1 }
}},
{ "$sort": { "_id": 1 } },
{ "$group": {
"_id": null,
"tags": { "$push": { "k": "$_id", "v": "$count" } } ,
"total": { "$sum": "$count" }
}},
{ "$replaceRoot": {
"newRoot": {
"$mergeObjects": [
{ "$arrayToObject": {
"$map": {
"input": "$tags",
"in": {
"k": "$$this.k",
"v": {
"count": "$$this.v",
"perc": { "$multiply": [{ "$divide": [ "$$this.v", "$total" ] }, 100 ] }
}
}
}
}},
{ "total": "$total" }
]
}
}}
])
或更低版本,仍在处理输出:
db.getCollection('tags').aggregate([
{ "$unwind": "$tags" },
{ "$group": {
"_id": "$tags",
"count": { "$sum": 1 }
}},
{ "$sort": { "_id": 1 } },
{ "$group": {
"_id": null,
"tags": { "$push": { "k": "$_id", "v": "$count" } },
"total": { "$sum": "$count" }
}}
]).map( d =>
Object.assign(
d.tags.reduce((acc,curr) =>
Object.assign(acc, { [curr.k]: { count: curr.v, perc: curr.v / d.total * 100 } }),
{}
),
{ total: d.total }
)
)
输出包括每个分组键上的两个键:
{
"A" : {
"count" : 2.0,
"perc" : 28.5714285714286
},
"B" : {
"count" : 2.0,
"perc" : 28.5714285714286
},
"C" : {
"count" : 1.0,
"perc" : 14.2857142857143
},
"D" : {
"count" : 2.0,
"perc" : 28.5714285714286
},
"total" : 7.0
}
请注意,MongoDB shell对现代JavaScript功能有一点限制。在现代JavaScript环境中,例如最近发布的Nodejs,您可以将转换缩短一点:
result.map(({ _id, tags, ...d }) =>
({
..tags.reduce((acc,curr) =>
({ ...acc, [curr.k]: { count: curr.v, perc: curr.v / d.total * 100 }),
{}
),
...d
})
)