Популярность, Как сделать так, чтобы новые хиты значили больше, чем старые?


Каждый продукт product_date_added, который является полем Date, содержал дату его добавления. У них также есть поле product_views, которое представляет собой поле int, содержащее количество просмотров продукта.

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

SELECT 
    AVG(product_views / DATEDIFF(NOW(), product_date_added)) as avg_hits
    , product_table.* 
FROM product_table
WHERE product_available = "yes" 
GROUP BY product_id
ORDER BY avg_hits DESC

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

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

Каков наилучший способ создать алгоритм популярности, подобный тому, о чем просит мой босс?

В идеале я хотел бы иметь возможность придумать что-то, что не изменит структуру таблицы. Если это невозможно, я хотел бы, по крайней мере, придумать решение, которое может использовать существующий данные, поэтому мы не начинаем с 0. Если это тоже невозможно, то все, что сработает.

Author: JD Isaacks, 2010-09-20

2 answers

Вам не нужно (как таковому) сохранять дату каждого просмотра. Вместо этого вы могли бы хранить до 366 строк на элемент в таблице со столбцами: product_id, day_of_year, count. Каждый день выполняйте задание, чтобы обнулить все показатели годичной давности. Если вы не возражаете против денормализованных данных, эта задача также может обновить поле "количество" в самом элементе для быстрого извлечения, чтобы ваш запрос не нужно было изменять. product_views просто становится product_views_in_the_last_year. Период времени в 1 день является произвольным - я сомневаюсь, что вас волнует, что популярность основана на периоде ровно в 1 год, поэтому я ожидаю, что это может быть час, неделя или две недели, в зависимости от того, со сколькими ведрами вы готовы иметь дело.

Альтернативной схемой может быть использование экспоненциального затухания. Преобразуйте поле count в десятичный тип. Один раз в день уменьшайте количество каждого элемента на фиксированный процент (менее 1 %, более 0,1 %), чтобы чем более недавнее попадание, тем больший "вес" оно имеет. Так что старая популярность никогда не умирает полностью, но хиты от год назад это мало что даст. Эквивалент этой схемы, кстати, состоит в том, чтобы оставить код как есть, но гарантировать, что ваш сайт в целом со временем станет экспоненциально более популярным;-)

Что касается того, чтобы не начинать с нуля - возможно, немедленно уменьшите количество каждого элемента, как одноразовое действие, на пропорцию, которая зависит от возраста элемента. В целом можно было бы ожидать, что более старые объекты имеют более старые представления и, следовательно, имеют завышенную оценку по текущей схеме. Это не доказательство дурака, так как, возможно, некоторые старые предметы в последнее время получили много просмотров. Вы можете определить эти элементы, просмотрев последние журналы веб-сервера или потратив неделю или месяц на подсчет обращений, прежде чем выполнять одноразовое сокращение. Даже без этого, если есть фундаментальная причина их популярности (не только потому, что в настоящее время они занимают высокие позиции в ваших рейтингах и, следовательно, получают трафик от людей, просматривающих ваш "самый популярный" график), то, надеюсь, они восстановятся со временем.

 2
Author: Steve Jessop, 2010-09-20 17:07:11

Возможно, вы захотите проверить это сообщение в блоге . Он нацелен на движок приложений, но техника является общей. Основной подход заключается в том, чтобы популярность падала экспоненциально и увеличивалась каждый раз, когда вы записываете голосование/загружаете/что угодно.

 1
Author: Nick Johnson, 2010-09-21 07:18:19