(рекомендация бедного человека) о продукте - PullRequest
5 голосов
/ 18 июля 2011

Я пытаюсь создать систему рекомендаций для бедных для интернет-магазина. Я хочу реализовать такую ​​функцию Amazon «Клиенты, которые купили этот товар, также купили», и я много об этом читал. Я знаю, что это Apache Mahout, но я не могу настроить сервер таким образом. Тогда был бы API прогнозирования Google, но он стоил денег, поэтому я сам начал экспериментировать.

Я получил историю заказов с 250 000+ элементами и написал вложенный MySQL Query для поиска заказов, содержащих текущую статью, ранжирования других элементов заказа и сортировки этой таблицы для ранжирования, поэтому я получил набор продуктов, которые заказали другие люди вместе с текущей статьей.

Проблема в том, что запрос может занять до 10 секунд, поэтому его нельзя использовать напрямую. Я подумал о таблице кэширования, но этот запрос останавливается через 20 минут (есть 60 000 товаров и 250 000 заказанных товаров), поэтому я не могу заполнить эту таблицу.

Мой текущий обходной путь следующий: HTML рекомендации загружается через AJAX ondocumentready, поэтому сайт загружается, а рекомендация загружается в фоновом режиме. Данные рекомендаций обрабатываются один раз и сохраняются в файловом кэше (простой кэш PEAR), поэтому в следующий раз они загружаются быстрее. Таким образом, кеш создается по запросу, если кто-то посещает сайт, и хранится в течение дня или, возможно, недели.

Я спрашиваю себя и вас, будет ли это приемлемым подходом или это глупо и бесполезно? Было бы лучше хранить кэшированные данные в БД или в файле (я думаю о производительности и параллельных попаданий). Я имею в виду, что в худшем случае я получу 60 000 кеш-файлов.

Я бы предпочел предварительно вычисленную таблицу со всеми данными, но, как я уже сказал, это занимает много времени, и я не знаю, как ее оптимизировать. (Ожидание, пока чувак SQL вернется из отпуска ^^)

Спасибо за любую подсказку, мнение.

кстати. это запрос:

SELECT c.ArtNr as artnr , count(c.ArtNr) as rank, s.ArtNr as parent_artnr
FROM (
SELECT a.ID_order, a.ArtNr
        FROM net_orderposition a
        WHERE a.ArtNr = 'TT-PV0005'
) s
JOIN net_orderposition c 
WHERE s.ID_order = c.ID_order AND s.ArtNr != c.ArtNr
GROUP BY c.ArtNr
ORDER BY rank DESC,c.Stamp DESC
LIMIT 10;

EDIT:

Я думал о данных ответах и ​​думаю, что они похожи на мою первоначальную идею. Код выше приведен в следующей таблице:

ID,ParentID , ChildID  , Rank
1, TT-PV0005, TT-PV0040, 220
2, TT-PV0005, TT-PV0355, 135
3, TT-PV0005, TT-PV0450, 134
4, TT-PV0005, TT-PV0451, 89
5, TT-PV0005, RH-01V2  , 83
6, TT-PV0005, TT-PV0041, 83
7, TT-PV0005, TT-PV0353, 82
8, TT-PV0005, TT-PV0037, 80

ParentID - это текущий элемент, ChildID - элементы, которые заказывались в прошлом вместе с ParentID, Rank - это предварительно вычисленный счетчик того, как часто ребенок заказывается с текущим элементом. Теперь я могу обновлять или вставлять связанные элементы в каждом новом заказе и подсчитывать ранг, если он уже присутствует в БД. Единственное, чего я боюсь, я окажусь за действительно очень большим столом. Может быть, это не должно быть проблемой, если я пересчитываю его в автономном режиме раз в неделю? Но тогда мне нужно оптимизировать запрос, чтобы он не занимал 10 секунд на элемент.

Что ты думаешь?

Ответы [ 3 ]

3 голосов
/ 12 октября 2011

проверить easyrec он имеет необходимые функции и является бесплатным.нет необходимости в настройке, и вы можете использовать демонстрационный экземпляр, например, Google Analytics.Я думаю, что будет гораздо проще просто использовать этот бесплатный веб-сервис, а потом писать всю логику самостоятельно.

В твите сегодня они упомянули, что они поддерживают полную поддержку mahout для easyrec, так что у вас есть все с easyrec.Вы можете использовать бесплатный веб-сервис easyrec или развернуть бесплатный файл WAR на своемвеб-сервер.

2 голосов
/ 19 июля 2011

Чтобы добавить ответ @ GalacticCowboy и указать, где был ваш комментарий, @Marcus ...

Одной из схем для этого было бы создание таблицы вроде:

RelatedItems
RelatedItemsId
purchasedItemId
relatedItemId

Затем, когда заказ будет выполнен (или просмотрен в зависимости от ваших требований), вы запишете записи в таблицу RelatedItems, где каждый купленный предмет получает запись, в которой этот идентификатор - купленный идентификатор. Тогда все остальные элементы будут записаны как relatedItemId.

Например, если я совершу покупку предметов 5, 9, 12 и 19, у меня будет 12 записей, которые были записаны в мою таблицу, которые выглядят так:

RelatedItemId, PurchasedItemId, RelatedItemId
1, 5, 9
2, 5, 12
3, 5, 19
4, 9, 5
5, 9, 12
6, 9, 19
7, 12, 5
8, 12, 9
9, 12, 19
10, 19, 5
11, 19, 9
12, 19, 12

Тогда вы могли бы использовать запрос, аналогичный GalacticCowboy, чтобы получить 10 лучших товаров, которые обычно покупались вместе с любым из этих предметов.

Обратите внимание, что это не самая эффективная схема для такой задачи, ее можно немного изменить, чтобы уменьшить избыточные данные, но, учитывая, что мы не очень много знаем о вашей системе и общем дизайне схемы ( и что кажется шатким пониманием некоторых понятий SQL) Я не буду углубляться в это.

0 голосов
/ 19 июля 2011

Каждый раз, когда есть заказ, сохраняйте запись отношений между различными элементами в заказе. Затем сделайте что-то вроде:

SELECT ItemID, COUNT(RelatedItemID) AS RelatedItemCount
FROM RelatedItems
WHERE RelatedItemID = @viewingItemID
GROUP BY ItemID
ORDER BY RelatedItemCount DESC
LIMIT 10

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

...