📖

Supabase の PGroonga 全文検索で同義語検索してみる

2023/01/28に公開

こちらの記事の続きです。

https://zenn.dev/hmatsu47/articles/supabase_pgroonga_flutter

PGroonga による全文検索で同義語検索できるようにしてみます。

PGroonga のドキュメントを参考に実装していきます。

https://pgroonga.github.io/ja/how-to/synonym-expansion.html

同義語テーブルとインデックスを作成する

まずは同義語テーブルを作成します。

同義語テーブル作成
CREATE TABLE synonyms (
  term text PRIMARY KEY,
  synonyms text[]
);

そして、そのテーブルにインデックスを作成します。

同義語テーブル用インデックス作成
CREATE INDEX synonyms_search ON synonyms USING pgroonga (term pgroonga_text_term_search_ops_v2);

テーブルとインデックスの作成ができたら、同義語をテーブルに追加します。

同義語をテーブルに追加
INSERT INTO synonyms (term, synonyms) VALUES ('美術館', ARRAY['美術館', 'ミュージアム']);
INSERT INTO synonyms (term, synonyms) VALUES ('博物館', ARRAY['博物館', 'ミュージアム']);
INSERT INTO synonyms (term, synonyms) VALUES ('ミュージアム', ARRAY['ミュージアム', '美術館', '博物館']);
  • 「美術館」で検索したときに「ミュージアム」を含む文章も対象とする
  • 「博物館」で検索したときに「ミュージアム」を含む文章も対象とする
  • 「ミュージアム」で検索したときに「美術館」「博物館」を含む文章も対象とする

という指定です。

ストアドファンクションを同義語検索対応にする

前回の記事で、WHERE句の条件に

  • ft_text &@~ keywords

と指定したところを、

  • ft_text &@~ pgroonga_query_expand('synonyms', 'term', 'synonyms', keywords)

に書き換えます。

https://pgroonga.github.io/ja/reference/functions/pgroonga-query-expand.html

ストアドファンクション同義語検索対応
CREATE OR REPLACE
 FUNCTION get_spots(point_latitude double precision, point_longitude double precision, dist_limit int, category_id_number int, keywords text)
RETURNS TABLE (
  distance double precision,
  category_name text,
  title text,
  describe text,
  latitude double precision,
  longitude double precision,
  prefecture text,
  municipality text
) AS $$
BEGIN
  RETURN QUERY
  SELECT ((ST_POINT(point_longitude, point_latitude)::geography <-> spot_opendata.location::geography) / 1000) AS distance,
    category.category_name,
    spot_opendata.title,
    spot_opendata.describe,
    ST_Y(spot_opendata.location),
    ST_X(spot_opendata.location),
    spot_opendata.prefecture,
    spot_opendata.municipality
  FROM spot_opendata
  INNER JOIN category ON spot_opendata.category_id = category.id
  WHERE
    (CASE WHEN dist_limit = -1 AND keywords = '' THEN false ELSE true END)
  AND
    (CASE WHEN dist_limit = -1 THEN true
      ELSE (ST_POINT(point_longitude, point_latitude)::geography <-> spot_opendata.location::geography) <= dist_limit END)
  AND
    (CASE WHEN category_id_number = -1 THEN true
      ELSE category.id = category_id_number END)
  AND
    (CASE WHEN keywords = '' THEN true
      ELSE ft_text &@~ pgroonga_query_expand('synonyms', 'term', 'synonyms', keywords) END)
  ORDER BY distance;
END;
$$ LANGUAGE plpgsql;

以上で全文検索が同義語対応になりました。

SQL Editor で確認

SQL Editor で「ミュージアム」を検索してみると、

「美術館」「博物館」もヒットしていることがわかります。


2023/2/1 追記:

続きの記事を書きました。

https://zenn.dev/hmatsu47/articles/supabase_pgroonga_stopword_wa

GitHubで編集を提案

Discussion