2016-12-16 1 views
1

Je suis en train de peaufiner mes requêtes de recherche de texte pour obtenir les meilleurs résultats possibles pour des termes de recherche donnés. Ce que je recherche est une fonction de classement qui augmentera le score uniquement pour les nouvelles valeurs uniques dans le champ recherché. Il devrait également marquer des coups exacts meilleurs que juste des coups de préfixe. J'ai été en mesure d'atteindre les résultats souhaités avec une requête encombrante, mais je me demandais si vous pourriez obtenir des résultats similaires plus élégants en utilisant une fonction de classement. Je vais vous donner un exemple:Fonction de classement de plusieurs valeurs uniques dans PostgreSQL

CREATE TABLE book (
    id BIGSERIAL NOT NULL PRIMARY KEY, 
    title VARCHAR(255) NOT NULL 
); 

INSERT INTO book (title) VALUES ('Kate Mat'); 
INSERT INTO book (title) VALUES ('Kate Kate Mate'); 
INSERT INTO book (title) VALUES ('Cat Mat'); 

Voici ma requête volumineuse avec les termes de recherche de Kate '+ « Mat »:

SELECT 
    title, 
    a1 + a2 + b1 + b2 AS score 
FROM (
     SELECT 
     title, 
     CASE WHEN to_tsvector('english', title) @@ to_tsquery('kate:*') 
      THEN 1 
     ELSE 0 
     END AS a1, 
     CASE WHEN to_tsvector('english', title) @@ to_tsquery('kate') 
      THEN 0.5 
     ELSE 0 
     END AS a2, 
     CASE WHEN to_tsvector('english', title) @@ to_tsquery('mat:*') 
      THEN 1 
     ELSE 0 
     END AS b1, 
     CASE WHEN to_tsvector('english', title) @@ to_tsquery('mat') 
      THEN 0.5 
     ELSE 0 
     END AS b2 
     FROM book 
    ) scoredProducts 
ORDER BY score DESC; 

#----------------------results------------------------- 
title   score 
Kate Mat  3  -- exact hit for both terms 
Kate Kate Mate 2.5  -- exact hit for 'Kate'. prefix hit for 'Mat' 
Cat Mat   1.5  -- exact hit for 'Mat' 

Ceci est en fait l'ordre de résultat que je veux voir. Le problème évident avec la requête est que je dois l'adapter pour chaque terme de recherche supplémentaire. Je voudrais une chose syntaxe plus comme ceci:

SELECT 
    title, 
    ts_rank(to_tsvector('english', book.title), to_tsquery('kate:* | mat:*')) AS score 
FROM book 
ORDER BY score DESC; 

#----------------------results------------------------- 
title   score 
Kate Kate Mate 0.0683918  -- prefix hits for both terms 
Kate Mat  0.06079271  -- exact hit gets scored less 
Cat Mat   0.030396355 

qui fournit malheureusement pas l'ordre que je veux parce qu'il scores plusieurs fois les mêmes coups mieux que les succès uniques exactement. Est-il possible d'écrire une telle fonction de classement personnalisée?

Répondre

0

Je ne suis pas tout à fait sûr si je comprends votre problème,
Vous pouvez simplifier votre requête en utilisant quelques mots-clés SQL de base et un funtion global de cette façon:

SELECT 
    b.title, 
    sum(case when to_tsvector('english' , title) @@ to_tsquery(a.keyword) 
      then a.score end) AS score 
    FROM book b 
    cross join ( 
    values 
    ('kate:*', 1), 
    ('kate', 0.5), 
    ('mat:*', 1), 
    ('mat', 0.5) 
) as a(keyword, score) 
group by b.title 
ORDER BY score DESC; 

Il vous reste à adapter cette requête pour chaque nouveau terme de recherche, mais maintenant il semble légèrement plus facile.

+0

Cela est plus compact, ne connaissait pas les valeurs de jointure. Mon objectif serait d'avoir une fonction qui pourrait prendre les termes de recherche comme 'kate mat ...' et calcule juste l'ordre avec la priorité des hits uniques et exactes. – SlideM