映射/减少新记录的原子性(MongoDB)


Atomicity in Map/Reducing over new records (MongoDB)

情况如下:我有一个MongoDB集群和一个web应用程序,它可以执行相当密集的Map/Reduce查询。该查询在cron作业中周期性地(每5分钟(发生一次,结果存储(使用$merge(到集合中。

工作原理:当前,查询对其集合中的每个记录执行。所说的集合正在慢慢增长到数百万行,每次运行都需要更长的时间。

显而易见的解决方案是对新记录运行Map/Reduce,并对旧存储的值使用Reduce函数来计算正确的值。MongoDB非常棒,它允许您指定一个reduce选项,而不是merge

我不知道的是:如何仅对初始集合中的新记录正确执行M/R。我看到了两种潜在的解决方案,但都不好。想法?

  1. 我可以标记已处理的记录。问题是如何标记与我刚刚M/R覆盖的记录完全相同的记录
  2. 我可以查询匹配的项目,然后将ID列表作为$in: [id1, id2, ...]查询传递给Map/Reduce,然后发送更新以使用相同的$in设置我的标志。但这真的很不雅,我不知道当唱片数量巨大时会如何表现

tl;dr:如何在将结果缩减为集合的Map/Reduce查询中只选择新记录。

#mongodb IRC频道上的一个善良的灵魂帮助我解决了这个问题。一个简单的解决方案是有一个状态机字段,并执行以下操作(在伪代码中(:

set {state:'processing'} where {state:{$exists:false}}
mapreduce {...} where {state:'processing'}
set {state:'done'} where {state:'processing'}

现在,这是次优的,因为它在包含数百万条记录的集合上浪费了大量磁盘空间。但真正的问题是,为什么我没有早点想到这一点?