Группировать по количеству в массиве MongoDB

Это одна из ~ 10 миллионов строк в моей базе данных:

{
    "_id" : ObjectId("58f569159f809c49ffc5cdbb"),
    "date" : ISODate("2017-03-21T09:10:07.686Z"),
    "p1" : {
        "_id" : 1765906,
        "deck" : [ 
            33, 
            25, 
            59, 
            38, 
            62, 
            3, 
            33, 
            57
        ],
        "crowns" : 3
    },
    "p2" : {
        "_id" : 2520156,
        "deck" : [ 
            25, 
            69, 
            86, 
            8, 
            44, 
            61, 
            69, 
            50
        ],
        "crowns" : 2
    }
}

Журнал игрового боя. Колода представляет собой массив, состоящий из 8 разных карт. Я пытаюсь найти карту, у которой больше всего выигрышей. Победителя можно определить путем сравнения корон (мне удалось отобрать все документы, в которых выиграл игрок 1).

Чего я пытаюсь достичь:

  1. К сожалению, мне не удалось выполнить групповой запрос, который вернул бы то, что я ищу (карта с наибольшим количеством выигрышей).

  2. Я также пытаюсь найти наиболее удачную колоду (количества выигрышей достаточно - порядок карт, указанный в этом массиве, следует игнорировать).

То, что я пробовал, но через некоторое время вернул пустую ошибку:

db.battle_logs.aggregate([
    {
        $addFields: {
            "player1won": { "$cmp": [ "$p1.crowns", "$p2.crowns" ] }
        }
    },
    { $match: { "player1won": 1 }},
    { 
        $group: 
        {
            _id: "$p1.deck",
            count: { $sum: 1 }
        }
    }
], {
  allowDiskUse:true,
  cursor:{}
 })

Я ожидал, что все комбинации колод будут сгруппированы по количеству побед (учитываются только победы игрока1)


person kentor    schedule 18.04.2017    source источник
comment
не очень понятно, можете ли вы добавить ожидаемый результат для предоставленного вами документа?   -  person felix    schedule 18.04.2017
comment
@felix Для 2) это будет колода (которая представляет собой массив, состоящий из целых чисел) с количеством / подсчетом выигрышей (я уже отфильтровал player1Won в данном запросе, поэтому мне нужно только сгруппировать по колодам и посчитать их полученные результаты). Я предполагаю, что мне нужно отсортировать массив int (p1.deck), чтобы он игнорировал порядок карточек   -  person kentor    schedule 18.04.2017


Ответы (1)


Поскольку вы используете массив p1.deck как _id в своем групповом запросе, вам необходимо отсортировать массив, иначе порядок карты создаст новую группу.

Вот что может сработать в вашем случае:

1)

db.battle_logs.aggregate([
    {
        $addFields: {
            "player1won": { "$cmp": [ "$p1.crowns", "$p2.crowns" ] }
        }
    },
    //Fiter out ties
    { 
        $match: { 
            "$or" : [
                {"player1won": 1},  //Player 1 won
                {"player1won" : -1} //Player 2 won
            ]
        }
    },
    // Get the winning deck
    {
        $project: {
            "deck": { $cond : [ { $gte : [ "$p1.crowns", "$p2.crowns" ]}, "$p1.deck", "$p2.deck" ]} 
        }
    },
    //Unwind the deck to get every card
    { 
        $unwind : "$deck"
    },
    //Get count of each card
    { 
        $group : { 
            "_id" : "$deck" , 
            "count" : {"$sum" : 1}
        }
    }, 
    // Sort on count
    {
        $sort: {"count" : -1}

    },
    //Get the card with highest count
    { 
        $limit: 1
    }
], {
  allowDiskUse:true,
  cursor:{}
 })

2)

db.battle_logs.aggregate([
    {
        $addFields: {
            "player1won": { "$cmp": [ "$p1.crowns", "$p2.crowns" ] }
        }
    },
    //Fiter out ties
    { 
        $match: { 
            "$or" : [
                {"player1won": 1},  //Player 1 won
                {"player1won" : -1} //Player 2 won
            ]
        }
    },
    // Get the winning deck
    {
        $project: {
            "deck": { $cond : [ { $gte : [ "$p1.crowns", "$p2.crowns" ]}, "$p1.deck", "$p2.deck" ]} 
        }
    },
    //Unwind the deck to get every card
    { 
        $unwind : "$deck"
    },
    //Sort the cards
    { 
        $sort : {"deck": 1}
    },
    //Group sorted cards back in deck
    { 
        $group : { 
            "_id" : "$_id" , 
            "deck" : {"$push" : "$deck"}
        }
    }, 
    { 
        $group: 
        {
            _id: "$deck",
            count: { $sum: 1 }
        }
    }
], {
  allowDiskUse:true,
  cursor:{}
 })
person thegreenogre    schedule 18.04.2017