全文検索を実装するには、ドキュメントからtsvector
を作成し、ユーザークエリからtsquery
を作成する関数が必要です。 また、有用な順序で結果を返す必要があるため、クエリとの関連性に関してドキュメントを比較する関数が必要です。 結果をうまく表示できることも重要です。
ドキュメントの解析
PolarDB PostgreSQLは、ドキュメントをtsvector
データ型に変換するための関数to_tsvector
を提供します。
to_tsvector([ config regconfig, ] document text) はtsvectorを返します
to_tsvector
は、テキストドキュメントをトークンに構文解析し、トークンを語彙素に縮小し、語彙素とドキュメント内の位置を一覧表示するtsvector
を返します。 ドキュメントは、指定されたテキスト検索設定またはデフォルトのテキスト検索設定に従って処理されます。 簡単な例を次に示します。
SELECT to_tsvector (「english」、「マットの上に座っている太った猫-太ったネズミを食べた」);
to_tsvector
-----------------------------------------------------
'ate':9 'cat':3 'fat':2,11 'mat':7 'rat':12 'sat':4
上記の例では、結果のtsvector
にa
、on
、またはit
という単語が含まれていないことがわかります。rats
という単語はrat
になり、句読点記号-
は無視されました。
to_tsvector
関数は、ドキュメントテキストをトークンに分解し、各トークンに型を割り当てるパーサーを内部的に呼び出します。 トークンごとに、辞書のリストが参照され、リストは、トークンのタイプに応じて変化し得る。 トークンを認識する第1の辞書は、トークンを表す1つ以上の正規化された語彙素を発する。 たとえば、ラット
という単語がラット
の複数形であることを辞書の1つが認識したため、ラット
はラット
になりました。 いくつかの単語は、ストップワードとして認識され、これは、それらがあまりに頻繁に出現して検索に有用ではないので、それらを無視させる。 この例では、これらはa
、on
、およびit
です。 リスト内のどの辞書もトークンを認識しない場合、それも無視される。 この例では、句読点記号-
に発生しました。実際には、トークンのタイプ (スペース記号
) に割り当てられた辞書がないためです。 パーサー、ディクショナリ、およびどのタイプのトークンをインデックスするかの選択は、選択されたテキスト検索構成によって決定される。 同じデータベースに多くの異なる構成を持つことが可能であり、事前定義された構成はさまざまな言語で利用できます。 この例では、英語のデフォルト設定英語
を使用しました。
関数setweight
を使用して、tsvector
のエントリに所与の重みでラベルを付けることができ、重みは、文字a
、B
、C
、またはD
のうちの1つである。 これは通常、タイトルと本文など、ドキュメントのさまざまな部分からのエントリをマークするために使用されます。 後に、この情報は、検索結果のランキングに使用することができる。
to_tsvector
(NULL
) はNULL
を返すため、フィールドがnullになる場合は常にcoalesce
を使用することをお勧めします。 構造化ドキュメントからtsvector
を作成するための推奨方法は次のとおりです。
UPDATE tt SET ti=
seweight (to_tsvector(coalesce(title、'')) 、'A') | | |
seitweight (to_tsvector(coalesce(keyword、'')) 、'B') | | |
seweight (to_tsvector(coalesce(abstract,'')), 'C') | | |
seitweight (to_tsvector(coalesce(body、'')) 、'D');
ここでは、完成したtsvector
内の各語彙素のソースにラベルを付けるためにseweight
を使用し、次にtsvector
連結演算子 | |
を使用してラベルの付いたtsvector
値をマージしました。
クエリの解析
PolarDB PostgreSQLは、クエリをtsquery
データ型に変換するための関数to_tsquery
、plainto_tsquery
、phraseto_tsquery
、websearch_to_tsquery
を提供します。 to_tsquery
は、plainto_tsquery
またはphraseto_tsquery
よりも多くの機能へのアクセスを提供しますが、その入力についてはあまり寛容ではありません。 websearch_to_tsquery
は、ウェブ検索エンジンで使用されているものと同様の代替構文を備えたto_tsquery
の簡略版です。
to_tsquery([ config regconfig, ] querytext text) はtsqueryを返します
to_tsquery
は、querytext
からtsquery
値を作成します。これは、tsquery
演算子 &
(AND) 、|
(OR) 、!
(NOT) 、および <->
(FOLLOWED BY) 、場合によっては括弧を使用してグループ化されます。 つまり、to_tsquery
への入力は、すでにtsquery
入力の一般的なルールに従っている必要があります。 違いは、基本的なtsquery
入力は額面のトークンを受け取りますが、to_tsquery
は指定された設定またはデフォルトの設定を使用して各トークンを語彙に正規化し、設定に従ってストップワードであるトークンを破棄することです。 設定例:
SELECT to_tsquery('english '、'The & Fat & Rats');
to_tsquery
---------------
「脂肪」&「ラット」
基本的なtsquery
入力と同様に、各語彙素に重みを付けて、それらの重みのtsvector
語彙素のみに一致するように制限できます。 設定例:
SELECT to_tsquery('english' 、'Fat | Rats:AB');
to_tsquery
------------------
'fat' | 'rat':AB
また、*
を語彙素に添付してプレフィックスマッチングを指定することもできます。
SELECT to_tsquery('supern:* A & star:A * B');
to_tsquery
--------------------------
'supern':* A & 'star ':* AB
このような語彙素は、所与の文字列で始まるtsvector
内の任意の単語と一致する。
to_tsquery
は、単一引用語句も受け入れることができます。 これは主に、構成がそのようなフレーズをトリガするシソーラス辞書を含む場合に有用である。 以下の例では、シソーラスに超新星星: sn
というルールが含まれています。
SELECT to_tsquery(''超新星の星'' & !crab);
to_tsquery
---------------
'sn' & ! 'crab'
引用符がない場合、to_tsquery
は、AND、OR、またはFOLLOWED by演算子で区切られていないトークンの構文エラーを生成します。
plainto_tsquery([ config regconfig, ] querytext text) returns tsquery
plainto_tsquery
は、未フォーマットのテキストquerytext
をtsquery
値に変換します。 テキストは解析され、to_tsvector
のように正規化され、&
(and) tsquery
演算子が生き残った単語の間に挿入されます。
例:
SELECT plainto_tsquery('english '、'The Fat Rats');
plainto_tsquery
-----------------
「脂肪」&「ラット」
plainto_tsquery
は、入力でtsquery
演算子、重みラベル、またはプレフィックス一致ラベルを認識しません。
SELECT plainto_tsquery('english' 、'The Fat & Rats:C');
plainto_tsquery
---------------------
「脂肪」&「ラット」&「c」
ここでは、すべての入力句読点が破棄されました。
phraseto_tsquery([ config regconfig, ] querytext text) returns tsquery
phraseto_tsquery
はplainto_tsquery
とよく似ていますが、&
(AND) 演算子ではなく、生き残った単語の間に <->
(FOLLOWED BY) 演算子を挿入します。 また、ストップワードは単純に破棄されるのではなく、<->
演算子ではなく <>
演算子を挿入することによって考慮されます。 この関数は、FOLLOWED BY演算子がすべての語彙素の存在だけでなく語彙素の順序をチェックするため、正確な語彙素シーケンスを検索するときに役立ちます。
例:
SELECT phraseto_tsquery('english '、'The Fat Rats');
phraseto_tsquery
------------------
'fat' <-> 'rat'
plainto_tsquery
と同様に、phraseto_tsquery
関数は、入力内のtsquery
演算子、重みラベル、またはプレフィックス一致ラベルを認識しません。
SELECT phraseto_tsquery('english' 、'The Fat & Rats:C');
phraseto_tsquery
-----------------------------
'fat' <-> 'rat' <-> 'c'
websearch_to_tsquery([ config regconfig, ] querytext text) はtsqueryを返します
websearch_to_tsquery
は、単純なフォーマットされていないテキストが有効なクエリである代替構文を使用して、querytext
からtsquery
値を作成します。 plainto_tsquery
やphraseto_tsquery
とは異なり、特定の演算子も認識します。 さらに、この関数は構文エラーを発生させないため、ユーザーが指定した生の入力を検索に使用できます。
次の構文がサポートされています。
unquoted text
: 引用符内にないテキストは、plainto_tsquery
によって処理されたかのように、&
演算子で区切られた用語に変換されます。"quoted text"
: 引用符内のテキストは、phraseto_tsquery
によって処理されるかのように、<->
演算子で区切られた用語に変換されます。OR
: "or" という単語は|
演算子に変換されます。-
: ダッシュはに変換されます!
演算子のみ使用できます。
他の句読点は無視される。 したがって、plainto_tsquery
やphraseto_tsquery
と同様に、websearch_to_tsquery
関数は、入力内のtsquery
演算子、重みラベル、またはプレフィックス一致ラベルを認識しません。
例:
SELECT websearch_to_tsquery('english '、'The fat rats');
websearch_to_tsquery
----------------------
「脂肪」&「ラット」
(1行)
SELECT websearch_to_tsquery('english '、' "supernovae stars" -crab);
websearch_to_tsquery
----------------------------------
「超新星」 <-> 「スター」&! 'crab'
(1行)
SELECT websearch_to_tsquery('english' 、'"sad cat" または "fat rat"');
websearch_to_tsquery
-----------------------------------
'sad' <-> 'cat' | 'fat' <-> 'rat'
(1行)
SELECT websearch_to_tsquery('english' 、'signal -"セグメンテーションフォールト" ');
websearch_to_tsquery
---------------------------------------
'信号' & ! ('segment' <-> 'fault')
(1行)
SELECT websearch_to_tsquery('english', '"" " )(ダミー \\ query <->');
websearch_to_tsquery
----------------------
「ダミー」&「ケリ」
(1行)
ランキング検索结果
PostgreSQLには、語彙、近接、構造情報を考慮した2つの事前定義されたランキング関数が用意されています。つまり、クエリ用語がドキュメントに表示される頻度、ドキュメント内の用語がどの程度近くにあるか、そして、それらが発生する文書の部分がどれほど重要か。 しかし、関連性の概念は曖昧であり、非常にアプリケーション固有である。 異なるアプリケーションは、ランク付けのための追加情報、例えば文書修正時間を必要とし得る。 組み込みランキング関数は単なる例である。 独自のランキング関数を作成したり、特定のニーズに合わせて結果を追加の要素と組み合わせたりすることができます。
現在利用可能な2つのランキング機能は次のとおりです。
一致する語彙素の頻度に基づいてベクトルをランク付けします。
ts_rank([ weights float4[], ] ベクトルtsvector, query tsquery [, normalization integer ]) returns float4
指定されたドキュメントベクトルとクエリのカバー密度ランキング。
ts_rank_cd([ weights float4[], ] ベクトルtsvector, query tsquery [, normalization integer ]) returns float4
この関数は、指定されたドキュメントベクトルとクエリのカバー密度のランキングを計算します。 カバー密度は、マッチングする語彙素の互いに対する近接性が考慮されることを除いて、
ts_rank
ランキングと同様である。この関数は、その計算を実行するために語彙素位置情報を必要とする。 したがって、
tsvector
内の「ストリップされた」語彙素は無視されます。 入力にストリップされていない語彙素がない場合、結果はゼロになります。
これらの関数の両方で、引数オプションの重み
は、単語インスタンスのラベル付け方法に応じて、単語インスタンスを多かれ少なかれ重み付けする機能を提供します。 重み配列は、単語の各カテゴリの重みを次の順序で指定します。
{D-重、C-重、B-重、A-重}
重み
が指定されていない場合は、次のデフォルトが使用されます。
{0.1、0.2、0.4、1.0}
通常、重みは、タイトルまたは最初の要約のような、ドキュメントの特別な領域からの単語をマークするために使用され、したがって、それらは、ドキュメント本体内の単語よりも高いまたは低い重要度で扱うことができる。
より長い文書は、クエリ用語を含む可能性がより高いので、文書サイズを考慮に入れることが合理的であり、例えば、検索ワードの5つのインスタンスを有する百語文書は、おそらく、5つのインスタンスを有する千語文書よりも関連性が高い。 どちらのランキング関数も、ドキュメントの長さがランクに影響するかどうか、およびどのように影響するかを指定する整数正規化
オプションを使用します。 integerオプションは複数の動作を制御するため、ビットマスクです。|
(2 | 4
など) を使用して1つ以上の動作を指定できます。
0 (デフォルト) はドキュメントの長さを無視します
1はランクを1 + ドキュメントの長さの対数で割ります
2ランクをドキュメントの長さで割る
4は、ランクをエクステント間の平均高調波距離で除算します (これは
ts_rank_cd
によってのみ実装されます) 。8ランクをドキュメント内の一意の単語の数で割る
16は、ランクを1 + ドキュメント内の一意の単語の数の対数で除算します。
32はランクを1で割ります
2つ以上のフラグビットが指定される場合、変換はリストされた順序で適用される。
ランキング関数はグローバルな情報を使用しないため、場合によっては必要に応じて1% または100% に公平な正規化を生成することは不可能であることに注意することが重要です。 正規化オプション32 (rank/(rank + 1)
) を適用して、すべてのランクを0から1の範囲にスケールすることができるが、もちろんこれは単なる外観上の変更であり、検索結果の順序付けには影響しない。
最高ランクの10試合のみを選択する例を次に示します。
SELECTタイトル、ts_rank_cd(textsearch, query) AS rank
FROM apod, to_tsquery('neutrino |(dark & matter)') クエリ
WHEREクエリ @ @ textsearch
ランクDESCによる注文
LIMIT 10;
タイトル | ランク
-----------------------------------------------+----------
太陽のニュートリノ | 3.1
サドベリーニュートリノ検出器 | 2.4
銀河暗黒物質のMACHOビュー | 2.01317
高温ガスと暗黒物質 | 1.91171
おとめ座クラスター: ホットプラズマと暗黒物質 | 1.90953
ソーラーニュートリノのラフティング | 1.9
NGC 4650A: 奇妙な銀河と暗黒物質 | 1.85774
高温ガスと暗黒物質 | 1.6123
宇宙のニュートリノのための氷釣り | 1.6
弱いレンズは宇宙を歪める | 0.818218
これは、正規化されたランキングを使用する同じ例です。
SELECTタイトル, ts_rank_cd(textsearch, query, 32 /* rank/(rank + 1) */ ) AS rank
FROM apod, to_tsquery('neutrino |(dark & matter)') クエリ
WHEREクエリ @ @ textsearch
ランクDESCによる注文
LIMIT 10;
タイトル | ランク
-----------------------------------------------+-------------------
太陽のニュートリノ | 0.756097569485493
サドベリーニュートリノ検出器 | 0.705882361190954
銀河暗黒物質のMACHOビュー | 0.668123210574724
高温ガスと暗黒物質 | 0.65655958650282
おとめ座クラスター: ホットプラズマと暗黒物質 | 0.656301290640973
ソーラーニュートリノのラフティング | 0.655172410958162
NGC 4650A: 奇妙な銀河と暗黒物質 | 0.650072921219637
高温ガスと暗黒物質 | 0.617195790024749
宇宙のニュートリノのための氷釣り | 0.615384618911517
弱いレンズは宇宙を歪める | 0.450010798361481
ランク付けは、各一致ドキュメントのtsvector
を調べる必要があるため、高価になる可能性があります。 残念ながら、実際のクエリはしばしば多数の一致をもたらすため、回避することはほとんど不可能です。
ハイライト結果
検索結果を提示するには、各ドキュメントの一部と、それがクエリにどのように関連しているかを示すことが理想的です。 通常、検索エンジンは、マークされた検索用語を持つドキュメントの断片を表示します。PostgreSQLは、この機能を実装する関数ts_headline
を提供します。
ts_headline([ config regconfig, ] document text, query tsquery [, options text ]) returns text
ts_headline
はクエリとともにドキュメントを受け取り、クエリの用語が強調表示されているドキュメントからの抜粋を返します。 具体的には、関数はクエリを使用して関連するテキスト断片を選択し、クエリに表示されるすべての単語を、それらの単語の位置がクエリの制限に一致しない場合でも、強調表示します。 ドキュメントの解析に使用する設定は、config
で指定できます。config
が省略されている場合、default_text_search_config
設定が使用されます。
options
文字列を指定する場合は、1つ以上のoption
=
value
ペアのコンマ区切りリストで構成する必要があります。 使用可能なオプションは次のとおりです。
MaxWords
、MinWords
(整数): これらの数値は、出力する最長見出しと最短見出しを決定します。 デフォルト値は35と15です。ShortWord
(整数): この長さ以下の単語は、クエリ用語でない限り、見出しの先頭と末尾で削除されます。 デフォルト値の3は、一般的な英語の記事を削除します。HighlightAll
(boolean):true
の場合、ドキュメント全体が見出しとして使用され、前の3つのパラメータは無視されます。 デフォルトはfalse
です。MaxFragments
(整数): 表示するテキスト断片の最大数。 ゼロのデフォルト値は、非フラグメントベースのヘッドライン生成方法を選択する。 ゼロより大きい値は、フラグメントベースの見出し生成を選択する (以下を参照) 。StartSel
,StopSel
(strings): ドキュメントに現れるクエリ単語を他の抜粋単語と区別するために区切るための文字列。 デフォルト値は「<b>
」と「</b>
」で、HTML出力に適しています。FragmentDelimiter
(文字列): 複数のフラグメントが表示される場合、フラグメントはこの文字列で区切られます。 デフォルトは“...
".
これらのオプション名は、大文字と小文字を区別しないで認識されます。 文字列値にスペースまたはコンマが含まれている場合は、二重引用符が必要です。
非フラグメントベースの見出し生成では、ts_headline
は、所与のクエリ
に対する一致を見つけ、表示する単一のものを選択し、許容される見出しの長さ内により多くのクエリ単語を有する一致を優先する。 フラグメントベースのヘッドライン生成では、ts_headline
は、クエリの一致を見つけ、各一致をMaxWords
ワード以下の「フラグメント」に分割し、より多くのクエリワードを有するフラグメントを優先し、可能な場合、周囲のワードを含むようにフラグメントを「ストレッチ」する。 したがって、フラグメントベースのモードは、クエリの一致がドキュメントの大きなセクションにまたがる場合や、複数の一致を表示することが望ましい場合に便利です。 どちらのモードでも、クエリの一致が識別できない場合、ドキュメント内の最初のMinWords
ワードの単一のフラグメントが表示されます。
設定例:
SELECT ts_headline('english' 、
'検索の最も一般的なタイプ
指定されたクエリ用語を含むすべてのドキュメントを見つけることです
との類似性の順にそれらを返します。query.',
to_tsquery('english '、'query & similarity'));
ts_headline
------------------------------------------------------------
与えられた <b> クエリ </b> 用語を含む +
+ への <b> 類似 </b> の順にそれらを返します
<b> クエリ </b>
SELECT ts_headline('english' 、
'検索条件が発生する可能性があります
ドキュメントで何度も、どちらを決定するために検索マッチのランキングが必要
結果に表示するオカレンス。'、
to_tsquery('english' 、'search & term') 、
'MaxFragments=10、MaxWords=7、MinWords=3、StartSel =<<、StopSel =>> ');
ts_headline
------------------------------------------------------------
<<検索>> <<terms>> が発生する可能性があります +
何度も... 決定する
<<search>> マッチのランキングts_headline
は、tsvector
の要約ではなく元のドキュメントを使用するため、遅くなる可能性があり、注意して使用する必要があります。