在MongoDB中建立投票系统的最佳方式 [英] Best way to model a voting system in MongoDB

查看:124
本文介绍了在MongoDB中建立投票系统的最佳方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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


  1. 投票连接到对象

  2. 检查用户是否投票对象应用程序将需要知道登录用户是否在对象上进行投票,同时循环显示呈现投票按钮的对象列表。

  3. 最重要的是,它必须能够检索已订购的对象通过其在合理表现的给定时间段(最后一小时,日,月等)中的总分数。

  4. 应该能够支持每个对象数千票。

我在这里看到两种方法(如果我错了就纠正我的错误!):


  1. 在每个对象中嵌入一个投票文件数组。我可能会存储投票的用户的ObjectId,投票金额和投票时间。 voterId将是投票数组中每个嵌入式投票文件的关键,以便进行快速的哈希查询。

  2. 保留一个单独的投票集合,并以投票方式引用对象。

我也玩过一个想法,即将投票嵌入到桶中,按小时分组收集。



不。 1对于要求2而言将非常快,但是我不知道在这种情况下是否有可能要求3。



否。 2对于第2号要求较慢,我不知道第3号要求的性能如何?(Map reduce?)?



基本上看来,我需要从第3号要求开始一个相当快速的解决方案,然后确保No 2的要求不会太慢。想法?






潜在解决方案



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



该脚本将通过三个变体中的cron运行。


  1. 10分钟间隔:计算具有以前的小时分数> 0的对象的小时分数OR对最近被投票的对象= true。运行此脚本后,最近设置为= false。设置recent-hourly = true。

  2. 3小时间隔:计算任何具有近期的小时数= true的对象的每日评分。设置recent-hourly = false。设置recent-daily = true。

  3. 24小时间隔:计算任何具有近期每日= true的对象的月份分数。设置recent-daily = false。

这个想法是最小化与分数计算脚本无关的对象的不必要处理运行(每小时只能运行在上次运行小时后被投票的对象上,或者没有被投票的对象,需要重新设置为0)。另一个不错的好处是,*值不仅仅是要根据对象投票来计算。您可以包括页面浏览,例如,或其他。对这种方法的想法?

解决方案

查看Mongo Cookbook中原子操作员的投票配方: http://cookbook.mongodb.org/patterns/votes/ 。它不会告诉你如何实现聚合,但是您也可以通过使代表投票对象的备用对象,但在特定的时间段内实现。


I'm trying to model a voting system in MongoDB. You could imagine it as a voting system similar to reddit. Requirements:

  1. Votes are connected to objects
  2. It is very fast to check if a user has voted on an object. The application will need to know if the logged in user has voted on an object while it loops through a list of objects rendering vote buttons.
  3. Most importantly, it must be able to retrieve objects ordered by their aggregate scores over a given time period (last hour, day, month, etc) with reasonable performance.
  4. Should be able to support thousands of votes per object.

I see two approaches here (correct me if I'm wrong!):

  1. Embed an array of vote documents in each object. I'd probably store the ObjectId of the user that voted, the vote amount, and the vote time. The voterId would be the key for each embedded vote document in the votes array to allow for a quick hash lookup.
  2. Keep a separate votes collection with votes that reference objects.

I've also played with the idea of embedding votes into 'buckets' grouped by hour in a separate collection.

No. 1 would be very fast for requirement No. 2 but I don't know if requirement No. 3 is even possible in this scenario.

No. 2 would be slower for requirement No. 2 and I'm not sure what the performance would be like for requirement No. 3 / how it would be achieved (map reduce?).

Basically it seems like I need to start with a reasonably fast solution for requirement No. 3, and then make sure that requirement No 2 is not too slow. Ideas?


Potential Solution

Use embedded method. Add a parameter to each object for hourly-score, daily-score, monthly-score, etc. Add another boolean parameter recently-voted, recent-hourly, and recent-daily. Create a script that runs a map-reduce on objects to calculate and update these parameters.

The script would be run via cron in three variations.

  1. 10 minute interval: Calculate hourly-score for objects with a previous hourly-score > 0 OR objects that have recently-voted = true. Set recently-voted = false after running this script. Set recent-hourly = true.
  2. 3 hour interval: calculate daily-score for any objects that have recent-hourly = true. Set recent-hourly = false. Set recent-daily = true.
  3. 24 hour interval: calculate monthly-score for any objects that have recent-daily = true. Set recent-daily = false.

The idea is to minimize unnecessary processing on objects that aren't relevant to the score calculation script being run (hourly should only be run on objects that have been voted on since the last time hourly was run, or objects that have not been voted on and need to be reset to 0). Another nice benefit is the *-score values don't just have to be calculated based on the object votes. You could include page views for example, or whatever. Thoughts on this approach?

解决方案

Check out the Voting with Atomic Operators recipe in the Mongo Cookbook: http://cookbook.mongodb.org/patterns/votes/. It doesn't tell you how to implement aggregation, but you could perhaps do that by making stand-in objects that represent the objects to vote on, but for a specific time period.

这篇关于在MongoDB中建立投票系统的最佳方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