Group By Count on MongoDB

时间:2017-04-18 03:01:06

标签: mongodb mongodb-query aggregation-framework nosql-aggregation

这是我数据库中大约1000万行中的一行:

{
    "_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. 我也在努力找到最成功的套牌(胜利数量已经足够 - 应该忽略该数组中指定的牌的顺序)。

  3. 我尝试了什么,但在一段时间后又返回一个空错误:

    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)

1 个答案:

答案 0 :(得分: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:{}
 })