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 ?