Подтвердить что ты не робот

Лучший способ моделирования системы голосования в MongoDB

Я пытаюсь смоделировать систему голосования в MongoDB. Вы могли бы представить это как систему голосования, похожую на reddit. Требования:

  • Голоса связаны с объектами
  • Очень быстро проверить, проголосовал ли пользователь за объект. Приложению нужно будет знать, проголосовал ли пользователь вошедшего в систему объекта, пока он перебирает список объектов, отображающих кнопки голосования.
  • Самое главное, он должен иметь возможность получать объекты, упорядоченные по их совокупным баллам за определенный период времени (последний час, день, месяц и т.д.) с разумной производительностью.
  • Должна быть способна поддерживать тысячи голосов на объект.

Здесь я вижу два подхода (исправьте меня, если я ошибаюсь!):

  • Вставить массив документов для голосования в каждый объект. Я бы, вероятно, сохранил ObjectId пользователя, голосовавшего, количество голосов и время голосования. Элемент voterId будет ключом для каждого встроенного документа голосования в массиве голосов, чтобы обеспечить быстрый поиск хэша.
  • Держите отдельную коллекцию голосов с голосами, ссылающимися на объекты.

Я также играл с идеей включения голосов в "ведра", сгруппированные по часам в отдельной коллекции.

Нет. 1 будет очень быстрым для требования № 2, но я не знаю, возможно ли требование № 3 в этом сценарии.

Нет. 2 будет медленнее для требования № 2, и я не уверен, как будет выглядеть производительность для требования № 3/как это будет достигнуто (сокращение карты?).

В принципе, мне кажется, что мне нужно начать с достаточно быстрого решения для требования № 3, а затем убедиться, что требование № 2 не слишком медленное. Идеи?


Потенциальное решение

Использовать встроенный метод. Добавьте параметр к каждому объекту для почасового балла, ежедневного балла, ежемесячного счета и т.д. Добавьте еще один логический параметр, недавно проголосовавший, последний раз и ежедневно. Создайте script, который запускает сокращение карты на объектах для расчета и обновления этих параметров.

script будет выполняться через cron в трех вариантах.

  • 10-минутный интервал: вычислить почасовую оценку для объектов с предыдущим почасовым счетом > 0 ИЛИ объектов, которые недавно проголосовали = true. Установите последнее - проголосовало = false после запуска этого script. Установите значение recent-hourly = true.
  • 3-часовой интервал: вычислять дневной балл для любых объектов, которые имеют последнее-hourly = true. Установите значение recent-hourly = false. Установите значение recent-daily = true.
  • 24-часовой интервал: вычисляйте ежемесячный балл для любых объектов, имеющих последние-ежедневные = истинные. Установите последнее-daily = false.

Идея состоит в том, чтобы свести к минимуму ненужную обработку объектов, которые не имеют отношения к вычислению счета script (почасовой запуск должен выполняться только на объектах, которые были проголосованы с момента последнего почасового запуска, или объектов, которые не голосовали и должны быть reset до 0). Еще одно приятное преимущество - значения "-score" не просто должны быть рассчитаны на основе голосований объектов. Например, вы можете включить просмотр страниц или что-то еще. Мысли об этом подходе?

4b9b3361

Ответ 1

Ознакомьтесь с рецептом "Голосование с атомными операторами" в Монгольской поваренной книге: http://cookbook.mongodb.org/patterns/votes/. Он не говорит вам, как реализовать агрегацию, но вы могли бы это сделать, создав объекты ожидания, которые представляют объекты для голосования, но в течение определенного периода времени.

Ответ 2

Если вы используете ruby, есть плагин votable_mongo для Mongoid и MongoMapper.