MongoDB——aggregate聚合优化技巧

此文章简要介绍MongoDB聚合的技巧,第二条的技巧思路也可以适用于MapReduce统计过程。

按天统计数据

db.test.aggregate([
    {"$project" : { "newTime" : {"$add" : ["$originalTime" , 1000 * 60 * 60 * 8] } , "newAccountTime" : 1, "otherField" : 1} },
    {"$group" : {
        "_id" : {
            "year" : {"$year" : "$newTime" }, "month" : {"$month" : "$newTime"} , "day" : {"$dayOfMonth" : "$newTime"} ,
                "timeStr" : {"$substr" : ["$newTime", 0, 10 ] } , "otherField" : "$otherField"
            }
        }
    },
    // ....
    {"$sort" : {"year" : 1, "month" : 1, "day" : 1}}
])

将按不同的key聚合语句,合并为一条

其思路也可以用到MapReduce处理流程。 
在某些情况下,需要统计每个比赛模式的玩家综合数据,也需要统计每个玩家在不同比赛模式的数据。 
例如,有”排位模式“、”大乱斗模式“、”休闲模式“等。需要统计各个游戏模式下,玩家参与数、胜率等数据。这样统计需要以gameId作为聚合的key。 
同时,也需要统计各个玩家在不同“排位模式”、“休闲模式”的参与次数、胜率等。这样统计需要以玩家的userId作为聚合的key。 
解决思路:

  1. 按gameId和userId进行group。
  2. 对上一步的gameId进行group,同时将userId push 到数组里面。这样就得到第一个要求的数据,且将玩家的信息保存下来了。
  3. 对上一步的数组用unwind进行拆分
  4. 对上一步的拆分结果的userId进行group。这样每个userId聚合的结果也带了游戏模式的统计结果。
  5. 进行过滤处理。

经测试,这样只读取了一次数据库,中间过程对内存的要求比较高,需要开启allowDiskUse选项,一次聚合比两次聚合效率高很多。

参考代码:


global.ldb.collection("grandLog").aggregate([
    // ....
        {"$group" : {"_id" :{"gameId" : "$gameId", "userId" : "$userId"} , "otherField" : "$otherField" } },
        {"$group" : {
            "_id" : "$_id.gameId", "userCount" : {"$sum" : 1} ,
                "userInfo" : {"$push" : {"userId" : "$_id.userId" ,"otherField" : "$otherField"} }
            }
        },
        {"$unwind" : "$userInfo"},
        {"$group" : {"_id" :"$userInfo.userId", "gameId" : {"$push" : "$_id"},
            "userCount" : {"$push" : "$userCount" } }
        }
], {"allowDiskUse" : true } );
也可以根据业务数据将group的两个步骤颠倒。


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值