想象我有这样的集合:
{
"_id": "10280",
"city": "NEW YORK",
"state": "NY",
"departments": [
{"departmentType":"01",
"departmentHead":"Peter"},
{"departmentType":"02",
"departmentHead":"John"}
]
},
{
"_id": "10281",
"city": "LOS ANGELES",
"state": "CA",
"departments": [
{"departmentType":"02",
"departmentHead":"Joan"},
{"departmentType":"03",
"departmentHead":"Mary"}
]
},
{
"_id": "10284",
"city": "MIAMI",
"state": "FL",
"department": [
"departments": [
{"departmentType":"01",
"departmentHead":"George"},
{"departmentType":"02",
"departmentHead":"Harry"}
]
}
我希望获得每个departmentType的计数,例如:
[{"departmentType":"01", "dCount":2},
{"departmentType":"02", "dCount":3},
{"departmentType":"03", "dCount":1}
]
为此,我已经尝试了几乎所有内容,但我在网上找到的所有示例都更容易,其中group by是在文档的根级别的字段上完成的。相反,在这里我尝试按departmentType进行分组,这似乎打破了我到目前为止发现的所有内容。
有关如何使用Mongoose的聚合实现或mapreduce执行此操作的任何想法?
理想情况下,我希望排除所有显示< = 1的departmentTypes,并按departmentType对结果进行排序。
提前谢谢大家!
答案 0 :(得分:0)
您需要展开departments数组,该数组将为数组中的每个条目创建一个文档,以便您可以在管道中聚合它们。
不幸的是,您无法预先过滤departmentTypes< = 1,因为$ size只会获取一个确切的值,但您可以将其从结果中过滤掉。它不是很好,但它的确有效。此示例仅预先过滤那些具有完全2个部门的记录,但它仅用于演示,您可能希望删除第一个$匹配,因为我们在稍后的结果上使用第二个$匹配过滤掉< = 1;
db.runCommand({
aggregate: "so",
pipeline: [
{ // filter out only records with 2 departments
$match: {
departments: { $size: 2 }
}
},
// unwind - create a doc for each department in the array
{ $unwind: "$departments" },
{ // aggregate sum of departments by type
$group: {
_id: "$departments.departmentType",
count: { $sum: 1 },
}
},
{ // filter out departments with <=1
$match: {
count: { $gt: 1 },
}
},
{ // rename fields as per example
$project: {
_id: 0,
departmentType: "$_id",
dCount: "$count",
}
}
]
});
请注意,我还假设您之前的json样本有拼写错误,而“部门”实际上并不存在。假设所有文档与前两个文档具有相同的模式,此代码将起作用。
如果您对所获得的实际字段名称不感兴趣,请随意删除第一个$ match和最后一个$ project。