如何在聚合中找到集合的映射ID

时间:2016-08-12 09:25:34

标签: mongodb mongodb-query aggregation-framework

我想找到"studentId"的计数,其中"classId""cls12sc""subjectId""19690112"且此"subjectId"每次使用都不同聚合。此处"classId"会动态传递,"classId"我需要获得与"subjectId"相关联的"classId"点数与"subjectId""sScore"条件匹配。 这是我的收藏(学生)Json数据:

架构:

{
"_id" : ObjectId("53f63fc8f2b643f6ebb8a1a9"),
"subjectId" : 19690112,
"studentId" : "ads5ad2",
"sScore" : 25
},
{
"_id" : ObjectId("53f63fc8f2b643f6ebb8a1a2"),
"subjectId" : 19690112,
"studentId" : "s5sdf45",
"sScore" : 85
},
{
"_id" : ObjectId("53f63fc8f2b643f6ebb8a902"),
"subjectId" : 19690112,
"classId" : "cls12sc",
"sScore" : 64
}

为了更清晰enter image description here

,请参阅此附加图片

这是我的聚合管道:

var classId = "cls12sc" ;
var subjectId = "19690112";
db.Students.aggregate([
  {$match:{"classId" : classId, "subjectId": subjectId }},
  {$group:{"_id" : "$subjectId", count: { $sum: 1 }}}
]);

但我不想在同一个集合中两次使用var声明。我想只传递classId。从classId开始,它应该获取subjectId并获得计数。 查看可能的收集数据并输出可能性:

{
    "_id" : ObjectId("53f63fc8f2b643f6ebb8a1a9"),
    "subjectId" : 19690112,
    "studentId" : "ads5ad2",
    "sScore" : 25
    },
    {
    "_id" : ObjectId("53f63fc8f2b643f6ebb8a1a2"),
    "subjectId" : 19690112,
    "studentId" : "s5sdf45",
    "sScore" : 85
    },
    {
    "_id" : ObjectId("53f63fc8f2b643f6ebb8a902"),
    "subjectId" : 19690112,
    "classId" : "cls12sc",
    "sScore" : 64
}
{ 
    "_id" : ObjectId("53Ro6GpGjJTeam2JxfN"), 
    "subjectId" : "567818ec20a3d410709bb202", 
    "studentId" : "kobo2WfCpN7RHMxi7",
    "sScore" : 89
}
{ 
    "_id" : ObjectId("53badBbn9dnv88qXdrT"), 
    "subjectId" : "567818ec20a3d410709bb202", 
    "studentId" : "AYQ48otoD345ZWAumnMD",
    "sScore" : 8
}
{ 
    "_id" : ObjectId("53pLhmMajApQDDzhonf"), 
    "subjectId" : "567818ec20a3d410709bb202", 
    "studentId" : "czASSwXvaeRA2ZXfp", 
    "sScore" : "12"
}
{ 
    "_id" : ObjectId("53g4tCFQFhobasRCkTy"), 
    "subjectId" : "567818ec20a3d410709bb202", 
    "classId" : "AYQ48otoDZWAumnMD",
    "sScore" : 77
}
{ 
    "_id" : ObjectId("53TkCfKE29ZCsXJv7CZ"), 
    "subjectId" : "567814d620a3d410709b91ba", 
    "studentId" : "5yJdSrdrLKt9DDQRW",
    "sScore" : 20
}
{ 
    "_id" : ObjectId("538JruGLRnMDaE4gyc3"), 
    "subjectId" : "567814d620a3d410709b91ba", 
    "classId" : "5yJdSrdrLKt9DDQRW",
    "sScore" : 66
}
{ 
    "_id" : ObjectId("533Qu3zt5suR8ymkRJ6"), 
    "subjectId" : "567814d620a3d410709b91ba", 
    "studentId" : "AYQ48ot234h4oDZWAumnMD",
    "sScore" : 99
}

input 
if classId == "5yJdSrdrLKt9DDQRW" and "sScore" == 99
then 
output : 3

input 
if classId == "AYQ48otoDZWAumnMD" and "sScore" == 99
then 
output : 4

有人可以帮我吗?

1 个答案:

答案 0 :(得分:0)

运行以下管道以获得所需的结果:

var classId = "AYQ48otoDZWAumnMD";
db.Students.aggregate([    
    {
        "$group": {
            "_id": "$subjectId",
            "classId": { 
                "$max": {
                    "$cond": [
                        { "$gt": ["$classId", null] },
                        "$classId", null
                    ]
                }
            },
            "count": { "$sum": 1 }
        }
    },
    { "$match": { "classId": classId } }        
])

示例输出

{
    "_id" : "567818ec20a3d410709bb202",
    "classId" : "AYQ48otoDZWAumnMD",
    "count" : 4
}

在上面的 $group 管道中,您需要按subjectId键对所有文档进行分组,但在管道的下方需要classId密钥您要按以下方式过滤分组的文档。由于某些文档没有classId字段,因此您需要一种机制,使用$group available accumulators 管道中创建此字段。所以一个好的黑客就是使用 $max 运算符返回现有的classId字段或占位符null值,全部通过 $cond tenary运算符,使用BSON Types Comparison Order来评估字段的存在。

最后一个 $match 管道将过滤文档,以返回与创建的 $group 管道上的给定classId值匹配的文档字段。