Oracle Text まとめ 全文検索　CONTAINS関数の仕様

日本語文字列を扱う時
JAPANESE_VGRAM_LEXER　
Oracle　全文検索　CONTAINS関数 の仕様まとめ
# ざっくりいうと
全文検索CONTAINSはあいまい検索LIKEとはちがう
検索の仕様を知らないとHITしなくて困る
# よくあるはなし
・「Facebook」が「face」で検索しているのにHITしない
・「製造番号ABC-1234」が「ABC-1234」で検索してるのにHITしない
・「IT企業」が「IT」で検索を行ってもHITしない
文末で解決方法を書いています
# CONTAINS関数　基本的な使い方
textというカラムの中に「オラクル」という文字列があるかどうか調べるには
where 句で下記のようにする
`WHERE CONTAINS (text, 'オラクル') > 0`
索引情報を参照するため
事前にtextのindexは登録してSYNCしておく必要がある
**だいなりで 0以外の数値を書いてはいけない**
## 使える演算子
「AND(&)」「OR(|)」「ACCUM(,)」「NOT(~)」「MINUS(-)」「MNOT」
基本的にはANDとORとNOTさえ覚えれば良い。演算記号には注意する
### AND演算　& アンド
`WHERE CONTAINS (text, 'オラクル and 日本') > 0`
`WHERE CONTAINS (text, 'オラクル & 日本') > 0`
「オラクル」と「日本」両方が含まれているときtrueになる。順番は関係ない。
### OR演算　| たてぼう
`WHERE CONTAINS (text, 'オラクル or 日本') > 0`
`WHERE CONTAINS (text, 'オラクル | 日本') > 0`
「オラクル」と「日本」どちらかが含まれているときtrueになる
### NOT演算　~ チルダ
`WHERE CONTAINS (text, 'オラクル not 日本') > 0`
`WHERE CONTAINS (text, 'オラクル  ~日本') > 0`
「オラクル」があるが「日本」がないものが含まれているときtrueになる
## ワイルドカード
### %　パーセント　と　_　アンダースコア
英数字のみ使える
「%」任意のｎ文字と一致
「_」任意の１文字と一致
`WHERE CONTAINS (text, '%ac%') > 0`
でtextに「Oracle」があるとtrue
**日本語の検索ではワイルドカード検索は出来ない**
## エスケープ
###　中括弧{}  と　\ バックスラッシュ
「{犬　AND　猫}」などのように中括弧で囲った文字全体がエスケープされる
「`blue\-green`」などのようにして直後の演算子をエスケープできる

とりあえずなりふりかまわず中括弧で括ってしまったほうが余計なこと考えなくて良い
# 検索の仕様
検索文字と索引に登録されている**トークンが連続で一致**するとHITする
## 索引（index）トークンの保存され方
Oracle Text V-Gramインデックスの仕様
### 基本的には文字を２文字ずつトークンにわける

|原文|トークン|  
|-----------------|------------------|
|新宿区民|[新宿][宿区][区民][民]|

区切りの最後の文字は必ず１文字トークンになる

### 英数字の場合はシングルバイトの大文字に変換される。

|原文|トークン|  
|-----------------|------------------|
|OracleText|[ORACLETEXT]|
|Oracle Text|[ORACLE][TEXT]|
**スペースは単語の区切りとして扱う**

### マルチバイト文字は漢字・カタカナ・平仮名でトークンが区切られる。

|原文|トークン|  
|-----------------|------------------|
|日本オラクル|[日本][本][オラ][ラク][クル][ル]|
|日本　オラクル|[日本][本][オラ][ラク][クル][ル]|
**スペースは無視する**

### 連結文字（を、ん、長音、ゃ、ゅ、ょ　etc）がある時は次の文字までがトークンになる

|原文|トークン|  
|-----------------|------------------|
|りんご|[りんご][ご]|
|インターフェース|[インタ][ターフ][フェース][ス]|
|プリン製造|[プリ][リン製][製造][造]|

