2016-12-16 17 views
1

現在、指定された検索用語に対して最良の結果を得るために、テキスト検索クエリを調整しています。私が探しているのは、検索されたフィールド内の新しい一意の値に対してのみスコアを上げるランキング関数です。また、接頭辞ヒットだけでなく正確なヒットをスコアする必要があります。私は大量のクエリで目的の結果を達成することができましたが、ランク関数を使用して同様の結果をよりエレガントに達成できるかどうかは疑問でした。 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'); 

はここで検索用語「ケイト」+「マット」と私かさばらクエリです:私はあなたの例をあげる

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' 

これは実際に私が見たいと思って、結果の順序です。クエリの明白な問題は、追加の検索用語ごとにそれを適用する必要があることです。

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 

正確なユニークなヒットよりも、複数の同じヒットより良いので、それがスコア悲しげに私が欲しいの順序を提供していない:私はもっとこのような構文何かをしたいと思います。そのようなカスタムランク関数を書くことは可能ですか?

答えて

0

私はあなたがいくつかの基本的なSQLのキーワードと、このように集計目的球を使用してクエリを簡素化することができ、
私はあなたの問題を理解している場合、非常にわからない:

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; 

あなたはまだこのクエリを適応する必要があります新しい検索用語ごとに表示されますが、現在ははるかに簡単です。

+0

これはもっとコンパクトですが、結合値についてはわかりませんでした。私の目標は、「ケイト・マット」のような検索用語を取る機能を持つことであり、ユニークで正確なヒットを優先して注文を計算するだけです。 – SlideM

関連する問題