Skip to content

Instantly share code, notes, and snippets.

@askdkc
Last active May 16, 2025 02:48
Show Gist options
  • Save askdkc/1d3cebb16df4457ae8a238f2bbfcd98d to your computer and use it in GitHub Desktop.
Save askdkc/1d3cebb16df4457ae8a238f2bbfcd98d to your computer and use it in GitHub Desktop.
PGroongaを使って表記揺れ検索に対応させる方法

表記揺れ検索を実現するためのPGroongaの機能

例えば「斉藤」や「高橋」といった複数ある漢字の表記揺れを事前に辞書登録しておくことで、表記揺れ検索に対応できる(強敵:渡邊とかもいるね)

-- 必要な拡張機能追加
CREATE EXTENSION IF NOT EXISTS pgroonga;

-- ここで表記揺れ対応させる文字を登録するテーブルを作るよ
CREATE TABLE synonyms (
  target text,
  normalized text
);

-- 検索用にインデックスと表記揺れ用辞書データを作るよ
CREATE INDEX pgroonga_synonyms_index ON synonyms
 USING pgroonga (target pgroonga_text_term_search_ops_v2)
                INCLUDE (normalized);

INSERT INTO synonyms VALUES ('', '');
INSERT INTO synonyms VALUES ('', '');
INSERT INTO synonyms VALUES ('', '');
INSERT INTO synonyms VALUES ('', '');


-- 検索させるテーブルにデータを登録するよ
CREATE TABLE names (
  name text
);
CREATE INDEX pgroonga_names_index
          ON names
       USING pgroonga (name pgroonga_text_full_text_search_ops_v2)
   WITH (normalizers='
                NormalizerNFKC150,
                NormalizerTable(
                  "normalized", "${table:pgroonga_synonyms_index}.normalized",
                  "target", "target"
                )
             ');

INSERT INTO names
  (name)
  VALUES ('斉藤さん'),('齊藤さん'),('斎藤さん'),('鈴木さん'),('田中さん'),('佐藤さん'),('高橋さん'),('髙橋さん');


-- 斉藤で検索、どの斉藤もヒットする
SELECT name AS synonym_names from names where name &@~ '斉藤さん';
--  synonym_names 
-- ---------------
--  斉藤さん
--  齊藤さん
--  斎藤さん
-- (3 rows)


-- 同じく今度は高橋で検索している例、同じく全ての高橋がヒット
SELECT name AS synonym_names from names where name &@~ '高橋さん';
-- synonym_names 
-- ---------------
-- 高橋さん
-- 髙橋さん
-- (2 rows)

走れメロスに対応させる

これについて

https://forest.watch.impress.co.jp/docs/serial/yajiuma/1508769.html

ただし、「Aozorasearch」はちゃんとキーワードがマッチしないと探せません。たとえば「邪 知 暴虐」では『走れメロス』は見つけ出せず、「邪 智 暴虐」と入力しないといけません。Google検索ならばその程度の表記ゆれはマッチさせてくれるので適所適材、双方を使い分けるのがいいのかなと思います。

走れメロスの場合にもこうすれば対応可能

INSERT INTO synonyms VALUES ('', '');

INSERT INTO names
  (name)
  VALUES ('必ず、かの邪智暴虐の王を除かなければならぬと決意した');
  
-- 検索実施 「邪 知 暴虐」と「邪 智 暴虐」両方いけるぜ
SELECT name AS synonym_names from names where name &@~ '邪 知 暴虐';
--
--                     synonym_names 
-- ------------------------------------------------------
--  必ず、かの邪智暴虐の王を除かなければならぬと決意した
-- (1 row)


SELECT name AS synonym_names from names where name &@~ '邪 智 暴虐';
--
--                     synonym_names                      
-- ------------------------------------------------------
--  必ず、かの邪智暴虐の王を除かなければならぬと決意した
-- (1 row)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment