如何独立更新数百万个文档? PHP + Mongo

时间:2013-08-21 14:38:21

标签: php mongodb

我有一个非常大的聚合,它总结了每个用户(在集合中)的一些活动。 此聚合返回数百万个结果(每个用户活动)。使用这种格式:

 Array ( [_id] => Array ( [user] =>
      MongoId Object ( [$id] => 52050d48e654f6342c002d42 )
        [send] => 1
        [open] => 1
        [click] => 2 )

现在我需要做一些事情:

  • 使用这些结果更新用户(增加现有值)
  • 更新后计算每个用户的平均值(打开/发送)
  • 将每个平均值与一个数字进行比较,并根据结果向用户添加一个标志?

如何通过聚合更新这些结果的用户,而不是循环访问并一次更新每个结果?

1 个答案:

答案 0 :(得分:0)

如果我理解正确,您分享了示例结果:

{
  user: ObjectId("52050d48e654f6342c002d42"),
  send: 1,
  open: 1,
  click: 2
}

...需要执行以下操作:

  • 每个send增加该用户的open1字段。
  • 将后增量open / send比率(未存储)与某个值进行比较,并根据比较结果在用户文档上设置布尔标志。

充其量,我认为您可以预先汇总会收到类似更新的用户,并在值数组中_id multi-document updates处发出$in;但是,这仍然需要MongoDB单独查询每个用户。 $in数组参数的大小有限制,但此策略的主要好处是您将在驱动程序和服务器之间发送较少的操作,并且您将收到一个GLE(即获取最后一个错误) )回应。

open / send比率计算将更加棘手,因为这需要从所有文档中提取这些字段。在更新步骤之后,您可以针对用户集合发出第二个聚合,并在两个字段上使用$divide来计算该值。然后,您可以在comparison operator中使用商和其他值。这将使您的工艺成为仅包含用户ID和布尔值的聚合结果。从那里开始,您仍然需要从驱动程序发出更多更新语句,尽管将它们分组为多文档更新会更简单,因为标记字段只有两个可能的值。

我肯定会建议将标志字段设为一个始终存在的布尔值,因为这样可以让您更改其值而无需担心创建新字段,并且如果超出其分配的空间,则无意中要求将文档移动到磁盘上。你应尽可能瞄准in-place updates

最后,另一个使用PHP驱动程序的选项是write concern用于更新操作。通过使用写入关注度为零,您可以获得一些性能(以错误检查为代价),因为这将允许您尽快向MongoDB发送更新,而无需等待错误响应。