この章では、Oracleを使用したXMLの全文検索について説明します。Oracle SQL関数contains
およびOracle XPath関数ora:contains
の使用方法についても説明します。これらはOracle Databaseにより使用され、XMLデータの全文検索を実行する2つの関数です。
関連項目: 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通りがあります。
Oracle 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]'
XPath関数ora:contains
はXPathの拡張機能であり、SQL/XML関数XMLQuery
、XMLTable
またはXMLExists
のコールで使用できます。
この項では、この章の例について詳細に説明します。
この章の例は、W3Cの「XML Schema Part 0: Primer」にある「The Purchase Order Schema」に基づいています。
例で使用しているデータは、「発注書のXML文書、po001.xml」の文書からのものです。
この章の例で使用している表は、「CREATE TABLE文」「CREATE TABLE文」で定義されています。ただし、パフォーマンスの例の一部は、より大きい表(purchase_orders_xmltype_big
)に基づいており、この表はダウンロード可能なバージョンにのみ含まれています。http://www.w3.org/TR/xmlschema-0/#po.xml
を参照してください。
一部の例は、データ型VARCHAR2
を使用しています。XMLType
型を使用するものもあります。VARCHAR2
を使用している例はすべて、XMLType
を使用することもできます。
この項の内容は次のとおりです。
Oracle SQL関数contains
は、[schema.]column
がtext_query
と一致する行の正数を戻し、一致しない場合は0(ゼロ)を戻します。それ以外の場合は、0(ゼロ)を戻します。型CONTEXT
の索引が必要です。検索対象の列にCONTEXT
索引がない場合、contains
ではエラーが発生します。
CONTAINS構文
contains([schema.]column, text_query VARCHAR2 [,label NUMBER]) RETURN NUMBER
例12-1に、Oracle SQL関数contains
を使用した一般的な問合せを示します。表purchase_orders
で、doc
列に単語"lawn"が含まれ、id
が25よりも小さい値の各行のid
が戻されます。
例12-1 Oracle SQL関数CONTAINSを使用した単純な問合せ
SELECT id FROM purchase_orders WHERE contains(doc, 'lawn') > 0 AND id < 25;
doc
は、一連のXML文書が含まれる列であるとします。この場合、doc
に対して、そのXML構造を使用して問合せを限定する全文検索を実行できます。例12-2の問合せでは、表purchaseorders
で、XML要素comment
のtext()ノードにワード"lawn"が含まれるdoc
列のid
値が戻されます。
例12-2 CONTAINSおよびWITHINを使用した問合せの制限
SELECT id FROM purchase_orders WHERE contains(doc, 'lawn WITHIN comment') > 0;
INPATH
演算子およびXPath式を使用すると、XML構造によるさらに複雑な限定を適用できます。例12-3の問合せでは、XPath式/purchaseOrder/items/item/comment
のターゲットとなるcomment
要素のtext()ノードに、ワード"electric"が含まれる発注書が検索されます。
XPath関数ora:contains
は、XQuery式内のXPath式や、SQL/XML関数XMLQuery
、XMLTable
、XMLExists
のコールで使用できます。これは、全文述語を伴う構成検索を制限する場合に使用されます。標準のメカニズムを使用してXPathを拡張する、Oracle XML DB名前空間ora
内のユーザー定義関数です。索引は不要ですが、索引を使用することでパフォーマンスを向上できます。
ora:contains構文
ora:contains(input_text NODE*, text_query STRING [,policy_name STRING] [,policy_owner STRING])
関数ora:contains
はinput_text
がtext_query
と一致した場合は正の整数を戻し(数字が大きいほど、一致の関連性は高くなります)、一致しない場合はゼロを戻します。XQuery式で使用される場合、XQueryの戻り型はxs:integer()
です。XQuery式の外部でXPath式で使用される場合、XPathの戻り型はnumber
です。
引数input_text
は単一のテキスト・ノードまたは属性に対して評価される必要があります。ora:contains
のtext_query
の構文およびセマンティクスはcontains
のtext_query
と同じですが、次の制限事項があります。
引数text_query
に構造演算子(WITHIN
、INPATH
またはHASPATH
)を含めることはできません。
スコア重み付け演算子weight
を使用した場合、重みは無視されます。
例12-4は、XMLExists
のXPathパラメータにおけるora:contains
のコールを示しています。Oracle XML DBネームスペースを表すものとして、接頭辞ora
を宣言するネームスペース宣言に注意してください。
例12-4 複雑な任意のテキスト問合せを使用したora:contains
SELECT id FROM purchase_orders_xmltype WHERE XMLExists( 'declare namespace ora = "http://xmlns.oracle.com/xdb"; (: :) $d/purchaseOrder/comment [ora:contains(text(), "($lawns AND wild) OR flamingo") > 0]' PASSING doc AS "d");
Oracle SQL関数contains
およびOracle XPath関数ora:contains
では、いずれもXML構造の検索と全文検索を組み合せることができます。これらの主な違いは次のとおりです。
Oracle SQL関数contains
の特性は、次のとおりです。
実行するにはCONTEXT
索引が必要です。索引がない場合はエラーが発生します。
索引検索を実行し、通常非常に高速です。
(Oracle SQL関数score
を使用して)スコアを戻します。
ノードではなく文書(表の行)に基づいて検索を限定します。
XML構造ベースの投影(XML文書の一部を抽出)には使用できません。
Oracle XPath関数ora:contains
の特性は、次のとおりです。
索引は不要ですが、索引を使用することでパフォーマンスを向上できます。
非索引検索であるため、大量のリソースを消費する場合があります。
格納方法および索引付け方法に関する考慮事項からアプリケーション・ロジックを分離しています。
スコアを戻しません。
XML構造ベースの投影(XML文書の一部を抽出)に使用できます。
XML文書で、単純なXML構造の制約を指定している場合など、高速な索引ベースの全文検索を実行する場合は、Oracle SQL関数contains
を使用します。XPathナビゲーションと組み合せた全文検索の柔軟性が必要な場合(索引がない場合も含めて)、または投影は必要でスコアは不要な場合は、Oracle XPath関数ora:contains
を使用します。
この項の内容は次のとおりです。
Oracle SQL関数contains
の2番目の引数text_query
は、全文検索を指定する文字列です。text_query
には、SQL/MMの全文標準に基づいた独自の言語があります。
関連項目:
|
この項の後半の例では、全文検索の優れた機能をいくつか示します。使用可能な2、3の演算子を使用します。例の問合せでは、テキスト索引(索引タイプ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リファレンス』を参照してください。 |
text_query
言語では、語幹検索がサポートされています。例12-7では、"lawns"と同じ言語語幹のワードが含まれるすべての文書が戻されるため、"lawn"または"lawns"が検索されます。ステミング演算子は、ドル記号($
)で記述されます。
例12-8に示すように、text_query
言語の演算子を組み合せることができます。
例12-8 複雑な問合せ式を使用したCONTAINS問合せ
SELECT id FROM purchase_orders WHERE contains(doc, '($lawns AND wild) OR flamingo') > 0;
関連項目: text_query 演算子の完全なリストは、『Oracle Textリファレンス』を参照してください。 |
Oracle SQL関数score
はOracle SQL関数contains
に関連します。関数score
は問合せ内のどの場所でも使用できます。これは関連性を測定するもので、大規模なドキュメント・セット全体を全文検索するときに特に有効です。関数score
は通常、問合せ結果の一部として戻されるか、ORDER BY
句で使用されるか、あるいはその両方です。
SCORE構文
score(label NUMBER) RETURN NUMBER
例12-9のscore(10)
では、結果セット内の各行に対するスコアが戻されます。Oracle SQL関数score
は、関数contains
の特定のコールに関する結果セット内の行の関連性を戻します。score
のコールは、LABEL
(この場合は番号10)によってcontains
のコールにリンクされます。
例12-9 SCOREを使用した単純なCONTAINS問合せ
SELECT score(10), id FROM purchase_orders WHERE contains(doc, 'lawn', 10) > 0 AND score(10) > 2 ORDER BY score(10) DESC;
関数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リファレンス』を参照してください。 |
Oracle SQL関数contains
では、デフォルトで文書全体が全文検索されます。前述の例で、構造による限定のない"lawn"の検索では、発注書内のどこかにワード"lawn"があるすべての発注書が検索されます。
XML構造を使用してcontains
問合せを限定する方法は、次の3通りあります。
WITHIN
INPATH
HASPATH
注意: この説明では、セクションはXMLノードと同じであると考えてください。 |
WITHIN
演算子は、問合せをXML文書内のあるセクションに限定します。コメント・セクションのどこかにワード"lawn"が含まれている発注書を検索するには、WITHIN
を使用します。セクション名の大/小文字は区別されます。
WITHIN
をネストすると、問合せをさらに限定できます。例12-11では、セクション"comment
"内にワード"lawn
"が含まれ、"lawn
"の出現箇所がセクション"item
"内にもあるすべての文書が検索されます。
例12-11 ネストしたWITHIN
SELECT id FROM purchase_orders WHERE contains(doc, '(lawn WITHIN comment) WITHIN item') > 0;
例12-11では行が戻されません。使用する発注書サンプルには、コメント内にワード"lawn
"が含まれています。しかし、項目内の唯一のコメントは"Confirm this is electric
"です。そのため、ネストしたWITHIN
問合せでは行が戻されません。
属性内を検索することもできます。例12-12では、purchaseOrder
要素のorderDate
属性にワード"10
"が含まれているすべての発注書が検索されます。
例12-12 属性内のWITHIN
SELECT id FROM purchase_orders WHERE contains(doc, '10 WITHIN purchaseOrder@orderDate') > 0;
デフォルトでは、マイナス記号(-
)は単語セパレータとして処理されます。つまり、"1999-10-20
"は3つの単語、"1999
"、"10
"および"20
"として処理されます。したがって、この問合せでは1行戻されます。
属性内のテキストは、主検索可能文書の一部ではありません。text_query
をWITHIN purchaseOrder@orderDate
で修飾せずに10
を検索すると、行は戻されません。
属性は、ネストしたWITHIN
では検索できません。
コメント・セクション内にlawnとelectricの2つのワードが含まれる発注書を検索するとします。purchaseOrder
にはコメント・セクションが複数ある場合があります。このため、この問合せの作成方法は2通りあり、異なる結果となります。
両方のワードが含まれ、各ワードがあるコメント・セクション内に出現する発注書を検索する場合は、例12-13のような問合せを作成します。
例12-13 WITHINおよびAND: あるコメント・セクション内の2つのワード
SELECT id FROM purchase_orders WHERE contains(doc, '(lawn WITHIN comment) AND (electric WITHIN comment)') > 0;
purchaseOrder
データに対してこの問合せを実行すると、1行戻されます。この例ではカッコは必要ありませんが、使用すると問合せがわかりやすくなります。
両方のワードが含まれ、両方のワードが同じコメント内に出現する発注書を検索する場合は、例12-14のような問合せを作成します。
例12-14 WITHINおよびAND: 同じコメント内の2つのワード
SELECT id FROM purchase_orders WHERE contains(doc, '(lawn AND electric) WITHIN comment') > 0;
例12-14の問合せでは、行が戻されません。例12-15の問合せのように、lawn AND electric
を囲むカッコを外すと、1行戻されます。
前述の例では、セクション内を検索するためにWITHIN
演算子を使用しました。次のセクションを指定できます。
パス・セクションまたはゾーン・セクション
これは、ノードの子孫であるテキスト・ノードのすべてを、間を空白で区切って文書順に連結したものです。ノードからゾーン・セクションに変換するには、ノードをシリアライズしてすべてのタグを空白で置換する必要があります。パス・セクションの有効範囲と動作はゾーン・セクションと同じですが、パス・セクションでは INPATH
およびHASPATH
構造演算子を使用した問合せがサポートされます。
フィールド・セクション
ゾーン・セクションと同じですが、文書内の繰返しノードが空白で区切られて単一のセクションに連結されます。
属性セクション
特殊セクション(文または段落)
関連項目: 特殊セクションの詳細は、『Oracle Textリファレンス』を参照してください。 |
演算子WITHIN
は、構造による単純な限定をtext_query
で表す簡単で直観的な方法です。豊富なXML構造を使用する問合せでは、ネストしたWITHIN
演算子のかわりに、演算子INPATH
とText Pathを使用できます。
演算子INPATH
では、左側にtext_query
を記述し、右側にカッコで囲んだText Pathを記述します。例12-17では、パス/purchaseOrder/items/item/comment
内で単語"electric
"が含まれるpurchaseOrders
が検索されます。
例12-17 全文述語内の構造: INPATH
SELECT id FROM purchase_orders WHERE contains(doc, 'electric INPATH (/purchaseOrder/items/item/comment)') > 0;
例12-17の検索範囲は、Text Pathで示されたセクションです。例12-18の問合せでは例12-17の問合せよりも範囲の広いパスを使用しますが、同じように1行しか戻されません。
例12-18 全文述語内の構造: INPATH
SELECT id FROM purchase_orders WHERE contains(doc, 'electric INPATH (/purchaseOrder/items)') > 0;
Text Pathの構文とセマンティクスは、W3CのXPath 1.0勧告に基づいています。単純なパス式はサポートされますが(省略構文のみ)、関数はサポートされません。以降の各例は、一般的な変形例を示しています。
関連項目:
|
例12-19では、属性partNum
が"872-AA
"と等しいitem
要素の子であるcomment
要素内にワード"electric
"が含まれるすべての発注書が検索されます。つまり、ルート・ノードからいくつか下のレベルのitems
要素の子です。
例12-19 複雑なパス式を使用したINPATH(1)
SELECT id FROM purchase_orders WHERE contains(doc, 'electric INPATH (//items/item[@partNum="872-AA"]/comment)') > 0;
例12-20では、3番目のレベルであるitem
要素(またはその子孫)内に単語"lawnmower
"が含まれ、すべてのレベルにcomment
要素があるすべての発注書が検索されます。この問合せでは1行戻されます。問合せの有効範囲はcomment
要素ではなく、子孫としてcomment
要素を持つ一連のitems
要素であることに注意してください。
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
の場合も変わりません。
例12-21では、任意のレベルのcomment
要素にワード"electric
"が含まれる発注書が検索されます。このワードの出現箇所は、最上位レベルpurchaseOrder
要素の子であるitem
要素内でもあります。
例12-21 ネストしたINPATH
SELECT id FROM purchase_orders WHERE contains(doc, '(electric INPATH (//comment)) INPATH (/purchaseOrder/items)') > 0;
このネストしたINPATH
問合せは、例12-22に示すように、簡潔に記述できます。
演算子HASPATH
で使用するオペランドはText Pathのみで、カッコで囲み、右側に記述します。=
述語などを使用して、特定のパス内に特定のセクションが含まれる文書を検索するときは、HASPATH
を使用します。これは全文検索ではなく、パス検索です。セクションが存在するかどうかの確認、またはセクションの内容の照合はできますが、ワード検索はできません。データ型がXMLType
の場合は、構造演算子HASPATH
ではなくSQL/XML関数XMLExists
の使用を考慮してください。
例12-23では、USPrice
を持つ項目があるpurchaseOrders
が検索されます。
例12-23 単純なHASPATH
SELECT id FROM purchase_orders WHERE contains(DOC, 'HASPATH (/purchaseOrder//item/USPrice)') > 0;
例12-24では、"148.95
"とテキスト等値であるUSPrice
を持つ項目があるpurchaseOrders
が検索されます。
例12-24 HASPATHの等値式
SELECT id FROM purchase_orders WHERE contains(doc, 'HASPATH (/purchaseOrder//item/USPrice="148.95")') > 0;
HASPATH
は、INPATH
など他のcontains
演算子と組み合せることができます。例12-25では、文書の任意の場所にワード electric
を含み、148.95
とテキスト等値であるUSPrice
を持つitem
があり、かつpurchaseOrder
属性orderDate
内に10
が含まれるpurchaseOrders
が検索されます。
WHERE
句内にcontains
式を使用したSQL問合せの結果は常に、行のセット(および多くの場合score
情報)、または問合せと一致する行全体の投影です。
contains
式を満たす各XML文書の一部のみを戻すには、SQL/XML関数XMLQuery
を使用します。この項の例では、XMLType
表purchase_orders_xmltype
が使用されます。
例12-26では、最上位レベルのpurchaseOrder
要素の子孫であるcomment
要素内にワード"electric
"が含まれるpurchaseOrder
が検索されます。各結果の行IDを戻すかわりに、XMLQuery
を使用してcomment
要素のみを戻します。
例12-26 CONTAINS問合せの結果の範囲指定
SELECT XMLQuery('declare namespace ora = "http://xmlns.oracle.com/xdb"; (: :) $d/purchaseOrder//comment' PASSING doc AS "d" RETURNING CONTENT) "Item Comment" FROM purchase_orders_xmltype WHERE CONTAINS(doc, 'electric INPATH (/purchaseOrder//comment)') > 0;
例12-26の結果は、要素comment
の2つのインスタンスです。関数contains
は、comment
要素内に単語"electric
"が含まれている行(ID
= 1
の行)を示します。関数XMLQuery
は文書内のその行にある要素comment
のインスタンスをすべて抽出します。purchaseOrder
要素には要素 comment
のインスタンスが2つあり、問合せではその両方が戻されます。
これは希望の結果と異なる場合があります。contains
式を満たすcomment
要素の実例のみを問合せで戻す場合は、XMLQuery
に渡されるXQuery式でその述語を繰り返す必要があります。これには、XPath関数ora:contains
を使用します。例12-27に、これを示します。
例12-27 ora:containsを使用したCONTAINS問合せ結果の投影
SELECT XMLQuery('declare namespace ora = "http://xmlns.oracle.com/xdb"; (: :) $d/purchaseOrder/items/item/comment [ora:contains(text(), "electric") > 0]' PASSING doc AS "d" RETURNING CONTENT) "Item Comment" FROM purchase_orders_xmltype WHERE CONTAINS(doc, 'electric INPATH (/purchaseOrder/items/item/comment)') > 0;
この項の内容は次のとおりです。
汎用の全文索引タイプは、データベース・ユーザーCTXSYS
が所有するCONTEXT
索引タイプです。デフォルトの全文索引を作成するには、例12-28に示すように、通常のSQL CREATE INDEX
コマンドを使用し、句INDEXTYPE IS CTXSYS.CONTEXT
を追加します。
例12-28 表PURCHASE_ORDERSの単純なCONTEXT索引
CREATE INDEX po_index ON purchase_orders(doc) INDEXTYPE IS CTXSYS.CONTEXT;
全文索引を作成するときには、多数の選択肢があります。これらの選択肢は、索引付けプリファレンスとして表されます。索引付けプリファレンスを使用するには、例12-29に示すように、CREATE INDEX
にPARAMETERS
句を追加します。
例12-29 パス・セクション・グループを使用したXMLType表の単純なCONTEXT索引
CREATE INDEX po_index ON purchase_orders(doc) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS ('section group CTXSYS.PATH_SECTION_GROUP');
Oracle Textには、CTXCAT
やCTXRULE
などの他の索引タイプが用意されていますが、この章では説明しません。
関連項目: CONTEXT 索引の詳細は、『Oracle Textリファレンス』を参照してください。 |
CONTEXT
索引は、テキストが含まれた任意のデータに対して作成できます。例12-28では、VARCHAR2
列に対するCONTEXT
索引が作成されます。型がCHAR
、VARCHAR
、VARCHAR2
、BLOB
、CLOB
、BFILE
、XMLType
またはURIType
の列にCONTEXT
索引を作成する構文は同じです。例12-30では、XMLType
型の列に対するCONTEXT
索引が作成されます。セクション・グループはデフォルトでPATH_SECTION_GROUP
に設定されます。
例12-30 XMLType列の単純なCONTEXT索引
CREATE INDEX po_index_xmltype ON purchase_orders_xmltype(doc) INDEXTYPE IS CTXSYS.CONTEXT;
XMLType
表がある場合は、例12-31に示すように、オブジェクト構文を使用してCONTEXT
索引を作成する必要があります。
例12-31 XMLType表の単純なCONTEXT索引
CREATE INDEX po_index_xmltype_table ON purchase_orders_xmltype_table (OBJECT_VALUE) INDEXTYPE IS CTXSYS.CONTEXT;
例12-32に示すように、表を問合せできます。
例12-32 XMLType表のCONTAINS問合せ
SELECT XMLCast(XMLQuery( 'declare namespace ora = "http://xmlns.oracle.com/xdb"; (: :) $p/purchaseOrder/@orderDate' PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT) AS DATE) "Order Date" FROM purchase_orders_xmltype_table po WHERE contains(po.OBJECT_VALUE, 'electric INPATH (/purchaseOrder//comment)') > 0;
Oracle 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
索引の作成時にそのように選択する必要があります。例12-33では1行戻されます。これは、text_query
内の"HURRY
"が、デフォルトの大/小文字が区別されない索引が設定されたpurchaseOrder
内の"Hurry
"と一致するためです。
例12-33 CONTAINS: デフォルトの大/小文字を区別しない一致
SELECT id FROM purchase_orders WHERE contains(doc, 'HURRY INPATH (/purchaseOrder/comment)') > 0;
例12-34では、属性mixed_case
がTRUE
に設定された新しいレクサー・プリファレンスmy_lexer
が作成されます。この例では、printjoin文字も"-
"、"!
"、",
"に設定されます。CONTEXT
索引の作成およびポリシーの作成に同じプリファレンスを使用できます。
関連項目: レクサー属性の完全なリストは、『Oracle Textリファレンス』を参照してください。 |
例12-34 大/小文字混合のプリファレンスの作成
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; /
例12-35では、新しいmy_lexer
レクサー・プレファレンスを使用してCONTEXT
索引が作成されます。ここではプレファレンスpreference-case-mixed
が使用されます。
例12-35 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');
例12-33では、text_query
内の"HURRY
"がpurchaseOrder
内の"Hurry
"と一致しないため、行は戻されません。例12-36では、text_query
の"Hurry
"がpurchaseOrder
内のワード"Hurry
"と正確に一致するため、1行戻されます。
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リファレンス』を参照してください。 |
セクション・グループを索引と関連付けるには、例12-37のように、PARAMETERS
文字列にsection group <section group name>
を追加します。
関数ora:contains
は、SQL/XML関数XMLQuery
、XMLTable
およびXMLExists
のXQuery式の引数で使用するために、Oracleによって定義されたXQuery(XPath)関数です。
ora:contains
を使用する場合は、Oracle XML DB名前空間xmlns:ora="http://xmlns.oracle.com/xdb"
に接頭辞ora
をマップする名前空間宣言も指定する必要があります。
関数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
(!
)
例12-4に、ブール演算子と$
(ステミング)を任意に組み合せた全文検索を示します。
関連項目:
|
一致規則は、ポリシー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文書の一部のみを戻す場合は、関数XMLQuery
を使用してノード順序を投影し、その結果にXMLCast
を適用してノードのスカラー値を投影します。
例12-38では、ワード"lawn
"を含むcomment
がある各発注書のorderDate
が戻されます。
例12-38 XMLQueryおよびXMLExistsでのora:containsの使用
SELECT XMLCast(XMLQuery( 'declare namespace ora = "http://xmlns.oracle.com/xdb"; (: :) $d/purchaseOrder/@orderDate' PASSING doc AS "d" RETURNING CONTENT) AS DATE) "Order date" FROM purchase_orders_xmltype WHERE XMLExists( 'declare namespace ora = "http://xmlns.oracle.com/xdb"; (: :) $d/purchaseOrder/comment [ora:contains(text(), "($lawns AND wild) OR flamingo") > 0]' PASSING doc AS "d");
関数XMLExists
は、ワード"lawn
"の入ったcomment
がpurchaseOrder
要素に含まれる行(文書)に結果を限定します。その後、関数XMLQuery
が、それらのpurchaseOrder
要素から属性orderDate
の値を戻します。関数XMLCast
は、この結果をSQL DATE
値としてキャストします。
//comment
が抽出されていれば、WHERE
句と一致したコメントのみではなく、両方のコメントがサンプル・ドキュメントから戻されます。
列のCONTEXT
索引によって、その列に対するcontains
問合せのセマンティクスが決まります。ora:contains
はサポートしている索引に依存しないため、ora:contains
問合せを実行するときは、同様の選択肢を多数提供する他の方法を検索する必要があります。ポリシーは、ora:contains
問合せに関連付けることができるプリファレンスの集合であり、索引付けに関する選択でcontains
ユーザーに提供される内容と同じようなセマンティクス制御を提供します。
Oracle 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
のパラメータとして使用されます。
例12-39では、空のストップワード・リストを持つポリシーが作成されます。
例12-39 ora:containsで使用するポリシーの作成
BEGIN
CTX_DDL.create_policy(POLICY_NAME => 'my_nostopwords_policy',
STOPLIST => 'CTXSYS.EMPTY_STOPLIST');
END;
/
わかりやすいように、このポリシーは空のストップリストで構成されており、所有者はユーザーCTXSYS
です。このポリシーに組み込む新しいストップリストを作成するか、またはCONTEXT
索引用に作成したストップリスト(またはレクサー)定義を再利用できます。
最も一般的なワード(ストップワード)も含めてすべてのワードを検索するには、ora:contains
式でこのポリシーを参照してください。例12-40では、"is
"はデフォルトでストップワードであり問合せできないため、コメントは戻されません。
例12-40 ora:containsを使用したストップワードの検索
SELECT id FROM purchase_orders_xmltype
WHERE XMLExists(
'declare namespace ora = "http://xmlns.oracle.com/xdb"; (: :)
$d/purchaseOrder/comment[ora:contains(text(), "is") > 0]'
PASSING doc AS "d");
例12-41では、空のストップワード・リストを指定するために、例12-39で作成されたポリシーが使用されます。この問合せでは"is
"が検索され、コメントが1つ戻されます。
例12-41 ora:containsおよびポリシーmy_nostopwords_policyを使用したストップワードの検索
SELECT id FROM purchase_orders_xmltype
WHERE XMLExists(
'declare namespace ora = "http://xmlns.oracle.com/xdb"; (: :)
$d/purchaseOrder/comment
[ora:contains(text(), "is", "MY_NOSTOPWORDS_POLICY") > 0]'
PASSING doc AS "d");
例12-41では、ポリシーmy_nostopwords_policy
を使用します。例12-39では、このポリシーの名前は暗黙的にすべて大文字になります。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
問合せで、任意のポリシーを使用できます。
例12-42では1行戻されます。これは、text_query
内の"HURRY
"が、デフォルトの大/小文字が区別されない索引が設定されたpurchaseOrder
内の"Hurry
"と一致するためです。
例12-42 ora:contains、デフォルトの大/小文字の区別
SELECT id FROM purchase_orders_xmltype WHERE XMLExists( 'declare namespace ora = "http://xmlns.oracle.com/xdb"; (: :) $d/purchaseOrder/comment[ora:contains(text(), "HURRY") > 0]' PASSING doc AS "d");
例12-43では、属性mixed_case
がTRUE
に設定された新しいレクサー・プリファレンスmy_lexer
が作成されます。この例では、printjoin
文字も"-
"、"!
"、",
"に設定されます。CONTEXT
索引の作成およびポリシーの作成に同じプリファレンスを使用できます。
関連項目: レクサー属性の完全なリストは、『Oracle Textリファレンス』を参照してください。 |
例12-43 大/小文字混合のプリファレンスの作成
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; /
例12-44では、新規ポリシーmy_policy
が作成され、レクサーのみが指定されます。他のプリファレンスはすべてデフォルトに設定されます。例12-44では、preference-case-mixed
が使用されます。
例12-44 大/小文字混合の(大/小文字が区別されない)ポリシーの作成
BEGIN CTX_DDL.create_policy(POLICY_NAME => 'my_policy', LEXER => 'my_lexer'); END; /
例12-45では、問合せで新規ポリシーが使用されます。text_query
内の"HURRY
"はpurchaseOrder
内の"Hurry
"と一致しないため、行は戻されません。
例12-45 ora:contains、大/小文字の区別(1)
SELECT id FROM purchase_orders_xmltype WHERE XMLExists( 'declare namespace ora = "http://xmlns.oracle.com/xdb"; (: :) $d/purchaseOrder/comment [ora:contains(text(), "HURRY", "my_policy") > 0]' PASSING doc AS "d");
例12-46では、text_query
の"Hurry
"がcomment
要素内のテキスト"Hurry
"と正確に一致するため、1行戻されます。
ora:contains
のポリシーの引数はオプションです。省略した場合、問合せではデフォルトのポリシーCTXSYS.DEFAULT_POLICY_ORACONTAINS
が使用されます。
ora:contains
で使用するポリシーを作成するときは、すべてのプリファレンスを指定する必要はありません。たとえば、例12-44では、レクサー・プリファレンスのみが指定されていました。指定されないプリファレンスについては、CREATE_POLICY
によって次のデフォルトのプリファレンスが使用されます。
CTXSYS.DEFAULT_LEXER
CTXSYS.DEFAULT_STOPLIST
CTXSYS.DEFAULT_ WORDLIST
ポリシーの作成では、CONTEXT
索引の作成が索引メタデータのコピー・セマンティクスに従うのと同様に、プリファレンスとその属性のコピー・セマンティクスに従います。
ora:contains
のXPath関数は、サポートしている索引に依存しません。ora:contains
は非常に柔軟性があります。しかし、索引のない大量のデータを検索する場合、大量のリソースを消費することもあります。この項では、XPath関数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
で処理される行数が最小化されます。
例12-47では、実行計画からわかるように、表内の各行が検査(全表スキャン)されます。この例で、ora:contains
は各行に対して評価されます。
例12-47 大規模な表のora:contains
SELECT id FROM purchase_orders_xmltype_big WHERE XMLExists( 'declare namespace ora = "http://xmlns.oracle.com/xdb"; (: :) $d/purchaseOrder/comment[ora:contains(text(), "constitution") > 0]' PASSING doc AS "d");
Execution Plan ------------------------------------------------------------------------------------------------ | Id | Operation | Name |Rows|Bytes|Cost(%CPU)| Time| ------------------------------------------------------------------------------------------------ | 0| SELECT STATEMENT | | 32|64480|686(38)|00:00:09| |* 1| FILTER | | | | | | | 2|TABLE ACCESS FULL |PURCHASE_ORDERS_XMLTYPE_BIG|1161|2284K| 140(3)|00:00:02| |* 3|COLLECTION ITERATOR PICKLER FETCH| XMLSEQUENCEFROMXMLTYPE | | | | | ------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter( EXISTS (SELECT 0 FROM TABLE() "KOKBF$" WHERE SYS_XMLCONTAINS(SYS_XQ_UPKXML2SQL(SYS_XQEXVAL(SYS_XQEXTRACT(SYS_XQCON2SEQ(VALUE(KOKBF$)), '/comment/text()'),1,50),50,1,0),'constitution')>0)) 3 - filter(SYS_XMLCONTAINS(SYS_XQ_UPKXML2SQL(SYS_XQEXVAL(SYS_XQEXTRACT(SYS_XQCON2SEQ(VALUE(KOKBF$)), '/comment/text()'),1,50),50,1,0),'constitution')>0) Note ----- - dynamic sampling used for this statement
例12-48のように、列id
に対して索引を作成し、例12-49のように、選択性の高い述語id
を問合せに追加すると、実行計画に示すように、索引id
によって実行処理が起動されます。関数ora:contains
は、id
が5未満の行でのみ実行されます。
例12-49 大規模な表のora:contains(追加の述語を使用)
SELECT id FROM purchase_orders_xmltype_big
WHERE XMLExists(
'declare namespace ora = "http://xmlns.oracle.com/xdb"; (: :)
$d/purchaseOrder/comment[ora:contains(text(), "constitution") > 0]'
PASSING doc AS "d")
AND id > 5;
Execution Plan ----------------------------------------------------------------------------------------------- | Id | Operation | Name |Rows| Bytes |Cost(%CPU)| Time| ----------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 2015 |8 (13)|00:00:01| |* 1 | TABLE ACCESS BY INDEX ROWID|PURCHASE_ORDERS_XMLTYPE_BIG| 1 | 2015 |8 (13)|00:00:01| |* 2 | INDEX RANGE SCAN |ID_INDEX | 10 | |2 (0)|00:00:01| ----------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(EXISTSNODE(SYS_MAKEXML("PURCHASE_ORDERS_XMLTYPE_BIG"."SYS_NC00003$ "),'/purchaseOrder/items/item/comment[ora:contains(text(), "constitution") > 0]','xmlns:ora="http://xmlns.oracle.com/xdb"')=1) 2 - access("ID">5) Note ----- - dynamic sampling used for this statement
Oracle Databaseでは、XPath式を使用する問合せを最適化することがあります。このXPathリライトは、問合せの最適化の一部として自動的に行われます。
Oracle XQuery関数ora:contains
はサポートしている索引に依存しませんが、XPathリライトが行われる際には多くの場合、高いパフォーマンスを得るためにora:contains
は既存のCONTEXT
索引を使用します。
関連項目:
|
例12-50 ora:containsでの"electric"の検索
SELECT id FROM purchase_orders_xmltype WHERE XMLExists( 'declare namespace ora = "http://xmlns.oracle.com/xdb"; (: :) $d/purchaseOrder/items/item/comment [ora:contains(text(), "electric") > 0]' PASSING doc AS "d");
例12-50のXPath式の単純評価では、列doc
の各セルがその式と一致しているかどうかをテストします。
しかし、doc
がXML Schemaに基づいており、purchaseOrder
文書がオブジェクト・リレーショナル表に物理的に格納されている場合は、列comment
(存在する場合)に直接アクセスし、そこで各セルが"electric
"と一致しているかどうかをテストするほうが効率的です。
ora:contains
の最初の引数が単一のリレーショナル列にマップされている場合、完全なXPath式をXML文書全体に適用するかわりに、ora:contains
をその列に適用することができます。この結果、索引が含まれていない場合でも、問合せのパフォーマンスが大幅に向上します。
ora:contains
をCONTEXT
索引を持つ列にマップするテキスト・ノードまたは属性とともに使用している場合、その索引を基礎となる列のデータに適用することがあります。CONTEXT
索引をオブジェクト・リレーショナルXMLType
データとともに使用するには、次の両方の条件を満たす必要があります。
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
です。
最後に、CONTEXT
索引は通常非同期です。ワード"dog
"が含まれる新しい文書を追加した場合にCONTEXT
索引を同期化しないと、"dog
"のcontains
問合せでその文書が戻されません。しかし、同じデータに対するora:contains
問合せでは戻されます。ora:contains
とリライトされたcontains
で常に同じ結果が戻されるようにするには、PARAMETERS
文字列にTRANSACTIONAL
キーワードを指定してCONTEXT
索引を作成します。
関連項目: パラメータTRANSACTIONAL を指定してALTER INDEX を使用してトランザクション型のCONTEXT 索引を作成する方法については、『Oracle Textリファレンス』を参照してください |
XMLQuery
、XMLTable
またはXMLExists
を使用した問合せ。XPathにはora:contains
が含まれ、ora:contains
ポリシーがCONTEXT
索引の索引に関する選択内容と正確に一致し、次のいずれかの条件が当てはまる場合、XPathリライト対象とみなすことができます。
XMLデータはobject-relationallyに格納されます。最初のora:contains
引数(input_text
)が、親ノードが単一のリレーショナル列にマップされている単一のテキスト・ノードであるか、または単一のリレーショナル列にマップされている属性である場合。その列には、トランザクション型のCONTEXT
索引があります。
XMLデータがXMLIndex
索引によって索引付けされたバイナリXMLで、非構造化XMLIndex
コンポーネントのパス表VALUE
列または構造化XMLIndex
コンポーネントのスカラー値列にCONTEXT
索引があります。
CONTEXT
索引が非トランザクション型の場合は、XQuery拡張式プラグマora:use_text_index
を使用して、CONTEXT
索引の使用を強制する必要もあります。例12-51に、これを示します。
例12-51 XQueryプラグマora:use_text_indexをora:containsとともに使用する
CREATE INDEX po_otext_ix ON my_path_table (VALUE) INDEXTYPE IS CTXSYS.CONTEXT; EXPLAIN PLAN FOR SELECT DISTINCT XMLCast(XMLQuery('$p/PurchaseOrder/ShippingInstructions/address' PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT) AS VARCHAR2(256)) "Address" FROM po_binxml po WHERE XMLExists( '$p/PurchaseOrder/ShippingInstructions/address [(# ora:use_text_index #) {ora:contains(., "$(Fortieth)")} > 0]' PASSING po.OBJECT_VALUE AS "p"); ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes|Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 3046 | 12 (17)|00:00:01| | 1 | SORT GROUP BY | | 1 | 3524 | | | |* 2 | TABLE ACCESS BY INDEX ROWID BATCHED| MY_PATH_TABLE | 2 | 7048 | 3 (0)|00:00:01| |* 3 | INDEX RANGE SCAN | SYS89559_PO_XMLINDE_PIKEY_IX | 1 | | 2 (0)|00:00:01| | 4 | HASH UNIQUE | | 1 | 3046 | 12 (17)|00:00:01| | 5 | NESTED LOOPS | | 1 | 3046 | 8 (13)|00:00:01| | 6 | SORT UNIQUE | | 1 | 3034 | 6 (0)|00:00:01| |* 7 | TABLE ACCESS BY INDEX ROWID | MY_PATH_TABLE | 1 | 3034 | 6 (0)|00:00:01| |* 8 | DOMAIN INDEX | PO_OTEXT_IX | | | 4 (0)|00:00:01| | 9 | TABLE ACCESS BY USER ROWID | PO_BINXML | 1 | 12 | 1 (0)|00:00:01| ---------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter(SYS_XMLI_LOC_ISNODE("SYS_P3"."LOCATOR")=1) 3 - access("SYS_P3"."RID"=:B1 AND "SYS_P3"."PATHID"=HEXTORAW('6F7F')) 7 - filter("SYS_P1"."PATHID"=HEXTORAW('6F7F') AND SYS_XMLI_LOC_ISNODE("SYS_P1"."LOCATOR")=1) 8 - access("CTXSYS"."CONTAINS"("SYS_P1"."VALUE",'$(Fortieth)')>0) Note ----- - dynamic sampling used for this statement (level=2) 28 rows selected.
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 ::= "_"
この項の内容は次のとおりです。
例12-52 発注書の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>
例12-53 表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;
例12-54 表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;
例12-55 表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;
例12-56 全文検索する発注書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="en"> 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>