0

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

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

现在我需要做几件事:

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

如何用聚合中的这些结果更新用户而不循环它们并一次更新每个用户的好方法?

4

1 回答 1

0

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

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

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

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

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

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

我肯定会建议将标志字段设置为始终存在的布尔值,因为这样可以让您更改其值,而不必担心创建新字段并在文档超出其分配空间时无意中要求将其移动到磁盘上。您应该尽可能以就地更新为目标。

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

于 2013-08-30T15:08:21.853 回答