Question

J'ai un problème de développement d'application Web pour lequel j'ai développé une solution, mais j'essaie de trouver d'autres idées qui pourraient contourner certains problèmes de performances que je vois.

énoncé du problème :

  • un utilisateur saisit plusieurs mots-clés/jetons
  • l'application recherche des correspondances avec les jetons
  • besoin d'un résultat pour chaque jeton
    • c'est-à-dire que si une entrée a 3 jetons, j'ai besoin de l'identifiant d'entrée 3 fois
  • classer les résultats
    • attribuer X points pour la correspondance des jetons
    • trier les identifiants d'entrée en fonction des points
    • si les valeurs des points sont les mêmes, utilisez la date pour trier les résultats

Ce que je veux pouvoir faire, mais je n'ai pas compris, c'est envoyer 1 requête qui renvoie quelque chose qui ressemble aux résultats d'un in(), mais renvoie un identifiant d'entrée en double pour chaque jeton correspondant à chaque identifiant d'entrée vérifié.

Existe-t-il une meilleure façon de procéder que ce que je fais, consistant à utiliser plusieurs requêtes individuelles exécutant une requête par jeton ?Si oui, quelle est la manière la plus simple de les mettre en œuvre ?

modifier
J'ai déjà tokenisé les entrées, donc, par exemple, "see spot run" a un identifiant d'entrée de 1 et trois jetons, "see", "spot", "run", et ceux-ci sont dans une table de jetons séparée, avec les identifiants d'entrée qui leur correspondent, le tableau pourrait donc ressembler à ceci :

'see', 1 
'spot', 1 
'run', 1 
'run', 2 
'spot', 3 
Était-ce utile?

La solution

vous pouvez y parvenir en une seule requête en utilisant « UNION ALL » dans MySQL.

Parcourez simplement les jetons en PHP en créant un UNION ALL pour chaque jeton :

Par exemple, si les jetons sont « x », « y » et « z », votre requête peut ressembler à ceci

SELECT * FROM `entries` 
WHERE token like "%x%" union all 
    SELECT * FROM `entries` 
    WHERE token like "%y%" union all 
        SELECT * FROM `entries` 
        WHERE token like "%z%" ORDER BY score ect...

La clause order doit fonctionner sur l’ensemble des résultats comme un seul, ce dont vous avez besoin.

En termes de performances, ce ne sera pas si rapide (je suppose), mais avec les bases de données, la principale surcharge en termes de vitesse est souvent l'envoi de la requête au moteur de base de données depuis PHP et la réception des résultats.Avec cette technique, cela ne se produit qu'une fois au lieu d'une fois par jeton, donc les performances augmenteront, je ne sais tout simplement pas si cela suffira.

Autres conseils

Je sais que ce n'est pas strictement une réponse à la question que vous posez mais si votre table comporte des milliers plutôt que des millions de lignes, alors une solution FULLTEXT pourrait être la meilleure façon de procéder ici.

Dans MySQL, lorsque vous utilisez MATCH sur votre colonne indexée, chaque mot-clé que vous fournissez se verra attribuer un score de pertinence (calculé approximativement par le nombre de fois où chaque mot-clé a été mentionné) qui sera plus précis que votre méthode et certainement plus efficace pour plusieurs mots-clés.

Vois ici:http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

Si vous utilisez le modèle UNION ALL, vous souhaiterez peut-être également inclure les parties suivantes à votre requête :

SELECT COUNT(*) AS C
...
GROUP BY ID
ORDER BY c DESC

Bien qu'il s'agisse d'un exemple vraiment trivial, il vous donne la fréquence des correspondances pour chaque résultat et cela pourrait être un pseudo-classement pour commencer.

Vous obtiendrez probablement de bien meilleures performances si vous utilisez une structure de données conçue pour les tâches de recherche plutôt qu'une base de données.Par exemple, vous pourriez essayer de créer un indice inversé.Plutôt que de l'écrire vous-même, vous voudrez peut-être aussi vous pencher sur quelque chose comme Lucène qui fait la majeure partie du travail à votre place.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top