MongoDB中实时聚合的策略

时间:2011-04-27 16:46:19

标签: ruby-on-rails mongodb real-time

在探索使用MongoDB进行实时分析的方法时,似乎有一种相当标准的方法来进行求和,但在更复杂的聚合方面却没有。一些有帮助的事情......

执行求和的基本方法是以原子方式递增每个新记录的文档键,以缓存常见查询:

Stats.collection.update({"keys" => ["a", "b", "c"]}, {"$inc" => {"counter_1" => 1, "counter_2" => 1"}, "upsert" => true);

但这不适用于除sum之外的聚合。我的问题是,对于mongodb中的 averages min max ,是否可以这样做?

假设你有这样的文件:

{
  :date => "04/27/2011",
  :page_views => 1000,
  :user_birthdays => ["12/10/1980", "6/22/1971", ...] # 1000 total
}

你能做一些将生日分组成这样的原子或优化/实时操作吗?

{
  :date => "04/27/2011",
  :page_views => 1000,
  :user_birthdays => ["12/10/1980", "6/22/1971", ...], # 1000 total
  :average_age => 27.8,
  :age_rank => {
    "0 to 20" => 180,
    "20 to 30" => 720,
    "30 to 40" => 100,
    "40 to 50" => 0
  }
}

...就像你可以Doc.collection.update({x => 1}, {"$push" => {"user_birthdays" => "12/10/1980"}})向数组中添加内容而不必加载文档一样,你可以做类似的事情来平均/聚合数组吗?这些行中是否存在用于实时聚合的内容?

MapReduce用于在批处理作业中执行此操作,我正在寻找类似于实时map-reduce的模式:

  1. 平均值:每次将新项目推送到mongodb中的数组时,实时平均这些值的最佳方法是什么?
  2. 分组:如果您将年龄分组为10年括号,并且您有年龄数组,那么当您使用新年龄更新文档时,如何以最佳方式更新每个组的计数?说年龄数组将不断推/拉。
  3. 最小/最大:在该文档中计算和存储该年龄数组的最小值/最大值有哪些方法?

2 个答案:

答案 0 :(得分:5)

  

你能做一些将生日分组成这样的原子或优化/实时操作吗?

您似乎添加了两个字段age_rankaverage_age。这些是基于您已有数据的有效计算字段。如果我向您提供了包含页面浏览量和用户生日的文档,那么客户端代码找到最小值/最大值,平均值等应该是非常简单的。

在我看来,你要求MongoDB为服务器端执行聚合。但是你添加了你不想使用Map / Reduce的限制吗?

如果我正确理解您的问题,您正在寻找可以说“将此项目添加到数组并让所有相关项目自行更新”的内容?你不希望读者执行任何逻辑,你希望一切都在服务器端“神奇地”发生。

因此,有三种不同的方法可以解决这个问题,但目前只有其中一种可用:

  1. 写这个逻辑客户端。它听起来不像你想要的解决方案,但它会起作用。如果您有基础数据,那么在大多数语言中执行max / min / med / avg应该是非常简单的。
  2. 利用Aggregation即将推出的功能。这些不会安排到1.9.x.改进的聚合将允许提取您正在寻找的数据,但是,您仍然必须编写适当的查询。基础数据库仍然不包含您正在寻找的数据。
  3. 您需要triggers。如果您确实希望数据库始终保持一致并包含汇总数据,那么这就是您所需要的。但是,触发器功能尚不存在。
  4. 不幸的是,你现在唯一的选择是#1。幸运的是,我知道有几个人成功使用选项#1。

答案 1 :(得分:1)

有计划为即将发布的1.9.x不稳定版本进行聚合。

请参阅:https://jira.mongodb.org/browse/SERVER-447

当然,它可能会在以后的版本中获得bumepd /