2014-06-28 1 views
1

Я только начинаю с mongodb и читаю документацию по агрегации, но все еще пытаюсь связать эквивалентное знание операторов sql с методами, используемыми в mongo.Агрегатирование и сравнение команд с использованием mongodb

У меня есть эти данные:

{ 
     "_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 вокруг одного среднего и расчета разница в их баллах (не может быть отрицательной разницей, только положительной).

Большинство примеров, с которыми я сталкиваюсь, не совсем соответствуют моим требованиям и надеются, что какой-нибудь гуру-манго может помочь мне. Благодаря!

+0

В ваших образцовых данных не хватает информации, чтобы сказать, какие «две» команды сопоставляются друг с другом. Я не буду комментировать недействительную структуру результата, кроме как сказать, что это неверно. Но на самом деле, если вы хотите, чтобы «пары» не просто требовали двух команд за раз, вам нужно общее поле, чтобы «спарить» их. –

+0

Извините, вы правы, 2 команды на самом деле являются uid's. Я делаю данные более семантически корректными, но в момент mo, это то, что у меня есть. Я буквально ищу, чтобы сравнить каждый uid с каждым другим uid. – dolyth

+0

Обновлены данные, поэтому имеет смысл. Общность - это середина. – dolyth

ответ

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 и другую обработку.

+0

Это замечательно! Теперь я понимаю, что вы имеете в виду после того, как вы так выразились. Я не могу вас поблагодарить! – dolyth