web-dev-qa-db-fra.com

MySQL match () contre () - ordre par pertinence et colonne?

Bon, j'essaie de faire une recherche en texte intégral sur plusieurs colonnes, quelque chose de simple comme ceci:

SELECT * FROM pages WHERE MATCH(head, body) AGAINST('some words' IN BOOLEAN MODE)

Maintenant, je veux classer par pertinence (combien de mots sont trouvés?) Ce que j'ai pu faire avec quelque chose comme ceci:

SELECT * , MATCH (head, body) AGAINST ('some words' IN BOOLEAN MODE) AS relevance 
FROM pages
WHERE MATCH (head, body) AGAINST ('some words' IN BOOLEAN MODE)
ORDER BY relevance

Maintenant, voici la partie où je me perds, je veux donner la priorité à la pertinence dans la colonne head.

Je suppose que je pourrais créer deux colonnes de pertinence, une pour head et une pour body, mais à ce moment-là, je ferais à peu près la même recherche dans le tableau trois fois, et pour ce que j Avec cette fonction, les performances sont importantes, car la requête sera jointe et comparée à d’autres tables.

Donc, ma question principale est, existe-t-il un moyen plus rapide de rechercher la pertinence et de hiérarchiser certaines colonnes? (Et en prime, la pertinence peut même compter le nombre de fois où les mots apparaissent dans les colonnes?)

Toute suggestion ou conseil serait génial.

Note: Je vais l'exécuter sur un serveur LAMP. (WAMP en test local)

72

Ceci pourrait donner une pertinence accrue à la partie principale que vous souhaitez. Cela ne doublera pas, mais cela pourrait suffire à votre bien:

SELECT pages.*,
       MATCH (head, body) AGAINST ('some words') AS relevance,
       MATCH (head) AGAINST ('some words') AS title_relevance
FROM pages
WHERE MATCH (head, body) AGAINST ('some words')
ORDER BY title_relevance DESC, relevance DESC

-- alternatively:
ORDER BY title_relevance + relevance DESC

Une alternative que vous souhaitez également explorer, si vous avez la possibilité de changer de moteur de base de données, est Postgres . Cela permet de définir le poids des opérateurs et de jouer avec le classement.

146
Denis de Bernardy

Ajoutez juste pour qui pourrait avoir besoin .. N'oubliez pas de modifier le tableau!

ALTER TABLE table_name ADD FULLTEXT(column_name);
11
Camilla

Je ne l'ai jamais fait, mais il semble que

MATCH (head, head, body) AGAINST ('some words' IN BOOLEAN MODE)

Devrait donner un poids double aux allumettes trouvées dans la tête.


Il suffit de lire ce commentaire sur le page docs , pensait que cela pourrait vous être utile:

Publié par Patrick O'Lone le 9 décembre 2002 à 6h51

Il convient de noter dans la documentation que IN BOOLEAN MODE retournera presque toujours une pertinence de 1,0. Pour obtenir une pertinence significative, vous devez:

SELECT MATCH('Content') AGAINST ('keyword1 keyword2') as Relevance 
FROM table 
WHERE MATCH ('Content') AGAINST('+keyword1+keyword2' IN BOOLEAN MODE) 
HAVING Relevance > 0.2 
ORDER BY Relevance DESC 

Notez que vous effectuez une requête de pertinence régulière pour obtenir des facteurs de pertinence combinés avec une clause WHERE qui utilise BOOLEAN MODE. Le mode BOOLEAN vous donne le sous-ensemble qui répond aux exigences de la recherche BOOLEAN, la requête de pertinence respecte le facteur de pertinence et la clause HAVING (dans ce cas) garantit que le document est pertinent pour la recherche (c'est-à-dire des documents dont le score est inférieur à 0,2). sont considérés comme non pertinents). Cela vous permet également de classer par pertinence.

Cela peut être ou ne pas être un bug dans la façon dont fonctionne IN BOOLEAN MODE, bien que les commentaires que j'ai lus sur la liste de diffusion suggèrent que le classement de la pertinence de IN BOOLEAN MODE n'est pas très compliqué, se prêtant donc mal à fournissant effectivement les documents pertinents. BTW - Je n’ai pas remarqué de perte de performances, car il semble que MySQL n’effectue la recherche FULLTEXT qu’une seule fois, même si les deux clauses MATCH sont différentes. Utilisez EXPLAIN pour le prouver.

Il semblerait donc que vous n’ayez peut-être pas à vous soucier d’appeler deux fois la recherche en texte intégral, même si vous devez tout de même "utiliser EXPLAIN pour le prouver".

9
jisaacstone

Je jouais juste avec ça aussi. Vous pouvez ajouter du poids supplémentaire dans la zone ORDER BY du code.

Par exemple, si vous faites correspondre 3 colonnes différentes et souhaitez pondérer davantage certaines colonnes:

SELECT search.*,
MATCH (name) AGAINST ('black' IN BOOLEAN MODE) AS name_match,
MATCH (keywords) AGAINST ('black' IN BOOLEAN MODE) AS keyword_match,
MATCH (description) AGAINST ('black' IN BOOLEAN MODE) AS description_match
FROM search
WHERE MATCH (name, keywords, description) AGAINST ('black' IN BOOLEAN MODE)
ORDER BY (name_match * 3  + keyword_match * 2  + description_match) DESC LIMIT 0,100;
3
Noah King