ホームページ >ウェブフロントエンド >jsチュートリアル >PostgreSQL 全文検索の位置別ランク

PostgreSQL 全文検索の位置別ランク

Patricia Arquette
Patricia Arquetteオリジナル
2024-12-13 13:08:10967ブラウズ

PostgreSQL Full Text Search Rank by Position

最近、全文検索で問題が発生しました。私は検索入力でこの機能を使用しており、入力時にバックエンドが一致する可能性のあるヒントを送信します。バックエンドデータベースはPostgreSQLです。テキスト内の検索語の位置によってヒントをランク付けする必要がありました。

そのため、「スター ウォーズ」のタイトルを検索すると、「スター ウォーズ 7 ~ 9 がスター ウォーズの世界をどう変えたか (スター ウォーズに関する楽しいドキュメンタリー)」ではなく、「スター ウォーズ」の投稿が最初に表示されます。期間が3回あるほど上位にランクされます。

PostgreSQL での全文検索

PostgreSQL での全文検索は非常に簡単に実現できます。使用する主なツールは 2 つあります:

  • tsvector - 検索可能なドキュメントを表します。
  • tsquery - ドキュメントに対して実行する検索クエリを表します。

ブログ投稿のタイトルを検索したいとします。それらを検索可能にするには、次のクエリを使用できます:

SELECT 
id, 
title 
FROM blogposts
WHERE to_tsquery('JavaScript') @@ to_tsvector(posts.title);

この場合、検索ごとに投稿タイトルを動的に tsvector に変換しています。ただし、この変換には時間がかかります。より良いアプローチは、この変換をデータベース内で事前に実行し、それをタイトルのインデックスとして保存して、検索を高速化することです。

タイトルのベクトルの新しい列を作成し、この新しい列にインデックスを付けましょう:

ALTER TABLE blogposts ADD COLUMN search_vector tsvector;
UPDATE blogposts SET search_vector = (to_tsvector(posts.title));
CREATE INDEX titles_fts_idx ON blogposts USING gin(search_vector);

次に、「JavaScript」という用語を検索してみてください

SELECT 
id, 
title
FROM blogposts
WHERE to_tsquery('JavaScript') @@ search_vector;

次のように、ts ベクトルから直接タイトル列にインデックスを作成することもできます。

CREATE INDEX titles_fts_idx ON blogposts USING GIN (to_tsvector(posts.title));

次のように検索を使用します:

SELECT 
id, 
title
FROM blogposts
WHERE to_tsquery('JavaScript') @@ posts.title;

全文検索が非常に高速になり、数ミリ秒で完了します。

結果のランキング

PostgreSQL には ts_rank 機能があり、検索結果にスコアを付け、ランキングに基づいて並べ替えることができます。 PostgreSQL は次のランキング オプションをサポートしています:

  • 0 (デフォルト) はドキュメントの長さを無視します
  • 1 はランクをドキュメントの長さの対数の 1 で割ります
  • 2 はランクをドキュメントの長さで割ります
  • 4 はランクをエクステント間の平均調和距離で割ります (これは ts_rank_cd によってのみ実装されます)
  • 8 は、文書内の固有の単語の数でランクを割ります
  • 16 は、ランクを文書内の固有の単語数の対数 1 で割ります
  • 32 はランクを 1 で割ります

ts_rank は次のように使用できます:

SELECT
    ...
ts_rank(search_vector, to_tsquery('JavaScript'), 0) as rank_title
    ...
ORDER BY rank_title DESC NULLS LAST

ただし、文字列 (タイトル列など) 内の検索語の位置に基づく組み込みのランキング オプションはありません。

救助の位置

幸いなことに、PostgreSQL には POSITION 関数があります。 PostgreSQL POSITION 関数は、指定された文字列内の部分文字列の位置を見つけるために使用されます。私たちの場合、次のように使用できます

SELECT 
id, 
title 
FROM blogposts
WHERE to_tsquery('JavaScript') @@ to_tsvector(posts.title);

ts_rank は正規化整数 2 を使用します。2 はランクをドキュメントの長さで割るためです。
マジックナンバー 0.0001 は、POSTION 関数が 0 ではなく 1 からカウントし、文字列が見つからない場合は 0 を返すため、0 による除算を避けるためのものです。

最終的なコードは次のようになります:

ALTER TABLE blogposts ADD COLUMN search_vector tsvector;
UPDATE blogposts SET search_vector = (to_tsvector(posts.title));
CREATE INDEX titles_fts_idx ON blogposts USING gin(search_vector);

さらに用語を検索する

一度に複数の用語を検索する場合は、1 つの注意点があります (JavaScriptTypeScript など)。

to_tsquery 関数の引数は、論理演算子などを含め、非常に柔軟に使用できます。一方、POSITION 関数は文字列内の「単なる」部分文字列です。

現実世界の例

これは、postgres (SQL) npm ライブラリを使用する SvelteKit Web アプリケーションの実際のエンドポイントからの私の例です:

SELECT 
id, 
title
FROM blogposts
WHERE to_tsquery('JavaScript') @@ search_vector;

問題のドキュメントへのリンクは次のとおりです:

  • https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-DOCUMENTS
  • https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-RANKING
  • https://www.postgresql.org/docs/9.1/functions-string.html

以上がPostgreSQL 全文検索の位置別ランクの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。