Алгоритм выбора вариантов из коллекции на основе их рейтинга? - PullRequest
0 голосов
/ 09 декабря 2011

Допустим, у меня есть коллекция объектов. У меня есть другая коллекция лайков, каждая из которых определенным пользователем и к определенному объекту. Таким образом, с течением времени через оценки пользователей каждый объект имеет переменное количество лайков (все больше 0).

Я хочу выбрать объект из этой коллекции. Объекты с большим количеством лайков следует выбирать чаще, но иногда нужно выбирать и объекты с более низким лайком, чтобы дать им шанс.

Алгоритм, который я сейчас имею в виду, состоит в том, чтобы упорядочить объекты по лайкам, сгенерировать случайное число и использовать число для выбора случайного объекта в диапазоне. Предполагая, что у меня было сто объектов, 50% времени выбираются из 0-10, 25% времени 10-15 и 25% времени 15-100.

Очевидная проблема с этим алгоритмом - масштабируемость. Когда их 1000000 объектов, возвращение массива всех из них занимает время. У кого-нибудь есть лучшее решение? База данных реализована в mongodb.

1 Ответ

1 голос
/ 09 декабря 2011

Я бы немного денормализовал и добавил бы поле «Мне нравится» к понравившимся объектам.Увеличивайте его, когда объектам нравится, уменьшайте его, когда объектам не нравятся.

db.test.insert({
    stuff: "likable stuff",
    likes: 7
})

Тогда у меня также было бы другое поле, представляющее корзину, в которой находится объект в результате лайков.Так, например, объекты начинаются с этого поля, установленного на «обычное», и после того, как кто-то получит 10 лайков, они станут «элитными».(или что вы хотите) Обновите его, когда они достигнут этого порога.Идея заключается в том, что выполнение работы над записью сделает чтение намного проще.

db.test.insert({
    stuff: "likable stuff",
    likes: 7,
    status: "ordinary/elite",
})

Хорошо, так что теперь выбор набора объектов, которые находятся в группах, которые вы определили на основе количества лайков,легко верно?db.collection.find({ status: 'elite' })

Чтобы рандомизировать выбор документа в этих наборах, вы можете случайно пропустить заданное количество записей, но это приведет к ужасной производительности и не будет масштабироваться.

Однако, естьТрюк, который вы можете сделать, когда вы храните случайно сгенерированные числа в самих документах.

Давайте вставим одного из этих парней в тестовую базу данных и проверим его

db.test.insert({
    stuff: "likable stuff",
    likes: 7,
    status: "ordinary/elite",
    random: Math.random()
})

Давайте посмотрим надокумент сейчас:

{
    stuff: "likable stuff",
    likes: 7,
    status: "ordinary/elite",
    random: 0.9375813045563468
}

Хорошо, вот где это действительно здорово.Выполните запрос findOne (), где статус: elite и rand_num: $ gt {другое случайно сгенерированное число от 0 до 1}.

db.collection.find({ status: "elite", random: { "$gt": new_rand_num } })

Если findOneЗапрос () не возвращает результат, повторите его с $ lt, так как вы обязательно найдете документ хотя бы в одном из направлений.

Теперь давайте индексировать статус и случайность.

db.collection.ensureIndex({ status: 1, random: 1} })

Как вы думаете?

...