8.2. 検索#
select コマンドがqueryパラメータを使ってどのように検索するのかを説明します。
8.2.1. 検索の挙動#
検索の挙動には以下の3種類あり、検索結果によって動的に使い分けています。
完全一致検索
非わかち書き検索
部分一致検索
どのように検索の挙動を使い分けているかを説明する前に、まず、それぞれの検索の挙動を説明します。
8.2.1.1. 完全一致検索#
検索対象文書は複数の語彙にトークナイズ(分割)され、それぞれを単位とした語彙表に索引を管理します。 検索キーワードも同一の方法でトークナイズされます。
このとき、検索キーワードをトークナイズした結果得られる語彙の配列と同一の配列を含む文書を検索する処理を完全一致検索と呼んでいます。
たとえば、TokenMecabトークナイザを使用した索引では「東京都民」という文字列は
東京 / 都民
という二つの語彙の配列として格納されます。この索引に対して「東京都」というキーワードで検索した時、このキーワードは、
東京 / 都
という二つの語彙の配列として処理されます。この語彙の並びは、「東京 / 都民」という語彙の並びには一致しませんので、完全一致検索ではヒットしません。
これに対して、TokenBigramトークナイザを使用した索引では「東京都民」という文字列は
東京 / 京都 / 都民 / 民
という四つの語彙の配列として格納されます。この索引に対して「東京都」というキーワードで検索した時、このキーワードは、
東京 / 京都
という二つの語彙の配列として処理されます。この語彙の並びは、「東京 / 京都 / 都民」という語彙の並びに含まれますので、完全一致検索でヒットします。
なお、TokenBigramトークナイザでは、アルファベット・数値・記号文字列についてはbigramを生成せず、一つの連続したトークンとして扱います。たとえば、「楽しいbilliard」という文字列は、
楽し / しい / billiard
という三つの語彙の配列として格納されます。これに対して「bill」というキーワードで検索した時、このキーワードは、
bill
という一つの語彙として処理されます。この語彙の並びは「楽し / しい / billiard」という語彙の並びには含まれないので、完全一致でヒットしません。
これに対して、TokenBigramSplitSymbolAlphaトークナイザではアルファベット文字列についてもbigramを生成し、「楽しいbilliard」という文字列は、
楽し / しい / いb / bi / il / ll / li / ia / ar / rd / d
という十一の語彙の配列として格納されます。これに対して「bill」というキーワードで検索した時、このキーワードは、
bi / il / ll
という三つの語彙として処理されます。この語彙の並びは「楽し / しい / いb / bi / il / ll / li / ia / ar / rd / d」という語彙の並びに含まれるので、完全一致でヒットします。
8.2.1.2. 非わかち書き検索#
非わかち書き検索はパトリシア木で語彙表を構築している場合のみ利用可能です。
非わかち書き検索の挙動はTokenBigramなどN-gram系のトークナイザーを利用している場合とTokenMecabトークナイザーを利用している場合で挙動が変わります。
N-gram系のトークナイザーを利用している場合はキーワードで前方一致検索をします。
例えば、「bill」というキーワードで検索した場合、「bill」も「billiard」もヒットします。
TokenMeCabトークナイザーの場合はわかち書き前のキーワードで前方一致検索をします。
例えば、「スープカレー」というキーワードで検索した場合、「スープカレーバー」(1単語扱い)にヒットしますが、「スープカレー」("スープ"と"カレー"の2単語扱い)や「スープカレーライス」("スープ"と"カレーライス"の2単語扱い)にはヒットしません。
8.2.1.3. 部分一致検索#
部分一致検索はパトリシア木で語彙表を構築していて、かつ、KEY_WITH_SISオプションを指定している場合のみ利用可能です。KEY_WITH_SISオプションが指定されていない場合は非わかち書き検索と同等です。
部分一致検索の挙動はTokenBigramなどN-gram系のトークナイザーを利用している場合とTokenMecabトークナイザーを利用している場合で挙動が変わります。
Bigramの場合は前方一致検索と中間一致検索と後方一致検索を行います。
例えば、「ill」というキーワードで検索した場合、「bill」も「billiard」もヒットします。
TokenMeCabトークナイザーの場合はわかち書き後のキーワードで前方一致検索と中間一致検索と後方一致検索をします。
例えば、「スープカレー」というキーワードで検索した場合、「スープカレー」("スープ"と"カレー"の2単語扱い)や「スープカレーライス」("スープ"と"カレーライス"の2単語扱い)、「スープカレーバー」(1単語扱い)にもヒットします。
8.2.2. 検索の使い分け#
Groongaは基本的に完全一致検索のみを行います。完全一致検索でのヒット件数が所定の閾値以下の場合に限り、非わかち書き検索を行い、それでもヒット件数が閾値以下の場合は部分一致検索を行います。(閾値のデフォルト値は0です。)
ただし、すでに検索結果セットが存在する場合はたとえヒット件数が閾値以下でも完全一致検索のみを行います。
例えば、以下のようなクエリの場合は、それぞれの検索でヒット件数が閾値以下の場合は完全一致検索、非わかち書き検索、部分一致検索を順に行います。:
select Shops --match_column description --query スープカレー
しかし、以下のように全文検索を行う前に検索結果セットが存在する場合は完全一致検索のみを行います。(point > 3で閾値の件数よりヒットしている場合):
select Shops --filter '"point > 3 && description @ \"スープカレー\""'
そのため、descriptionに「スープカレーライス」が含まれていても、「スープカレーライス」は「スープカレー」に完全一致しないのでヒットしません。