MongoDB运行以前记录的total-like聚合,直到出现值为止

MongoDB运行以前记录的total-like聚合,直到出现值为止,mongodb,mapreduce,aggregation-framework,cumulative-sum,Mongodb,Mapreduce,Aggregation Framework,Cumulative Sum,我目前正在处理各种比赛的一系列游戏内事件。在游戏中,可以杀死敌人并在商店购买物品 我现在一直想做的是,计算在每一次购买活动之前,一场比赛中发生的死亡人数 { "_id" : ObjectId("5988f89ae5873exxxxxxx"), "gameId" : NumberLong(2910126xxx) "participantId" : 3, "type" : "ITEM_PURCHASED", "timestamp" : 656664 },

我目前正在处理各种比赛的一系列游戏内事件。在游戏中,可以杀死敌人并在商店购买物品

我现在一直想做的是,计算在每一次购买活动之前,一场比赛中发生的死亡人数

{
    "_id" : ObjectId("5988f89ae5873exxxxxxx"),
    "gameId" : NumberLong(2910126xxx)
    "participantId" : 3,
    "type" : "ITEM_PURCHASED",
    "timestamp" : 656664 },    
{
    "_id" : ObjectId("5988f89ae5873exxxxxxx"),
    "gameId" : NumberLong(2910126xxx)
    "participantId" : 3,
    "victimId" : 9,
    "type" : "ENEMY_KILLED",
    "timestamp" : 745245 },
{
    "_id" : ObjectId("5988f89ae5873exxxxxxx"),
    "gameId" : NumberLong(2910126xxx)
    "participantId" : 3,
    "victimId" : 7,
    "type" : "ENEMY_KILLED",
    "timestamp" : 746223 },
{
    "_id" : ObjectId("5988f89ae5873exxxxxxx"),
    "gameId" : NumberLong(2910126xxx)
    "participantId" : 3,
    "type" : "ITEM_PURCHASED",
    "timestamp" : 840245 },    
这是我所期望的结果:

{
    "_id" : ObjectId("5988f89ae5873exxxxxxx"),
    "gameId" : NumberLong(2910126xxx)
    "participantId" : 3,
    "type" : "ITEM_PURCHASED",
    "timestamp" : 656664,
    "kills": 0  },
 {
    "_id" : ObjectId("5988f89ae5873exxxxxxx"),
    "gameId" : NumberLong(2910126xxx)
    "participantId" : 3,
    "type" : "ITEM_PURCHASED",
    "timestamp" : 840245 ,
     "kills": 2  }
虽然我倾向于认为这是不可能的,但我对mongo提供的所有功能还没有足够的经验

有没有办法计算某些值的发生率,直到出现购买事件为止?

尝试此聚合

  • $match
    -按游戏ID筛选
  • $sort
    -按时间戳排序文档
  • $group
    -累加与数组匹配的所有
  • $addFields
    -
    $reduce
    计算kill,过滤kill并将其映射到文档
  • $unwind
    -平面数组以获取原始文档结构
  • $replaceRoot
    -将数据移动到原始结构中的顶层
  • 管道

    db.games.aggregate([
        {$match : {gameId : 1}},
        {$sort : {timestamp : 1}},
        {$group : {_id : "$gameId", data : {$push : "$$ROOT"}}},
        {$addFields : {data : {
            $reduce : {
                input : "$data",
                initialValue : {kills : [], data : [], count : 0},
                in : {
                    count : {$sum : ["$$value.count", {$cond : [{$eq : ["$$this.type", "ENEMY_KILLED"]}, 1, 0]}]},
                    data : { $concatArrays : [
                         "$$value.data", 
                         {$cond : [
                                {$ne : ["$$this.type", "ENEMY_KILLED"]}, 
                                [
                                    {
                                        _id : "$$this._id",
                                        gameId : "$$this.gameId",
                                        participantId : "$$this.participantId",
                                        type : "$$this.type",
                                        timestamp : "$$this.timestamp",
                                        kills : {$sum : ["$$value.count", {$cond : [{$eq : ["$$this.type", "ENEMY_KILLED"]}, 1, 0]}]}
                                    }
                                ],
                                []
                            ]}
                        ]}
                    }
                }}
        }},
        {$unwind : "$data.data"},
        {$replaceRoot : {newRoot : "$data.data"}}
    ]).pretty()
    
    收藏

    > db.games.find()
    { "_id" : 1, "gameId" : 1, "participantId" : 3, "type" : "ITEM_PURCHASED", "timestamp" : 656664 }
    { "_id" : 2, "gameId" : 1, "participantId" : 3, "victimId" : 9, "type" : "ENEMY_KILLED", "timestamp" : 745245 }
    { "_id" : 3, "gameId" : 1, "participantId" : 3, "victimId" : 7, "type" : "ENEMY_KILLED", "timestamp" : 746223 }
    { "_id" : 4, "gameId" : 1, "participantId" : 3, "type" : "ITEM_PURCHASED", "timestamp" : 840245 }
    
    结果

    {
        "_id" : 1,
        "gameId" : 1,
        "participantId" : 3,
        "type" : "ITEM_PURCHASED",
        "timestamp" : 656664,
        "kills" : 0
    }
    {
        "_id" : 4,
        "gameId" : 1,
        "participantId" : 3,
        "type" : "ITEM_PURCHASED",
        "timestamp" : 840245,
        "kills" : 2
    }
    > 
    

    非常感谢您的回答!它确实在一定程度上解决了我的问题。然而,我认为我们可以摆脱“杀死”阵列,对吗?由于实际杀死的数量将增加到“计数”中,事件将有条件地放在“数据”中。@DwayneHart,是的,我昨天做了一些编辑,这不是必需的,我们可以删除它。还有一种引入并行化的方法,例如在reduce步骤中?我正在处理一个至少18GB大小的数据集,并希望尽可能最好地利用我的多线程六核处理器。