【发布时间】:2011-10-26 03:56:04
【问题描述】:
我正在尝试在 MongoDB 中为投票系统建模。你可以把它想象成一个类似于 reddit 的投票系统。要求:
- 投票与对象相关
- 检查用户是否对某个对象进行了投票非常快。应用程序需要知道登录用户是否对某个对象进行了投票,同时它会遍历呈现投票按钮的对象列表。
- 最重要的是,它必须能够以合理的性能检索在给定时间段(最后一小时、一天、一个月等)内按总分数排序的对象。
- 应该能够支持每个对象数千票。
我在这里看到了两种方法(如果我错了,请纠正我!):
- 在每个对象中嵌入一组投票文档。我可能会存储投票用户的 ObjectId、投票数量和投票时间。 voterId 将是投票数组中每个嵌入式投票文档的键,以允许快速查找哈希。
- 保留一个单独的投票集合,其中包含引用对象的投票。
我还尝试过将投票嵌入到单独集合中按小时分组的“桶”中。
没有。对于要求 2 来说,1 会非常快,但我不知道在这种情况下要求 3 是否可能。
没有。对于要求 2,2 会慢一些,我不确定要求 3 的性能如何/如何实现(地图减少?)。
基本上,我似乎需要从第 3 项要求的合理快速解决方案开始,然后确保第 2 项要求不会太慢。想法?
潜在解决方案
使用嵌入式方法。为每个对象添加一个参数,用于每小时得分、每日得分、每月得分等。添加另一个布尔参数最近投票、最近每小时和最近每天。创建一个脚本,在对象上运行 map-reduce 以计算和更新这些参数。
该脚本将通过 cron 以三种变体形式运行。
- 10 分钟间隔:计算先前每小时得分 > 0 或最近投票的对象的每小时得分 = true。运行此脚本后设置最近投票= false。设置最近每小时 = true。
- 3 小时间隔:计算最近每小时 = true 的任何对象的每日得分。设置最近每小时 = 假。设置最近的每日 = true。
- 24 小时间隔:计算最近每天 = true 的任何对象的每月得分。设置最近的每日 = 假。
这个想法是尽量减少对与正在运行的分数计算脚本无关的对象的不必要处理(每小时应该只对自上次每小时运行以来已经投票的对象运行,或者没有已投票,需要重置为 0)。另一个不错的好处是 *-score 值不仅仅需要根据对象投票来计算。例如,您可以包括页面浏览量或其他任何内容。对这种方法有什么想法?
【问题讨论】:
-
好问题。我使用过 mongoDB,可能会给你一个可能很糟糕的解决方案,但我期待看到人们提出什么想法。
-
我确信您尝试在 Mongo 中执行此操作是有充分理由的,但考虑到要求,我认为在具有传统数据仓库索引策略的传统关系数据库将胜过它(并且仅将星型模型作为主要数据模型,无需从传统的规范化模型转移到数据仓库或类似的东西),并且不需要常规的 cron 作业- 很好地处理#3(这是星型模式擅长的)