Mongodb - 从嵌套项获得最高结果

时间:2015-04-21 08:35:01

标签: mongodb aggregation-framework

我需要从各种分数中获得用户的最高分。 这是一个示例mongo数据集:

{
    _id: "peter",
    name: "Peter Griffin",
    scores : [
        {
           event: "Peter Copter race",
           score: 100,
        },
        {
           event: "World domination",
           score: 0,
        },
        {
           event: "Listening",
           score: 10,
        }
    ]
},
{
   _id: "stewie",
   name: "Stuart Griffin",
   scores : [
       {
           event: "Peter Copter race",
           score: 0,
       },
       {
           event: "World domination",
           score: 1000,
       },
       {
           event: "Listening",
           score: 100,
       }
   ]
}

我想获得每个用户的最高分,返回像

这样的东西
[{"_id": "peter", "top_score" : 100}, {"_id": "stewie", "top_score" : 1000}]

这是我到目前为止所得到的:

   db.famguyMongo.find({ "scores": { $exists: true } }).forEach(function(famMember) {
    var newScore = 0
    famMember.scores.forEach(function(getScore) {
        newScore = {$max: getScore.score}
    });
    print(newScore )
    newScore = 0
});

正如您所看到的那样,我每次都要设置一个var进行检查..我还试过这个:

db.famguyMongo.find({ "scores": { $exists: true } }).forEach(function(famMember) {
    var newScore = 0
    famMember.scores.forEach(function(getScore) {
        newScore = { $cond: { $gte: [getScore.score, newScore] } getScore.score, 0 }
    });
    print(newScore)
    newScore = 0
});

2 个答案:

答案 0 :(得分:3)

您可以尝试使用MongoDB的 aggregation framework 来计算每位用户的最高得分。在聚合管道中,第一步是使用$unwind运算符从输入文档中解构scores数组字段,以便为每个元素输出一个文档,然后可以在以后的管道中进行聚合。每个输出文档都使用元素值替换数组。下一个管道阶段将是$group运算符,然后您可以使用scores.score字段上的$max聚合运算符计算最高分数。最后一步是$project操作,您可以在其中重新整形流中的每个文档,以适当的格式显示所需的字段:

db.collection.aggregate([
    {
        "$unwind": "$scores"
    },
    {
        "$group": {
            "_id": "$_id",
            "highest_score": { "$max": "$scores.score" }
        }
    },
    {
        "$project": {
            "_id": 0,
            "name": "$_id",
            "highest_score": 1
        }
    }
]);

<强>结果

/* 0 */
{
    "result" : [ 
        {
            "highest_score" : 1000,
            "name" : "stewie"
        }, 
        {
            "highest_score" : 100,
            "name" : "peter"
        }
    ],
    "ok" : 1
}

答案 1 :(得分:1)

我建议使用chridam's answer,但如果你想要一个JavaScript替代品;

var objScores = {}; //Instantiate object
db.test.find({ "scores": { $exists: true } }).forEach(function(famMember) {
    var newScore = 0;
    objScores[famMember._id] = 0; //Set default for each person as score 0
    famMember.scores.forEach(function(getScore) { //loop through persons score
        if( getScore.score > objScores[famMember._id] ) {
            objScores[famMember._id] = getScore.score; //Record the highest score
        }
    });
});
print( objScores ); //print output

输出将是;

{
    "peter" : 100,
    "stewie" : 1000
}