Mongodb 基于嵌套文档集的聚合

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

假设我有接下来的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", "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}}
)