Mongodb 基于嵌套文档集的聚合
假设我有接下来的5个文档:Mongodb 基于嵌套文档集的聚合,mongodb,aggregation-framework,Mongodb,Aggregation Framework,假设我有接下来的5个文档: { "_id" : "1", "student" : "Oscar", "courses" : [ "A", "B" ] } { "_id" : "2", "student" : "Alan", "courses" : [ "A", "B", "C" ] } { "_id" : "3", "student" : "Kate", "courses" : [ "A", "B", "D" ] } { "_id" : "4", "student" : "John", "cou
{ "_id" : "1", "student" : "Oscar", "courses" : [ "A", "B" ] }
{ "_id" : "2", "student" : "Alan", "courses" : [ "A", "B", "C" ] }
{ "_id" : "3", "student" : "Kate", "courses" : [ "A", "B", "D" ] }
{ "_id" : "4", "student" : "John", "courses" : [ "A", "B", "C" ] }
{ "_id" : "5", "student" : "Bema", "courses" : [ "A", "B" ] }
我想对集合进行操作,这样它将按学生所修课程的集合(组合)返回一组学生(带他们的_id),并计算每个集合中有多少学生。
在上述示例中,我有3套(组合)课程和学生人数,如下所示:
1-
[“A”,“B”]
这是一个使用分组的聚合操作
db.students.aggregate([{
$group: {
// Uniquely identify the document.
// The $ syntax queries on this field
_id: "$courses",
// Add 1 for each field found (effectively a counter)
count: {$sum: 1}
}
}]);
编辑:
如果课程可以按任何顺序排列,您可以按照编辑的问题中的建议再次执行$unwind
、$sort
和$group
。也可以通过mapReduce
来实现这一点,但我不确定哪一个更快
db.students.mapReduce(
function () {
// Use the sorted courses as the key
emit(this.courses.sort(), this._id);
},
function (key, values) {
return {"students": values, count: values.length};
},
{out: {inline: 1}}
)
谢谢是否可以将学生的
\u id
列表作为每个组的嵌套属性输出?您可以添加另一个组,如学生:{$push:$\u id}
非常感谢!太好了!:)它似乎是根据元素在课程中的排列方式进行分组的。例如,如果有一个记录{“\u id”:“6”,“学生”:“Alan”,“课程”:[“C”,“B”,“a”]}
,则将其视为不同的组合。现在,我想我需要先进行排序,然后再进行分组…@oscar真棒谢谢分享你的发现。我也会看一看并更新我的答案。
{ "_id" : "1", "student" : "Oscar", "courses" : [ "A", "B" ] }
{ "_id" : "2", "student" : "Alan", "courses" : [ "A", "B", "C" ] }
{ "_id" : "3", "student" : "Kate", "courses" : [ "A", "B", "D" ] }
{ "_id" : "4", "student" : "John", "courses" : [ "A", "B", "C" ] }
{ "_id" : "5", "student" : "Bema", "courses" : [ "A", "B" ] }
{ "_id" : "6", "student" : "Alex", "courses" : [ "C", "A", "B" ] }
{ "_id" : [ "C", "A", "B" ], "count" : 1, "students" : [ "6" ] }
{ "_id" : [ "A", "B", "D" ], "count" : 1, "students" : [ "3" ] }
{ "_id" : [ "A", "B", "C" ], "count" : 2, "students" : [ "2", "4" ] }
{ "_id" : [ "A", "B" ], "count" : 2, "students" : [ "1", "5" ] }
db.students.aggregate([
{$unwind: "$courses" },
{$sort : {"courses": 1}},
{$group: {_id: "$_id", courses: {$push: "$courses"}}},
{$group: {_id: "$courses", count: {$sum:1}, students: {$push: "$_id"}}}
])
{ "_id" : [ "A", "B", "D" ], "count" : 1, "students" : [ "3" ] }
{ "_id" : [ "A", "B" ], "count" : 2, "students" : [ "5", "1" ] }
{ "_id" : [ "A", "B", "C" ], "count" : 3, "students" : [ "6", "4", "2" ] }
db.students.aggregate([{
$group: {
// Uniquely identify the document.
// The $ syntax queries on this field
_id: "$courses",
// Add 1 for each field found (effectively a counter)
count: {$sum: 1}
}
}]);
db.students.mapReduce(
function () {
// Use the sorted courses as the key
emit(this.courses.sort(), this._id);
},
function (key, values) {
return {"students": values, count: values.length};
},
{out: {inline: 1}}
)