使用mongodb汇总和比较团队的得分

时间:2014-06-28 10:27:00

标签: mongodb mongodb-query aggregation-framework

我刚刚开始使用mongodb并且已经阅读了有关聚合的文档,但仍然在努力将sql语句的等效知识与mongo中使用的方法联系起来。

我有这些数据:

{
         "_id" : ObjectId("53ac7bce4eaf6de4d5601c19"),
         "uid" : ObjectId("53ac7bb84eaf6de4d5601c15"),
         "mid" : ObjectId("53ab27504eaf6de4d5601be4"),
         "score" : 1
},{
        "_id" : ObjectId("53ac7bce4eaf6de4d5601c1a"),
        "uid" : ObjectId("53ac7bb84eaf6de4d5601c16"),
        "mid" : ObjectId("53ab27504eaf6de4d5601be4"),
        "score" : 5
}
...

我正试图达到这个结果:

{
        "uid" : ObjectId("53ac7bb84eaf6de4d5601c15"),
        "uid_2" : ObjectId("53ac7bb84eaf6de4d5601c16"),
        "mid" : ObjectId("53ab27504eaf6de4d5601be4"),
        "score" : 1,
        "score_2" : 5,
        "difference" : 4
}
...

我将每个uid与一个中间的uid进行比较并计算其得分的差异(不能是负差异,只有正数)。

我遇到的大多数例子都不符合我的要求,希望有些mongo guru可以帮助我。谢谢!

1 个答案:

答案 0 :(得分:1)

如上所述,我认为您的数据建模有点偏离,因为您需要一些东西来“匹配”“匹配”。我在这里有一个“简化”案例:

{ 
    "_id" : ObjectId("53ae9da2e24682cac4215e0c"), 
    "match" : ObjectId("53ae9d78e24682cac4215e0b"), 
    "score" : 1 
}
{
    "_id" : ObjectId("53ae9da5e24682cac4215e0d"),
    "match" : ObjectId("53ae9d78e24682cac4215e0b"),
    "score" : 5
}
{ 
    "_id" : ObjectId("53aea6cde24682cac4215e15"),
    "match" : ObjectId("53aea6c1e24682cac4215e14"), 
    "score" : 2
}
{
    "_id" : ObjectId("53aea6e4e24682cac4215e16"),
    "match" : ObjectId("53aea6c1e24682cac4215e14"),
    "score" : 1
}
{ 
    "_id" : ObjectId("53aea6eae24682cac4215e18"), 
    "match" : ObjectId("53aea6e6e24682cac4215e17"), 
    "score" : 2
}
{ 
    "_id" : ObjectId("53aea6ece24682cac4215e19"),
    "match" : ObjectId("53aea6e6e24682cac4215e17"),
    "score" : 2
}

基本上代表的是“六个”不同比赛中“六支”球队的得分。

鉴于此,我对结果的看法是:

db.matches.aggregate([

    // Group on matches and find the "min" and "max" score
    { "$group": {
        "_id": "$match",
        "teams": {
            "$push": {
               "_id": "$_id",
               "score": "$score"
            }
        },
        "minScore": { "$min": "$score" },
        "maxScore": { "$max": "$score" }
    }},

    // Unwind the "teams" array created
    { "$unwind": "$teams" },

    // Compare scores for "win", "loss" or "draw"
    { "$group": {
        "_id": "$_id",
        "win": {
           "$min": { "$cond": [
               { "$and": [
                   { "$eq": [ "$teams.score", "$maxScore" ] },
                   { "$gt": [ "$teams.score", "$minScore" ] }
               ]},
               "$teams",
               false
           ]}
        },
        "loss": {
           "$min": { "$cond": [
               { "$and": [
                   { "$eq": [ "$teams.score", "$minScore" ] },
                   { "$lt": [ "$teams.score", "$maxScore" ] }
               ]},
               "$teams",
               false
           ]}
        },
        "draw": {
            "$push": { "$cond": [
               { "$eq": [ "$minScore", "$maxScore" ] },
               "$teams",
               false
            ]}
        },
        "difference": { 
            "$max": { "$subtract": [ "$maxScore", "$minScore" ] }
        }
    }},

    // Just fix up those "draw" results with a [false,false] array
    { "$project": {
        "win": 1,
        "loss": 1,
        "draw": { "$cond": [ 
             { "$gt": [
                 { "$size": { "$setDifference": [ "$draw", [false] ] } },
                 0
             ]},
             "$draw",
             false
        ]},
        "difference": 1
    }}
])

这给你一个非常好的结果:

{
    "_id" : ObjectId("53ae9d78e24682cac4215e0b"),
    "win" : {
            "_id" : ObjectId("53ae9da5e24682cac4215e0d"),
            "score" : 5
    },
    "loss" : {
            "_id" : ObjectId("53ae9da2e24682cac4215e0c"),
            "score" : 1
    },
    "draw" : false,
    "difference" : 4
}
{
    "_id" : ObjectId("53aea6c1e24682cac4215e14"),
    "win" : {
            "_id" : ObjectId("53aea6cde24682cac4215e15"),
            "score" : 2
    },
    "loss" : {
            "_id" : ObjectId("53aea6e4e24682cac4215e16"),
            "score" : 1
    },
    "draw" : false,
    "difference" : 1
}
{
    "_id" : ObjectId("53aea6e6e24682cac4215e17"),
    "win" : false,
    "loss" : false,
    "draw" : [
            {
                    "_id" : ObjectId("53aea6eae24682cac4215e18"),
                    "score" : 2
            },
            {
                    "_id" : ObjectId("53aea6ece24682cac4215e19"),
                    "score" : 2
            }
    ],
    "difference" : 0
}

这基本上是每次“匹配”的结果,并确定胜利者和宽松者之间的“差异”,同时确定哪支球队“赢了”或“输了”。最后阶段使用了一些仅在MongoDB 2.6中引入的运算符,但如果您没有该版本可用则不需要。或者,如果你想通过$unwind和其他一些处理,你实际上仍然可以做同样的事情。