5 votes

mise en œuvre de la recommandation de produit (du pauvre)

J'essaie de créer un système de recommandation pour une boutique en ligne. Je veux réaliser ce genre de fonctionnalité Amazon "Les clients qui ont acheté cet article ont également acheté" et j'ai lu beaucoup de choses à ce sujet. Je sais qu'il existe ce truc Apache Mahout, mais je ne parviens pas à modifier le serveur de cette manière. Ensuite, il y a l'API de prédiction de Google, mais elle coûte cher, alors je commence à expérimenter moi-même.

J'ai obtenu un historique des commandes de plus de 250 000 articles et j'ai écrit une requête MySQL imbriquée pour trouver les commandes qui contiennent l'article actuel, classer les autres articles de la commande et trier cette table pour le classement, afin d'obtenir un ensemble de produits que d'autres personnes ont commandés avec l'article actuel.

Le problème, c'est que la requête peut prendre jusqu'à 10 secondes, ce qui ne permet pas de l'utiliser directement. J'ai pensé à une table de cache, mais cette requête s'arrête au bout de 20 minutes (il y a 60.000 produits et 250.000 articles commandés) Donc je ne peux pas remplir cette table.

Ma solution de rechange actuelle est la suivante : Le HTML de la recommandation est chargé via AJAX ondocumentready, de sorte que le site se charge, tandis que la recommandation se charge en arrière-plan. Les données de la recommandation sont traitées une fois et stockées dans un cache de fichiers (cache simple de PEAR) afin qu'elles se chargent plus rapidement la fois suivante. Le cache est donc créé à la demande si quelqu'un visite le site et stocké pendant un jour ou peut-être une semaine.

Je me demande, et je vous demande, si cette approche est acceptable ou si elle est stupide et peu performante. Serait-il préférable de stocker les données en cache dans une base de données ou dans un fichier (je pense aux performances et aux hits parallèles). Je veux dire, dans le pire des cas, je me retrouverais avec 60.000 cachefiles.

Je préférerais un tableau pré-calculé avec toutes les données, mais comme je l'ai dit, cela prend trop de temps et je ne sais pas comment l'optimiser. (J'attends le retour de vacances de SQL Dude ^^)

Merci pour tout conseil ou avis.

btw. c'est la requête :

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 :

J'ai réfléchi aux réponses données et je pense qu'elles sont similaires à mon idée initiale. Le code ci-dessus donne le tableau suivant :

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

Le ParentID est l'élément actuel, ChildID les éléments qui ont été commandés dans le passé avec ParentID, Rank est le compte précalculé de la fréquence à laquelle l'enfant est commandé avec l'élément actuel. Maintenant je peux UPDATE ou INSERT les articles liés à chaque nouvelle commande et compter le rang s'il est déjà présent dans la base de données. La seule chose que je crains, c'est de me retrouver avec une table vraiment très grande. Peut-être que cela ne devrait pas être un problème, si je le précalcule hors ligne une fois par semaine ? Mais alors je dois optimiser la requête pour qu'elle ne prenne pas 10 secondes par élément.

Qu'en pensez-vous ?

3voto

user982911 Points 141

Vérifier easyrec Il a les fonctionnalités dont vous avez besoin et il est gratuit. Aucun réglage n'est nécessaire et vous pouvez utiliser l'instance Demo comme google analytics. Je pense qu'il sera beaucoup plus facile d'utiliser ce service web gratuit que de coder toute la logique par vous-même.

Dans un tweet Aujourd'hui, ils ont mentionné qu'ils supportent le support complet de mahout à easyrec, donc vous avez tout avec easyrec. vous pouvez soit utiliser le webservice gratuit d'easyrec ou déployer le fichier WAR gratuit sur votre serveur web.

2voto

dmcnelis Points 2284

Pour ajouter à la réponse de @GalacticCowboy et compléter votre commentaire, @Marcus...

Un schéma pour accomplir ceci serait de créer une table comme :

RelatedItems
RelatedItemsId
purchasedItemId
relatedItemId

Ensuite, lorsqu'une commande est terminée (ou consultée, selon vos besoins), vous écrivez des enregistrements dans la table RelatedItems, où chaque article acheté reçoit un enregistrement dont l'identifiant est le purchasedItemId. Ensuite, tous les autres articles seraient écrits en tant que relatedItemId.

Par exemple, si j'ai acheté les articles 5, 9, 12 et 19, j'aurais 12 enregistrements écrits dans ma table qui ressembleraient à ceci :

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

Vous pourriez ensuite utiliser une requête similaire à celle de GalacticCowboy pour obtenir les 10 premiers articles qui ont été normalement achetés en même temps que l'un de ces articles.

Veuillez noter que ce n'est pas le schéma le plus efficace pour une tâche comme celle-ci, il pourrait être modifié pour réduire les données redondantes, mais étant donné que nous ne savons pas grand-chose de votre système et de la conception globale du schéma (et ce qui semble être une compréhension chancelante de certains concepts SQL), je ne vais pas m'étendre sur ce sujet.

0voto

GalacticCowboy Points 8185

Chaque fois qu'il y a une commande, stockez un enregistrement de relation entre les différents articles de la commande. Puis faites quelque chose comme :

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

Vous pourriez également présumer que cela utilise un processus de nuit ou quelque chose du genre et avoir un tableau qui ne contient que le haut de la liste. n les éléments connexes pour chaque ID d'élément.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X