在MongoDB中建模投票系统的最佳方法

时间:2011-08-12 21:22:01

标签: database-design mongodb

我正在尝试为MongoDB中的投票系统建模。你可以把它想象成一个类似于reddit的投票系统。要求:

  1. 投票已连接到对象
  2. 检查用户是否对某个对象进行了投票是非常快的。应用程序需要知道登录用户是否已经对某个对象进行了投票,同时它会循环显示一个呈现投票按钮的对象列表。
  3. 最重要的是,它必须能够以合理的性能检索在给定时间段(最后一小时,一天,一个月等)内按其总分数排序的对象。
  4. 每个对象应该能够支持数千票。
  5. 我在这里看到两种方法(如果我错了,请纠正我!):

    1. 在每个对象中嵌入一系列投票文档。我可能会存储投票用户的ObjectId,投票金额和投票时间。 voterId将是投票数组中每个嵌入式投票文档的关键,以允许快速哈希查找。
    2. 使用引用对象的投票保留单独的投票收集。
    3. 我也想过将投票嵌入到按小时分组的“桶”中的想法。

      没有。对于第2项要求,1速度非常快,但我不知道在这种情况下是否可以使用第3项要求。

      没有。对于第2项要求,2的速度会慢一些,我不确定3号要求/如何实现它的表现会是什么样的(map reduce?)。

      基本上我似乎需要从第3项要求的合理快速解决方案开始,然后确保要求No 2不会太慢。想法?


      潜在解决方案

      使用嵌入式方法。为每个对象添加一个参数,用于每小时得分,每日得分,每月得分等。最近添加另一个布尔参数 - 最近投票,最近每小时和最近每日。创建一个脚本,在对象上运行map-reduce以计算和更新这些参数。

      脚本将通过cron以三种版本运行。

      1. 10分钟间隔:计算具有前一小时得分的对象的每小时得分> 0 OR最近投票的对象=真。运行此脚本后设置recent-voted = false。设置recent-hourly = true。
      2. 3小时间隔:计算最近每小时= true的任何对象的每日得分。设置recent-hourly = false。设置recent-daily = true。
      3. 24小时间隔:计算最近每日= true的任何对象的每月分数。设置recent-daily = false。
      4. 这个想法是最大限度地减少对正在运行的分数计算脚本无关的对象的不必要处理(每小时应该只运行自上次每小时运行以来已经投票的对象,或者对象没有已经投票,需要重置为0)。另一个好处是* -score值不仅需要根据对象投票计算。例如,您可以包含页面视图,或者其他任何内容。关于这种方法的想法?

2 个答案:

答案 0 :(得分:2)

查看Mongo Cookbook中的原子操作员投票配方:http://cookbook.mongodb.org/patterns/votes/。它没有告诉您如何实现聚合,但您也许可以通过创建代表要投票的对象的替代对象来实现,但是在特定时间段内。

答案 1 :(得分:0)

如果你使用ruby,那么Mongoid&的插件有votable_mongo个插件。 MongoMapper。