この章では、Oracleを使用したXMLの全文検索について説明します。また、Oracle DatabaseによるXMLデータの全文検索で使用される2つの関数である、SQL関数contains
およびXPath関数ora:contains
の使用方法について説明します。
関連項目: Oracle Textの詳細は、『Oracle Textリファレンス』および『Oracle Textアプリケーション開発者ガイド』を参照してください。 |
この章の内容は次のとおりです。
Oracleは、Oracle Databaseにより管理される文書の全文検索をサポートしています。文書がXMLの場合は、その文書のXML構造を使用して全文検索を限定できます。たとえば、全文検索を使用してワード"electric"が含まれる発注書をすべて検索するとします。発注書がXML形式の場合は、コメント内にワード"electric"が含まれるすべての発注書を検索するか、または明細項目の下にあるコメント内にワード"electric"が含まれるすべての発注書を検索するかして、検索内容を限定できます。XML文書がXMLType
型の場合は、その文書のXML構造を使用して問合せの結果を投影できます。たとえば、コメント内にワード"electric"が含まれるすべての発注書を検索した後で、コメント全体を戻すか、またはワード"electric"が含まれるコメントのみを戻すことができます。
全文検索は、構造化検索や部分文字列検索と次の点で異なります。
全文検索では、部分文字列ではなくワード全体が検索されます。文字列"law"が含まれるコメントの部分文字列検索を行うと、"my lawn is going wild"が含まれるコメントが戻されます。ワード"law"の全文検索では、このコメントは戻されません。
全文検索では、部分文字列検索ではサポートできない言語ベースとワードベースの検索がいくつかサポートされています。たとえば、言語ベースの検索を使用すると、"mouse"と言語語幹が同じワードを含むすべてのコメントを検索でき、Oracle Textでは"mouse"と"mice"が検索されます。ワードベースの検索の例では、"wild"を含む5ワード以内にワード"lawn"があるすべてのコメントを検索できます。
全文検索には通常、関連性の概念が含まれています。たとえば、ワード"lawn"が含まれるすべてのコメントを全文検索する場合、ある結果は他の結果より関連性が高い場合があります。関連性は通常、検索ワード(または類似ワード)の文書内での出現回数に関連しています。
XML検索は、非構造化文書の検索とは異なります。非構造化文書の検索では通常、一連の文書を検索して、指定したテキスト述語を満たす文書を戻します。XML検索では多くの場合、XML文書の構造を使用して検索を限定します。また、検索を満たす文書の一部のみを戻す場合があります。
全文検索とXML構造が含まれる検索の実行方法には、次の2通りがあります。
SQL関数contains
を使用して、全文述語内に構造を含める方法:
... WHERE contains(doc, 'electric INPATH (/purchaseOrder/items/item/comment)') > 0 ...
関数contains
はSQLの拡張機能であり、すべての問合せで使用できます。この関数には、CONTEXT
全文索引が必要です。
ora:contains
XPath関数を使用して、構造内に全文述語を含める方法:
... '/purchaseOrder/items/item/comment[ora:contains(text(), "electric")>0]' ...
ora:contains
XPath関数はXPathの拡張機能であり、existsNode
、extract
またはextractValue
のすべてのコールで使用できます。
この項では、この章の例について詳細に説明します。
この章の例は、W3Cの「XML Schema Part 0: Primer」にある「The Purchase Order Schema」に基づいています。
例で使用しているデータは、「発注書のXML文書、po001.xml」です。パフォーマンスの例の一部は、より大きい表(PURCHASE_ORDERS_xmltype_big
)に基づいています。この表はダウンロード可能なバージョンにのみ含まれています。
ここでは、データ型としてVARCHAR2
を使用する例と、XMLType
を使用する例があります。VARCHAR2
を使用している例はすべて、XMLType
を使用することもできます。
この項の内容は次のとおりです。
SQL関数contains
は、[schema.]column
がtext_query
と一致する行の正数を戻し、一致しない場合は0(ゼロ)を戻します。これはユーザー定義関数で、SQLの標準拡張方法の1つです。この関数には、型CONTEXT
の索引が必要です。検索対象の列にCONTEXT
索引がない場合、contains
ではエラーが発生します。
構文
contains([schema.]column, text_query VARCHAR2 [,label NUMBER]) RETURN NUMBER
例11-1 単純なCONTAINS問合せ
一般的な問合せは次のようになります。
SELECT id FROM purchase_orders WHERE contains(doc, 'lawn') > 0;
この問合せでは、表purchase_orders
および索引po_index
が使用されます。表purchase_orders
内でdoc
列にワード"lawn
"が含まれる各行のIDが戻されます。
例11-2 構造化された述語を使用したCONTAINS
SQL関数contains
は、すべてのSQL問合せで使用できます。次に、表purchase_orders
および索引po_index
の使用例を示します。
SELECT id FROM purchase_orders WHERE contains(doc, 'lawn') > 0 AND id < 25;
XPath関数ora:contains
は、XQuery式内のXPath式や、SQL関数existsNode
、extract
、extractValue
などのコールで使用できます。この関数は、全文述語を使用する構造検索を限定する場合に使用されます。また、標準のメカニズムを使用してXPathを拡張する、Oracle XML DB名前空間ora
内のユーザー定義関数です。索引は不要ですが、索引を併用することでパフォーマンスを向上できます。
構文
ora:contains(input_text NODE*, text_query STRING [,policy_name STRING] [,policy_owner STRING])
関数ora:contains
は、input_text
がtext_query
と一致した場合は正の整数を戻します(数字が大きいほど、一致の関連性は高くなります)。一致しない場合は0(ゼロ)を戻します。XQuery式内部で使用される場合、XQueryの戻り型はxs:integer()
です。XQuery式外部のXPath式で使用される場合、XPathの戻り型はnumber
です。
引数input_text
は単一のテキスト・ノードまたは属性に対して評価される必要があります。ora:contains
のtext_query
の構文およびセマンティクスはcontains
のtext_query
と同じですが、次の制限事項があります。
引数text_query
に構造演算子(WITHIN
、INPATH
またはHASPATH
)を含めることはできません。
スコア重み付け演算子weight
を使用した場合、重みは無視されます。
例11-5は、existsNode
のXPathパラメータにおけるora:contains
のコールを示しています。existsNode
の3番目のパラメータ(Oracle XML DB名前空間ora
)は必須ですので注意してください。この例では、表purchase_orders_xmltype
が使用されます。
例11-5 複雑な任意のテキスト問合せを使用したora:contains
SELECT id FROM purchase_orders_xmltype WHERE existsNode(doc, '/purchaseOrder/comment [ora:contains(text(), "($lawns AND wild) OR flamingo") > 0]', 'xmlns:ora="http://xmlns.oracle.com/xdb"') = 1;
containsおよびora:containsでは、いずれもXML構造の検索と全文検索を組み合せることができます。
SQL関数contains
の特性は、次のとおりです。
実行するにはCONTEXT
索引が必要です。索引がない場合はエラーが発生します。
索引検索を実行し、通常非常に高速です。
(SQL関数score
を使用して)スコアを戻します。
ノードではなく文書(表の行)に基づいて検索を限定します。
XML構造ベースの投影(XML文書の一部を抽出)には使用できません。
XPath関数ora:contains
の特性は、次のとおりです。
索引は不要ですが、索引を使用することでパフォーマンスを向上できます。
非索引検索であるため、大量のリソースを消費する場合があります。
格納方法および索引付け方法に関する考慮事項からアプリケーション・ロジックを分離しています。
スコアを戻しません。
XML構造ベースの投影(XML文書の一部を抽出)に使用できます。
XML文書で、単純なXML構造の制約を指定している場合など、高速な索引ベースの全文検索を実行する場合は、contains
を使用します。XPathナビゲーションと組み合せた全文検索の柔軟性が必要な場合(索引がない場合も含めて)、または投影は必要でスコアは不要な場合は、ora:contains
を使用します。
この項の内容は次のとおりです。
SQL関数contains
の2番目の引数text_query
は、全文検索を指定する文字列です。text_query
には、SQL/MMの全文標準に基づいた独自の言語があります。
関連項目:
|
この項の後半の例では、全文検索の優れた機能をいくつか示します。これらの例では、使用可能な演算子であるブール演算子(AND
、OR
、NOT
)およびステミングをいくつか使用するだけです。例の問合せでは、テキスト索引(索引タイプCTXSYS.CONTEXT
)を使用してVARCHAR2
列(PURCHASE_ORDERS.doc
)が検索されます。
text_query
言語では、AND
、OR
およびNOT
の任意の組合せがサポートされています。優先順位はカッコを使用して制御できます。ブール演算子は次のいずれの方法でも記述できます。
AND
、OR
、NOT
and
、or
、not
&
、|
、~
ここでは、NOT
は単項演算子ではなくバイナリですので注意してください。式alpha NOT(beta)
は、alpha AND
unary-not(beta)
と同等です。unary-notは単項否定を表します。
関連項目: contains およびora:contains で使用できる演算子の詳細は、『Oracle Textリファレンス』を参照してください。 |
例11-6 単純なブールを使用したCONTAINS問合せ
SELECT id FROM purchase_orders WHERE contains(doc, 'lawn AND wild') > 0;
この例では、表purchase_orders
および索引po_index
が使用されます。
例11-7 複雑なブールを使用したCONTAINS問合せ
SELECT id FROM purchase_orders WHERE contains(doc, '((lawn OR garden) AND (wild OR flooded)) NOT(flamingo)') > 0;
この例では、表purchase_orders
および索引po_index
が使用されます。
text_query
言語では、語幹検索がサポートされています。例11-8では、"lawns
"と同じ言語語幹のワードが含まれるすべての文書が戻されるため、"lawn
"または"lawns
"が検索されます。ステミング演算子は、ドル記号($
)で記述されます。演算子STEM
またはstem
はありません。
この例では、表purchase_orders
および索引po_index
が使用されます。
例11-9に示すように、text_query
言語の演算子は任意に組み合せることができます。
例11-9 複雑な問合せ式を使用したCONTAINS問合せ
SELECT id FROM purchase_orders WHERE contains(doc, '($lawns AND wild) OR flamingo') > 0;
この例では、表purchase_orders
および索引po_index
が使用されます。
関連項目: text_query演算子の完全なリストは、『Oracle Textリファレンス』を参照してください。 |
SQL関数contains
には、関連付けられた関数score
があります。この関数は、問合せ内のどの場所でも使用できます。これは関連性を測定するもので、大規模なドキュメント・セット全体を全文検索するときに特に有効です。score
は通常、問合せ結果の一部として戻されるか、ORDER BY
句で使用されるか、あるいはその両方です。
構文
score(label NUMBER) RETURN NUMBER
例11-10のscore(10)
では、結果セット内の各行に対するスコアが戻されます。SQL関数score
は、関数contains
の特定のコールに関する結果セット内の行の関連性を戻します。score
のコールは、LABEL
(この場合は番号10)によってcontains
のコールにリンクされます。
例11-10 SCOREを使用した単純なCONTAINS問合せ
SELECT score(10), id FROM purchase_orders WHERE contains(doc, 'lawn', 10) > 0 AND score(10) > 2 ORDER BY score(10) DESC;
この例では、表purchase_orders
および索引po_index
が使用されます。
関数score
は、対応するcontains
で、テキスト索引で規定された一致規則に従ってtext_query
引数がinput_text
と一致しない場合は、常に0
を戻します。contains
のtext_query
がinput_text
と一致した場合、score
は、0
より大きく100
以下の数値を戻します。この数値は、input_text
に対するtext_query
の関連性を示します。数値が大きいほど、一致精度が高いことを意味します。
contains
のtext_query
がHASPATH
演算子およびText Pathのみで構成されている場合、HASPATH
は完全一致をテストするため、スコアは0
または100
になります。
関連項目: スコアの計算方法の詳細は、『Oracle Textリファレンス』を参照してください。 |
SQL関数contains
では、デフォルトで文書全体が全文検索されます。前述の例で、構造による限定のない"lawn"の検索では、発注書内のどこかにワード"lawn"があるすべての発注書が検索されます。
Oracleには、XML構造を使用してcontains
問合せを限定する方法が3通りあります。
WITHIN
INPATH
HASPATH
注意: この説明で、セクションはXMLノードと同じであると考えてください。 |
WITHIN
演算子は、問合せをXML文書内のあるセクションに限定します。コメント・セクションのどこかにワード"lawn"が含まれている発注書を検索するには、WITHIN
を使用します。セクション名の大/小文字は区別されます。
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
WITHIN
をネストすると、問合せをさらに限定できます。例11-12では、セクション"comment
"内にワード"lawn
"が含まれ、"lawn
"の出現箇所がセクション"item
"内にもあるすべての文書が検索されます。
例11-12 ネストしたWITHIN
SELECT id FROM purchase_orders WHERE contains(doc, '(lawn WITHIN comment) WITHIN item') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
例11-12では行が戻されません。使用する発注書サンプルには、コメント内にワード"lawn
"が含まれています。しかし、項目内の唯一のコメントは"Confirm this is electric
"です。そのため、ネストしたWITHIN
問合せでは行が戻されません。
属性内を検索することもできます。例11-13では、purchaseOrder
要素のorderDate
属性にワード"10
"が含まれているすべての発注書が検索されます。
例11-13 属性内のWITHIN
SELECT id FROM purchase_orders WHERE contains(doc, '10 WITHIN purchaseOrder@orderDate') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
デフォルトでは、マイナス記号(-
)はワード・セパレータとして処理されます。つまり、"1999-10-20
"は3つのワード"1999
"、"10
"および"20
"として処理されます。したがって、この問合せでは1行戻されます。
属性内のテキストは、主検索可能文書の一部ではありません。text_query
をWITHIN purchaseOrder@orderDate
で修飾せずに10
を検索すると、行は戻されません。
属性は、ネストしたWITHIN
では検索できません。
コメント・セクション内にlawnとelectricの2つのワードが含まれる発注書を検索するとします。purchaseOrder
にはコメント・セクションが複数ある場合があります。このため、この問合せの作成方法は2通りあり、異なる結果となります。
両方のワードが含まれ、各ワードがあるコメント・セクション内に出現する発注書を検索する場合は、例11-14のような問合せを作成します。
例11-14 WITHINおよびAND: あるコメント・セクション内の2つのワード
SELECT id FROM purchase_orders WHERE contains(doc, '(lawn WITHIN comment) AND (electric WITHIN comment)') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
purchaseOrder
データに対してこの問合せを実行すると、1行戻されます。この例ではカッコは必要ありませんが、使用すると問合せがわかりやすくなります。
両方のワードが含まれ、両方のワードが同じコメント内に出現する発注書を検索する場合は、例11-15のような問合せを作成します。
例11-15 WITHINおよびAND: 同じコメント内の2つのワード
SELECT id FROM purchase_orders WHERE contains(doc, '(lawn AND electric) WITHIN comment') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
例11-15では行は戻されません。例11-16のようにlawn AND electric
を囲むカッコを外すと、1行戻されます。
例11-16 WITHINおよびAND: カッコを付けない場合
SELECT id FROM purchase_orders WHERE contains(doc, 'lawn AND electric WITHIN comment') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
演算子WITHIN
の優先順位はAND
より高いため、例11-16は例11-17と同じように解析されます。
例11-17 WITHINおよびAND: 演算子優先順位を示すカッコ
SELECT id FROM purchase_orders WHERE contains(doc, 'lawn AND (electric WITHIN comment)') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
前述の例では、セクション内を検索するためにWITHIN
演算子を使用しました。次のセクションを指定できます。
パス・セクションまたはゾーン・セクション
このセクションは、ノードの子孫であるテキスト・ノードのすべてを、間を空白で区切って文書順に連結したものです。ノードからゾーン・セクションに変換するには、ノードをシリアライズしてすべてのタグを空白で置換する必要があります。パス・セクションの有効範囲と動作はゾーン・セクションと同じですが、パス・セクションではINPATH
およびHASPATH
構造演算子を使用した問合せがサポートされます。
フィールド・セクション
ゾーン・セクションと同じですが、文書内の繰返しノードが空白で区切られて単一のセクションに連結されます。
属性セクション
特殊セクション(文または段落)
関連項目: 特殊セクションの詳細は、『Oracle Textリファレンス』を参照してください。 |
演算子WITHIN
は、構造による単純な限定をtext_query
で表す簡単で直観的な方法です。豊富なXML構造を使用する問合せでは、ネストしたWITHIN
演算子のかわりに、演算子INPATH
とText Pathを使用できます。
演算子INPATH
では、左側にtext_query
を記述し、右側にカッコで囲んだText Pathを記述します。例11-18では、パス/purchaseOrder/items/item/comment
内でワード"electric"が含まれるpurchaseOrders
が検索されます。
例11-18 全文述語内の構造: INPATH
SELECT id FROM purchase_orders WHERE contains(doc, 'electric INPATH (/purchaseOrder/items/item/comment)') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
検索範囲は、Text Pathで示されたセクションです。例11-19に示すように、/purchaseOrder/items
などの範囲の広いパスを選択しても、戻されるのは1行です。
例11-19 全文述語内の構造: INPATH
SELECT id FROM purchase_orders WHERE contains(doc, 'electric INPATH (/purchaseOrder/items)') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
Text Pathの構文とセマンティクスは、W3CのXPath 1.0勧告に基づいています。単純なパス式はサポートされますが(省略構文のみ)、関数はサポートされません。以降の各例は、一般的な変形例を示しています。
関連項目:
|
例11-20では、属性partNum
が"872-AA
"と等しいitem
要素の子であるcomment
内にワード"electric
"が含まれるすべての発注書が検索されます。このitem
要素は、ルート・ノードからいくつか下のレベルのitems
要素の子です。
例11-20 複雑なパス式を使用したINPATH(1)
SELECT id FROM purchase_orders WHERE contains(doc, 'electric INPATH (//items/item[@partNum="872-AA"]/comment)') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
例11-21では、3番目のレベルであるitem
要素(またはその子孫)内にワード"lawnmower
"が含まれ、item
のいくつか下のレベルにcomment
要素の子孫があるすべての発注書が検索されます。この問合せでは1行戻されます。問合せの有効範囲はcomment
要素ではなく、子孫としてcomment
要素を持つ一連のitem
要素です。
例11-21 複雑なパス式を使用したINPATH(2)
SELECT id FROM purchase_orders WHERE contains(doc, 'lawnmower INPATH (/*/*/item[.//comment])') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
Text Path言語は、XPath言語と次の点で異なります。
すべてのXPath演算子がText Path言語に含まれているわけではありません。
XPathの組込み関数はText Path言語に含まれていません。
Text Path言語の演算子は大/小文字が区別されません。
フィルタ内(カッコ内)で=
を使用した場合、一致はテキスト一致規則に従います。
大/小文字の区別、正規化、ストップワードおよび空白の規則はテキスト索引の定義によって異なります。この相違を強調するために、この種類の等価性をこのマニュアルではテキスト等値と呼びます。
名前空間サポートはText Path言語に含まれていません。
名前空間接頭辞(存在する場合)など、要素名は文字列として処理されます。そのため、同じ名前空間URIにマップされている2つの名前空間接頭辞は、Text Path言語では等価として処理されません。
Text Pathでは、コンテキストは常に文書のルート・ノードです。
したがって、発注データpurchaseOrder/items/item
、/purchaseOrder/items/item
および./purchaseOrder/items/item
はすべて等価です。
属性値内を検索する場合は、属性の直接の親を指定する必要があります(ワイルド・カードは使用できません)。
Text Pathはワイルド・カード(*
)で終了できません。
INPATH
式はネストできます。Text Pathのコンテキストは常にルート・ノードです。ネストしたINPATH
の場合も変わりません。
例11-22では、任意のレベルのcomment
要素にワード"electric
"が含まれる発注書が検索されます。このワードの出現箇所は、最上位レベルpurchaseOrder
要素の子であるitem
要素内でもあります。
例11-22 ネストしたINPATH
SELECT id FROM purchase_orders WHERE contains(doc, '(electric INPATH (//comment)) INPATH (/purchaseOrder/items)') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
このネストしたINPATH
問合せは、例11-23に示すように、簡潔に記述できます。
例11-23 リライト済のネストしたINPATH
SELECT id FROM purchase_orders WHERE contains(doc, 'electric INPATH (/purchaseOrder/items//comment)') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
演算子HASPATH
で使用するオペランドはText Pathのみで、カッコで囲み、右側に記述します。=
述語などを使用して、特定のパス内に特定のセクションが含まれる文書を検索するときは、HASPATH
を使用します。これは全文検索ではなく、パス検索です。セクションが存在するかどうかの確認、またはセクションの内容の照合はできますが、ワード検索はできません。データ型がXMLType
の場合は、構造演算子HASPATH
ではなくSQL関数existsNode
の使用を考慮してください。
例11-24では、USPrice
を持つ項目があるpurchaseOrders
が検索されます。
例11-24 単純なHASPATH
SELECT id FROM purchase_orders WHERE contains(DOC, 'HASPATH (/purchaseOrder//item/USPrice)') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
例11-25では、"148.95
"とテキスト等値であるUSPrice
を持つ項目があるpurchaseOrders
が検索されます。
例11-25 HASPATHの等値式
SELECT id FROM purchase_orders WHERE contains(doc, 'HASPATH (/purchaseOrder//item/USPrice="148.95")') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
HASPATH
は、INPATH
など他のcontains
演算子と組み合せることができます。例11-26では、文書の任意の場所にワード electric
を含み、148.95
とテキスト等値であるUSPrice
を持つitem
があり、かつpurchaseOrder
属性orderDate
内に10
が含まれるpurchaseOrders
が検索されます。
例11-26 HASPATHと他の演算子の組合せ
SELECT id FROM purchase_orders WHERE contains(doc, 'electric AND HASPATH (/purchaseOrder//item/USPrice="148.95") AND 10 INPATH (/purchaseOrder/@orderDate)') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
WHERE
句内にcontains
式を使用したSQL問合せの結果は常に、行のセット(および多くの場合score
情報)、または問合せと一致する行全体の投影です。contains
式を満たす各XML文書の一部のみを戻すには、SQL関数extract
およびextractValue
を使用します。extract
およびextractValue
はXMLType
で動作するため、次の例では表 purchase_orders_xmltype
が使用されることに注意してください。
例11-27では、最上位レベルのpurchaseOrder
要素の子孫であるcomment
要素内にワード"electric
"が含まれるpurchaseOrder
が検索されます。各結果の行IDを戻すかわりに、extract
を使用してcomment
要素のみを戻します。
例11-27 extractを使用したCONTAINS問合せの結果の範囲指定
SELECT extract(doc, '/purchaseOrder//comment', 'xmlns:ora="http://xmlns.oracle.com/xdb"') "Item Comment" FROM purchase_orders_xmltype WHERE contains(doc, 'electric INPATH (/purchaseOrder//comment)') > 0;
この例では、表purchase_orders_xmltype
および索引po_index_xmltype
が使用されます。
例11-27の結果は、comment
要素の2つの実例であることに注意してください。関数contains
は、comment
要素内にワード"electric
"の含まれている行(ID
=1
の行)を示します。extract
関数は、文書内のその行にあるcomment
要素の実例をすべて抽出します。使用しているpurchaseOrder
要素にはcomment
要素の実例が2つあり、問合せではその両方が戻されます。
これは希望の結果と異なる場合があります。contains
式を満たすcomment
要素の実例のみを問合せで戻す場合は、extract
式でその述語を繰り返す必要があります。これには、XPath関数ora:contains
を使用します。
例11-28では、contains
式と一致するcomment
要素のみが戻されます。
例11-28 EXTRACTとora:containsを使用したCONTAINS問合せ結果の投影
SELECT extract(doc, '/purchaseOrder/items/item/comment [ora:contains(text(), "electric") > 0]', 'xmlns:ora="http://xmlns.oracle.com/xdb"') "Item Comment" FROM purchase_orders_xmltype WHERE contains(doc, 'electric INPATH (/purchaseOrder/items/item/comment)') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
この項の内容は次のとおりです。
汎用の全文索引タイプは、データベース・ユーザーCTXSYS
が所有するCONTEXT
索引タイプです。デフォルトの全文索引を作成するには、例11-29に示すように、通常のSQL CREATE INDEX
コマンドを使用し、句INDEXTYPE IS CTXSYS.CONTEXT
を追加します。
例11-29 表PURCHASE_ORDERSの単純なCONTEXT索引
CREATE INDEX po_index ON purchase_orders(doc) INDEXTYPE IS CTXSYS.CONTEXT ;
この例では、表PURCHASE_ORDERS
が使用されます。
全文索引を作成するときには、多数の選択肢があります。これらの選択肢は、索引付けプリファレンスとして表されます。索引付けプリファレンスを使用するには、例11-30に示すように、CREATE INDEX
にPARAMETERS
句を追加します。
例11-30 パス・セクション・グループを使用した表PURCHASE_ORDERSの単純なCONTEXT索引
CREATE INDEX po_index ON purchase_orders(doc) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS ('section group CTXSYS.PATH_SECTION_GROUP');
この例では、表purchase_orders
が使用されます。
Oracle Textには、CTXCAT
やCTXRULE
などの他の索引タイプが用意されていますが、この章では説明しません。
関連項目: CONTEXT 索引の詳細は、『Oracle Textリファレンス』を参照してください。 |
CONTEXT
索引は、テキストが含まれた任意のデータに対して作成できます。例11-29では、VARCHAR2
列に対するCONTEXT
索引が作成されます。型がCHAR
、VARCHAR
、VARCHAR2
、BLOB
、CLOB
、BFILE
、XMLType
またはURIType
の列にCONTEXT
索引を作成する構文は同じです。例11-31では、型XMLType
の列に対するCONTEXT
索引が作成されます。
例11-31 表PURCHASE_ORDERS_xmltypeの単純なCONTEXT索引
CREATE INDEX po_index_xmltype ON purchase_orders_xmltype(doc) INDEXTYPE IS CTXSYS.CONTEXT;
この例では、表purchase_orders_xmltype
が使用されます。セクション・グループはデフォルトでPATH_SECTION_GROUP
に設定されます。
表の型がXMLType
である場合は、例11-32に示すように、オブジェクト構文を使用してCONTEXT
索引を作成する必要があります。
例11-32 XMLType表の単純なCONTEXT索引
CREATE INDEX po_index_xmltype_table ON purchase_orders_xmltype_table (OBJECT_VALUE) INDEXTYPE IS CTXSYS.CONTEXT;
この例では、表purchase_orders_xmltype
が使用されます。
例11-33の構文を使用して、表を問合せできます。
例11-33 XMLType表のCONTAINS問合せ
SELECT extract(OBJECT_VALUE, '/purchaseOrder/@orderDate') "Order Date" FROM purchase_orders_xmltype_table WHERE contains(OBJECT_VALUE, 'electric INPATH (/purchaseOrder//comment)') > 0;
この例では、表purchase_orders_xmltype_table
および索引po_index_xmltype_table
が使用されます。
ほとんどの全文索引と同様に、CONTEXT
索引は非同期です。索引付けされたデータが変更された場合、CONTEXT
索引は、プロシージャをコールして索引を同期化するなど、なんらかの処理を行うまで変更されません。CONTEXT
索引の変更を管理する方法は複数あり、いくつかは今回のリリースでの新機能です。
CONTEXT
索引は、時間経過とともに断片化される可能性があります。断片化された索引では通常より多くの領域が使用されるため、問合せが遅くなります。CONTEXT
索引の最適化(断片化解消)方法は複数あり、いくつかは今回のリリースでの新機能です。
関連項目: CONTEXT 索引のメンテナンスの詳細は、『Oracle Textリファレンス』を参照してください。 |
SQL関数contains
を使用するには、CONTEXT
型の索引を作成する必要があります。contains
をコールしたとき、最初の引数で指定された列にCONTEXT
型の索引がない場合は、エラーが発生します。
text_query
の構文およびセマンティクスは、CONTEXT
索引の作成時に選択した内容によって異なります。次に例を示します。
ワードとしてカウントする対象
最も一般的なワードを処理対象とするかどうか
最も一般的なワード
テキスト検索で大/小文字を区別するかどうか
テキスト検索にキーワードの他にテーマ(概念)を含めることができるかどうか
プリファレンスは、索引付けに関する選択肢の集合と考えることができます。プリファレンスには、セクション・グループ、データストア、フィルタ、ワードリスト、ストップリストおよび記憶域が含まれます。この項では、検索で大/小文字を区別するためのレクサー・プリファレンスの設定方法を示します。
プリファレンスを作成するには、プロシージャCTX_DDL.create_preference
(またはCTX_DDL.create_stoplist
)を使用します。プロシージャCTX_DDL.set_attribute
を使用して新規プリファレンスの属性を設定することによって、そのプリファレンス・グループのデフォルトの選択肢をオーバーライドします。その後、CREATE INDEX
のPARAMETERS
文字列内にpreference type preference_name
を含めることによって、CONTEXT
索引でプリファレンスを使用します。
プリファレンスを作成すると、それを使用して索引をいくつでも作成できます。
contains
を使用した全文検索では、デフォルトで大/小文字が区別されません。つまり、文書内のワードに対してtext_query
内のワードを照合する際に、大/小文字は考慮されません。ただし、セクション名および属性名は常に、大/小文字が区別されます。
全文検索で大/小文字を区別する場合は、CONTEXT
索引の作成時にそのように選択する必要があります。例11-34では1行戻されます。これは、text_query
内の"HURRY
"が、デフォルトの大/小文字が区別されない索引が設定されたpurchaseOrder
内の"Hurry
"と一致するためです。
例11-34 CONTAINS: デフォルトの大/小文字を区別しない一致
SELECT id FROM purchase_orders WHERE contains(doc, 'HURRY INPATH (/purchaseOrder/comment)') > 0;
この例では、表purchase_orders
および索引po_index-path-section
が使用されます。
例11-35では、属性mixed_case
がTRUE
に設定された新規のレクサー・プリファレンスmy_lexer
が作成されます。この例では、printjoin文字も"-
"、"!
"、",
"に設定されます。CONTEXT
索引の作成およびポリシーの作成に同じプリファレンスを使用できます。
関連項目: レクサー属性の完全なリストは、『Oracle Textリファレンス』を参照してください。 |
例11-35 大/小文字混合のプリファレンスの作成
BEGIN CTX_DDL.create_preference(PREFERENCE_NAME => 'my_lexer', OBJECT_NAME => 'BASIC_LEXER'); CTX_DDL.set_attribute(PREFERENCE_NAME => 'my_lexer', ATTRIBUTE_NAME => 'mixed_case', ATTRIBUTE_VALUE => 'TRUE'); CTX_DDL.set_attribute(PREFERENCE_NAME => 'my_lexer', ATTRIBUTE_NAME => 'printjoins', ATTRIBUTE_VALUE => '-,!'); END ; /
例11-36では、my_lexer
という新しいレクサー・プリファレンスを使用してCONTEXT
索引が作成されます。
例11-36 PURCHASE_ORDERS表のCONTEXT索引、大/小文字混合
CREATE INDEX po_index ON purchase_orders(doc) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS('lexer my_lexer section group CTXSYS.PATH_SECTION_GROUP');
この例では、表purchase_orders
およびプリファレンスpreference-case-mixed
が使用されます。
例11-34では、text_query
内の"HURRY
"がpurchaseOrder
内の"Hurry
"と一致しないため、行は戻されません。例11-37では、text_query
の"Hurry
"がpurchaseOrder
内のワード"Hurry
"と正確に一致するため、1行戻されます。
例11-37 CONTAINS: 大/小文字混合の(正確な)一致
SELECT id FROM purchase_orders WHERE contains(doc, 'Hurry INPATH (/purchaseOrder/comment)') > 0;
この例では、表purchase_orders
および索引po_index-case-mixed
が使用されます。
CONTEXT
索引の作成時に行う選択の1つにセクション・グループがあります。セクション・グループ・インスタンスは、セクション・グループ・タイプに基づいています。セクション・グループ・タイプでは、文書の構造の種類、およびその構造の索引付け方法(したがって検索方法)が指定されます。セクション・グループ・インスタンスによって、索引付けされる構造要素が指定される場合もあります。ほとんどのユーザーは、デフォルトのセクション・グループまたは事前定義のセクション・グループのいずれかを使用します。
XMLの検索で有効なセクション・グループ・タイプは、次のとおりです。
PATH_SECTION_GROUP
問合せでWITHIN
、INPATH
およびHASPATH
を使用し、すべてのセクションを問合せの有効範囲とする場合はこのタイプを選択します。
XML_SECTION_GROUP
問合せでWITHIN
を使用するが、INPATH
およびHASPATH
は使用せず、明示的に定義されたセクションのみを問合せの有効範囲とする場合は、このタイプを選択します。XML_SECTION_GROUP
セクション・グループ・タイプでは、ZONE
セクションの他にFIELD
セクションがサポートされます。状況によっては、FIELD
セクションの方が問合せのパフォーマンスが大幅に向上する場合があります。
AUTO_SECTION_GROUP
問合せでWITHIN
を使用するが、INPATH
およびHASPATH
は使用せず、大部分のセクションを問合せの有効範囲とする場合は、このタイプを選択します。デフォルトでは、すべてのセクションが索引付けされます(問合せの限定に使用可能)。一部のセクションには索引付けしないことを指定できます(STOP
セクションを定義)。
NULL_SECTION_GROUP
XMLセクションを定義しない場合は、このタイプを選択します。
その他のセクション・グループ・タイプは、次のとおりです。
BASIC_SECTION_GROUP
HTML_SECTION_GROUP
NEWS_SECTION_GROUP
XMLの全文検索要件がある大部分のユーザーは、PATH_SECTION_GROUP
を使用することをお薦めします。一部のユーザーには、FIELD
セクションを使用するXML_SECTION_GROUP
の使用が適している場合もあります。この選択によって、通常、問合せパフォーマンスが向上し、索引が小さくなりますが、フィールド化構造の文書に限定されます(検索可能なノードは、繰返しのないすべてのリーフ・ノードです)。
関連項目: XML_SECTION_GROUP セクション・グループ・タイプの詳細は、『Oracle Textリファレンス』を参照してください。 |
索引で使用するセクション・グループを選択するときは、選択したセクション・グループ・タイプに基づいて、提供されているセクション・グループを選択するか、デフォルトを使用するか、または新しいセクション・グループを作成するかを選択できます。
セクション・グループ・タイプPATH_SECTION_GROUP
、AUTO_SECTION_GROUP
およびNULL_SECTION_GROUP
には、提供されているセクション・グループがあります。提供されているセクション・グループの所有者はCTXSYS
で、名前はセクション・グループ・タイプと同じです。たとえば、セクション・グループ・タイプPATH_SECTION_GROUP
の提供されているセクション・グループはCTXSYS.PATH_SECTION_GROUP
です。
セクション・グループ・タイプXML_SECTION_GROUP
には提供されているセクション・グループがありません。これは、デフォルトのXML_SECTION_GROUP
は空であり、無意味であるためです。セクション・グループ・タイプXML_SECTION_GROUP
を使用する場合は、新しいセクション・グループを作成し、セクションとして組み込む各ノードを指定する必要があります。
XMLType
型のデータにCONTEXT
索引を作成した場合、デフォルトのセクション・グループは、提供されているセクション・グループCTXSYS.PATH_SECTION_GROUP
です。データがVARCHAR
またはCLOB
の場合、デフォルトのセクション・グループはCTXSYS.NULL_SECTION_GROUP
です。
関連項目: 独自のセクション・グループを作成する方法は、『Oracle Textリファレンス』を参照してください。 |
セクション・グループを索引と関連付けるには、例11-38のように、PARAMETERS
文字列にsection group <section group name>
を追加します。
例11-38 パス・セクション・グループを使用したpurchase_orders表の単純なCONTEXT索引
CREATE INDEX po_index ON purchase_orders(doc) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS ('section group CTXSYS.PATH_SECTION_GROUP');
この例では、表purchase_orders
が使用されます。
関数ora:contains
は、SQL関数existsNode
、extract
およびextractValue
のXPath引数で使用するために、Oracleによって定義されたXPath関数です。
ora:contains
の関数名は、名前(contains
)および名前空間接頭辞(ora
)で構成されます。existsNode
、extract
またはextractValue
でora:contains
を使用するときは、名前空間マッピング・パラメータxmlns:ora="http://xmlns.oracle.com/xdb"
も指定する必要があります。
ora:contains
は、スコアではなく数値を戻します。text_query
がinput_text
と一致した場合、正数を戻します。そうでない場合は0(ゼロ)を戻します。
ora:contains
の引数text_query
は、全文検索を指定する文字列です。ora:contains
のtext_query
はcontains
のtext_query
と同じですが、次の制限事項があります。
ora:contains
のtext_query
には、構造演算子WITHIN
、INPATH
またはHASPATH
を含めることができません。
ora:contains
のtext_query
には、スコア重み付け演算子weight(*)
を含めることができますが、重みは無視されます。
ora:contains
のtext_query
に次のいずれかの演算子を含めた場合は、その問合せでCONTEXT
索引を使用できません。
スコアベースの演算子MINUS
(-
)またはthreshold
(>
)
選択的なコーパスベースの拡張演算子FUZZY
(?
)またはsoundex
(!
)
例11-39に、ブール演算子と$
(ステミング)を任意に組み合せた全文検索を示します。
例11-39 複雑な任意のテキスト問合せを使用したora:contains
SELECT id FROM purchase_orders_xmltype WHERE existsNode(doc, '/purchaseOrder/comment [ora:contains(text(), "($lawns AND wild) OR flamingo") > 0]', 'xmlns:ora="http://xmlns.oracle.com/xdb"') = 1;
この例では、表purchase_orders_xmltype
が使用されます。
関連項目:
|
一致規則は、ポリシーpolicy_owner
.
policy_name
で定義されます。policy_owner
の指定がない場合、ポリシー所有者はデフォルトで現行ユーザーに設定されます。policy_name
とpolicy_owner
の両方が指定されない場合、ポリシーはデフォルトでCTXSYS.DEFAULT_POLICY_ORACONTAINS
に設定されます。
XPath式でora:contains
を使用する場合、有効範囲は引数input_text
で定義されます。この引数は、現在のXPathのコンテキスト内で評価されます。結果が単一のテキスト・ノードまたは属性の場合、そのノードはora:contains
検索のターゲットです。input_text
が単一のテキスト・ノードまたは属性に対して評価されない場合は、エラーが発生します。
ポリシーによって、ora:contains
の一致規則が決定されます。ora:contains
のデフォルト・ポリシーに関連付けられたセクション・グループの型はNULL_SECTION_GROUP
です。
ora:contains
はXPath式のどこでも使用でき、そのinput_text
引数は単一のテキスト・ノードまたは属性に対して評価されるXPath式です。
各XML文書の一部のみを戻す場合は、ノード順序を投影するextract
、またはノードの値を投影するextractValue
を使用します。
例11-40 EXISTSNODEおよびEXTRACT内のora:contains
この例では、ワード"lawn
"を含むcomment
がある各purchaseOrder
のorderDate
が戻されます。表purchase_orders_xmltype
が使用されます。
SELECT extract(doc, '/purchaseOrder/@orderDate') "Order date" FROM purchase_orders_xmltype WHERE existsNode(doc, '/purchaseOrder/comment[ora:contains(text(), "lawn") > 0]', 'xmlns:ora="http://xmlns.oracle.com/xdb"') = 1;
関数existsNode
は、ワード"lawn
"の入ったcomment
がpurchaseOrder
要素に含まれる行(文書)に結果を限定します。その後、関数extract
が、それらのpurchaseOrder
要素から属性orderDate
の値を戻します。//comment
が抽出されていれば、WHERE
句と一致したコメントのみではなく、両方のコメントがサンプル・ドキュメントから戻されます。
列のCONTEXT
索引によって、その列に対するcontains
問合せのセマンティクスが決まります。ora:contains
はサポートしている索引に依存しないため、ora:contains
問合せを実行するときは、同様の選択肢を多数提供する他の方法を検索する必要があります。ポリシーは、ora:contains
問合せに関連付けることができるプリファレンスの集合であり、索引付けに関する選択でcontains
ユーザーに提供される内容と同じようなセマンティクス制御を提供します。
SQL関数contains
を使用すると、索引付けのプリファレンスが問合せのセマンティクスに影響を与えます。プロシージャCTX_DDL.create_preference
(またはCTX_DDL.create_stoplist
)を使用して、プリファレンスを作成します。プロシージャCTX_DDL.set_attribute
を使用して新規プリファレンスの属性を設定することによって、デフォルトの選択肢をオーバーライドします。その後、CREATE INDEX
のPARAMETERS
文字列内にpreference_type preference_name
を含めることによって、CONTEXT
索引でプリファレンスを使用します。
ora:contains
にはサポートしている索引がないため、問合せにプリファレンスを適用するには、別のメカニズムが必要です。そのメカニズムはポリシーであり、プリファレンスの集合で構成されます。これはora:contains
のパラメータとして使用されます。
例11-41では、空のストップワード・リストを持つポリシーが作成されます。
例11-41 ora:containsで使用するポリシーの作成
BEGIN
CTX_DDL.create_policy(POLICY_NAME => 'my_nostopwords_policy',
STOPLIST => 'CTXSYS.EMPTY_STOPLIST');
END;
/
わかりやすいように、このポリシーは空のストップリストで構成されており、所有者はユーザーCTXSYS
です。このポリシーに組み込む新しいストップリストを作成するか、またはCONTEXT
索引用に作成したストップリスト(またはレクサー)定義を再利用できます。
最も一般的なワード(ストップワード)も含めてすべてのワードを検索するには、ora:contains
式でこのポリシーを参照してください。例11-42では、"is
"はデフォルトでストップワードであり問合せできないため、コメントは戻されません。
例11-42 ora:containsを使用した一般的なワードの問合せ
SELECT id FROM purchase_orders_xmltype WHERE existsNode(doc, '/purchaseOrder/comment[ora:contains(text(), "is") > 0]', 'xmlns:ora="http://xmlns.oracle.com/xdb"') = 1;
この例では、表purchase_orders_xmltype
が使用されます。
例11-43では、空のストップワード・リストを指定するために、例11-41で作成されたポリシーが使用されます。この問合せでは"is
"が検索され、コメントが1つ戻されます。
例11-43 ora:containsおよびポリシーmy_nostopwords_policyを使用した一般的なワードの問合せ
SELECT id FROM purchase_orders_xmltype
WHERE existsNode(doc,
'/purchaseOrder/comment
[ora:contains(text(), "is", "MY_NOSTOPWORDS_POLICY") > 0]',
'xmlns:ora="http://xmlns.oracle.com/xdb"')
= 1;
この例では、表purchase_orders_xmltype
およびポリシーmy_nostopwords_policy
が使用されます。(例11-41では、このポリシーの名前は暗黙的にすべて大文字になります。XPathでは大/小文字が区別されるため、XPath述語内でこのポリシーは、my_nostopwords_policy
ではなくMY_NOSTOPWORDS_POLICY
のように、すべて大文字を使用して記述する必要があります。)
ora:contains
ポリシーは、text_query
の一致セマンティクスに影響を与えます。ora:contains
ポリシーには、レクサー、ストップリスト、ワードリスト・プリファレンスまたはこれらの組合せが含まれる場合があります。CONTEXT
索引の作成に使用できる他のプリファレンスは、ora:contains
には適用できません。プリファレンスの効果は次のとおりです。
ワードリスト・プリファレンスによって、ステミング演算子のセマンティクスが改良されます。
ストップリスト・プリファレンスによって、一般的であるために索引付け(検索可能に)しないワードが定義されます。
レクサー・プリファレンスによって、ワードのトークン化および一致方法が定義されます。たとえば、ワードの一部としてカウントする文字および一致で大/小文字を区別するかどうかが定義されます。
関連項目:
|
特定のワードが含まれる文書を検索する場合は通常、検索で大/小文字を区別しない方法が使用されます。大/小文字を区別する検索を実行すると、予期した結果を得られない場合があリます。たとえば、"baby monitor"という句が含まれるpurchaseOrders
を検索する場合、使用しているサンプル文書では"Baby Monitor"と記述されているというだけの理由で、この文書の検索が行われないとは予測しません。
ora:contains
を使用した全文検索では、デフォルトで大/小文字が区別されません。ただし、セクション名および属性名は常に、大/小文字が区別されます。
全文検索で大/小文字を区別する場合は、ポリシーの作成時にそのように選択する必要があります。次の手順を使用します。
プロシージャCTX_DDL.create_preference
(またはCTX_DDL.create_stoplist
)を使用して、プリファレンスを作成します。
プロシージャCTX_DDL.set_attribute
を使用して新規プリファレンスの属性を設定することによって、そのプリファレンス・オブジェクトのデフォルトの選択肢をオーバーライドします。
そのプリファレンスをCTX_DDL.create_policy
のパラメータとして使用します。
問合せではora:contains
の3番目の引数として、ポリシー名を使用します。
プリファレンスを作成した後は、そのプリファレンスを他のポリシーまたはCONTEXT
索引の定義で再利用できます。すべてのora:contains
問合せで、任意のポリシーを使用できます。
例11-44では1行戻されます。これは、text_query
内の"HURRY
"が、デフォルトの大/小文字が区別されない索引が設定されたpurchaseOrder
内の"Hurry
"と一致するためです。
例11-44 ora:contains、デフォルトの大/小文字の区別
SELECT id FROM purchase_orders_xmltype WHERE existsNode(doc, '/purchaseOrder/comment[ora:contains(text(), "HURRY") > 0]', 'xmlns:ora="http://xmlns.oracle.com/xdb"') = 1;
この例では、表purchase_orders_xmltype
が使用されます。
例11-45では、属性mixed_case
がTRUE
に設定された新しいレクサー・プリファレンスmy_lexer
が作成されます。この例では、printjoin
文字も"-
"、"!
"、",
"に設定されます。CONTEXT
索引の作成およびポリシーの作成に同じプリファレンスを使用できます。
関連項目: レクサー属性の完全なリストは、『Oracle Textリファレンス』を参照してください。 |
例11-45 大/小文字混合のプリファレンスの作成
BEGIN CTX_DDL.create_preference(PREFERENCE_NAME => 'my_lexer', OBJECT_NAME => 'BASIC_LEXER'); CTX_DDL.set_attribute(PREFERENCE_NAME => 'MY_LEXER', ATTRIBUTE_NAME => 'MIXED_CASE', ATTRIBUTE_VALUE => 'TRUE'); CTX_DDL.set_attribute(PREFERENCE_NAME => 'my_lexer', ATTRIBUTE_NAME => 'printjoins', ATTRIBUTE_VALUE => '-,!'); END ; /
例11-46では、新規ポリシーmy_policy
が作成され、レクサーのみが指定されます。他のプリファレンスはすべてデフォルトに設定されます。
例11-46 大/小文字混合の(大/小文字が区別されない)ポリシーの作成
BEGIN CTX_DDL.create_policy(POLICY_NAME => 'my_policy', LEXER => 'my_lexer'); END ; /
この例ではpreference-case-mixedが使用されます。
例11-47では、問合せで新規ポリシーが使用されます。text_query
内の"HURRY
"は、purchaseOrder
内の"Hurry
"と一致しないため、行は戻されません。
例11-47 ora:contains、大/小文字の区別(1)
SELECT id FROM purchase_orders_xmltype WHERE existsNode(doc, '/purchaseOrder/comment [ora:contains(text(), "HURRY", "my_policy") > 0]', 'xmlns:ora="http://xmlns.oracle.com/xdb"') = 1;
この例では、表purchase_orders_xmltype
が使用されます。
例11-48では、text_query
の"Hurry
"がcomment
要素内のテキスト"Hurry
"と正確に一致するため、1行戻されます。
例11-48 ora:contains、大/小文字の区別(2)
SELECT id FROM purchase_orders_xmltype WHERE existsNode(doc, '/purchaseOrder/comment [ora:contains(text(), "Hurry") > 0]', 'xmlns:ora="http://xmlns.oracle.com/xdb"') = 1;
この例では、表purchase_orders_xmltype
が使用されます。
ora:contains
のポリシーの引数はオプションです。省略した場合、問合せではデフォルトのポリシーCTXSYS.DEFAULT_POLICY_ORACONTAINS
が使用されます。
ora:contains
で使用するポリシーを作成するときは、すべてのプリファレンスを指定する必要はありません。たとえば、例11-46では、レクサー・プリファレンスのみが指定されていました。指定されないプリファレンスについては、CREATE_POLICY
によって次のデフォルトのプリファレンスが使用されます。
CTXSYS.DEFAULT_LEXER
CTXSYS.DEFAULT_STOPLIST
CTXSYS.DEFAULT_ WORDLIST
ポリシーの作成では、CONTEXT
索引の作成が索引メタデータのコピー・セマンティクスに従うのと同様に、プリファレンスとその属性のコピー・セマンティクスに従います。
ora:contains
のXPath関数は、サポートしている索引に依存しません。ora:contains
は非常に柔軟性があります。しかし、索引のない大量のデータを検索する場合、大量のリソースを消費することもあります。この項では、ora:contains
を使用するXPath式が含まれる問合せのパフォーマンスを最大にする方法を説明します。
注意: ファンクション索引はXML問合せの高速化にも非常に有効ですが、一般的にテキスト問合せには適用できません。 |
この項の例では、表PURCHASE_ORDERS_xmltype_big
が使用されます。この表には、PURCHASE_ORDERS_xmltype
と同じ表構造とXML Schemaがありますが、約1,000行が格納されています。各行には、(id
列に)一意のIDと、/purchaseOrder/items/item/comment
内に少しずつ異なるテキストが含まれています。示されている実行計画は、SQL*PlusコマンドAUTOTRACE
を使用して生成されたものです。実行計画は、SQLコマンドTRACE
およびTKPROF
を使用しても生成できます。コマンドAUTOTRACE
、trace
およびtkprof
については、この章で説明しません。
この項の内容は次のとおりです。
ora:contains
は、処理のコストが比較的かかるため、可能な場合は1次フィルタを組み込んだ問合せの作成をお薦めします。この結果、ora:contains
で処理される行数が最小化されます。
例11-49では、例11-50の計画からわかるように、表内のすべての行が検査されます(全表スキャンの実行)。この例で、ora:contains
はすべての行に対して評価されます。
例11-49 EXISTSNODE内のora:contains、大規模な表
SELECT id FROM purchase_orders_xmltype_big WHERE existsNode(doc, '/purchaseOrder/items/item/comment [ora:contains(text(), "constitution") > 0]', 'xmlns:ora="http://xmlns.oracle.com/xdb"') = 1;
例11-50 EXPLAIN PLAN: EXISTSNODE
Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE 1 0 TABLE ACCESS (FULL) OF 'PURCHASE_ORDERS_XMLTYPE_BIG' (TABLE)
例11-51に示すようにid
列に索引を作成し、例11-52に示すように選択的なid
述語を問合せに追加した場合は、例11-53からもわかるように、Oracleではid
索引が使用されません。ora:contains
は、id
述語がtrue(id
が5未満)の行に対してのみ実行されます。
この例では、表purchase_orders
が使用されます。
ora:contains
はサポートしている索引に依存しません。ただし、状況によっては、パフォーマンス向上のために、ora:contains
で既存のCONTEXT
索引が使用される場合があります。
Oracleでは、状況によってSQL/XML問合せがオブジェクト・リレーショナル問合せにリライトされます。これは問合せ最適化の一部として行われ、ユーザーに対しては透過的です。XPathリライトには、次の2つのメリットがあります。
リライトされた問合せは、XML文書全体を処理するかわりに、基礎となるオブジェクト・リレーショナル表に直接アクセスできます。
リライトされた問合せは使用可能な索引をすべて利用できます。
XPathリライトは、パフォーマンスの最適化です。XPathリライトが実行されるのは、XMLデータがオブジェクト・リレーショナル形式で格納される場合、つまりXMLデータがXML Schemaに基づく必要がある場合のみです。
単純なora:contains
問合せである例11-54について考えてみます。この問合せのXPath式をネイティブに処理するには、doc
列内の各セルを考慮する必要があり、各セルがこのXPath式と一致しているかどうかをテストする必要があります。
/purchaseOrder/items/item/comment[ora:contains(text(), "electric")>0]
例11-54 EXISTSNODE内のora:contains
SELECT id FROM purchase_orders_xmltype WHERE existsNode(doc, '/purchaseOrder/items/item/comment [ora:contains(text(), "electric") > 0]', 'xmlns:ora="http://xmlns.oracle.com/xdb"') = 1 ;
この例では、表purchase_orders_xmltype
が使用されます。
しかし、doc
がXML Schemaに基づいており、purchaseOrder
文書がオブジェクト・リレーショナル表に物理的に格納されている場合は、列/purchaseOrder/items/item/comment
(存在する場合)に直接アクセスし、そこで各セルが"electric
"と一致しているかどうかをテストするほうが効率的です。
これは、XPathリライトの最初のステップです。ora:contains
の最初の引数(text_input
)が単一のリレーショナル列にマップされている場合、ora:contains
はその列に対して実行されます。この結果、索引が含まれていない場合でも、問合せのパフォーマンスが大幅に向上します。
「文書からノードへの変換」で説明したように、Oracle XML DBでは、XPath式全体をXML文書全体に適用するのではなく、基礎となる列にora:contains
を適用することによって関数existsNode
に渡されたXPath式が解決されるように、問合せがリライトされる場合があります。この項では、その問合せで、基礎となる列のCONTEXT
索引を利用する方法を示します。
CONTEXT
索引が付いた列にマップされているテキスト・ノードまたは属性に対してora:contains
を実行している場合、その索引を使用しない理由を考えてみます。1つの理由は、リライトされた問合せが元の問合せと同じ結果になる必要があることです。一貫した結果を保証するには、CONTEXT
索引を使用する前に次の条件を満たす必要があります。
ora:contains
のターゲット(input_text
)は、親ノードが列にマップされている単一のテキスト・ノード、または列にマップされている属性の必要があります。列は(Ordered Collection Table内の列も含めて)、単一のリレーショナル列である必要があります。
「ora:contains問合せのポリシー」で説明したように、索引付けに関する選択内容(contains
用)およびポリシーの選択内容(ora:contains
用)は問合せのセマンティクスに影響を与えます。単純な違いは、索引ベースのcontains
では大/小文字が区別される検索であるのに対して、ora:contains
では大/小文字が区別されない検索が指定される点です。ora:contains
およびリライトされたcontains
のセマンティクスが同じになるように、ora:contains
のポリシーがCONTEXT
索引の索引に関する選択内容と正確に一致する必要があります。
ora:contains
のポリシーとCONTEXT
の索引の両方で、NULL_SECTION_GROUP
セクション・グループ・タイプを使用する必要もあります。ora:contains
ポリシーのデフォルトのセクション・グループはctxsys.NULL_SECTION_GROUP
です。
3番目に、CONTEXT
索引は通常非同期です。ワード"dog
"が含まれる新しい文書を追加した場合にCONTEXT
索引を同期化しないと、"dog
"のcontains
問合せでその文書が戻されません。しかし、同じデータに対するora:contains
問合せでは戻されます。ora:contains
とリライトされたcontains
で常に同じ結果が戻されるようにするには、PARAMETERS
文字列にTRANSACTIONAL
キーワードを指定してCONTEXT
索引を作成する必要があります。
関連項目: 『Oracle Textリファレンス』 |
XPathにora:contains
が含まれているexistsNode
、extract
またはextractValue
を使用する問合せでは、次の場合にXPathリライトを考慮できます。
XMLがXML Schemaに基づいている場合。
ora:contains
の最初の引数(text_input
)が、親ノードが列にマップされている単一のテキスト・ノードであるか、または列にマップされている属性である場合。列は(Ordered Collection Table内の列も含めて)、単一のリレーショナル列である必要があります。
リライトされた問合せでは、次の場合にCONTEXT
索引が使用されます。
text_input
の親ノード(または属性ノード)がマップされる列に、CONTEXT
索引が設定されている場合。
ora:contains
ポリシーがCONTEXT
索引の索引に関する選択内容と完全に一致する場合。
CONTEXT
索引が、PARAMETERS
文字列にTRANSACTIONAL
キーワードを指定して作成された場合。
XPathリライトは、最適なCONTEXT
索引がある場合は特に、問合せを大幅に高速化できます。
HasPathArg ::= LocationPath | EqualityExpr InPathArg ::= LocationPath LocationPath ::= RelativeLocationPath | AbsoluteLocationPath AbsoluteLocationPath ::= ("/" RelativeLocationPath) | ("//" RelativeLocationPath) RelativeLocationPath ::= Step | (RelativeLocationPath "/" Step) | (RelativeLocationPath "//" Step) Step ::= ("@" NCName) | NCName | (NCName Predicate) | Dot | "*" Predicate ::= ("[" OrExp "]") | ("[" Digit+ "]") OrExpr ::= AndExpr | (OrExpr "or" AndExpr) AndExpr ::= BooleanExpr | (AndExpr "and" BooleanExpr) BooleanExpr ::= RelativeLocationPath | EqualityExpr | ("(" OrExpr ")") | ("not" "(" OrExpr ")") EqualityExpr ::= (RelativeLocationPath "=" Literal) | (Literal "=" RelativeLocationPath) | (RelativeLocationPath "=" Literal) | (Literal "!=" RelativeLocationPath) | (RelativeLocationPath "=" Literal) | (Literal "!=" RelativeLocationPath) Literal ::= (DoubleQuote [~"]* DoubleQuote) | (SingleQuote [~']* SingleQuote) NCName ::= (Letter | Underscore) NCNameChar* NCNameChar ::= Letter | Digit | Dot | Dash | Underscore Letter ::= ([a-z] | [A-Z]) Digit ::= [0-9] Dot ::= "." Dash ::= "-" Underscore ::= "_"
この項の内容は次のとおりです。
例11-55 発注書のXML文書、po001.xml
<?xml version="1.0" encoding="UTF-8"?> <purchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xmlschema/po.xsd" orderDate="1999-10-20"> <shipTo country="US"> <name>Alice Smith</name> <street>123 Maple Street</street> <city>Mill Valley</city> <state>CA</state> <zip>90952</zip> </shipTo> <billTo country="US"> <name>Robert Smith</name> <street>8 Oak Avenue</street> <city>Old Town</city> <state>PA</state> <zip>95819</zip> </billTo> <comment>Hurry, my lawn is going wild!</comment> <items> <item partNum="872-AA"> <productName>Lawnmower</productName> <quantity>1</quantity> <USPrice>148.95</USPrice> <comment>Confirm this is electric</comment> </item> <item partNum="926-AA"> <productName>Baby Monitor</productName> <quantity>1</quantity> <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate> </item> </items> </purchaseOrder>
例11-56 CREATE TABLE purchase_orders
CREATE TABLE purchase_orders (id NUMBER, doc VARCHAR2(4000)); INSERT INTO purchase_orders (id, doc) VALUES (1, '<?xml version="1.0" encoding="UTF-8"?> <purchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xmlschema/po.xsd" orderDate="1999-10-20"> <shipTo country="US"> <name>Alice Smith</name> <street>123 Maple Street</street> <city>Mill Valley</city> <state>CA</state> <zip>90952</zip> </shipTo> <billTo country="US"> <name>Robert Smith</name> <street>8 Oak Avenue</street> <city>Old Town</city> <state>PA</state> <zip>95819</zip> </billTo> <comment>Hurry, my lawn is going wild!</comment> <items> <item partNum="872-AA"> <productName>Lawnmower</productName> <quantity>1</quantity> <USPrice>148.95</USPrice> <comment>Confirm this is electric</comment> </item> <item partNum="926-AA"> <productName>Baby Monitor</productName> <quantity>1</quantity> <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate> </item> </items> </purchaseOrder>');COMMIT;
例11-57 CREATE TABLE purchase_orders_xmltype
CREATE TABLE purchase_orders_xmltype (id NUMBER , doc XMLType); INSERT INTO purchase_orders_xmltype (id, doc) VALUES (1, XMLTYPE ('<?xml version="1.0" encoding="UTF-8"?> <purchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="po.xsd" orderDate="1999-10-20"> <shipTo country="US"> <name>Alice Smith</name> <street>123 Maple Street</street> <city>Mill Valley</city> <state>CA</state> <zip>90952</zip> </shipTo> <billTo country="US"> <name>Robert Smith</name> <street>8 Oak Avenue</street> <city>Old Town</city> <state>PA</state> <zip>95819</zip> </billTo> <comment>Hurry, my lawn is going wild!</comment> <items> <item partNum="872-AA"> <productName>Lawnmower</productName> <quantity>1</quantity> <USPrice>148.95</USPrice> <comment>Confirm this is electric</comment> </item> <item partNum="926-AA"> <productName>Baby Monitor</productName> <quantity>1</quantity> <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate> </item> </items> </purchaseOrder>')); COMMIT;
例11-58 CREATE TABLE purchase_orders_xmltype_table
CREATE TABLE purchase_orders_xmltype_table OF XMLType; INSERT INTO purchase_orders_xmltype_table VALUES ( XMLType ('<?xml version="1.0" encoding="UTF-8"?> <purchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xmlschema/po.xsd" orderDate="1999-10-20"> <shipTo country="US"> <name>Alice Smith</name> <street>123 Maple Street</street> <city>Mill Valley</city> <state>CA</state> <zip>90952</zip> </shipTo> <billTo country="US"> <name>Robert Smith</name> <street>8 Oak Avenue</street> <city>Old Town</city> <state>PA</state> <zip>95819</zip> </billTo> <comment>Hurry, my lawn is going wild!</comment> <items> <item partNum="872-AA"> <productName>Lawnmower</productName> <quantity>1</quantity> <USPrice>148.95</USPrice> <comment>Confirm this is electric</comment> </item> <item partNum="926-AA"> <productName>Baby Monitor</productName> <quantity>1</quantity> <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate> </item> </items> </purchaseOrder>')); COMMIT;
例11-59 全文検索する発注書XML Schemaの例
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:annotation> <xsd:documentation xml:lang="ja"> Purchase order schema for Example.com. Copyright 2000 Example.com. All rights reserved. </xsd:documentation> </xsd:annotation> <xsd:element name="purchaseOrder" type="PurchaseOrderType"/> <xsd:element name="comment" type="xsd:string"/> <xsd:complexType name="PurchaseOrderType"> <xsd:sequence> <xsd:element name="shipTo" type="USAddress"/> <xsd:element name="billTo" type="USAddress"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="items" type="Items"/> </xsd:sequence> <xsd:attribute name="orderDate" type="xsd:date"/> </xsd:complexType> <xsd:complexType name="USAddress"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="street" type="xsd:string"/> <xsd:element name="city" type="xsd:string"/> <xsd:element name="state" type="xsd:string"/> <xsd:element name="zip" type="xsd:decimal"/> </xsd:sequence> <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/> </xsd:complexType> <xsd:complexType name="Items"> <xsd:sequence> <xsd:element name="item" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="productName" type="xsd:string"/> <xsd:element name="quantity"> <xsd:simpleType> <xsd:restriction base="xsd:positiveInteger"> <xsd:maxExclusive value="100"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="USPrice" type="xsd:decimal"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/> </xsd:sequence> <xsd:attribute name="partNum" type="SKU" use="required"/> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> <!-- Stock Keeping Unit, a code for identifying products --> <xsd:simpleType name="SKU"> <xsd:restriction base="xsd:string"> <xsd:pattern value="\d{3}-[A-Z]{2}"/> </xsd:restriction> </xsd:simpleType> </xsd:schema>