几乎实时跟踪MongoDB中的聚合

时间:2018-02-12 23:02:01

标签: mongodb

我们需要根据“类型”字段跟踪帐户集合中记录的记录计数。因此,我们想知道TYPE1中有多少个帐户,TYPE2中有多少个帐户等...此外,我们需要知道每个帐户中“金额”字段的总数。

聚合查询对我们来说不够快(这些计数需要在UI中实时更新,我们将拥有数百万条记录,需要花费很多秒才能运行的聚合查询不会切割它,所以我正在寻找一个单独的总计集合,其中一个对象跟踪每种类型的计数器。

当我们更改'type'字段的值(即将帐户从一种类型移动到另一种类型)时,我们需要调整计数和'值'总计(减少原始类型的计数器,增加计数器新型)。然后,我们可以使用带有$ incr()的更新命令来调整存储类型计数和值总和的总计记录中的字段。 (这确实意味着我们为每个'类型'更新都有两个数据库写入,但我没有看到解决方法,除非有人有建议)。

对于单个记录调整,这非常简单 - 我们可以在数据访问层中捕获类型更改,并在总计跟踪对象中进行二次更新。

问题是如何跟踪'金额'总计。对于单个记录调整,这不是问题。但对于批量操作(db.collection.update()可能影响数千条记录),我们需要获取每个调整记录的“金额”字段的总和。

到目前为止,我还未能轻易找到让Mongo获取所需信息的方法。

我制定了一个策略,包括在Account对象中添加一个标记的历史数组,其中包含唯一的“changeId”和文档记录在更改时的“金额”,然后针对该策略运行聚合changeId的历史记录获得总数。然后可选择删除历史记录(或在定期清理过程中执行此操作)。

例如,如果我进行了批量更改,我会生成一个唯一的ID(以下为'aaaaaaa'),然后为历史记录执行数组插入,作为调整'type'的批量更新的一部分:

{
  "amount": 123,
  "type": "TYPE1",
  "history": [
     {
       "changeId": "aaaaaaaaaa",
       "amount": 123,
       "oldType": "TYPE2",
       "newType": "TYPE1"
     }
  ]
}

然后我可以做一个聚合,它给出了刚刚运行的changeId的'amount'的总和。

我认为这会奏效,但它很笨拙 - 有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

我的第一直觉是将更改日志存储在单独的集合中,但我没有在MongoDB批量收集文档中看到这样做的方法。我同意维护聚合的工作需要在一个单独的过程中进行。您在帐户集合中创建历史数组的想法可以使用。我不知道你的申请,但我会略微改变结构以避免计时漏洞。我创建了一个变更的自动收报机磁带,汇总过程可以应用,而对帐户知之甚少。

{
 "amount": active amount,
 "type":  active type,
 "history" [
   {
     "changeId": "aaaaaaaa",
     "NewType": 1    
     "amount": new amount
   },
   {
     "changeId": "aaaaaaaa",
     "OldType":  -1
     "amount": old amount as a negative value     
   }
  ]
}   

原因是由于聚合收集过程的时间安排。使用您的原始结构,它必须从帐户本身获取新的金额。但是,如果帐户在聚合收集过程运行之前再次更改,该怎么办比如,交易如下:

Type1 2000
Changes to Type2 3000
Changes to Type1 1000 

使用以下结构,您的聚合过程必须忽略类型2更改,因为它会自行取消。

{
  "amount": 1000
  "type":   Type1
  "history" [
   {
     "changeID": "aaaaaa",
     "amount": 2000
     "oldtype": Type1
     "newtype": Type2
   },
   { 
     "changeID": "bbbbbb",
     "amount": 3000
     "oldtype": Type2
     "newtype": Type1
   }
 ]
}

我要做以下事情。聚合过程将查找历史记录中的所有Type1记录并执行聚合。因此对于Type1,它将计数1和-1,计数没有差别,-2000和1000将Type1金额减1.Indio2聚合将取消。

{
"amount": 1000
"type":   Type1
"history" [
    {
      "changeID": "aaaaaa",
      "Type1":  -1
      "amount": -2000
    },
   {
     "changeID": "aaaaaa",
     "Type2":  1
     "amount": 3000
   },
   {
     "changeID": "bbbbbb",
     "Type2":  -1
     "amount": -3000
   },
   {
     "changeID": "bbbbbb",
     "Type1":  1
     "amount": 1000
   }
 ]
}

无论您选择做什么,您都需要确定哪些历史记录已经处理过。您可以删除历史文档一次,标记它们,或将它们移动到审计集合中。