2008-11-24 11 views
3

Je développe une sorte de moteur de recherche personnalisé dans Ruby on Rails, et j'essaie actuellement de trouver le meilleur moyen de trier les résultats en fonction du dossier de l'utilisateur, en temps réel. Exemple: les éléments recherchés peuvent avoir des points (entités séparées avec des identifiants), par exemple item a tags = [1, 5, 10, 23, 45]. D'autre part, l'utilisateur peut avoir marqué certaines balises comme étant d'un intérêt particulier, donc l'utilisateur a des balises = [5, 23].RT traitement parallèle dans Rails

Le score utilisé pour trier les résultats doit prendre en compte le nombre de points de l'élément qui sont «regardés» par l'utilisateur. Par exemple, le score de l'objet serait de 50% basé sur les attributs de l'objet et de 50% sur le rang selon l'utilisateur (nombre de tags regardé). Une idée était d'injecter ceci dans la fonction de tri dans le système de recherche d'information. Mais dans Sphinx, que j'utiliserai probablement, il serait très difficile à implémenter (lorsque le vecteur de l'utilisateur est grand). Je ne sais pas à propos de Lucene/solr, mais ils ne semblent pas avoir avancé les capacités de recherche de texte dont j'ai besoin de toute façon (distance, date, heure, etc.)

L'autre option est de récupérer l'ensemble intermédiaire de Système IR, puis le traiter au niveau de l'application. Cependant, je suis certain que le traitement séquentiel de 100 à 1000 enregistrements, puis leur tri dans Rails serait très lent. D'autre part, il semble que la tâche peut être facilement traitée en parallèle - diviser 1000 enregistrements en ensembles qui sont traités par des threads séparés, puis triés. J'ai lu plusieurs implémentations de réduction de carte, aussi bien universelles que hadoop et spécifiques aux rails comme skynet etc., mais elles conviennent mieux aux gros travaux par lots, pas au traitement en temps réel (à moins que je ne me trompe?).

Existe-t-il une implémentation MR légère en mémoire que je pourrais utiliser pour cela? Ou peut-être avez-vous d'autres idées pour le gérer?

(Sidenote: Je crois que cette configuration est similaire au fonctionnement de google news, d'après ce que je comprends de l'article de "personnalisation de Google Actualités: filtrage collaboratif en ligne évolutif" qui correspond en temps réel à un ensemble de clusters auquel appartient l'utilisateur (pré-calculé plus tôt) pour trier les histoires de façon personnalisée)

Répondre

1

Map/Reduce est idéal pour ce genre de chose mais vous pouvez l'utiliser en SQL en utilisant une table intermédiaire.

On peut supposer que vous avez déjà des tables comme ceci:

 
users (id, ...) 
items (id, ...) 
tags (id, ...) 
users_tags (user_id, tag_id) 
items_tags (item_id, tag_id) 

Alors, pourquoi ne pas maintenir une table comme ceci:

users_items_tags (user_id, item_id, tag_id)

où chaque ligne signifie « cet utilisateur et ce item partager ce tag ".

Ensuite, votre requête de recherche est quelque chose comme ceci:

 
    select item_id, count(tag_id) as score 
    from users_items_tags 
    where user_id = <USER_ID> 
group by item_id 
order by score desc 

Lorsqu'un utilisateur ajoute une étiquette, users_items_tags est mis à jour comme ceci:

 
insert into users_items_tags (user_id, item_id, tag_id) 
    select <USER_ID>, item_id, <TAG_ID> 
     from items_tags 
     where tag_id = <TAG_ID> 

et également lors de l'ajout d'une étiquette à un élément .Lorsqu'un tag est supprimé, il suffit de le supprimer sur l'étiquette et l'utilisateur/l'article.

Cette solution présente quelques problèmes. Si un tag particulier est commun parmi les éléments, alors beaucoup d'écritures seront effectuées lorsqu'un utilisateur ajoute cette balise, et vice versa. Si un tag est commun entre les éléments et les utilisateurs, la table deviendra très volumineuse. Vous devrez tenir compte de ces cas pour votre ensemble de données particulier.

+0

Thx, c'est une possibilité, cependant puisque l'utilisateur pourrait bien cibler avoir 20-50% des articles qui lui sont recommandés et le nombre de tags est intentionnellement limité, cela se traduirait par une quantité de données assez massive. – Otigo