Quantcast
Channel: Mattermost Discussion Forums - Latest posts
Viewing all articles
Browse latest Browse all 25778

MySQL and Postgres to support Japanese search

$
0
0

Groonga(日本語も他の言語もいける全文検索エンジン)とMroonga(GroongaをMySQLから使えるようにするプラグイン)とPGroonga(GroongaをPostgreSQLから使えるようにするプラグイン)を開発していて全文検索に関する知識があり、助けになれるかもしれないと思ったのでコメントします。

やりとりの中であっていることとあっていないことを示します。他にも、これはあっているか?という項目があれば回答するので言ってください。

個人的にはいいと思うんですが、N-gramって日本語以外のマルチバイト文字列でも使えるはずなので、その辺も考慮できればよりいいんじゃないでしょうか。

N-gramを使うと日本語以外の言語も扱えるというのはあっています。

ただし、(後でも触れますが)to_tsvectorを使う仕組みではN-gramを使うことはできません。

PostgreSQLでの N-gram 検索は 照合演算子(@@) ではなく LIKE を使用する

あっています。

(ググった限り、textsearch_ja & MeCab 方式はちょっとレガシーみたいですし…)

textsearch_jaを開発していた人はすでにメンテナンスをしていないのでそういう意味ではレガシーですが、GitHubで(非公式といいつつ)メンテナンスしている人がいるので、その人が頑張っているうちは使っても大丈夫かと思います。

ただ、最新PostgreSQLに対応する点についてメンテナンスしているようなので、なにか問題があったときにどこまで対応できるかは未知数かと思います。

ただ、英語圏の人にとってはN-gramのLIKE検索は使い勝手が悪いと思うので、現在の@@検索とどちらを使うか選択できるようになっていなければならないのでは、とも思います。

これはN-gramは関係なくLIKE検索かどうかという話になります。

LIKE検索は部分一致検索になりますが、そうすると、単語の一部でヒットすることがあります。たとえば、部分一致では「sum」で検索すると「consumer」もヒットします。このとき、「consumer」が望んでいない結果の場合は検索ノイズとなります。検索ノイズが増えると探している情報を見つけにくくなるので使い勝手が悪くなります。

日本語で言えば、「京都」で検索したら「東京都」もヒットするかどうか、というようなケースです。

to_tsvector('english')の場合は部分一致検索ではなく単語で検索できます。そうすると「sum」で検索したときに「consumer」はヒットしません。なお、to_tsvector('english')他にもステミングと呼ばれるの語形の変化を吸収する処理もしています。たとえば、「speak」と「speaks」と「speaking」をすべて同じものとして扱う、ということです。

to_tsvector('japanese')なら、「京都」で検索しても「東京都」はヒットしない、というような感じです。単語の区切りが「東」と「京都」ではないからです。

ただ、日本語の場合は必ずしも単語の区切りで検索できたほうがよいというわけではありません。単語の区切りを見つけることが難しく、単語の区切りにならないことがあるからです。英語など単語を空白で区切る言語にはない難しさです。人名や新語などはうまく区切ることができないことがあります。

実際は部分一致の方が便利なことが多いです。部分一致を高速に実現するために使う技術がN-gramになります。

なぜなら、regconfigを明示しない場合にはIndex ScanされずSeq Scanで実行されるため、パフォーマンス上の懸念となるためです。
(注: 実際どの程度パフォーマンスに差異があるのか計測したわけではなく、まあそうなんだろうなあ、という想像で書いています。)

どの程度パフォーマンスに影響があるかは1レコードあたりのバイト数とレコード数が影響します。環境にもよりますが、たとえば、250万件あっても1レコードのバイト数が20バイト程度なら1秒程度で実行できます。一方、1レコードのバイト数がもっと大きければもっと少ない件数でも1秒以上かかります。

参考: http://www.clear-code.com/blog/2015/5/25.html

to_tsvector(Terms) // with N-Gram

これはできません。

まず、言語を指定しなければインデックスを作れないからです。

CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector(body));
-- ERROR:  functions in index expression must be marked IMMUTABLE

それと、N-gramを使うときはインデックス側だけでなく、検索キーワード側もN-gram用の処理をしなければいけないからです。なので、もし実現しようとすれば、to_tsvectorを変更しただけでは足りなく、to_tsqueryも変更しなければいけません。しかし、to_tsqueryではN-gramで作ったインデックスで検索するための条件を表現することができません。具体的に言うと「フレーズ検索」を表現できません。

(用語として "tokenizer" というのが適切なのかもちょっと自信ないです。)

あまり適切ではありません。tokenizer(英語ならスペースで区切って日本語なら単語で区切ったりするやつ)とその言語特有の処理を含んでいるからです。たとえば、英語なら上述のステミングという処理が入っています。textsearch_jaならいわゆる半角カタカナを全角カタカナに正規化したりします。


Viewing all articles
Browse latest Browse all 25778

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>