トライグラムインデックスまたは「タイプミスで検索」

どういうわけか、勤務中に、サイトの検索によく知られている機能を追加することが必要になりました。サービス「おそらくあなたは...」または「タイプミスで検索」です。 彼らは実装方法を考え始めました。 サードパーティのサービスとapiを使用したくありませんでした。なぜなら、他の人のサーバーに戻って戻ってくる時間が、一般的にあまり良くないからです。 ところで、pg_trgmモジュールが登場しました。このモジュールは、トリグラムインデックスに基づいてクエリに近い単語を検索します。





実装



手始めに-使用方法。

同様の単語を検索するには、正しいオプションのリストを作成する必要があります。 テキストフィールドを使用してテーブルを作成し、後でトリグラムインデックスをハングアップします。



CREATE TABLE " public "."tbl_words" (

"word" VARCHAR (255) NOT NULL

) WITHOUT OIDS;




* This source code was highlighted with Source Code Highlighter .








さまざまな方法で表に記入できますが、私たちはこの問題を次のように解決しました。

-Zaliznyakの文法辞書(〜9万語)、ロシア文学の辞書(〜16万語)、またはその他のまたはすべてをまとめたもの。 辞書はネットワーク上で簡単に見つかり、通常は行ごとの単語のリストであり、そのようなデータベースを解析することは難しくありません。

-データベースには約20万のオンライン書店があり、それぞれに名前、著者、簡単な要約などがあります。 ユーザーはこのデータの単語を使用して検索する可能性が高いため、すべてをまとめて空白で区切り、テーブル内の一意の単語を入力します。



次に、インデックスを追加します。



CREATE INDEX "tbl_words_trgm_idx" ON " public "."tbl_words"

USING gist ("word" " public "."gist_trgm_ops");




* This source code was highlighted with Source Code Highlighter .








この形式では、回路はすでに使用できます。



select word, similarity(word, '' ) from tbl_words



* This source code was highlighted with Source Code Highlighter .








同様のクエリは、類似の単語とレートを提供し、単語が提案された単語とどれだけ類似しているかを示します。 「類似性」を逆順に評価して並べ替えると、最も類似した単語が得られます。



select word from tbl_words where word % '' order by similarity(word, '' ) desc , word limit 5



* This source code was highlighted with Source Code Highlighter .








次に、結局、人が間違えられ、正しい選択肢が提供されるべきであるかどうかを判断する必要があります。 最も明らかなオプションは、ユーザーがリクエストで何も見つからなかった場合、または、例えば、ほとんど結果が見つからなかった場合、同様のオプションをチェックします。 同様のオプションの検索で特定の数の結果が返された場合、ユーザーにヒントが表示されます。

この段階で、正しい結果を得るために、値をねじって、類似する単語やその他のプロパティの検索結果がどれだけ表示されたかを示すことができます。 「類似性評価」のしきい値を設定する価値があります。これは、単語を類似と見なす必要すらありません。



ただし、この方法にはいくつかの大きな欠点があります。

1)辞書は個々の単語で構成されていますが、検索クエリは通常多音節です。 同様のフレーズの検索は、単語ごとに個別に実行し、それらを結合する必要があります。 つまり、たとえば、「Pushkin's poignant poetry」という検索フレーズがあり、結果が得られない場合、「poignant」、「poetry」、「Pushkin」のそれぞれに類似した単語を探す必要があります。 同様の単語を2つ取ると、バリエーションの数は8になります。これにより、ベースに適切な負荷がかかりますが、これは通常は不満です。

2)必要なすべてのパラメーターが設定されている場合でも、クエリに関係のない単語を検索すると元のクエリよりも多くの結果が生成されると、奇妙な奇妙なことが起こります。 したがって、たとえば「ティナ」という単語を検索すると、「プーチン大統領を念頭に置いている」とか、「神は禁じられている」、またはその逆のような文が表示されます。



合計:

長所-簡単な実装、ヒント用の多数のオプション。

短所-大量のリクエストでデータベースをロードすると、定期的に間違ったプロンプトが表示されます。





オプション2



検索クエリの統計を保持する場合は、別のオプションを使用できます。

一意の検索クエリでテーブルが作成され、同じ原則を使用してクエリフィールドにトライグラムインデックスが追加されます。 また、一致は単語を個別に検索するのではなく、保存されたクエリの完全な検索フレーズを検索します。



合計:

長所-ツールチップのフレーズはユーザーが作成するため、「愚かな」ヒントの可能性は低くなります。

短所-データベースの完全性は、クエリ統計のみに依存します。



テストを繰り返した後、2番目の方法を優先して最初の方法を放棄することにしまし 。結果はすでに予測不可能でした)2番目の方法の結果はここにあります





どのように機能しますか?



すべてを明確にするために、その仕組みを説明します。 すべてが非常に簡単です。

各単語は3文字の組み合わせ-トライグラムに分割されます。

例:







同様のフレーズを検索する場合、同一のトライグラムが検索されます。 トライグラムが等しいほど、フレーズは元のフレーズに似てきます。





関連アイテム。



トライグラムインデックスは、もう1つの場合に役立ちます。 製品ページには、「この著者の製品」、「この出版社の製品」など、さまざまなオファーのブロックがあります。 それらの1つは「関連製品」です。

多くのサイトには同様の機能がありますが、経験から、通常はメイン製品と同じカテゴリの製品、または手動で割り当てられたリストのいずれかです。 また、全文検索を使用して見つかった製品が、たとえばメイン製品の名前から2語または1語で表示される実装もありました。 しかし、これはしばしば、あまり予測できない結果をもたらします。 たとえば、「C ++のアプリケーションアーキテクチャ」という本は、アーキテクチャと構築に関する本を発行しました。



商品の名前に設定されたトライグラムインデックスは、適切な「関連性のある」結果をもたらしました。例はこちら 、またはサイトの製品ページにあります。





誰かが興味があるなら、次回はパフォーマンステストとソースコードを投稿します。





UPD:別の検索例- 文字を並べ替えます。






All Articles