## 例外処理　内部的なあいまい検索
基本的にトークンが一致しないと検索を行ってもHITしないが例外処理がある
### 日本語１文字で検索をした時は例外的にトークンに％が追加されて処理される
|原文|トークン|  
|-----------------|------------------|
|日本海|[日本][本海][海]|
日本海には[本]というトークンがないが
「本」で検索を行った時[本%]として扱うためHITする
### 語尾が長音や「ャ」「ュ」「ョ」などで終る語句のときもトークンに％が追加される
|原文|トークン|  
|-----------------|------------------|
|シュレディンガーの猫|[シュレ][レデ][ディンガ][ガーの][の][猫]|
「ディン」というトークンはないが
「ディン」で検索を行った時[ディン%]として扱うためHITする
「シュ」でもHIT

**この仕様を抑えておくと**
**「ィン」や「ュレ」で検索しても「シュレディンガーの猫」がHITしないのがわかる**

## ストップワード
英語の冠詞a、theなど、ドキュメントを特定するのに役立たないキーワードは索引情報から排除されている

### 英語のデフォルトストップリスト

||||||
|:--:|:--:|:--:|:--:|:--:|
|a|all|almost|also|although|
|an|and|any|are|as|
|at|be|because|been|both|
|but|by|can|could|d|
|did|do|does|either|for|
|from|had|has|have|having|
|he|her|here|hers|him|
|his|how|however|i|if|
|in|into|is|it|its|
|just|ll|me|might|Mr|
|Mrs|Ms|my|no|non|
|nor|not|of|on|one|
|only|onto|or|our|ours|
|s|shall|she|should|since|
|so|some|still|such|t|
|than|that|the|their|them|
|then|there|therefore|these|they|
|this|those|though|through|thus|
|to|too|until|ve|very|
|was|we|were|what|when|
|where|whether|which|while|who|
|whose|why|will|with|would|
|yet|you|your|yours||
||||||

これらはレクサーによってトークンに分割されたあと除去されて索引に登録される
ストップワードが存在したことだけが索引情報として記録される。
ストップワードのうち、具体的にどのストップワードが存在したのかという情報は失われる。

### ストップワードによる検索
検索条件「That was the sample document.」で
文字列「This is a sample document.」を含む文書がヒットする
That was the もThis is a もストップワードであるため同一視される

検索条件「That was the very sample document.」の場合はHITしない
ストップワードの個数が異なるためHITしなくなる

### 注意点
日本語文書に含まれる英単語が、意図せずストップワードとして処理されてしまう場合がある。
「it」がストップワードなため
「IT」で検索を行っても「IT企業」がHITしないのはこのため

ストップリストの機能を無効にするには、CREATE INDEX時に明示的に CTXSYS.EMPTY_STOPLIST を指定するとよい

### 記号なども索引に登録されていない模様
公式ドキュメントに記述はみられなかったが
下記のような記号もCONTAINS関数でHITしなそうである
（	）	〔	〕	［	］	｛	｝	〈	〉	《	》	「	」	『	』	【	】	＋	－	±	×		÷	＝	≠	＜	＞	≦	≧	∞	∴	♂	♀	°	′	″	℃	￥	＄	￠	￡	％	＃	＆	＊	＠	§	☆	★	○	●	◎	◇	◆	□	■	△	▲	▽	▼	※	〒	→	←	↑	↓	

記号も索引として意味を持たない文字となっている模様

## よくあるはなし　トラブルシューティング
・「Facebook」が「face」で検索しているのにHITしない
　→　Facebookは[FACEBOOK]というトークンなので「Face%」と検索しないといけない
・「製造番号ABC-1234」が「ABC-1234」で検索してるのにHITしない
　→マイナス記号が演算子なので「ABC`\`-1234」か「{ABC-1234}」と検索するべき
・「IT企業」が「IT」で検索を行ってもHITしない
　→「it」がストップワードなのでストップリストを解除して索引をつくりなおす

# 参考文献
Oracle Text 詳細解説
日本オラクル株式会社
http://www.oracle.com/technetwork/jp/ondemand/db-technique/oracletext-ver12-351879-ja.pdf