1.7 SEM_MATCH表関数を使用したRDFデータの問合せ

RDFデータを問い合せるには、SEM_MATCH表関数を使用します。

ノート:

SEM_MATCH表関数は、Oracle Autonomous Databaseサーバーレス・デプロイメントでOracle JVMが有効になっている場合にのみサポートされます。Oracle JVMを有効にするには、Oracle Autonomous Databaseサーバーレスの使用Oracle Javaの使用で詳細を参照してください。

この関数には、次の属性が含まれます。

SEM_MATCH(
  query         VARCHAR2,
  models        SEM_MODELS,
  rulebases     SEM_RULEBASES,
  aliases       SEM_ALIASES,
  filter        VARCHAR2,
  index_status  VARCHAR2    DEFAULT NULL,
  options       VARCHAR2    DEFAULT NULL,
  graphs        SEM_GRAPHS  DEFAULT NULL,
  named_graphs  SEM_GRAPHS  DEFAULT NULL,
  network_owner VARCHAR2    DEFAULT NULL,
  network_name  VARCHAR2    DEFAULT NULL
 ) RETURN ANYDATASET;

queryおよびmodels属性は必須です。その他の属性はオプションです(それぞれNULL値を指定できます)。

query属性は、通常は変数が含まれる1つ以上のトリプル・パターンを備えた文字列リテラル(または文字列リテラルを連結したもの)です。(query属性には、バインド変数またはバインド変数を含む式を指定することはできません。)トリプル・パターンは、ピリオドで囲まれた3つのアトムです。各アトムには、変数(?xなど)、デフォルトの名前空間およびaliases属性の値に基づいて拡張された修飾名(rdf:type)、または完全なURI (<http://www.example.org/family/Male>など)を指定できます。また、3番目のアトムには、数値リテラル(3.14など)、プレーン・リテラル("Herman"など)、言語タグ付きのプレーン・リテラル("Herman"@enなど)または型付きリテラル("123"^^xsd:intなど)を指定できます。

たとえば、次のquery属性では、3つのトリプル・パターンを使用して祖父(祖父母の男性の方)とその孫の身長を検索します。

'SELECT * WHERE { ?x :grandParentOf ?y . ?x rdf:type :Male . ?y :height ?h }'

models属性では、使用するRDFグラフを指定します。そのデータ型は、TABLE OF VARCHAR2(25)という定義を持つSEM_MODELSです。RDFグラフ・コレクションを問い合せる場合は、RDFグラフ・コレクションの名前のみを指定し、他のRDFグラフは指定しません。(RDFグラフ・コレクションについては、「RDFグラフ・コレクション」を参照してください。)

rulebases属性では、問合せに適用するルールが含まれる1つ以上のルールベースを指定します。そのデータ型はSEM_RULEBASESで、TABLE OF VARCHAR2(25)という定義を持っています。RDFグラフ・コレクションを問い合せる場合、この属性はnullである必要があります。

aliases属性では、デフォルトの名前空間以外に、問合せパターンの修飾名の拡張に使用する1つ以上の名前空間を指定します。そのデータ型は、TABLE OF SEM_ALIASという定義を持つSEM_ALIASESです。各SEM_ALIAS要素により、名前空間IDと名前空間値が識別されます。SEM_ALIASデータ型は、(namespace_id VARCHAR2(30), namespace_val VARCHAR2(4000))という定義を持ちます。

SEM_MATCH表関数とSEM_CONTAINSおよびSEM_RELATED演算子では、次のデフォルトの名前空間(namespace_id属性とnamespace_val属性)が使用されます。

('ogc', 'http://www.opengis.net/ont/geosparql#')
('ogcf', 'http://www.opengis.net/def/function/geosparql/')
('ogcgml', 'http://www.opengis.net/ont/gml#')
('ogcsf', 'http://www.opengis.net/ont/sf#')
('orardf', 'http://xmlns.oracle.com/rdf/')
('orageo', 'http://xmlns.oracle.com/rdf/geo/')
('owl',    'http://www.w3.org/2002/07/owl#')
('rdf',    'http://www.w3.org/1999/02/22-rdf-syntax-ns#')
('rdfs',   'http://www.w3.org/2000/01/rdf-schema#')
('xsd',    'http://www.w3.org/2001/XMLSchema#')

これらのデフォルトを上書きするには、aliases属性でnamespace_id値および異なるnamespace_val値を指定します。

filter属性では、追加の選択基準を指定します。この属性がNULLではない場合、WHEREキーワードのないWHERE句の形式で文字列を指定する必要があります。たとえば、この項で前に示したトリプル・パターンの例で'(h >= ''6'')'と指定すると、身長が6以上である祖父の孫に検索結果を絞り込めます。

ノート:

filter属性を使用するかわりに、できるかぎり問合せパターン内でFILTERキーワードを使用してください(「グラフ・パターン: 中カッコの構文とOPTIONAL、FILTER、UNIONおよびGRAPHキーワードのサポート」を参照)。FILTERキーワードを使用すると、内部が最適化されるため、パフォーマンスが向上する傾向があります。ただし、FILTERキーワードで表現できないSQL構成要素が必要な場合は、filter引数が便利です。

index_status属性では、関連する推論グラフに有効なステータスがない場合でも、RDFデータを問い合せることができます。(RDFグラフ・コレクションを問い合せる場合、この属性は、RDFグラフ・コレクションに関連付けられている推論グラフを参照します。)この属性がNULLの場合、推論グラフに有効なステータスがない場合、問合せによりエラーが戻されます。この属性がNULLではない場合、文字列INCOMPLETEまたはINVALIDを指定する必要があります。異なるindex_status値を持つ問合せの動作については、「不完全な伴意または無効な伴意を使用した問合せの実行」の説明を参照してください。

options属性は、問合せの結果に影響を与えることのできるオプションを指定します。オプションは、キーワードと値のペアで表記します。次のオプションがサポートされています。

  • ALL_AJ_HASHALL_AJ_MERGEおよびALL_BGP_NLは、グローバル問合せオプティマイザ・ヒントです。これにより、指定された結合タイプが、NOT EXISTS演算子およびMINUS演算子に対するすべての反結合で使用されることになります。

  • ALL_BGP_HASHおよびALL_BGP_NLは、すべてのBGP間の結合(ルートBGPとOPTIONAL BGPの間の結合など)で指定の結合タイプを使用する必要があることを示すグローバル問合せオプティマイザ・ヒントです。(BGPは、basic graph patternの略語です)。W3C勧告の「SPARQL Query Language for RDF」の説明では、「SPARQLのグラフ・パターン照合は、基本グラフ・パターンの照合結果を組み合せるという観点で定義されています。単一の基本グラフ・パターンは、フィルタの割込がある一連のトリプル・パターンによって形成されます。任意のグラフ・パターンによって、基本グラフ・パターンが終了します」と記述されています。

    BGP_JOIN(USE_NL)およびBGP_JOIN(USE_HASH) HINT0問合せオプティマイザ・ヒントを使用して、結合タイプをきめ細かく制御できます。

    例1-17に、SEM_MATCH問合せで使用されるALL_BGP_HASHオプションを示します。

  • AUTO_HINTS=Tは、選択されていないSPARQL問合せのUSE_HASHヒントを自動的に検出して生成します。

  • ALL_LINK_HASHおよびALL_LINK_NLは、すべてのRDF_LINK$結合(BGP内のトリプル・パターン間のすべての結合)の結合タイプを指定するグローバル問合せオプティマイザ・ヒントです。ALL_LINK_HASHALL_LINK_NLも、きめ細かい制御のためにHINT0問合せオプティマイザ内で使用できます。

  • ALL_MAX_PP_DEPTH(n)はグローバル問合せオプティマイザ・ヒントです。これは、プロパティ・パス演算子*と+の評価に使用する最大深度を設定します。デフォルト値は10です。MAX_PP_DEPTH(n) HINT0ヒントは、さらに細かく最大深度を指定するために使用できます。

  • ALL_NO_MERGEはグローバル問合せオプティマイザ・ヒントであり、これにより、SPARQL問合せ用の生成されたSQLにおいて各副問合せにNO_MERGEが追加されます。このヒントは、SPARQL問合せ内の選択的副問合せがSPARQL問合せの他の部分とマージされないようにするために使用します。

  • ALL_ORDEREDは、問合せ内の各BGPのトリプル・パターンが順番に評価される必要があることを指定するグローバル問合せオプティマイザ・ヒントです。

    例1-17に、SEM_MATCH問合せで使用されるALL_ORDEREDオプションを示します。

  • ALL_USE_PP_HASHおよびALL_USE_PP_NLは、プロパティ・パス表現の評価に使用する結合タイプを指定するグローバル問合せオプティマイザ・ヒントです。USE_PP_HASHおよびUSE_PP_NL HINT0ヒントは、結合タイプをさらにきめ細かく指定するために使用できます。

  • ALLOW_DUP=Tは、RDFグラフと推論データ(適用可能な場合)のUNIONではなくUNION ALLを実行する、基礎となるSQL文を生成します。このオプションを使用した場合、結果セットに追加の行(重複するトリプル)が生成されるために、それに応じてアプリケーション・ロジックを調整する必要があることがあります。このオプションを指定しない場合、すべてのRDFグラフと推論データにわたって、重複するトリプルは自動的に削除され、マージされたRDFグラフの設定済セマンティクが保持されます。ただし、重複するトリプルを削除すると、問合せの処理時間が長くなります。一般に、1つのSEM_MATCH問合せに複数のRDFグラフが関連している場合、'ALLOW_DUP=T'を指定することで、パフォーマンスが大幅に向上します。

    RDFグラフ・コレクションを問い合せる場合、ALLOW_DUP=Tを指定すると、SEMV_vm_nameビューが問い合せられます。指定しない場合、SEMU_vm_nameビューが問い合せられます。

  • ALLOW_PP_DUP=Tは、+および*プロパティ・パス問合せで結果の重複を許可します。結果の重複が認められると、最初の結果行が早く戻されます。

  • AS_OF [SCN, <SCN_VALUE>]は、指定したSCN時点におけるRDFネットワークの状態の問合せに、フラッシュバック問合せ使用しなければならないことを示すものです。ここで、<SCN_VALUE>は、有効なシステム変更番号です。

  • AS_OF [TIMESTAMP, <TIMESTAMP_VALUE>]は、指定したタイムスタンプ時点におけるRDFネットワークの状態の問合せに、フラッシュバック問合せ使用しなければならないことを示すものです。ここで、<TIMESTAMP_VALUE>は、「YYYY/MM/DD HH24:MI:SS.FF」の形式を持つ有効なタイムスタンプ文字列です。

  • CLOB_AGG_SUPPORT=Tは、集計(MIN、MAX、GROUP_CONCAT、SAMPLE)でCLOB値のサポートを有効にします。CLOBサポートを有効化するとパフォーマンスが大幅に低下することに注意してください。

  • CLOB_EXP_SUPPORT=Tは、一部の組込みSPARQL関数でのCLOB値のサポートを有効にします。CLOBサポートを有効化するとパフォーマンスが大幅に低下することに注意してください。

  • CONSTRUCT_STRICT=Tは、SPARQL CONSTRUCTまたはSPARQL DESCRIBE構文の問合せの結果から無効なRDFトリプルを消去します。主語の位置にリテラルがあるRDFトリプル、または述語の位置にリテラルか空白ノードがあるRDFトリプルは無効とみなされます。

  • CONSTRUCT_UNIQUE=Tは、SPARQL CONSTRUCTまたはSPARQL DESCRIBE構文の問合せの結果から重複RDFトリプルを消去します。

  • DISABLE_IM_VIRTUAL_COLは、問合せコンパイラがインメモリー仮想列を使用しないことを指定します。

  • DISABLE_MVIEWは、問合せコンパイラがマテリアライズド・ビューを使用しないように指定します。

  • DISABLE_NULL_EXPR_JOINは、すべてのSELECT式について、NULLでない出力を生成するものとして処理するよう、コンパイラに対し指定するものです。

  • DISABLE_SAMEAS_BLOOMは、owl:sameAsトリプルが結合されている場合に問合せコンパイラがブルーム・フィルタを使用しないことを指定します。(詳細は、『Oracle Database SQLチューニング・ガイド』のブルーム・フィルタの説明を参照してください。)

  • DO_UNESCAPE=Tは、返却列のvar、var$_PREFIX、var$_SUFFIX、var$RDFCLOB、var$RDFLTYP、var$RDFLANGおよびvar$RDFTERMの文字を、W3CのN-Triples仕様(http://www.w3.org/TR/rdf-testcases/#ntriples)に従ってエスケープしません。

    SEM_APIS.ESCAPE_CLOB_TERMSEM_APIS.ESCAPE_CLOB_VALUESEM_APIS.ESCAPE_RDF_TERMSEM_APIS.ESCAPE_RDF_VALUESEM_APIS.UNESCAPE_CLOB_TERMSEM_APIS.UNESCAPE_CLOB_VALUESEM_APIS.UNESCAPE_RDF_TERMおよびSEM_APIS.UNESCAPE_RDF_VALUEのリファレンス情報も参照してください。

  • FINAL_VALUE_HASHおよびFINAL_VALUE_NLは、FILTER句で使用されていない問合せ変数の字句の値を取得するために、使用する必要がある結合メソッドを指定するグローバル問合せオプティマイザ・ヒントです。

  • GRAPH_MATCH_UNNAMED=Tを使用すると、名前なしトリプル(null G_ID)をGRAPH句内で照合可能になります。つまり、グラフが等しい場合、またはグラフの一方または両方がnullの場合、2つのトリプルはグラフ結合条件を満たすことになります。データセットに名前なしTBOXトリプルまたは名前なし伴意トリプルが含まれている場合に、このオプションが役立つことがあります。

  • HINT0={<hint-string>}(発音および表記は"hint (ヒント)"と数字のゼロ)は、1つ以上のキーワードを、問合せの実行計画および結果に影響を与えるヒントとともに指定します。概念的には、n個のトリプル・パターンを持つグラフ・パターンで、m個の異なる変数を参照すると、(n+m)方向の結合が発生します。つまり、ターゲットRDFgraphsおよび対応する推論グラフのn方向の自己結合が発生し、m個の変数の値を検索するために、RDF_VALUE$とのm個の結合が発生します。ヒント指定は、問合せ実行で使用される結合順序と結合タイプに影響を与えます。

    ヒント指定<hint-string>では、キーワードを使用します。一部のキーワードは、問合せで使用される各トリプル・パターンおよび変数ごとに、一連(一群)の別名または参照で構成されるパラメータを持ちます。トリプル・パターンの別名の形式は、tiです。iは、問合せ内のトリプル・パターンの0から始まる序数です。たとえば、問合せ内の最初のトリプル・パターンの別名はt0で、2番目のトリプル・パターンの別名はt1、...のようになります。問合せで使用される変数の別名は単に、その変数の名前です。このため、ヒント指定では、グラフ・パターンで使用される変数?xの別名として?xが使用されます。

    問合せの実行計画に影響を与えるために使用するヒントには、LEADING(<sequence of aliases>)、USE_NL(<set of aliases>)、USE_HASH(<set of aliases>)およびINDEX(<alias> <index_name>)があります。これらのヒントの書式と基本的な意味は、SQL文のヒントと同じです(『Oracle Database SQL言語リファレンス』を参照)。

    例1-12に、SEM_MATCH問合せで使用されるHINT0オプションを示します。

  • HTTP_METHOD=POST_PARは、URLエンコーディング・パラメータ・パスを含むHTTP POSTメソッドをSERVICEリクエストに対して使用する必要があると指定します。リクエストのデフォルト・オプションはHTTP GETメソッドです。SPARQLプロトコルの詳細は、http://www.w3.org/TR/2013/REC-sparql11-protocol-20130321/#protocolを参照してください。

  • INF_ONLY=Tは、指定されたRDFグラフおよびルールベースの伴意グラフのみを問い合せます。

  • OVERLOADED_NL=Tは、過負荷のSERVICE句に対し、ネストした手続き型ループによる実行が必要であることを指定するものです。

  • PLUS_RDFT=Tは、SPARQL SELECT構文(「SELECT句の式」を参照)で、射影される各問合せ変数のvar$RDFTERM CLOB列を追加で返す場合に使用できます。この列の値は、SEM_APIS.COMPOSE_RDF_TERM(var, var$RDFVTYP, var$RDFLTYP, var$RDFLANG, var$RDFCLOB)の結果と同等です。このオプションを使用する場合、各変数varの戻り列は、varvar$RDFVID、var$_PREFIX、var$_SUFFIX、var$RDFVTYP、var$RDFCLOB、var$RDFLTYP、var$RDFLANGおよびvar$RDFTERMになります。

  • PLUS_RDFT=VCは、SPARQL SELECT構文(「SELECT句の式」を参照)で、射影される問合せ変数ごとにvar$RDFTERM VARCHAR2(NETWORK_MAX_STRING_SIZE)列を追加で返すために使用できます。この列の値は、SEM_APIS.COMPOSE_RDF_TERM(var, var$RDFVTYP, var$RDFLTYP, var$RDFLANG)の結果と同等です。このオプションを使用する場合、各変数varの戻り列は、var、var$RDFVID、var$_PREFIX、var$_SUFFIX、var$RDFVTYP、var$RDFCLOB、var$RDFLTYP、var$RDFLANGおよびvar$RDFTERMになります。なお、RDFネットワークでNETWORK_STORAGE_FORM=UNESCが使用されている場合、var$RDFTERM内の特殊文字は自動的にエスケープされて、構文的に有効なRDF値が形成されます。これによって、var$RDFTERMのサイズがNETWORK_MAX_STRING_SIZEを超える可能性があります。そのため、そのような場合にはエラーが発生します。このエラーを回避するには、かわりにPLUS_RDFT=Tを使用してCLOBを返します。

  • PROJ_EXACT_VALUES=Tは、関数から返される値と、値割当て文で使用される定数値の正規化を無効にします。これらの値はデフォルトでは正規化されます。

  • SERVICE_CLOB=Fは、サービスをコールするときにvar$RDFCLOBの列値を保存するかわりに値にnullを設定します。CLOBデータがアプリケーションで必要ない場合、このオプションを使用してCLOB処理を省略するとパフォーマンスを向上させることができます。

  • SERVICE_ESCAPE=Fは、SPARQL SERVICEコールから返されるRDFリテラル値の文字のエスケープを無効にします。RDFリテラル値はデフォルトではエスケープされます。文字のエスケープがアプリケーションに関係ない場合は、文字のエスケープを無効にするとパフォーマンスを向上させることができます。

  • SERVICE_JPDWN=Tは、SPARQL SERVICEでネステッド・ループ結合を使用するための問合せオプティマイザ・ヒントです。例1-73に、SEM_MATCH問合せで使用されるSERVICE_JPDWN=Tオプションを示します。

  • SERVICE_PROXY=<proxy-string>は、http接続を実行するときに使用されるプロキシ・アドレスを設定します。指定したproxy-stringがSERVICE問合せで使用されます。例1-76に、プロキシ・アドレスを含むSEM_MATCH問合せを示します。

  • STRICT_AGG_CARD=Tは、一致しなかったグラフ・パターンを含む集計問合せで、SPARQLセマンティク(1つのnull行)をSQLセマンティク(0行)のかわりに使用します。このオプションによってパフォーマンスがわずかに低下します。

  • STRICT_DEFAULT=Tは、データセット情報が指定されない場合に、デフォルト・グラフを名前なしトリプルに制限します。

graphs属性は、SEM_MATCH問合せ用のデフォルト・グラフの構築元となる、名前付きグラフのセットを指定します。そのデータ型はSEM_GRAPHSで、TABLE OF VARCHAR2(4000)という定義を持ちます。この属性のデフォルト値はNULLです。graphsNULLの場合、models属性で指定されたRDFグラフ・セット内のすべてのデフォルト・グラフのすべての和集合が、デフォルト・グラフとして使用されます。

named_graphs属性は、GRAPH句で照合可能な名前付きグラフのセットを指定します。そのデータ型はSEM_GRAPHSで、TABLE OF VARCHAR2(4000)という定義を持ちます。この属性のデフォルト値はNULLです。named_graphsがNULLの場合、models属性で指定されたRDFグラフ・セット内のすべての名前付きグラフを、GRAPH句によって照合できます。

network_owner属性は、models属性で指定されたRDFグラフまたはRDFグラフ・コレクションを含むRDFネットワークを所有するスキーマを指定します。スキーマプライベートRDFネットワークを問い合せるには、この属性をnull以外にする必要があります。

network_name属性は、models属性で指定されたRDFグラフまたはグラフ・コレクションを含むRDFネットワークの名前を指定します。スキーマプライベートRDFネットワークを問い合せるには、この属性をnull以外にする必要があります。

SEM_MATCH表関数では、入力変数に応じた要素とともにANYDATASET型のオブジェクトが戻されます。次の説明において、varは問合せで使用される変数名を示します。変数varごとに、結果要素にはvarvar$RDFVID、var$_PREFIX、var$_SUFFIX、var$RDFVTYP、var$RDFCLOB、var$RDFLTYPおよびvar$RDFLANGの各属性が含まれます。

このような場合、varはその変数にバインドされた字句の値を保持し、var$RDFVIDは変数にバインドされた値のVALUE_IDを持ちます。var$_PREFIXおよびvar$_SUFFIXは、変数にバインドされた値の接頭辞接尾辞です。var$RDFVTYPは、変数にバインドされた値のタイプ(URILIT [literal]またはBLN [blank node])を示します。var$RDFCLOBは、値がロング・リテラルの場合に変数にバインドされた字句の値を持ちます。var$RDFLTYPは、リテラルがバインドされている場合にそのバインドされたリテラルのタイプを示します。var$RDFLANGは、言語タグ付きのリテラルがバインドされている場合に、そのバインドされたリテラルの言語タグを持ちます。var$RDFCLOBはCLOB型ですが、他のすべての属性はVARCHAR2型です。

リテラル値または空白ノードの場合、接頭辞は値そのものになり、接尾辞はNULLになります。URI値の場合、接頭辞は値の一番右側にある/(スラッシュ)、#(ポンド)または:(コロン)の3つのいずれかの文字から左側の部分となり、接尾辞はそれより右側の値部分となります。たとえば、URI値http://www.example.org/family/grandParentOfの場合、接頭辞はhttp://www.example.org/family/、接尾辞はgrandParentOfとなります。

変数値の列とともに、SPARQL SELECT構文を使用するSEM_MATCH問合せは、追加のNUMBER列であるSEM$ROWNUMを戻します(この列は、SPARQL ORDER BY句を含む問合せの正しい結果順序を保証するために使用できます)。

SPARQL ASK構文を使用するSEM_MATCH問合せは、列ASK、ASK$RDFVID、ASK$_PREFIX、ASK$_SUFFIX、ASK$RDFVTYP、ASK$RDFCLOB、ASK$RDFLTYP、ASK$RDFLANGおよびSEM$ROWNUMを返します。これは、1つの?ask変数を射影するSPARQL SELECT構文の問合せと同じです。

SPARQL CONSTRUCTまたはSPARQL DESCRIBE構文を使用するSEM_MATCH問合せは、問合せ結果バインディングではなくRDFトリプル・データを含む列を返します。これらの問合せは、主語、述語および目的語のコンポーネントについて値を返します。詳細は、「グラフ・パターン: SPARQL CONSTRUCT構文のサポート」を参照してください。

SEM_RELATED演算子を使用してOWLオントロジを問い合せる方法の詳細は、「セマンティク演算子を使用したリレーショナル・データの問合せ」を参照してください。

複数のRDFグラフを問い合せる、または1つ以上のRDFグラフおよび対応する推論グラフを問い合せる場合は、パフォーマンス上の利点があるため、RDFグラフ・コレクション(「RDFグラフ・コレクション」を参照)の使用を検討してください。

例1-11 SEM_MATCH表関数

例1-11では、RDFSfamily_rbの2つのルールベースによる推論を使用して、familyRDFグラフからすべての祖父(祖父母の男性の方)とその孫を選択します。(この例は、例: 家系の情報例1-130からの抜粋です。)

SELECT x$rdfterm grandfather, y$rdfterm grandchild
  FROM TABLE(SEM_MATCH(
    'PREFIX  rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
     PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
     PREFIX     : <http://www.example.org/family/>
     SELECT ?x ?y
     WHERE {?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null,  null, null,
    ' PLUS_RDFT=VC ',
    null, null,
    'RDFUSER', 'NET1'));

例1-12 SEM_MATCH表関数を使用したHINT0オプション

例1-12例1-11と同じ機能ですが、HINT0オプションが追加されています。

SELECT x$rdfterm grandfather, y$rdfterm grandchild
  FROM TABLE(SEM_MATCH(
    'PREFIX  rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
     PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
     PREFIX     : <http://www.example.org/family/>
     SELECT ?x ?y
     WHERE {?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null,  null, null,
    ' PLUS_RDFT=VC HINT0={LEADING(t0 t1) USE_NL(?x ?y)}',
    null, null,
    'RDFUSER', 'NET1'));

例1-13 SEM_MATCH表関数を使用したDISABLE_SAMEAS_BLOOMオプション

例1-12では、owl:sameAsトリプルが結合されている場合に問合せコンパイラがブルーム・フィルタを使用しないことを指定します。

SELECT select s, o
FROM table(sem_match('{ # HINT0={LEADING(t1 t0) USE_HASH(t0 t1)}
 ?s owl:sameAs ?o. ?o owl:sameAs ?s}', sem_models('M1'), null,null,null,null,
  ' DISABLE_SAMEAS_BLOOM ')) order by 1,2;

例1-14 SEM_MATCH表関数

例1-14では、Pathway/Genome BioPaxオントロジを使用して、ProteinsComplexesの両方に属するすべての化学的複合タイプを取得します。

SELECT t.r 
  FROM TABLE (SEM_MATCH ( 
      'PREFIX : <http://www.biopax.org/release1/biopax-release1.owl>
       SELECT ?r
       WHERE {
        ?r rdfs:subClassOf :Proteins .  
        ?r rdfs:subClassOf :Complexes}', 
      SEM_Models ('BioPax'), 
      SEM_Rulebases ('rdfs'), 
      NULL, NULL, NULL, '', NULL, NULL,
      'RDFUER','NET1')) t;

例1-14のとおり、SEM_MATCH表関数の検索パターンは、変数が疑問符文字(?)で始まるSPARQL構文を使用して指定します。この例の場合、変数?rは、同じ語に一致する必要があるため、ProteinsComplexesの両方のサブクラスである必要があります。

1.7.1 不完全または無効な推論グラフを使用した問合せの実行

関連する推論グラフに有効なステータスがない場合でも、SEM_MATCH表関数のindex_status属性に文字列値INCOMPLETEまたはINVALIDを指定すると、RDFデータを問い合せることができます。(推論グラフ・ステータスは、SEM_RULES_INDEX_INFOビューのSTATUS列に格納されます(「推論グラフ」を参照)。(SEM_MATCH表関数については、「SEM_MATCH表関数を使用したRDFデータの問合せ」を参照してください。)

index_status属性の値は、問合せの動作に次のように影響します。

  • 推論グラフのステータスが有効の場合、問合せ動作はindex_status属性の値に影響を受けません。

  • index_statusに値を指定しないか、NULL値を指定した場合に、推論グラフに有効なステータスがないと、問合せからエラーが返されます。

  • index_status属性に文字列INCOMPLETEを指定すると、推論グラフのステータスが不完全または有効である場合、問合せが実行されます。

  • index_status属性に文字列INVALIDを指定すると、推論グラフの実際のステータス(無効、不完全または有効)にかかわらず問合せが実行されます。

ただし、推論グラフのステータスが未完了または無効の場合、次の考慮事項が適用されます。

  • ステータスが未完了の場合、基礎となるRDFグラフに最近挿入されて推論可能になったいくつかのトリプルは、推論グラフに実際には存在しない可能性があり、したがって問合せによって戻された結果は不正確になる可能性があるため、推論グラフの内容は近似値となる可能性があります。

  • ステータスが無効の場合、基礎となるRDFグラフまたはルールベース(あるいはその両方)が最近変更されて推論不可能となったいくつかのトリプルは、推論グラフにまだ存在し、問合せによって戻される結果の正確性が影響を受ける可能性があるため、推論グラフの内容は近似値となる可能性があります。推論不可能となったトリプルが存在する可能性に加え、一部の推論可能な行が実際には推論グラフに存在しない可能性もあります。

1.7.2 グラフ・パターン: 中カッコの構文とOPTIONAL、FILTER、UNIONおよびGRAPHキーワードのサポート

SEM_MATCH表関数は、一連のトリプル・パターンを中カッコで囲むグラフ・パターンの構文を受け入れます。OPTIONAL、FILTER、UNIONまたはGRAPHキーワードが続く場合以外は、セパレータとしてピリオドが必要です。この構文では、次の操作を任意に組み合せて実行できます。

  • OPTIONAL構成要素を使用して、部分一致の場合にも結果を取得できます。

  • FILTER構成要素を使用して、ソリューションを問合せに制限するグラフ・パターンのフィルタ式を指定できます。

  • UNION構成要素を使用して、複数の代替グラフ・パターンのいずれかを一致させることができます。

  • GRAPH構成要素(「GRAPHキーワード・サポート」を参照)を使用して、グラフ・パターンの一致範囲を名前付きグラフのセットに制限できます。

算術演算子(+、-、*、/)、ブール演算子と論理連結語(||、&&、!)、および比較演算子(<、>、<=、>=、=、!=)に加えて、いくつかの組込み関数をFILTER句で使用できます。表1-14に、FILTER句で使用できる組込み関数を示します。表1-14の「説明」列で、xyおよびzは、適切な型の引数です。

表1-14 FILTER句で使用できる組込み関数

関数 説明

ABS(RDF term)

termの絶対値を戻します。termが数値以外の場合は、nullを戻します。

BNODE(literal)またはBNODE()

問合せのデータセット内のすべての空白ノード、および他の問合せでこの関数によって作成された空白ノードとは別の空白ノードを構築します。引数を指定しない形式では、すべてのコールで異なる空白ノードが構築されます。単純なリテラルを指定する形式の場合、異なる単純なリテラルに対しては異なる空白ノードが構築され、同じ単純なリテラルを使用したコールでは同じ空白ノードが構築されます。

BOUND(variable)

BOUND(x)は、xが結果でバインドされる場合(つまりnull以外の場合)はtrueを戻し、それ以外の場合はfalseを戻します。

CEIL(RDF term)

term以上の最も近い小数部分なしの数値を戻します。termが数値以外の場合は、nullを戻します。

COALESCE(term list)

エラーが発生せずに評価された引数リストの最初の要素を戻します。評価される場合は、バインドされていない変数でエラーが発生します。有効な要素が語句リストにない場合は、nullを戻します。

CONCAT(term list)

語句リスト内の文字列値を連結した結果のxsd:String値を戻します。

CONTAINS(literal, match)

文字列matchliteral内で検出された場合に、trueを戻します。それ以外の場合はfalseを戻します。

DATATYPE(literal)

DATATYPE(x)は、xのデータ型を表すURIを戻します。

DAY(argument)

引数の日部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

ENCODE_FOR_URI(literal)

literal内の予約済文字がエスケープされ、そのパーセントエンコード形式に変換される文字列を戻します。

EXISTS(pattern)

含まれているグループ・グラフ・パターンと現在のアクティブ・グラフ内の現在のバインディングを使用して、パターンが問合せデータセットと一致する場合に、trueを戻します。一致がない場合は、falseを戻します。

FLOOR(RDF term)

termを下回る、最も近い小数部分なしの数を戻します。termが数値以外の場合は、nullを戻します。

HOURS(argument)

argumentの時間部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

IF(condition, expression1, expression2)

条件を評価して、有効なブール値を取得します。trueの場合、最初の式が評価され、その値が戻されます。falseの場合、2つ目の式が使用されます。条件でエラーが発生した場合、エラーはIF文の結果として渡されます。

IRI(RDF term)

引数termの文字列表現を解決するIRIを戻します。問合せで定義されているベースIRIがある場合、IRはそれに対して解決され、結果は絶対IRIになる必要があります。

isBLANK(RDF term)

isBLANK(x)は、xが空白ノードの場合にtrueを戻し、それ以外の場合はfalseを戻します。

isIRI(RDF term)

isIRI(x)は、xがIRIの場合にtrueを戻し、それ以外の場合はfalseを戻します。

isLITERAL(RDF term)

isLiteral(x)は、xがリテラルの場合にtrueを戻し、それ以外の場合はfalseを戻します。

IsNUMERIC(RDF term)

termが数値の場合はtrueを戻し、それ以外の場合はfalseを戻します。

isURI(RDF term)

isURI(x)は、xがURIの場合にtrueを戻し、それ以外の場合はfalseを戻します。

LANG(literal)

LANG(x)は、xの言語タグをシリアライズするプレーン・リテラルを戻します。

LANGMATCHES(literal, literal)

LANGMATCHES(x、y)は、言語タグxが言語レンジyと一致する場合にtrueを戻し、それ以外の場合はfalseを戻します。

LCASE(literal)

リテラル内の各文字を対応する子文字に変換して、文字列を戻します。

MD5(literal)

ノート:

Oracle Database 21cリリース以降、MD5アルゴリズムの使用は非推奨になりました。この関数は今後のリリースでサポート対象外となるため、MD5SHAハッシュ関数のいずれかに置き換えることをお薦めします。

MD5ハッシュ関数に対応する、literalのチェックサムを戻します。

MINUTES(argument)

argumentの分部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

MONTH(argument)

argumentの月部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

NOT_EXISTS(pattern)

含まれているグループ・グラフ・パターンと現在のアクティブ・グラフ内の現在のバインディングを使用して、パターンが問合せデータセットと一致しない場合に、trueを戻します。それ以外の場合はfalseを戻します。

NOW()

問合せ実行時点の現在の時刻に対応するxsd:dateTime値を戻します。

RAND()

[0,1)のレンジ内の数値を生成します。

REGEX(string, pattern)

REGEX(x,y)は、xが正規表現yに一致する場合にtrueを戻し、それ以外の場合はfalseを戻します。サポートされる正規表現の詳細は、『Oracle Database SQL言語リファレンス』の付録「Oracleの正規表現のサポート」を参照してください。

REGEX(string, pattern, flags)

REGEX (x,y,z)は、xzに指定されたオプションを使用して正規表現yと一致する場合にtrueを戻し、それ以外の場合はfalseを戻します。使用可能なオプション: 's'はドットがすべてに一致するモード('.'は改行文字を含む任意の文字と一致)、'm'は複数行モード('^'は任意の行の先頭と一致し、'$'は任意の行の末尾と一致)、'i'は大/小文字を区別しないモード、'x'は照合前に正規表現から空白文字を削除します。

REPLACE(string, pattern, replacement)

string内の正規表現patternの一致箇所が、それぞれreplacementに置き換えられた文字列を戻します。サポートされる正規表現の詳細は、『Oracle Database SQL言語リファレンス』の付録「Oracleの正規表現のサポート」を参照してください。

REPLACE(string, pattern, replacement, flags)

string内の正規表現patternの一致箇所が、それぞれreplacementに置き換えられた文字列を戻します。使用可能なオプション: 's'はドットがすべてに一致するモード('.'は改行文字を含む任意の文字と一致)、'm'は複数行モード('^'は任意の行の先頭と一致し、'$'は任意の行の末尾と一致)、'i'は大/小文字を区別しないモード、'x'は照合前に正規表現から空白文字を削除します。

サポートされる正規表現の詳細は、『Oracle Database SQL言語リファレンス』の付録「Oracleの正規表現のサポート」を参照してください。

ROUND(RDF term)

termに最も近い小数部分なしの数を戻します。2つの値が存在する場合、正の無限大に近い方の値が戻されます。termが数値以外の場合は、nullを戻します。

sameTerm(RDF term, RDF term)

sameTerm(x, y)は、xおよびyが同じRDF語句の場合にtrueを戻し、それ以外の場合はfalseを戻します。

SECONDS(argument)

argumentの秒部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

SHA1(literal)

SHA1ハッシュ関数に対応する、literalのチェックサムを戻します。

SHA256(literal)

SHA256ハッシュ関数に対応する、literalのチェックサムを戻します。

SHA384(literal)

SHA384ハッシュ関数に対応する、literalのチェックサムを戻します。

SHA512(literal)

SHA512ハッシュ関数に対応する、literalのチェックサムを戻します。

STR(RDF term)

STR(x)は、xの文字列表現のプレーン・リテラル(つまり、二重引用符で囲まれた、RDF_VALUE$のVALUE_NAME列に格納される内容)を返します。

STRAFTER(literal, literal)

StrAfter (x,y)は、x内でyの最初の一致からxの末尾までの部分文字列に対応する文字列部分を戻します。x内にyの一致がない場合は、空の文字列が戻されます。

STRBEFORE(literal, literal)

StrBefore (x,y)は、xの先頭からyの最初の一致までに対応する文字列部分を戻します。x内にyの一致がない場合は、空の文字列が戻されます。

STRDT(string, datatype)

引数として渡されるstring字句形式とdatatypeで構成されるリテラル語句を構築します。datatypeはURIである必要があり、そうでない場合はNULL値を戻します。

STRENDS(literal, match)

文字列literalが文字列matchで終わる場合にtrueを戻します。それ以外の場合はfalseを戻します。

STRLANG (string, languageTag)

引数として渡されたstring字句形式と言語タグから成る文字列を構築します。

STRLEN(literal)

literalの字句形式の長さを戻します。

STRSTARTS(literal, match)

文字列literalが文字列matchで始まる場合に、trueを戻します。それ以外の場合はfalseを戻します。

STRUUID()

新しいUUIDのスキーム・セクションを含む文字列を戻します。

SUBSTR(term, startPos)

startPosからtermの末尾までの、termの部分と対応する文字列を戻します。先頭文字の索引は1です。

SUBSTR(term, startPos, length)

startPosからlength文字までの、termの部分に対応する文字列を戻します。先頭文字の索引は1です。

term IN (term list)

xtermlistの値のいずれかで検出できた場合、式x IN(term list)はtrueを戻します。検出されない場合は、falseを戻します。長さ0のリストは有効です。termlistの値のいずれかでエラーが発生すると、エラーのためxは検出されません。

term NOT IN (term list)

xをterm listの値のいずれかで検出できた場合、式x NOT IN(term list)はfalseを戻します。検出されない場合は、trueを戻します。長さ0のリストは有効です。term listの値のいずれかでエラーが発生すると、エラーのためxは検出されません。

TIMEZONE(argument)

xsd:dayTimeDuration値としてargumentのタイムゾーン・セクションを戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

TZ(argument)

argumentのタイムゾーン部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

UCASE(literal)

literal内の各文字を対応する大文字に変換して、文字列を戻します。

URI(RDF term)

IRI(RDF term)のシノニム

UUID()

新しいUniversal Unique Identifierを含むURIを戻します。この値およびバージョンは、PL/SQL関数sys_guid ()と対応します。

YEAR(argument)

argumentの年部分に対応する整数を戻します。

SEM_MATCHで使用可能な組込み関数の理解を深めるには、SPARQL問合せ言語指定(http://www.w3.org/TR/sparql11-query/)において定義される組込み関数の説明も参照してください。

さらに、Oracle Databaseの機能を利用したOracle独自の問合せ関数も用意されています。こうした関数は問合せでのパフォーマンス向上に有効です。次の表に、こうしたOracle固有の関数を一覧で示します。なお、組込みの接頭辞orardfは、<http://xmlns.oracle.com/rdf/>に展開されます。

表1-15 Oracle固有の問合せ関数

関数 説明
orardf:concat(RDF term, RDF term, …)

指定された用語が、指定されたlikeパターンと一致する場合、trueを返します。それ以外の場合、この関数はfalseを返します。

orardf:contains(RDF term, RDF term)

第1項の文字列表現に第2項の文字列表現が部分文字列として含まれる場合は、trueを返します。それ以外の場合、この関数はfalseを返します。

orardf:instr(RDF term, RDF term)

第2項の文字列表現に対し、第1項の文字列表現を検索します。第1項での出現の最初の文字の位置を示す整数(文字列の最初の文字は位置1)を返します。

検索が失敗した場合、返される値は0です。

orardf:instr(RDF term, RDF term, position)

第2項の文字列表現に対し、第1項の文字列表現を検索します。第1項の出現箇所の最初の文字の位置を示す整数(最初の文字は位置1)を返します。

検索が失敗した場合、返される値は0です。

位置は、検索を開始する第1項の文字列表現の文字を示すゼロ以外の整数です(最初の文字は位置1です)。positionがマイナスの場合、orardf:instrは第1項の最後から逆に数えて検索します。

orardf:instr(RDF term, RDF term, position, occurrence)

第2項の文字列表現に対し、第1項の文字列表現を検索します。第1項の出現箇所の最初の文字の位置を示す整数(最初の文字は位置1)を返します。

検索が失敗した場合、返される値は0です。

位置は、検索を開始する第1項の文字列表現の文字を示すゼロ以外の整数です(最初の文字は位置1です)。positionがマイナスの場合、orardf:instrは第1項の最後から逆に数えて検索します。

出現は、orardf:instrの第1項のどの出現を検索するかを示す正の整数です。

orardf:lcase(RDF term)

字句形式が入力項の文字列表現の小文字である文字列リテラルを返します。

orardf:like(RDF term, pattern)

指定された用語が、指定されたlikeパターンと一致する場合、trueを返します。それ以外の場合、この関数はfalseを返します。詳細は、「全文検索」を参照してください。

orardf:like(RDF term, pattern, flags)

指定された項が、指定されたフラグを使用して、指定されたlikeパターンと一致する場合、trueを返します。それ以外の場合、この関数はfalseを返します。使用可能なフラグ: 'i' - 大/小文字を区別しないモード。詳細は、「全文検索」を参照してください。

orardf:ltrim(RDF term)

左端からすべての空白文字が削除された入力項の文字列表現を返します。

orardf:ltrim(RDF term, set)

入力項の文字列表現を返します。setに含まれるすべての文字が左端から削除されます。

orardf:rtrim(RDF term)

右端からすべての空白文字が削除された入力項の文字列表現を返します。

orardf:rtrim(RDF term, set)

入力項の文字列表現を返します。setに含まれるすべての文字が右端から削除されます。

orardf:sameCanonTerm(RDF term, RDF term)

2つの項が、同じ正規のRDF項である場合にtrueを返します。それ以外の場合、この関数はfalseを返します。VALUE_IDに基づく比較ができるため、sameTerm(?x, ?y) or (?x = ?y)よりも効率的です。

orardf:strafter(RDF term, RDF term)

第2項の文字列表現の最初の出現に続く第1項の文字列表現の一部を返します。

そのような発生がない場合は、空の文字列リテラルが返されます。

orardf:strbefore(RDF term, RDF term)

第2項の文字列表現の最初の出現に先行する第1項の文字列表現の一部を返します。

そのような発生がない場合は、空の文字列リテラルが返されます。

orardf:strends(RDF term, RDF term)

第1項の文字列表現に第2項の文字列表現が末尾の部分文字列として含まれる場合は、trueを返します。それ以外の場合、この関数はfalseを返します。

orardf:strlen(RDF term)

入力項の文字列表現の文字数を返します。

orardf:strstarts(RDF term, RDF term) 第1項の文字列表現に第2項の文字列表現が先頭の部分文字列として含まれる場合は、trueを返します。それ以外の場合、この関数はfalseを返します。
orardf:substr(RDF term, start)

start値で示された位置から始まり、入力項の末尾まで続く入力項の文字列表現の一部を返します(最初の文字は位置1)。

orardf:substr(RDF term, start, length)

start値で示された位置からlength値で示される文字数(最初の文字は位置1)まで続く入力項の文字列表現の一部を返します。

orardf:textContains(RDF term, pattern)

指定された項が、指定されたOracle Text検索パターンと一致する場合、trueを返します。それ以外の場合、この関数はfalseを返します。詳細は、「全文検索」を参照してください。

orardf:textScore(invocation id)

orardf:textContains照合のスコアを返します。詳細は、「全文検索」を参照してください。

orardf:ucase(RDF term)

字句形式が入力項の字句形式の大文字である文字列リテラルを返します。

(組込みの空間関数)

(「空間のサポート」を参照してください。)

次のXMLスキーマをキャストする関数は、FILTER句で使用できます。これらの関数は、RDF語句を入力として取得して必要な型の新しいRDF語句を戻すか、RDF語句を目的の型にキャストできない場合はエラーを発生させます。型キャストの詳細は、XPath問合せの仕様(http://www.w3.org/TR/xpath-functions/#casting-from-primitive-to-primitive)の17.1項を参照してください。これらの関数は、XMLネームスペースxsd : http://www.w3.org/2001/XMLSchema#を使用します。

  • xsd:string (RDF term)

  • xsd:dateTime (RDF term)

  • xsd:boolean (RDF term)

  • xsd:integer (RDF term)

  • xsd:float (RDF term)

  • xsd:double (RDF term)

  • xsd:decimal (RDF term)

中カッコを含む構文を使用してグラフ・パターンを表現した場合、次のようになります。

  • 問合せは常に、変数の一致する値の正規字句形式を戻します。

  • options引数にHINT0={<hint-string>}を使用して指定するヒント(「SEM_MATCH表関数を使用したRDFデータの問合せ」を参照)は、ルートBGP内のグラフ・パターン部分に基づいてのみ構築する必要があります。たとえば、例1-16の問合せのヒント指定で使用できる有効な別名は、t0t1?xおよび?yのみです。インライン問合せオプティマイザ・ヒントを使用すると、グラフ・パターンの他の部分に影響を与えることができます(「インライン問合せオプティマイザ・ヒント」を参照)。

  • FILTER構成要素は、ロング・リテラルにバインドされた変数ではサポートされません。

例1-15 中カッコの構文

例1-15は、中カッコとピリオドを含む構文を使用してSEM_MATCH表関数内のグラフ・パターンを表現しています。

SELECT x, y
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, '', null, null,
    'RDFUSER', 'NET1'));

例1-16 中カッコの構文およびOPTIONAL構成要素

例1-16では、各祖父に対して参加する試合の名前(いずれの試合にも参加しない場合はNULL)が返されるように、OPTIONAL構成要素を使用して例1-15を変更しています。

SELECT x, y, game
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . 
      OPTIONAL{?x :plays ?game} 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null,
    null,
    'HINT0={LEADING(t0 t1) USE_NL(?x ?y)}', 
    null, 
    null,
    'RDFUSER', 'NET1'));

例1-17 中カッコの構文および複数パターンのOPTIONAL構成要素

OPTIONALグラフ・パターンに複数のトリプル・パターンが存在すると、オプションの変数の値は、OPTIONALグラフ・パターンの各トリプル・パターンに一致が検出された場合のみ戻されます。例1-17例1-16を変更したもので、祖父ごとに、孫が参加した試合の名前、または共通の試合がない場合はnullが返されるようになっています。ここでは、グローバル問合せオプティマイザ・ヒントも使用して、トリプル・パターンが各BGP内で順番に評価される必要があること、およびルートBGPをOPTIONAL BGPと結合するためにハッシュ結合を使用する必要があることを指定しています。

SELECT x, y, game
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . 
      OPTIONAL{?x :plays ?game . ?y :plays ?game} 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null,
    'ALL_ORDERED ALL_BGP_HASH', 
    null, null,
    'RDFUSER', 'NET1'));

例1-18 中カッコの構文およびネストしたOPTIONAL構成要素

単一の問合せに複数のOPTIONALグラフ・パターンを含むことが可能であり、ネスト化またはパラレル化することもできます。例1-18は、例1-17を変更してOPTIONALグラフ・パターンをネスト化したものです。この例では、(1)各祖父が参加する試合、または(2)祖父が試合に参加しない場合はnull、同じ試合に参加する孫の年齢を返します。共通する参加がない場合はnullを返します。例1-18では、ネストされたOPTIONALグラフ・パターン「?y :plays ?game . ?y :age ?age」が一致しない場合でも、?gameに対して値が戻される点に注意してください。

SELECT x, y, game, age
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . 
      OPTIONAL{?x :plays ?game 
                          OPTIONAL {?y :plays ?game . ?y :age ?age} } 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-19 中カッコの構文およびパラレルのOPTIONAL構成要素

例1-19では、パラレルのOPTIONALグラフ・パターンを使用して例1-17を変更しています。この例では、(1)各祖父が参加する試合、または(2)各祖父のEメール・アドレス、またはEメール・アドレスがない場合はnullを返します。ネストしたOPTIONALグラフ・パターンとは異なり、パラレルのOPTIONALグラフ・パターンはそれぞれ個別に処理されます。つまり、電子メール・アドレスが見つかると、それは試合が見つかったかどうかにかかわらず戻され、試合が見つかると、それは電子メール・アドレスが見つかったかどうかにかかわらず戻されます。

SELECT x, y, game, email
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . 
      OPTIONAL{?x :plays ?game}
      OPTIONAL{?x :email ?email} 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-20 中カッコの構文およびFILTER構成要素

例1-20では、NYまたはCAに居住している祖父のみの孫の情報が戻されるように、FILTER構成要素を使用して例1-15を変更しています。

SELECT x, y
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . ?x :residentOf ?z
       FILTER (?z = "NY"  || ?z = "CA")}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-21 中カッコの構文とREGEXおよびSTR組込み関数を使用したFILTER構成要素

例1-21では、REGEX組込み関数を使用して、Oracle電子メール・アドレスを持つすべての祖父を選択しています。正規表現パターン内のバックスラッシュ(\)文字は、問合せ文字列内でエスケープする必要があります(たとえば\\.はパターン\.となります)。

SELECT x, y, z
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . ?x :email ?z
       FILTER (REGEX(STR(?z), "@oracle\\.com$"))}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-22 中カッコの構文とUNIONおよびFILTER構成要素

例1-22では、祖父がNYまたはCAに居住しているか、NYまたはCAに不動産を所有している場合にのみ、あるいは両方の条件がtrueの場合(祖父がNYまたはCAに居住し、かつ不動産を所有している場合)に祖父が戻されるように、UNION構成要素を使用して例1-20を変更しています。

SELECT x, y
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male 
       {{?x :residentOf ?z} UNION {?x :ownsPropertyIn ?z}}
       FILTER (?z = "NY"  || ?z = "CA")}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

1.7.2.1 GRAPHキーワード・サポート

SEM_MATCH問合せは、RDFデータセットに対して実行されます。RDFデータセットは、1つの名前なしグラフ(デフォルト・グラフ)および1つ以上の名前付きグラフを含むグラフのコレクションです(URIで識別されます)。GRAPH句に出現するグラフ・パターンは名前付きグラフのセットに対して照合され、GRAPH句に出現しないグラフ・パターンはデフォルト・グラフに対して照合されます。graphsおよびnamed_graphs SEM_MATCHパラメータは、SEM_MATCH問合せに対してデフォルト・グラフおよび名前付きグラフのセットを構築するために使用されます。可能なデータセットの構成を、表1-16にまとめます。

表1-16 SEM_MATCHのgraphsとnamed_graphsの値、および結果のデータセット構成

パラメータ値 デフォルト・グラフ 名前付きグラフのセット

graphs: NULL

named_graphs: NULL

すべての名前なしトリプルと、すべての名前付きグラフ・トリプルのすべての和集合。(ただし、optionsパラメータにSTRICT_DEFAULT=Tが含まれる場合は、名前なしトリプルのみがデフォルト・グラフに含められます。)

すべての名前付きグラフ

graphs: NULL

named_graphs: {g1,…, gn}

空のセット

{g1,…, gn}

graphs: {g1,…, gm}

named_graphs: NULL

{g1,…, gm}のUNION ALL

空のセット

graphs: {g1,…, gm}

named_graphs: {gn,…, gz}

{g1,…, gm}のUNION ALL

{gn,…, gz}

RDFデータセットとGRAPH構成要素の詳細は、W3C SPARQL仕様、特にhttp://www.w3.org/TR/rdf-sparql-query/#rdfDatasetも参照してください。

例1-23 名前付きグラフの構成要素

例1-23では、GRAPH構成要素を使用して、グラフ・パターン照合の範囲を特定の名前付きグラフに指定しています。この例では、<http://www.example.org/family/Smith>名前付きグラフで、すべての人の名前および電子メール・アドレスを検出します。

SELECT name, email
  FROM TABLE(SEM_MATCH(
    '{GRAPH :Smith {
       ?x :name ?name . ?x :email ?email } }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-24 named_graphsパラメータの使用

URIの他に、GRAPHキーワードの後に変数を使用できます。例1-24では、GRAPHキーワードとともに変数?gを使用し、named_graphsパラメータを使用して、?gの可能な値を、<http://www.example.org/family/Smith>および<http://www.example.org/family/Jones>名前付きグラフに制限しています。SEM_ALIASES引数で指定される別名は、graphsおよびnamed_graphsパラメータで使用できます。

SELECT name, email
  FROM TABLE(SEM_MATCH(
    '{GRAPH ?g {
       ?x :name ?name . ?x :email ?email } }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null,null,null,null,
    SEM_GRAPHS('<http://www.example.org/family/Smith>',
               ':Jones'),
    'RDFUSER', 'NET1'));

例1-25 graphsパラメータの使用

例1-25では、デフォルト・グラフを使用して、<http://www.example.org/family/Smith><http://www.example.org/family/Jones>名前付きグラフの和集合を問い合せています。

FROM TABLE(SEM_MATCH(
    '{?x :name ?name . ?x :email ?email }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null,null,null,
    SEM_GRAPHS('<http://www.example.org/family/Smith>', 
               ':Jones'),
    null,
    'RDFUSER', 'NET1'));

1.7.3 グラフ・パターン: SPARQL ASK構文のサポート

SEM_MATCHでは、問合せパラメータに完全指定のSPARQL ASK問合せを使用できます。

ASK問合せは、指定の問合せパターンに対する解が存在するかどうかをテストするために使用されます。他の形式のSPARQL問合せとは異なり、ASK問合せでは問合せパターンの解に関する情報は返されません。かわりに、解が存在する場合は"true"^^xsd:boolean、解が存在しない場合は"false"^^xsd:booleanが返されます。

すべてのSPARQL ASK問合せは同じ列(ASK、ASK$RDFVID、ASK$_PREFIX、ASK$_SUFFIX、ASK$RDFVTYP、ASK$RDFCLOB、ASK$RDFLTYP、ASK$RDFLANG、SEM$ROWNUM)を返します。これらの列は、1つの?ask変数を射影するSPARQL SELECT構文の問合せと同じであることに注意してください。

SPARQL ASK問合せは、同等のSPARQL SELECT構文の問合せよりもパフォーマンスが高くなります。ASK問合せは、問合せ変数の字句の値を取得する必要がなく、1つの結果が見つかると問合せの実行を停止できるためです。

SPARQL ASK問合せはSPARQL SELECT問合せと同じ構文を使用しますが、最上位のSELECT句をキーワードASKで置き換える必要があります。

例1-26 SPARQL ASK

例1-26に、10メガ・ピクセル超で50ドル未満のカメラが売り出されているかどうかを判別するSPARQL ASK問合せを示します。

SELECT ask
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     ASK
     WHERE
      {?x :price ?p .
       ?x :megapixels ?m .
       FILTER (?p < 50 && ?m > 10)
      }',
    SEM_Models('electronics'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

SPARQL ASK問合せの詳細は、W3C SPARQL仕様、特にhttp://www.w3.org/TR/sparql11-query/#askも参照してください。

1.7.4 グラフ・パターン: SPARQL CONSTRUCT構文のサポート

SEM_MATCHでは、問合せパラメータに完全指定のSPARQL CONSTRUCT問合せを使用できます。

CONSTRUCT問合せは、格納されているRDFデータからRDFグラフを構築するために使用されます。SPARQL SELECT問合せとは対照的に、CONSTRUCT問合せは問合せの解(変数バインディング)のセットではなくRDFトリプルのセットを返します。

すべてのSPARQL CONSTRUCT問合せは、SEM_MATCHから同じ列を返します。これらの列は、RDFトリプルの主語、述語および目的語に対応し、トリプルの構成要素ごとに10個の列があります。この他にSEM$ROWNUM列も返されます。具体的には返される列は次のとおりです。

SUBJ
SUBJ$RDFVID
SUBJ$_PREFIX
SUBJ$_SUFFIX
SUBJ$RDFVTYP
SUBJ$RDFCLOB
SUBJ$RDFLTYP
SUBJ$RDFLANG
SUBJ$RDFTERM
SUBJ$RDFCLBT
PRED
PRED$RDFVID
PRED$_PREFIX
PRED$_SUFFIX
PRED$RDFVTYP
PRED$RDFCLOB
PRED$RDFLTYP
PRED$RDFLANG
PRED$RDFTERM
PRED$RDFCLBT
OBJ
OBJ$RDFVID
OBJ$_PREFIX
OBJ$_SUFFIX
OBJ$RDFVTYP
OBJ$RDFCLOB
OBJ$RDFLTYP
OBJ$RDFLANG
OBJ$RDFTERM
OBJ$RDFCLBT
SEM$ROWNUM

各コンポーネントで、COMP、COMP$RDFVID、COMP$_PREFIX、COMP$_SUFFIX、COMP$RDFVTYP、COMP$RDFCLOB、COMP$RDFLTYPおよびCOMP$RDFLANGは、SPARQL SELECT問合せの同じ列の値に対応します。COMP$RDFTERMでは、N-Triple構文でVARCHAR2(NETWORK_MAX_STRING_SIZE) RDF語句が保持され、COMP$RDFCLBTでは、N-Triple構文でCLOB RDF語句が保持されます。

SPARQL CONSTRUCT問合せはSPARQL SELECT問合せと同じ構文を使用しますが、最上位のSELECT句をCONSTRUCTテンプレートで置き換えます。CONSTRUCTテンプレートは、WHERE句に定義された問合せパターンの結果を使用して結果のRDFグラフの作成方法を決定します。CONSTRUCTテンプレートでは、キーワードCONSTRUCTの後に、中カッコで囲まれた一連のSPARQLトリプル・パターンが続きます。キーワードOPTIONAL、UNION、FILTER、MINUS、BIND、VALUESおよびGRAPHは、CONSTRUCTテンプレートでは使用できません。プロパティ・パス表現もCONSTRUCTテンプレート内で使用できません。ただし、WHERE句内の問合せパターンではこれらのキーワードを使用できます。

SPARQL CONSTRUCT問合せは、次の方法で結果のRDFグラフを構築します。WHERE句から返される結果行ごとに、変数値がCONSTRUCTテンプレートに代入され、1つ以上のRDFトリプルが作成されます。例1-27のWHERE句のグラフ・パターンが次の結果行を返すとします。

E$RDFTERM FNAME$RDFTERM LNAME$RDFTERM

ent:employee1

"Fred"

"Smith"

ent:employee2

"Jane"

"Brown"

ent:employee3

"Bill"

"Jones"

例1-27のSEM_MATCH CONSTRUCT問合せ全体は、6個のRDFトリプルに対応する次の行を返します(問合せパターンの結果行ごとに2個ずつ)。

SUBJ$RDFTERM PRED$RDFTERM OBJ$RDFTERM

ent:employee1

foaf:givenName

"Fred"

ent:employee1

foaf:familyName

"Smith"

ent:employee2

foaf:givenName

"Jane"

ent:employee2

foaf:familyName

"Brown"

ent:employee3

foaf:givenName

"Bill"

ent:employee3

foaf:familyName

"Jones"

SPARQL CONSTRUCTの動作に影響を与えるSEM_MATCH問合せオプションが2つあります。CONSTRUCT_UNIQUE=TおよびCONSTRUCT_STRICT=Tです。CONSTRUCT_UNIQUE=T問合せオプションを使用すると、CONSTRUCT問合せから一意のRDFトリプルのみが返されます。 CONSTRUCT_STRICT=T問合せオプションを使用すると、CONSTRUCT問合せから有効なRDFトリプルのみが返されます。有効なRDFトリプルは、主語の位置にURIまたは空白ノードがあり(1)、述語の位置にURIがあり(2)、目的語の位置にURI、空白ノードまたはRDFリテラルがあります(3)。問合せのパフォーマンスが向上するように、これらの問合せオプションはいずれもデフォルトではオフになっています。

例1-27 SPARQL CONSTRUCT

例1-27に、foafボキャブラリを使用して従業員名のRDFグラフを構築するSPARQL CONSTRUCT問合せを示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      {?e foaf:givenName  ?fname .
       ?e foaf:familyName ?lname 
      }
     WHERE
      {?e ent:fname ?fname .
       ?e ent:lname ?lname 
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-28 解の修飾子を含むCONSTRUCT

SPARQLの解の修飾子をCONSTRUCT問合せで使用できます。例1-28に、ORDER BYとLIMITを使用して、最も給与が高い2人の従業員のグラフを構築する方法を示します。LIMIT 2句はCONSTRUCT問合せ全体ではなく問合せパターンに適用されることに注意してください。つまり、問合せパターンは2つの結果行を返しますが、CONSTRUCT問合せ全体は6個のRDFトリプル(?eにバインドされた従業員2人に3個ずつ)を返します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      { ?e ent:fname       ?fname .
        ?e ent:lname       ?lname .
        ?e ent:dateOfBirth ?dob }
     WHERE
      { ?e ent:fname  ?fname .
        ?e ent:lname  ?lname .
        ?e ent:salary ?sal
      }
     ORDER BY DESC(?sal)
     LIMIT 2',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-29 SPARQL 1.1機能とCONSTRUCT

SPARQL 1.1の機能は、CONSTRUCT問合せパターン内でサポートされます。例1-29に、CONSTRUCT問合せで使用されている副問合せとSELECT式を示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      { ?e foaf:name  ?name }
     WHERE
      { SELECT ?e (CONCAT(?fname," ",?lname) AS ?name)
        WHERE { ?e ent:fname ?fname .
                ?e ent:lname ?lname }
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-30 名前付きグラフを含むSPARQL CONSTRUCT

名前付きグラフ・データをSPARQL CONSTRUCT問合せで返すことはできません。W3C SPARQL仕様に従って、RDFクワッドではなくRDFトリプルのみが返されるためです。ただし、FROM、FROM NAMEDおよびGRAPHキーワードは、WHERE句に定義された問合せパターンと一致する場合に使用できます。

例1-30は、名前付きグラフent:g1ent:g2のUNIONのent:nameトリプル、名前付きグラフent:g3ent:dateOfBirthトリプル、および名前付きグラフent:g4ent:ssnトリプルを含むRDFグラフを作成します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      { ?e ent:name ?name .
        ?e ent:dateOfBirth ?dob .
        ?e ent:ssn ?ssn
      }
     FROM ent:g1
     FROM ent:g2
     FROM NAMED ent:g3
     FROM NAMED ent:g4
     WHERE
      { ?e foaf:name ?name .
        GRAPH ent:g3 { ?e ent:dateOfBirth ?dob }
        GRAPH ent:g4 { ?e ent:ssn ?ssn } 
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-31 SPARQL CONSTRUCTの標準形

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      {?e foaf:givenName  ?fname .
       ?e foaf:familyName ?lname 
      }
     WHERE
      {?e ent:fname ?fname .
       ?e ent:lname ?lname 
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-32 SPARQL CONSTRUCTの短縮形

CONSTRUCTテンプレートがWHERE句とまったく同じ場合、CONSTRUCTの短縮形を使用できます。このケースではキーワードCONSTRUCTのみが必要です。WHERE句のグラフ・パターンもCONSTRUCTテンプレートとして使用されます。例1-32に、例1-31の短縮形を示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
     WHERE
      {?e ent:fname ?fname .
       ?e ent:lname ?lname 
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

1.7.4.1 SPARQL CONSTRUCTの一般的なワークフロー

SPARQL CONSTRUCTの一般的なワークフローでは、CONSTRUCT問合せを実行して、既存のRDFグラフのRDFトリプル・データを抽出または変換し(あるいは両方を行い)、そのデータを既存または新規RDFグラフにロードします。データのロードは、単純なINSERT文を使用するかSEM_APIS.BULK_LOAD_RDF_GRAPHプロシージャを実行して行うことができます。

例1-33 SPARQL CONSTRUCTのワークフロー

例1-33は、既存のent:fnameおよびent:lnameトリプルからfoaf:nameトリプルを作成し、それらの新しいトリプルを元のRDFグラフにバルク・ロードします。その後、元のグラフにfoaf:name値を問い合せることができます。

-- Use create table as select to build a staging table 
CREATE TABLE STAB(RDF$STC_sub, RDF$STC_pred, RDF$STC_obj) AS
SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
FROM TABLE(SEM_MATCH(
 'PREFIX  ent: <http://www.example.org/enterprise/> 
  PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  CONSTRUCT
   { ?e foaf:name  ?name }
  WHERE
   { SELECT ?e (CONCAT(?fname," ",?lname) AS ?name)
     WHERE { ?e ent:fname ?fname .
             ?e ent:lname ?lname }
   }',
 SEM_Models('enterprise'),
 null, null, null, null, ' ', null, null,
 'RDFUSER', 'NET1')); 
 

 
-- Bulk load data back into the enterprise model
BEGIN
  SEM_APIS.BULK_LOAD_RDF_GRAPH(
    rdf_graph_name=>'enterprise',
    table_owner=>'rdfuser',
    table_name=>'stab',
    flags=>' parallel_create_index parallel=4 ',
    network_owner=>'RDFUSER',
    network_name=>'NET1');
END;
/
 
-- Query for foaf:name data
SELECT e$rdfterm, name$rdfterm
FROM TABLE(SEM_MATCH(
 'PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  SELECT ?e ?name
  WHERE { ?e foaf:name ?name }',
 SEM_Models('enterprise'),
 null, null, null, null, ' ', null, null,
 'RDFUSER', 'NET1'));

SPARQL CONSTRUCT問合せの詳細は、W3C SPARQL仕様、特にhttp://www.w3.org/TR/sparql11-query/#constructも参照してください。

1.7.5 グラフ・パターン: SPARQL DESCRIBE構文のサポート

SEM_MATCHでは、問合せパラメータに完全指定のSPARQL DESCRIBE問合せを使用できます。

SPARQL DESCRIBE問合せは、RDFデータセットの調査に役立ちます。データセットで使用される正確なRDFプロパティの情報を把握していなくても、指定された1つのリソースまたは一連のリソースについて簡単に情報を見つけることができます。DESCRIBE問合せはリソースrの説明を返します。この説明は、主語または目的語の位置にrを含む、問合せデータセットの一連のRDFトリプルです。

CONSTRUCT問合せと同じく、DESCRIBE問合せは結果バインディングのかわりにRDFグラフを返します。したがって、各DESCRIBE問合せはCONSTRUCT問合せと同じ列を返します(戻り列のリストは、「グラフ・パターン: SPARQL CONSTRUCT構文のサポート」を参照してください)。

SPARQL DESCRIBE問合せはSPARQL SELECT問合せと同じ構文を使用しますが、最上位のSELECT句をDESCRIBE句で置き換えます。DESCRIBE句の構成として、DESCRIBEキーワードの後に一連のURIまたは変数(あるいは両方)を空白で区切って指定するか、DESCRIBEキーワードの後に* (1つのアスタリスク)を指定します。

SPARQL DESCRIBE問合せに影響を与えるSEM_MATCH問合せオプションが2つあります。CONSTRUCT_UNIQUE=TおよびCONSTRUCT_STRICT=Tです。CONSTRUCT_UNIQUE=Tによって結果から重複したトリプルが消去され、CONSTRUCT_STRICT=Tによって結果から無効なトリプルが消去されます。これらのオプションは両方ともデフォルトではオフになっています。これらのオプションの詳細は、「グラフ・パターン: SPARQL CONSTRUCT構文のサポート」を参照してください。

SPARQL DESCRIBET問合せの詳細は、W3C SPARQL仕様、特にhttp://www.w3.org/TR/sparql11-query/#describeも参照してください。

例1-34 SPARQL DESCRIBEの短縮形

SPARQL DESCRIBEの短縮形は、一定の1つのURIを記述するために用意されています。短縮形ではDESCRIBE句のみが必要です。例1-34に、SPARQL DESCRIBE問合せの短縮形を示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
FROM TABLE(SEM_MATCH(
 'DESCRIBE <http://www.example.org/enterprise/emp_1>',
 SEM_Models('enterprise'),
 null, null, null, null, ' ', null, null,
 'RDFUSER', 'NET1'));

例1-35 SPARQL DESCRIBEの標準形

SPARQL DESCRIBEの標準形では、DESCRIBE句とSPARQL問合せパターン(解の修飾子を含む場合もある)が指定されます。例1-35に、所属部門がニュー・ハンプシャーにあるすべての従業員を説明するSPARQL DESCRIBE問合せを示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
FROM TABLE(SEM_MATCH(
 'PREFIX  ent: <http://www.example.org/enterprise/>
  DESCRIBE ?e
  WHERE 
   { ?e ent:department ?dept .
     ?dept ent:locatedIn "New Hampshire" }',
 SEM_Models('enterprise'),
 null, null, null, null, ' ', null, null,
 'RDFUSER', 'NET1'));

例1-36 DESCRIBE *

例1-35に示す標準形のDESCRIBEでは、DESCRIBE句に指定された変数にバインドされるすべてのリソースが説明されます。例1-35では、問合せパターンから返され、?eにバインドされているすべての従業員が説明されます。DESCRIBE *が使用されると、問合せに含まれるすべての変数が説明されます。

例1-36例1-35を変更したもので、従業員(?eにバインド)と部門(?deptにバインド)の両方を説明しています。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
FROM TABLE(SEM_MATCH(
 'PREFIX  ent: <http://www.example.org/enterprise/>
  DESCRIBE *
  WHERE 
   { ?e ent:department ?dept .
     ?dept ent:locatedIn "New Hampshire" }',
 SEM_Models('enterprise'),
 null, null, null, null, ' ', null, null,
 'RDFUSER', 'NET1'));

1.7.6 グラフ・パターン: SPARQL SELECT構文のサポート

中カッコのグラフ・パターンに加えて、SEM_MATCHでは、queryパラメータに完全指定のSPARQL SELECT問合せを使用できます。SPARQL SELECT構文オプションを使用すると、SEM_MATCHは問合せ構成要素のBASE、PREFIX、SELECT、SELECT DISTINCT、FROM、FROM NAMED、WHERE、ORDER BY、LIMITおよびOFFSETをサポートします。各SPARQL SELECT構文の問合せは、SELECT句とグラフ・パターンを含める必要があります。

SEM_MATCHを使用する場合の中カッコとSPARQL SELECT構文の主な違いは、SPARQL SELECT構文を使用する場合、SPARQL SELECT句に出現している変数のみがSEM_MATCHから戻されるところにあります。

SPARQL SELECT構文を使用する場合、SEM$ROWNUMという1つの追加列がSEM_MATCHから戻されます。このNUMBER列を使用して、結果の順序がSPARQL ORDER BY句で指定された順序と一致するようにSEM_MATCH問合せの結果を並べ替えることができます。

SPARQL ORDER BY句を使用すると、SEM_MATCH問合せの結果を並べ替えることができます。この句によって、指定された問合せの結果を並べ替えるために使用する一連のコンパレータを指定します。コンパレータは、変数、RDF語句、算術演算子(+、-、*、/)、ブール演算子と論理連結語(||、&&、!)、比較演算子(<、>、<=、>=、=、!=)およびFILTER式で使用可能な任意の関数で作成される式で構成されます。

SPARQL SELECT問合せを評価する場合は、次の順序で操作を実行します。

  1. グラフ・パターン照合

  2. グループ化(「グループ化と集計」を参照してください。)

  3. 集計(「グループ化と集計」を参照してください。)

  4. HAVING (「グループ化と集計」を参照してください。)

  5. VALUES (「値の割当て」を参照してください。)

  6. SELECT式

  7. ORDER BY

  8. 投影

  9. 個別

  10. オフセット

  11. 制限

SPARQL BASE、PREFIX、SELECT、SELECT DISTINCT、FROM、FROM NAMED、WHERE、ORDER BY、LIMITおよびOFFSET構成要素については、W3C SPARQL仕様、特にhttp://www.w3.org/TR/sparql11-query/を参照してください。

例1-37 SPARQL PREFIX、SELECTおよびWHERE句

例1-37では、次のSPARQL構成要素を使用しています。

  • SPARQL PREFIX句(http://www.example.org/family/およびhttp://xmlns.com/foaf/0.1/名前空間に対して略称を指定する場合)

  • SPARQL SELECT句: 問合せから抽出する変数のセットを指定します。

  • SPARQL WHERE句: 問合せグラフ・パターンを指定します。

SELECT y, name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     SELECT ?y ?name
     WHERE
     {?x :grandParentOf ?y . 
      ?x foaf:name ?name }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-37では、y、y$RDFVID、y$_PREFIX、y$_SUFFIX、y$RDFVTYP、y$RDFCLOB、y$RDFLTYP、y$RDFLANG、name、name$RDFVID、name$_PREFIX、name$_SUFFIX、name$RDFVTYP、name$RDFCLOB、name$RDFLTYP、name$RDFLANGおよびSEM$ROWNUMの各列を戻します。

例1-38 SPARQL SELECT * (トリプル・パターン内のすべての変数)

SPARQL SELECT句では、(A)一連の変数または式あるいはその両方(「SELECT句の式」を参照)を指定するか、(B) アスタリスク(*)を使用して、指定されたトリプル・パターンで出現するすべての変数を射影します。例1-38では、SPARQL SELECT句を使用して、指定されたトリプル・パターンで出現するすべての変数を選択しています。

SELECT x, y, name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     SELECT *
     WHERE
     {?x :grandParentOf ?y . 
      ?x foaf:name ?name }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-39 SPARQL SELECT DISTINCT

DISTINCTキーワードをSELECTの後に使用すると重複結果行を除外できます。例1-39では、SELECT DISTINCTを使用して重複しない名前のみを選択しています。

SELECT name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     SELECT DISTINCT ?name
     WHERE
     {?x :grandParentOf ?y . 
      ?x foaf:name ?name }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-40 FROMおよびFROM NAMEDを使用したRDFデータセットの指定

SPARQL FROMおよびFROM NAMEDは、問合せに対してRDFデータセット指定する場合に使用します。FROM句はデフォルト・グラフを構成するグラフのセットを指定する場合に使用し、FROM NAMED句は名前付きグラフ・セットを構成するグラフ・セットを指定する場合に使用します。例1-40では、FROMおよびFROM NAMEDを使用して、<http://www.friends.com/friends>および<http://www.contacts.com/contacts>グラフの和集合から電子メール・アドレスと友人を選択し、<http://www.example.org/family/Smith>および<http://www.example.org/family/Jones>グラフから祖父母情報を選択しています。

SELECT x, y, z, email
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     PREFIX friends: <http://www.friends.com/>
     PREFIX contacts: <http://www.contacts.com/>
     SELECT *
     FROM friends:friends
     FROM contacts:contacts
     FROM NAMED :Smith
     FROM NAMED :Jones
     WHERE
     {?x foaf:frendOf ?y .
      ?x :email ?email .
      GRAPH ?g {
        ?x :grandParentOf ?z }
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-41 SPARQL ORDER BY

SPARQL ORDER BY句の場合:

  • 単一の変数の順序付け条件には前後のカッコは不要ですが、より複雑な順序付け条件にはカッコが必要です。

  • オプションのASC()またはDESC()順序修飾子を使用して、それぞれ昇順または降順となる目的の順序を指定できます。デフォルトの順序は昇順です。

  • SEM_MATCHでSPARQL ORDER BYを使用する場合、取り囲んでいるSQLブロック全体を通じて目的の順序を維持するためには、格納側のSQL問合せをSEM$ROWNUMで並べ替える必要があります。

例1-41では、SPARQL ORDER BY句ですべてのカメラを選択し、タイプの降順かつ総額(price * (1 - discount) * (1 + tax))の昇順になるように順序を指定しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT * 
     WHERE
      {?x :price ?p .
       ?x :discount ?d .
       ?x :tax ?t .
       ?x :cameraType ?cType .
      }
     ORDER BY DESC(?cType) ASC(?p * (1-?d) * (1+?t))',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'))
ORDER BY SEM$ROWNUM;

例1-42 SPARQL LIMIT

SPARQL LIMITおよびSPARQL OFFSETは、問合せの解の異なるサブセットを選択するために使用できます。例1-42ではSPARQL LIMITを使用して最も安価なカメラを5つ選択し、例1-43ではSPARQL LIMITおよびOFFSETを使用して5番目から10番目に安価なカメラを選択しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
      }
     ORDER BY ASC(?p)
     LIMIT 5',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'))
ORDER BY SEM$ROWNUM;

例1-43 SPARQL OFFSET

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
      }
     ORDER BY ASC(?p)
     LIMIT 5
     OFFSET 5',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'))
ORDER BY SEM$ROWNUM;

例1-44 完全なURIを使用した問合せ

SPARQL BASEキーワードは、グローバル接頭辞を設定するために使用します。すべての相対IRIは、「Uniform Resource Identifier (URI): Generic Syntax」(RFC3986)(http://www.ietf.org/rfc/rfc3986.txt)の5.2項で説明されている基本的なアルゴリズムを使用して、ベースIRIで解決されます。例1-44は完全なURIを使用する簡単な問合せで、例1-45はベースIRIを使用する同等の問合せです。

SELECT *
  FROM TABLE(SEM_MATCH(
    'SELECT ?employee ?position
     WHERE
      {?x <http://www.example.org/employee> ?p .
       ?p <http://www.example.org/employee/name> ?employee .
       ?p <http://www.example.org/employee/position> ?pos .
       ?pos <http://www.example.org/positions/name> ?position
      }',
    SEM_Models('enterprise'),
    null, 
     null, null, null, ' ', null, null,
   'RDFUSER', 'NET1'))
ORDER BY 1,2;

例1-45 ベースIRIを使用した問合せ

SELECT *
  FROM TABLE(SEM_MATCH(
    'BASE <http://www.example.org/>
     SELECT ?employee ?position
     WHERE
      {?x <employee> ?p .
       ?p <employee/name> ?employee .
       ?p <employee/position> ?pos .
       ?pos <positions/name> ?position
      }',
    SEM_Models('enterprise'),
    null, 
    null, null, null, ' ', null, null,
   'RDFUSER', 'NET1'))
ORDER BY 1,2;

1.7.7 グラフ・パターン: SPARQL 1.1の構成要素のサポート

SEM_MATCHでは、次のSPARQL 1.1の構成要素がサポートされています。

1.7.7.1 SELECT句の式

SELECT句では式を使用して、問合せから式の値を射影することができます。SELECT式は、変数、RDF語句、算術演算子(+、-、*、/)、ブール演算子と論理連結語(||、&&、!)、比較演算子(<、>、<=、>=、=、!=)およびFILTER式で使用可能な任意の関数で構成されます。式は、ASキーワードを使用して別名として単一の変数を指定する必要があり、<expression> AS <alias>フラグメント全体をカッコで囲む必要があります。この別名変数は、問合せで事前に定義することはできません。SELECT式は、前のSELECT式(つまり、SELECT句の前の方で指定された式)の結果を参照する場合があります。

例1-46 SPARQL SELECT式

例1-46では、SELECT式を使用してカメラごとの合計を射影しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ((?p * (1-?d) * (1+?t)) AS ?totalPrice) 
     WHERE
      {?x :price ?p .
       ?x :discount ?d .
       ?x :tax ?t .
       ?x :cameraType ?cType .
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-47 SPARQL SELECT式(2)

例1-47では、2つのSELECT式を使用して、売上税がある場合とない場合の割引価格を射影しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ((?p * (1-?d)) AS ?preTaxPrice) ((?preTaxPrice * (1+?t)) AS ?finalPrice)
     WHERE
      {?x :price ?p .
       ?x :discount ?d .
       ?x :tax ?t .
       ?x :cameraType ?cType .
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

1.7.7.2 副問合せ

副問合せは、SPARQL SELECT構文で可能です。つまり、完全指定のSPARQL SELECT問合せが、他のSPARQL SELECT問合せ内に埋め込まれる場合があります。副問合せには、問合せのサブコンポーネントからの結果数を制限する場合など、多くの用途があります。

例1-48 SPARQL SELECT副問合せ

例1-48では、最も安価なカメラを製造するメーカーを検索し、このメーカーが製造した他のすべてのカメラを検索するために副問合せを使用しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?c1
     WHERE {?c1 rdf:type :Camera .
            ?c1 :manufacturer ?m .
            {
             SELECT ?m
             WHERE {?c2 rdf:Type :Camera .
                    ?c2 :price ?p .
                    ?c2 :manufacturer ?m .
             }
             ORDER BY ASC(?p)
             LIMIT 1
            }
     }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

副問合せが最初に論理的に評価され、その結果が外部問合せに射影されます。外部問合せから参照できるのは、副問合せのSELECT句で射影された変数のみです。

1.7.7.3 グループ化と集計

グループ化を実行するにはGROUP BYキーワードを使用します。構文上、GROUP BYキーワードはWHERE句の後、および解の修飾子(ORDER BYまたはLIMITなど)の前に使用する必要があります。

集計は、グループ内の結果全体の値を計算するために使用されます。集計は値のコレクションを操作して、結果として単一の値を生成します。SEM_MATCHは、組込みの集計としてCOUNT、SUM、MIN、MAX、AVG、GROUP_CONCATおよびSAMPLEをサポートしています。これらの集計を、表1-17で説明します。

表1-17 組込みの集計

集計 説明

AVG(expression)

グループ内の値に対するexpressionの平均値を返します。

COUNT(* | expression)

expressionがグループ内にバインドされた非エラー値を持つ回数がカウントされ、アスタリスク(*)ではグループ内の結果数がカウントされます。

GROUP_CONCAT(expression [; SEPARATOR = "STRING"])

グループ内の値に関して、expressionの文字列連結を実行します。オプションのセパレータ文字列を指定すると、各値の間にセパレータ文字が配置されます。

MAX(expression)

SPARQL ORDER BYによって定義される順序付けに基づいて、グループ内のexpressionの最大値を戻します。

MIN(expression)

SPARQL ORDER BYによって定義される順序付けに基づいて、グループ内のexpressionの最少値を戻します。

SAMPLE(expression)

グループから単一の任意の値と評価されるexpressionを戻します。

SUM(expression)

グループ内の値に関してexpressionの数値合計を計算します。

グループ化と集計の使用時には、変数参照に特定の制限が適用されます。グループ化変数(GROUP BY句の単一の変数)およびGROUP BY値割当てからの別名変数のみを、SELECT句またはHAVING句内の非集計式で使用できます。

例1-49 簡単なグループ化の問合せ

例1-49に、GROUP BYキーワードを使用してすべての種類のカメラを検索する問合せを示します。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?cType
     WHERE
      {?x rdf:type :Camera .
       ?x :cameraType ?cType .
      }
     GROUP BY ?cType',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
     null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

グループ化問合せは、グループ化式(例1-49?cType)に基づいて問合せ結果をグループのコレクションに分割して、グループ内の各結果がグループ化式に関しては同じ値を持つようにします。グループ操作の最終結果には、各グループに1つの行が含まれます。

例1-50 複雑なグループ化式

グループ化式では、変数、式、または「<expression> as <alias>」の形式を持つ値割当てを1つ以上、ひと続きで指定します。例1-50は、グループ化式で各タイプのコンポーネントを1つずつ使用しているグループ化問合せを示しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?cType ?totalPrice
     WHERE
      {?x rdf:type :Camera .
       ?x :cameraType ?cType .
       ?x :manufacturer ?m .
       ?x :price ?p .
       ?x :tax ?t .
      }
     GROUP BY ?cType (STR(?m)) ((?p*(1+?t)) AS ?totalPrice)',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-51 集計

例1-51では、集計を使用して、各種類のカメラの最高、最低、平均価格を選択しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?cType 
            (MAX(?p) AS ?maxPrice) 
            (MIN(?p) AS ?minPrice) 
            (AVG(?p) AS ?avgPrice)
     WHERE
      {?x rdf:type :Camera .
       ?x :cameraType ?cType .
       ?x :manufacturer ?m .
       ?x :price ?p .
      }
     GROUP BY ?cType',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-52 グループ化なしの集計

集計をグループ化式なしで使用すると、結果セット全体が単一のグループとして処理されます。例1-52では、データセット全体のカメラの合計数を計算しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT (COUNT(?x) as ?cameraCnt)
     WHERE
      { ?x rdf:type :Camera 
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-53 DISTINCTを使用した集計

DISTINCTキーワードは、必要に応じて、集計ごとに修飾子として使用できます。DISTINCTを使用すると、集計を計算する前に各グループから重複値が除外されます。構文上、DISTINCTは集計の最初の引数として使用される必要があります。例1-53では、重複なしのカメラ・メーカー数を検索するためにDISTINCTを使用しています。この場合、STR(?m)の重複値は、カウント前に除外されます。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT (COUNT(DISTINCT STR(?m)) as ?mCnt)
     WHERE
      { ?x rdf:type :Camera .
        ?x :manufacturer ?m
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
     null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-54 HAVING句

制約に基づいてグループをフィルタ処理するには、HAVINGキーワードを使用できます。HAVING式は、変数、RDF語句、算術演算子(+、-、*、/)、ブール演算子と論理連結語(||、&&、!)、比較演算子(<、>、<=、>=、=、!=)、集計、およびFILTER式で使用可能な任意の関数で構成できます。構文上、HAVINGキーワードはGROUP BY句の後、および他の解の修飾子(ORDER BYまたはLIMITなど)の前に使用します。

例1-54では、HAVING式を使用して、200ドル未満のカメラを販売するすべてのメーカーを検索しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?m
     WHERE
      { ?x rdf:type :Camera .
        ?x :manufacturer ?m .
        ?x :price ?p
      }
     GROUP BY ?m
     HAVING (MIN(?p) < 200)
     ORDER BY ASC(?m)',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

1.7.7.4 否定

SEM_MATCHでは、SPARQL問合せパターンでNOT EXISTSおよびMINUSの2つの形式の否定がサポートされています。NOT EXISTSはグラフ・パターンが一致したかどうかに基づいて結果をフィルタ処理するために使用可能で、MINUSは別のグラフ・パターンとの関係に基づいて解を除外するために使用できます。

例1-55 NOT EXISTSによる否定

例1-55では、NOT EXISTS FILTERを使用して、ユーザー・レビューのないカメラを選択しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       FILTER( NOT EXISTS({?x :userReview ?r}) )
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-56 EXISTS

逆に、EXISTS演算子は、パターンの一致を確認する場合に使用できます。例1-56では、EXISTS FILTERを使用して、ユーザー・レビューを持つカメラのみを選択しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       FILTER( EXISTS({?x :userReview ?r}) )
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    RDFUSER', 'NET1'));

例1-57 MINUSによる否定

例1-57では、MINUSを使用して、例1-55と同じ結果を得ています。MINUSパターンの解と互換性がない解のみが、結果に含まれます。つまり、解がすべての共有変数にMINUSパターンの解と同じ値を持つ場合、それは結果から除外されます。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       MINUS {?x :userReview ?r}
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-58 NOT EXISTSによる否定(2)

NOT EXISTSとMINUSは2つの異なるスタイルの否定を表し、特定の状況では異なる結果を持ちます。例としては、否定パターンと残りの問合せの間で変数が共有されない場合が挙げられます。たとえば、例1-58のNOT EXISTS問合せでは{?subj ?prop ?obj}がどのトリプルにも一致するためすべての解が除外されますが、例1-59のMINUS問合せでは、共有変数がないため除外される解はありません。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       FILTER( NOT EXISTS({?subj ?prop ?obj}) )
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-59 MINUSによる否定(2)

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       MINUS {?subj ?prop ?obj}
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

1.7.7.5 値の割当て

SEM_MATCHには、値をSPARQL問合せの変数に割り当てる様々な方法が提供されています。

式の値を新しい変数に割り当てる方法には、(1)SELECT句の式、(2)GROUP BY句の式、および(3)BINDキーワードの3つがあります。どの場合も、新しい変数を問合せで事前に定義しておく必要はありません。割当て後は、この新しい変数を問合せで使用して、結果に戻すことが可能です。「SELECT句の式」で説明したように、値割当ての構文は(<expression> AS <alias>)となり、aliasは新しい変数を示し、たとえば((?price * (1+?tax)) AS ?totalPrice)とします。

例1-60 ネストしたSELECT式

例1-60では、ネストしたSELECT式を使用して、カメラの合計価格を計算し、その値を変数(?totalPrice)に割り当てています。その後、この変数を外部問合せのFILTERで使用して、200ドル未満のカメラを検索します。

SELECT *
 FROM TABLE(SEM_MATCH(
   'PREFIX : <http://www.example.org/electronics/> 
    SELECT ?x ?cType ?totalPrice
    WHERE
     {?x :cameraType ?cType .
       { SELECT ?x ( ((?price*(1+?tax)) AS ?totalPrice )
         WHERE { ?x :price ?price .
                 ?x :tax ?tax }
       }
      FILTER (?totalPrice < 200)
     }',
   SEM_Models('electronics'),
   SEM_Rulebases('RDFS'),
   null, null, null, ' ', null, null,
   'RDFUSER', 'NET1'));

例1-61 BIND

BINDキーワードは、基本グラフ・パターン内で値を割り当てるために使用可能で、構文上は同等のネストしたSELECT式より簡潔です。例1-61では、BINDキーワードを使用して、例1-60と論理的に同等な問合せを表しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?totalPrice
     WHERE
      {?x :cameraType ?cType .
       ?x :price ?price .
       ?x :tax ?tax .
       BIND ( ((?price*(1+?tax)) AS ?totalPrice )
       FILTER (?totalPrice < 200)
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
   'RDFUSER', 'NET1'));

例1-62 GROUP BY式

GROUP BY句の値割当ては、その後SELECT句、HAVING句および外部問合せ(ネストしたグループ化問合せの場合)で使用することができます。例1-62では、GROUP BY式を使用して、1000ドル未満の各価格のカメラの最大メガピクセル数を検索しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?totalPrice (MAX(?mp) as ?maxMP)
     WHERE
      {?x rdf:type :Camera .
       ?x :price ?price .
       ?x :tax ?tax .
       GROUP BY ( ((?price*(1+?tax)) AS ?totalPrice )
       HAVING (?totalPrice < 1000)
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-63 VALUES

新しい変数に式の値を割り当てる方法には、前述の3つの方法の他にVALUESキーワードを使用する方法があり、順序付けられていない解の順序を取得して、結合操作によって問合せ結果と組み合せることができます。VALUESブロックは、問合せパターン内、またはSPARQL SELECT問合せブロックの末尾の解の修飾子の後に使用できます。VALUES構成要素は、副問合せで使用できます。

例1-63では、VALUESキーワードを使用して、問合せ結果を:Company1製造のDSLRカメラ、または:Company2製造の任意の種類のカメラに制限しています。キーワードUNDEFは、解の順序内でバインドされていない変数を表すために使用されます。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?m
     WHERE 
      { ?x rdf:type :Camera .
        ?x :cameraType ?cType .
        ?x :manufacturer ?m
      }
     VALUES (?cType ?m)
     { ("DSLR" :Company1)
       (UNDEF  :Company2) 
     }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-64 簡略化されたVALUES構文

変数が1つの一般的な例では、簡略化された構文を使用できます。特に、変数および各解の前後のカッコは省略できます。例1-64は、簡略化された構文を使用して、問合せ結果を:Company1または:Company2によって製造されたカメラに制限しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?m
     WHERE 
      { ?x rdf:type :Camera .
        ?x :cameraType ?cType .
        ?x :manufacturer ?m
      }
     VALUES ?m
     { :Company1
       :Company2 
     }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-65 インラインVALUESブロック

例1-65でも、問合せ結果を:Company1または:Company2製造のカメラに制限していますが、問合せパターン内でVALUESブロックを指定しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?m
     WHERE 
      { VALUES ?m { :Company1 :Company2 }
        ?x rdf:type :Camera .
        ?x :cameraType ?cType .
        ?x :manufacturer ?m
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

1.7.7.6 プロパティ・パス

SPARQLプロパティ・パスは、RDFグラフ内の2つのRDFリソース(ノード)の間の可能なパスを示しています。プロパティ・パスはトリプル・パターンの述語位置に出現するもので、トリプル・パターンの主語からトリプル・パターンの目的語までのパスを形成するプロパティ(エッジ)に制約を適用するために、正規表現のような構文を使用します。プロパティ・パスによって、SPARQL問合せはRDFグラフの任意の長さのパスを照合し、他のグラフ・パターンを表現する簡潔な方法を提供できます。

表1-18に、SPARQLプロパティ・パスの構築に使用可能な構文構成要素を示します。iriはIRIまたは接頭辞の付いた名前で、eltはプロパティ・パス要素で、それ自体が他のプロパティ・パス要素で構成される場合があります。

表1-18 プロパティ・パスの構文の構成要素

構文の構成要素 一致

iri

IRIまたは接頭辞の付いた名前。長さが1のパス。

^elt

逆のパス(目的語から主語へ)。

!iriまたは!(iri1 | … | irin)

否定プロパティ・セット。 iriiのいずれかではないIRI。

!^iriまたは!(iri1 | … | irij | ^irij+1 | … | ^irin)

逆のプロパティを持つ否定プロパティ・セット。iriiまたはirij+1...irinのいずれでもない逆パスのIRI。!^iri!(^iri)の短縮形。プロパティと逆のプロパティの順番は、どちらが先でも問題ありません。順不同で実行されます。

(elt)

グループ・パスelt(カッコは優先順位を制御します)。

elt1 / elt2

elt1elt2の順の順序パス。

elt1 | elt2

elt1またはelt2の代替パス(すべての可能性が試行されます)。

elt*

0個以上のeltのパス。

elt+

1個以上のeltのパス。

elt?

0個または1個のeltのパス。

構文構成要素の優先順位を、高いものから順に示します。

  • IRI、接頭辞の付いた名前

  • 否定プロパティ・セット

  • グループ

  • 単項演算子 *、?、+

  • 単項^逆リンク

  • 二項演算子 /

  • 二項演算子 /

グループ内の優先順位は左から右に評価されます。

プロパティ演算子+および*の特別な考慮事項

通常、+ (プラス記号)と* (アスタリスク)演算子を使用した、完全に無制限のグラフ・トラバースはコストが非常に高くなります。この理由から、デフォルトでは深度制限のある+演算子と*演算子が使用されます。デフォルトの深度制限は10です。また、深度制限の実装は並列で実行できます。ALL_MAX_PP_DEPTH(n) SEM_MATCH問合せオプションまたはMAX_PP_DEPTH(n)インラインHINT0問合せオプティマイザ・ヒントを使用して、深度制限設定を変更できます。完全に無制限のトラバースを実現するには、深度制限を1未満に設定して、CONNECT BYベースの実装に戻ります。

プロパティ・パスの問合せヒント

プロパティ・パス問合せのパフォーマンスに影響するその他の問合せヒントも使用できます。ALLOW_PP_DUP=T問合せオプションを*問合せや+問合せと使用すると、結果の重複を認めることができます。結果の重複が認められると、問合せから最初の行が早く戻されます。また、ALL_USE_PP_HASHおよびALL_USE_PP_NL問合せオプションは、プロパティ・パス表現を評価するときに使用される結合タイプに影響します。同様のUSE_PP_HASHおよびUSE_PP_NLインラインHINT0問合せオプティマイザ・ヒントも使用できます。

例1-66 SPARQLプロパティ・パス(rdfs:subClassOf関係を使用)

例1-66では、プロパティ・パスを使用して、rdfs:subClassOf関係の推移性に基づいてすべての男性を検索しています。プロパティ・パスでは、任意の数の連続的なrdfs:subClassOf関係の一致が可能です。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    '{ ?x foaf:name ?name .
       ?x rdf:type ?t .
       ?t rdfs:subClassOf* :Male }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/') 
                SEM_ALIAS('foaf',' http://xmlns.com/foaf/0.1/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-67 SPARQLプロパティ・パス(foaf:friendOfまたはfoaf:knows関係を使用)

例1-67では、プロパティ・パスを使用して、Scottの親しい友人(foaf:friendOfまたはfoaf:knows関係を使用して2ホップ以内に到達可能な人々)をすべて検索しています。

SELECT name
  FROM TABLE(SEM_MATCH(
    '{ { :Scott (foaf:friendOf | foaf:knows) ?f }
       UNION
       { :Scott (foaf:friendOf | foaf:knows)/(foaf:friendOf | foaf:knows) ?f }
       ?f foaf:name ?name .
       FILTER (!sameTerm(?f, :Scott)) }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/'),
                SEM_ALIAS('foaf',' http://xmlns.com/foaf/0.1/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-68 プロパティ・パスの最大深度値の指定

例1-68では、ALL_MAX_PP_DEPTH(n)問合せオプション値を使用してすべてのプロパティ・パス表現に最大深度12を指定します。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    '{ ?x foaf:name ?name .
       ?x rdf:type ?t .
       ?t rdfs:subClassOf* :Male }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/') 
                SEM_ALIAS('foaf',' http://xmlns.com/foaf/0.1/')),
    null,
    null,
    ' ALL_MAX_PP_DEPTH(12) ', 
    null, null,
    'RDFUSER', 'NET1'));

例1-69 プロパティ・パス結合ヒントの指定

例1-69に、プロパティ・パス表現の評価にネステッド・ループ結合をリクエストするインラインHINT0問合せオプティマイザ・ヒントを示します。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    '{ # HINT0={ USE_PP_NL }
       ?x foaf:name ?name .
       ?x rdf:type ?t .
       ?t rdfs:subClassOf* :Male }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/') 
                SEM_ALIAS('foaf',' http://xmlns.com/foaf/0.1/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

1.7.8 グラフ・パターン: SPARQL 1.1のフェデレーテッド問合せのサポート

SEM_MATCHは、SPARQL 1.1のフェデレーテッド問合せをサポートしています(http://www.w3.org/TR/sparql11-federated-query/#SPROTを参照)。SERVICE構成要素を使用して、指定したSPARQLエンドポイントURLから結果を取得できます。この機能により、ローカルのRDFデータ(ネイティブRDFデータまたはリレーショナル・データのRDFビュー)を、W3C標準準拠のSPARQLエンドポイントによって提供される他のRDFデータ(おそらくリモート)と組み合せることができます。

例1-70 すべてのトリプルを取得するSPARQL SERVICE句

例1-70は、SERVICE句を使用して、http://www.example1.org/sparqlにあるSPARQLエンドポイントからすべてのトリプルを取得する問合せです。

SELECT s, p, o
  FROM TABLE(SEM_MATCH(
    'SELECT ?s ?p ?o
     WHERE {
       SERVICE <http://www.example1.org/sparql>{ ?s ?p ?o }
     }',
    SEM_Models('electronics'),
    null, null, null, null, ' ', 
    null, null,
    'RDFUSER', 'NET1'));

例1-71 リモートとローカルのRDFデータを結合するSPARQL SERVICE句

例1-71は、リモートRDFデータとローカルRDFデータを結合します。この例は、ローカルRDFグラフelectronicsのカメラのタイプ?cTypeを、http://www.example1.org/sparqlのSPARQLエンドポイントのカメラの名前?nameに結合します。

SELECT cType, name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?cType ?name
     WHERE {
       ?s :cameraType ?cType
       SERVICE <http://www.example1.org/sparql>{ ?s :name ?name }
      }',
    SEM_Models('electronics'),
    null, null, null, null, ' ', 
    null, null,
    'RDFUSER', 'NET1'));

1.7.8.1 フェデレーテッドSPARQL問合せの実行に必要な権限

SEM_MATCH問合せでSERVICE構成要素を使用するには、特定のデータベース権限が必要です。SPARQL_SERVICE関数に対するEXECUTE権限は、DBA権限を持つユーザーが付与する必要があります。次の例では、このアクセス権をRDFUSERというユーザーに付与しています。

grant execute on sparql_service to rdfuser;

また、アクセス制御リスト(ACL)を使用して、フェデレーテッド問合せを試行するユーザーにCONNECT権限を付与する必要があります。例1-72は、新しいACLを作成して、ユーザーRDFUSERにCONNECT権限を付与し、ドメイン*をACLに割り当てます。ACLの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

例1-72 アクセス制御リストとホスト割当て

dbms_network_acl_admin.create_acl (
  acl       => 'rdfuser.xml',
  description => 'Allow rdfuser to query SPARQL endpoints',
  principal => 'RDFUSER',
  is_grant  => true,
  privilege => 'connect'
);
 
dbms_network_acl_admin.assign_acl (
  acl  => 'rdfuser.xml',
  host => '*'
);      

必要な権限が付与されると、SEM_MATCHからフェデレーテッド問合せを実行する準備が整います。

1.7.8.2 SPARQL SERVICEの結合プッシュ・ダウン

SPARQL SERVICEの結合プッシュ・ダウン(SERVICE_JPDWN=T)機能を使用すると、特定のSPARQL SERVICE問合せのパフォーマンスを改善できます。デフォルトでは、SERVICE句の問合せパターンがリモートSPARQLエンドポイントで最初に実行されます。このリモート実行のすべての結果が、問合せのローカルの部分に結合されます。この方法では、問合せのローカル部分の選択性が非常に高く、問合せのリモート部分の選択性が非常に低いと、パフォーマンスが低下することがあります。

SPARQL SERVICEの結合プッシュ・ダウン機能は、SERVICE句を複数含む問合せでは使用できません。

例1-73 SPARQL SERVICEの結合プッシュ・ダウン

例1-73に、SPARQL SERVICEの結合プッシュ・ダウン機能を示します。

SELECT s, prop, obj
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?s ?prop ?obj
     WHERE {
       ?s rdf:type   :Camera .
       ?s :modelName "Camera 12345"
       SERVICE <http://www.example1.org/sparql> { ?s ?prop ?obj }
      }',
    SEM_Models('electronics'),
    null, null, null, null, ' SERVICE_JPDWN=T ', 
    null, null,
    'RDFUSER', 'NET1'));

例1-73では、問合せのローカル部分ではごく少数の行が返されますが、問合せのリモート部分は完全に無制限であるためリモート・データセット全体が返されます。SERVICE_JPDWN=Tオプションが指定されると、SEM_MATCHはネステッド・ループ方式の評価を実行します。まず、問合せのローカル部分を実行してから、ローカル部分によって返された行ごとに、変更したリモート問合せを1回ずつ実行します。結合変数?sにかわって効率よく実行するFILTER句を使用してリモート問合せを変更します。たとえば、<urn:camera1><urn:camera2>?sのバインディングとして例1-73のローカル部分から返されると、2つの問合せ、{ ?s ?prop ?obj FILTER (?s = <urn:camera1>) }{ s ?prop ?obj FILTER (?s = <urn:camera2>) }がリモート・エンドポイントに送られます。

1.7.8.3 SPARQL SERVICE SILENT

SILENTキーワードがフェデレーテッド問合せで使用されるとき、指定されたリモートSPARQLエンドポイントにアクセスする際のエラーが無視されます。SERVICE SILENTリクエストが失敗すると、バインディングなしの1つの解が返されます。

例1-74は、OPTIONAL句内でSILENTキーワードと一緒にSERVICEを使用しています。このため、http://www.example1.org/sparqlにアクセスする際に接続エラーが発生しても、そのようなエラーは無視され、トリプル?s :cameratype ?kから取得されたすべての行が?nのnull値と結合されます。

例1-74 SILENTキーワードを含むSPARQL SERVICE

SELECT s, n
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?s ?n
     WHERE {
       ?s :cameraType ?k
       OPTIONAL { SERVICE SILENT <http://www.example1.org/sparql>{ ?k :name ?n } }
      }',
    SEM_Models('electronics'),
    null, null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

1.7.8.4 SPARQL SERVICEでのプロキシ・サーバーの使用

次の方法を使用して、SPARQL SERVICEリクエストをHTTPプロキシで送信できます。

  • 現在のセッションでリクエストに使用する必要があるHTTPプロキシを指定します。これは、UTL_HTTPパッケージのSET_PROXY関数を使用して行うことができます。例1-75は、HTTPリクエストで使用するプロキシproxy.example.comを設定し、ドメインexample2.comのホストに対するリクエストを除外します。(SET_PROXYプロシージャの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。)

  • SPARQL SERVICEリクエストのプロキシ・アドレスを設定できるようにするSERVICE_PROXY SEM_MATCHオプションを使用します。ただし、このケースでは例外を指定できません。すべてのリクエストは指定したプロキシ・サーバーに送信されます。例1-76に、ポート80のプロキシ・アドレスproxy.example.comが指定されたSEM_MATCH問合せを示します。

例1-75 UTL_HTTP.SET_PROXYでのプロキシ・サーバーの設定

BEGIN
  UTL_HTTP.SET_PROXY('proxy.example.com:80', 'example2.com');
END;
/

例1-76 SPARQL SERVICEでのプロキシ・サーバーの設定

SELECT *
  FROM TABLE(SEM_MATCH(
    'SELECT *
     WHERE {
       SERVICE <http://www.example1.org/sparql>{ ?s ?p ?o }
      }',
    SEM_Models('electronics'),
    null, null, null, null, ' SERVICE_PROXY=proxy.example.com:80 ', 
    null, null,
    'RDFUSER', 'NET1'));

1.7.8.5 HTTP基本認証でのSPARQLエンドポイントへのアクセス

HTTP基本認証でSPARQLエンドポイントへのアクセスを許可するには、ユーザー資格証明をセッション・コンテキストSDO_SEM_HTTP_CTXに保存する必要があります。DBA権限を持つユーザーが、基本認証の使用を希望するユーザーにこのコンテキストのEXECUTEを付与する必要があります。次の例では、このアクセス権をRDFUSERというユーザーに付与しています。

grant execute on mdsys.sdo_sem_http_ctx to rdfuser;

権限が付与されると、ユーザーは各SPARQLエンドポイントのユーザー名とパスワードをHTTP認証に保存する必要があります。これには、関数mdsys.sdo_sem_http_ctx.set_usrおよびmdsys.sdo_sem_http_ctx.set_pwdを使用します。次の例では、SPARQLエンドポイント(http://www.example1.org/sparql)のユーザー名とパスワードが設定されます。

BEGIN
  mdsys.sdo_sem_http_ctx.set_usr('http://www.example1.org/sparql','user');
  mdsys.sdo_sem_http_ctx.set_pwd('http://www.example1.org/sparql','pwrd');
END;
/

1.7.9 インライン問合せオプティマイザ・ヒント

SEM_MATCHでは、HINT0インライン問合せオプティマイザ・ヒントを許可するために、SPARQLコメント構成要素がオーバーロードされています。SPARQLのハッシュ(#)文字は、行のそれ以降の部分がコメントであることを示します。インライン・ヒントを特定のBGPと関連付けるには、HINT0ヒント文字列をSPARQLコメント内に配置し、開始中カッコ({)とBGPの最初のトリプル・パターンの間にコメントを挿入します。インライン・ヒントを使用すると、問合せ内の各BGPの実行計画に影響を与えることができます。

インライン・オプティマイザ・ヒントは、options引数を使用してSEM_MATCHに渡されるすべてのヒントをオーバーライドします。たとえば、インライン・オプティマイザ・ヒントを指定していない各BGPには、グローバルALL_ORDEREDヒントが適用されますが、インライン・ヒントを持つBGPには、ALL_ORDEREDヒントではなくインライン・ヒントが使用されます。

例1-77 インライン問合せオプティマイザ・ヒント (BGP_JOIN)

次の例は、インライン問合せオプティマイザ・ヒントを含む問合せです。

SELECT x, y, hp, cp
  FROM TABLE(SEM_MATCH(
    '{ # HINT0={ LEADING(t0) USE_NL(?x ?y ?bd) }
      ?x :grandParentOf ?y . ?x rdf:type :Male . ?x :birthDate ?bd
      OPTIONAL { # HINT0={ LEADING(t0 t1) BGP_JOIN(USE_HASH) }
                 ?x :homepage ?hp . ?x :cellPhoneNum ?cp }
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

BGP_JOINヒントはBGP結合間に影響を与えるもので、BGP_JOIN(<join_type>)という構文を使用します(<join_type>はUSE_HASHまたはUSE_NLです)。例1-77では、BGP_JOIN(USE_HASH)ヒントを使用して、OPTIONAL BGPをその親BGPと結合する場合にハッシュ結合を使用する必要があることを指定しています。

インライン・オプティマイザ・ヒントは、options引数を使用してSEM_MATCHに渡されるすべてのヒントをオーバーライドします。たとえば、インライン・オプティマイザ・ヒントを指定していない各BGPには、グローバルALL_ORDEREDヒントが適用されますが、インライン・ヒントを持つBGPには、ALL_ORDEREDヒントではなくインライン・ヒントが使用されます。

例1-78 インライン問合せオプティマイザ・ヒント (ANTI_JOIN)

ANTI_JOINヒントは、NOT EXISTS句およびMINUS句の評価に影響を与えます。このヒントは、ANTI_JOIN(<join_type>)という構文で使用されます。ここで、<join_type>はHASH_AJ, NL_AJまたはMERGE_AJです。次の例では、ハッシュ非結合を使用するよう指定するヒントが使用されています。グローバルのALL_AJ_HASH、ALL_AJ_NL、ALL_AJ_MERGEをSEM_MATCHのオプション引数に使用して、問合せ全体で、すべてのNOT EXISTS句およびMINUS句に影響を与えることができます。

SELECT x, y
  FROM TABLE(SEM_MATCH(
    'SELECT ?x ?y
     WHERE {
       ?x :grandParentOf ?y . ?x rdf:type :Male . ?x :birthDate ?bd
       FILTER ( 
         NOT EXISTS {# HINT0={ ANTI_JOIN(HASH_AJ) }
                     ?x :homepage ?hp . ?x :cellPhoneNum ?cp })
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-79 インライン問合せオプティマイザ・ヒント(NON_NULL)

SPARQL SELECT句では、特定の変数が常にバインドされている(つまり結果の各行にはNULLでない値が含まれている)ことを示すHINT0={ NON_NULL}がサポートされています。このヒントにより、SELECTで生成された値に対する結合を問合せコンパイラで最適化できます。考えられるすべてのインプットに対して、式がNULLでない値を生成するとは限らないため、こうした最適化をデフォルトで適用することはできません。SELECT式でNULL値が生成されないことがわかっている場合には、NON_NULLヒントを使用することで、パフォーマンスが著しく向上します。このヒントは、SELECT式の「AS」キーワードの前に行のコメントで指定します。

次の例では、NON_NULLヒント・オプションがSEM_MATCH問合せで使用されており、?full_nameが必ずバインドされていることが明示されています。

SELECT s, t
  FROM TABLE(SEM_MATCH(
    'SELECT * WHERE {
       ?s :name ?full_name
       { SELECT (CONCAT(?fname, " ", ?lname) # HINT0={ NON_NULL }
                 AS ?full_name)
         WHERE { 
           ?t :fname ?fname .
           ?t :lname ?lname } 
         } 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

1.7.10 全文検索

Oracle固有のorardf:textContains SPARQL FILTER関数は、RDF_VALUE$表で全文索引を使用します。この関数は次の構文を使用します(orardf<http://xmlns.oracle.com/rdf/>に展開される組込みの接頭辞です)。

orardf:textContains(variable, pattern)

orardf:textContainsへの最初の引数はローカル変数(つまり、orardf:textContainsフィルタを含むBGPに存在する変数)である必要があり、2つ目の引数は一定のプレーン・リテラルである必要があります。

たとえば、orardf:textContains(x, y)は、xが式yと一致する場合にtrueを返します(yはOracle Text SQL演算子CONTAINSの有効な式です)。そのような式の詳細は、『Oracle Textリファレンス』を参照してください。

orardf:textContainsを使用する前に、RDFネットワークのOracle Text索引を作成する必要があります。そのような索引を作成するには、SEM_APIS.ADD_DATATYPE_INDEXプロシージャを次のように起動します。

EXECUTE SEM_APIS.ADD_DATATYPE_INDEX('http://xmlns.oracle.com/rdf/text', network_owner=>'RDFUSER', network_name=>'NET1');

orardf:textContains(?x, "%abc%")のようなワイルドカード検索のパフォーマンスは、プリフィックス索引と部分文字列索引を使用することで向上します。次の任意のオプションをSEM_APIS.ADD_DATATYPE_INDEXプロシージャに含めることができます。

  • PREFIX_INDEX=TRUE – プリフィックス索引の追加

  • PREFIX_MIN_LENGTH=<number> – プリフィックス索引トークンの最小長さ

  • PREFIX_MAX_LENGTH=<number> – プリフィックス索引トークンの最大長さ

  • SUBSTRING_INDEX=TRUE – 部分文字列索引の追加

  • LOGGING=T – テキスト索引のロギングを有効にします

Oracle Textの索引付け要素の詳細は、『Oracle Textリファレンス』を参照してください。

テキスト索引のあるRDFネットワークに対して大規模バルク・ロードを実行する場合、テキスト索引を削除してバルク・ロードを実行してからテキスト索引を再作成すると、ロード時間全体が短縮される可能性があります。データ型索引の詳細は、「データ型索引の使用」を参照してください。

テキスト索引を作成すると、SEM_MATCH問合せでorardf:textContains FILTER関数を使用できます。例1-80では、orardf:textContainsを使用して、名前が文字AまたはBで始まるすべての祖父を検索しています。

例1-80 全文検索

SELECT x, y, n
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * 
     WHERE { 
       ?x :grandParentOf ?y . ?x rdf:type :Male . ?x :name ?n 
       FILTER (orardf:textContains(?n, " A% | B% ")) }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null, null, ' ', null, null,
   'RDFUSER', 'NET1'));

例1-81 orardf:textScore

副演算子orardf:textScoreorardf:textContainsと組み合わせて使用することで、結果をテキスト一致の程度でランク付けできます。ただし、orardf:textScoreの使用には制限があります。orardf:textScore呼び出しは、対応するorardf:textContains FILTERを含んでいる基本のグラフ・パターンの、すぐ外側にあるSELECT句のSELECT式として記述されている必要があります。その後は、このSELECT式の別名を、問合せの他の箇所で使用することができます。さらに、REWRITE=F問合せヒントを、SEM_MATCHのoptions引数で使用する必要があります。

次の例では、スコアが0.5を超えるテキスト一致を探しています。ここで、orardf:textContainsには呼出しIDを付加して、同じ呼出しIDを持つorardf:textScore呼出しと結び付けられるようにする必要があることに注意してください。呼び出しIDは任意の整数であり、主演算子をその副演算子と照合するために使用されます。

SELECT x, y, n, scr
  FROM TABLE(SEM_MATCH(
    'PREFIX <http://www.example.org/family/>
     SELECT *
     WHERE {
       { SELECT ?x ?y ?n (orardf:textScore(123) AS ?scr)
         WHERE { 
           ?x :grandParentOf ?y . ?x rdf:type :Male . ?x :name ?n 
           FILTER (orardf:textContains(?n, " A% | B% ", 123)) }
       }
       FILTER (?scr > 0.5)
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null,           
    null,
    null,
    ' REWRITE=F ', 
    null, null,
    'RDFUSER', 'NET1'));

例1-82 orardf:like

負荷が大きくないテキスト検索では、orardf:like関数を使用できます。その場合、Oracle SQLのLIKE演算子を使用した単純なテストパターン照合を実行します。orardf:like関数の構文は次のとおりです。

  • orardf:like(string, pattern)
  • orardf:like(string, pattern, flags)

orardf:likeの最初の引数には任意の変数またはRDF語句を指定できます。それに対してorardf:Containsの最初の引数はローカル変数でなければなりません。orardf:likeの最初の引数がURIである場合、照合はURIの接尾辞のみを対象にして行われます。2つ目の引数にはパターン式を指定する必要があります。このとき、次の特殊パターン一致文字を含めることができます。

  • パーセント記号(%)は0個以上の文字を表します。
  • アンダースコアはちょうど1文字を表します。

flags引数は定数文字列である必要があります。フラグ"i"は、大/小文字を区別しない検索を許可するためにサポートされています。

次の例では、パーセント記号(%)をワイルドカードとして使用して、URIがJaで始まるすべての祖父母を検索しています。

SELECT x, y, n
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * 
     WHERE { 
        ?x :grandParentOf ?y . ?y :name ?n 
        FILTER (orardf:like(?x, "Ja%")) }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

次の例では、アンダースコア(_)をワイルドカードとして使用して、名前がJで始まり、その後に2文字が続いてkで終わる、すべての孫を検索しています。大文字と小文字を区別しないフラグ"i"は、検索で大文字と小文字を区別しないようにするために使用されます。

SELECT x, y, n
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * 
     WHERE { 
        ?x :grandParentOf ?y . ?y :name ?n 
        FILTER (orardf:like(?n, "j__k", "i")) 
    }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

orardf:likeの実行効率を高めるために、SEM_APIS.ADD_DATATYPE_INDEXプロシージャを使用し、http://xmlns.oracle.com/rdf/likeをデータ型URIとして、索引を作成できます。この索引によって、最初の引数がローカル変数で、かつ検索パターンの前にある文字がワイルドカードでない場合に、問合せを高速化することができます。ここで基礎となっている索引は、VARCHAR型関数に対する単純な関数ベースのBツリー索引であるため、完全なOracle Text索引よりも保守とストレージに要するコストが低く抑えられます。orardf:likeは、次のようにして作成します。

EXECUTE SEM_APIS.ADD_DATATYPE_INDEX('http://xmlns.oracle.com/rdf/like');

1.7.11 空間のサポート

RDFグラフは、OGC GeoSPARQL標準を介して、およびOracle固有のSPARQL拡張機能を介して空間ジオメトリ・データの記憶域および問合せをサポートしています。ジオメトリ・データはorageo:WKTLiteralogc:wktLiteralogc:gmlLiteralogc:geoJSONLiteralまたはogc:kmlLiteral型付きリテラルとして格納可能で、空間操作用のいくつかの問合せ関数を使用してジオメトリ・データを問い合せることができます。パフォーマンス向上のための空間索引付けも、サポートされます。

orageo<http://xmlns.oracle.com/rdf/geo/>に展開される組込み接頭辞、ogc<http://www.opengis.net/ont/geosparql#>に展開される組込み接頭辞、ogcf<http://www.opengis.net/def/function/geosparql>に展開される組込み接頭辞です。

1.7.11.1 OGC GeoSPARQLのサポート

RDFグラフは、Well-Known Text (WKT)シリアライズとシンプル・フィーチャのリレーション・ファミリを使用して、OGC GeoSPARQL標準(http://www.opengeospatial.org/standards/geosparql)に準拠する次のクラスをサポートします。

  • コア
  • トポロジ・ボキャブラリ拡張(シンプル・フィーチャ)
  • ジオメトリ拡張(WKT、1.2.0)
  • ジオメトリ・トポロジ拡張(シンプル・フィーチャ、WKT、1.2.0)
  • RDFS伴意拡張(シンプル・フィーチャ、WKT、1.2.0)

RDFグラフでは、Geography Markup Language (GML)シリアライズおよびシンプル・フィーチャのリレーション・ファミリを使用して、OGC GeoSPARQLに準拠する次のクラスをサポートします。

  • コア
  • トポロジ・ボキャブラリ拡張(シンプル・フィーチャ)
  • ジオメトリ拡張(GML、3.1.1)
  • ジオメトリ・トポロジ拡張(シンプル・フィーチャ、GML、3.1.1)
  • RDFS伴意拡張(シンプル・フィーチャ、GML、3.1.1)

RDFグラフでは、Geographic JavaScript Object Notation (GeoJSON)シリアライズおよびシンプル・フィーチャのリレーション・ファミリを使用して、OGC GeoSPARQLに準拠する次のクラスをサポートします。

  • コア
  • トポロジ・ボキャブラリ拡張(シンプル・フィーチャ)
  • ジオメトリ拡張(GeoJSON、1.0)
  • ジオメトリ・トポロジ拡張(シンプル・フィーチャ、GeoJSON、1.0)
  • RDFS伴意拡張(シンプル・フィーチャ、GeoJSON、1.0)

RDFグラフでは、Keyhole Markup Language (KML)シリアライズおよびシンプル・フィーチャのリレーション・ファミリを使用して、OGC GeoSPARQLに準拠する次のクラスをサポートします。

  • コア
  • トポロジ・ボキャブラリ拡張(シンプル・フィーチャ)
  • ジオメトリ拡張(KML、2.1)
  • ジオメトリ・トポロジ拡張(シンプル・フィーチャ、KML、2.1)
  • RDFS伴意拡張(シンプル・フィーチャ、KML、2.1)

GeoSPARQLを使用した空間データの表現および問合せの詳細は、以降の項で説明します。

1.7.11.2 RDFでの空間データの表現

空間ジオメトリは、RDFでorageo:WKTLiteralogc:wktLiteralogc:gmlLiteralogc:geoJSONLiteralまたはogc:kmlLiteral型付きリテラルとして表現できます。このドキュメントでは、ジオメトリ・リテラルという用語は、これら5つのリテラル・タイプのいずれかであるRDFリテラルを指すために使用しています。

例1-83 orageo:WKTLiteralとして表現される空間点ジオメトリ

次の例では、単純な点ジオメトリのorageo:WKTLiteralエンコーディングを示します。

"Point(-83.4 34.3)"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral>

例1-84 ogc:wktLiteralとして表現される空間点ジオメトリ

次の例では、前の例と同じ点のogc:wktLiteralエンコーディングを示します。

"Point(-83.4 34.3)"^^<http://www.opengis.net/ont/geosparql#wktLiteral>

orageo:WKTLiteralogc:wktLiteralエンコーディングはどちらも、オプションの空間参照システムURIと、それに続くWell-Known Text(WKT)文字列(ジオメトリ値をエンコードする)で構成されます。空間参照システムURIとWKT文字列は、空白文字で分離する必要があります。

サポートされる空間参照システムURIは、<http://www.opengis.net/def/crs/EPSG/0/{srid}>という形式を取ります({srid}は、European Petroleum Survey Group (EPSG)によって定義される有効な空間参照システムIDです)。EPSGジオメトリック・パラメータ・データセットに含まれないURIの場合、使用される空間参照システムURIは、<http://xmlns.oracle.com/rdf/geo/srid/{srid}>という形式を取ります({srid}は、Oracle Spatialの有効な空間参照システムIDです)。ジオメトリ・リテラル値に空間参照システムURIが含まれない場合、デフォルトの空間参照システムのWGS84経度-緯度(URI <http://www.opengis.net/def/crs/OGC/1.3/CRS84>)が使用されます。問合せ文字列内にジオメトリ・リテラル値が見つかると、同じデフォルトの空間参照システムが使用されます。

例1-85 ogc:gmlLiteralとして表現される空間点ジオメトリ

次の例では、点ジオメトリのogc:gmlLiteralエンコーディングを示します。

"<gml:Point srsName=\"urn:ogc:def:crs:EPSG::8307\" xmlns:gml=\"http://www.opengis.net/gml\"><gml:posList srsDimension=\"2\">-83.4 34.3</gml:posList></gml:Point>"^^<http://www.opengis.net/ont/geosparql#gmlLiteral>

ogc:gmlLiteralエンコーディングは、GM_Objectのサブタイプを実装するGMLスキーマの有効な要素で構成されます。WKTリテラルとは異なり、GMLエンコーディングには空間参照システム情報が明示的に含まれるため、空間参照システムURIの接頭辞が不要です。

例1-86 ogc:geoJSONLiteralとして表現される空間ポリゴン・ジオメトリ

次の例では、ポリゴン・ジオメトリの有効なogc:geoJSONLiteralエンコーディングを示します。

"{ \"type\": \"Polygon\", \"coordinates\": [ [ [-75, 44], [-75, 42], [-72, 42], 
[-72, 45], [-74, 45], [-75, 44] ] ] }"^^<http://www.opengis.net/ont/geosparql#geoJSONLiteral>

ogc:geoJSONLiteralエンコーディングは、ジオメトリ・オブジェクトの有効なGeoJSONシリアライズで構成されます。ogc:geoJSONLiteralsは常に、WGS84測地経度-緯度空間参照システムを使用して解釈されます。

例1-87 ogc:kmlLiteralとして表現される空間ポリゴン・ジオメトリ

次の例では、ポリゴン・ジオメトリのogc:kmlLiteralエンコーディングを示します。

"<Polygon><extrude>0</extrude><tessellate>0</tessellate><altitudeMode>relativeToGround</altitudeMode>
<outerBoundaryIs><LinearRing><coordinates>-73.0,44.0 -71.0,44.0 -71.0,47.0 -73.0,47.0 -73.0,44.0 </coordinates>
</LinearRing></outerBoundaryIs></Polygon>"^^<http://www.opengis.net/ont/geosparql#kmlLiteral>

ogc:kmlLiteralエンコーディングは、有効なKMLジオメトリ・シリアライズで構成されます。ogc:kmlLiteralsは常に、WGS84測地経度-緯度空間参照システムを使用して解釈されます。

いくつかのジオメトリ・タイプは、点、線ストリング、ポリゴン、多面体面、三角形、TIN、複数点、複数の線ストリング、複数のポリゴンおよびジオメトリ・コレクションを含む、ジオメトリ・リテラル値として表現できます。2次元ジオメトリでは、1ジオメトリ当たり最大500,000の頂点がサポートされます。

例1-88 ogc:wktLiteral値を使用してエンコードされる空間データ

次の例では、ogc:wktLiteral値を使用してエンコードされるRDF空間データ(N-triple形式)をいくつか示します。この例では、最初の2つのジオメトリ(lot1内)はデフォルトのWGS84座標系(SRID 4326)を使用し、その他の2つのジオメトリ(lot2内)はSRID 4269を指定しています。

# spatial data for lot1 using the default WGS84 Longitude-Latitude spatial reference system
<urn:lot1> <urn:hasExactGeometry> "Polygon((-83.6 34.1, -83.6 34.5, -83.2 34.5, -83.2 34.1, -83.6 34.1))"^^<http://www.opengis.net/ont/geosparql#wktLiteral> .
<urn:lot1> <urn:hasPointGeometry> "Point(-83.4 34.3)"^^<http://www.opengis.net/ont/geosparql#wktLiteral> .
# spatial data for lot2 using the NAD83 Longitude-Latitude spatial reference system
<urn:lot2> <urn:hasExactGeometry> "<http://www.opengis.net/def/crs/EPSG/0/4269> Polygon((-83.6  34.1, -83.6 34.3, -83.4 34.3, -83.4 34.1, -83.6 34.1))"^^<http://www.opengis.net/ont/geosparql#wktLiteral> .
<urn:lot2> <urn:hasPointGeometry> "<http://www.opengis.net/def/crs/EPSG/0/4269> Point(-83.5 34.2)"^^<http://www.opengis.net/ont/geosparql#wktLiteral> .

詳細は、Oracle Spatial開発者ガイドの座標系(空間参照システム)に関する章を参照してください。Open Geospatial Consortium (OGC)のシンプル・フィーチャのドキュメント(http://www.opengeospatial.org/standards/sfa)で、WKTジオメトリ表現に関する資料も参照してください。

1.7.11.3 ジオメトリの検証

空間データを操作する前に、RDFグラフに無効なジオメトリ・リテラルが格納されていないことを確認する必要があります。プロシージャSEM_APIS.VALIDATE_GEOMETRIESを使用すると、RDFグラフのジオメトリを検証できます。ジオメトリは、入力SRIDおよび許容値を使用して検証します。(SRIDおよび許容値の詳細は、「空間データの索引付け」を参照してください。)

無効なジオメトリが存在する場合、{graph_name}_IVG$という名前の表がユーザー・スキーマに作成されます({graph_name}は指定したRDFグラフの名前です)。このような表には、無効なジオメトリ・リテラルごとに、RDF_VALUE$表のジオメトリ・リテラルのvalue_id、ジオメトリが有効でない理由を説明するエラー・メッセージおよびジオメトリが修正できる場合は修正されたジオメトリ・リテラルが含まれます。ジオメトリの検証の詳細は、Oracle SpatialサブプログラムSDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXTおよびSDO_GEOM.VALIDATE_LAYER_WITH_CONTEXTのリファレンス情報を参照してください。

例1-89 RDFグラフのジオメトリの検証

次の例では、SRID=8307およびtolerance=0.1を使用してRDFグラフmを検証します。

-- Validate
EXECUTE sem_apis.validate_geometries(RDF graph_name=>'m',SRID=>8307,tolerance=>0.1, network_owner=>'RDFUSER', network_name=>'NET1');-- Check for invalid geometries
SELECT original_vid, error_msg, corrected_wkt_literal FROM M_IVG$;

1.7.11.4 空間データの索引付け

任意のSPARQL拡張関数(「空間データの問合せ」を参照)を使用して空間データを問い合せる前に、SEM_APIS.ADD_DATATYPE_INDEXプロシージャをコールしてRDFネットワークに空間索引を作成する必要があります。

空間索引を作成する場合、次の情報を指定する必要があります。

  • SRID - 空間索引を作成する空間参照システムのID。Oracle Spatial and Graphからの任意の有効な空間参照システムIDを、SRID値として使用できます。

    ノート:

    Oracle Spatial StudioなどのWebベースのマッピング・アプリケーションで地理空間RDFデータを使用する予定の場合は、データをWGS84経度緯度(SRID 4326または8307)に事前に変換し、また、空間索引にSRID 4326または8307を使用することをお薦めします。これにより、マップでの表示のためにWGS84経度緯度への座標変換が繰り返されなくなるため、パフォーマンスが向上します。
  • TOLERANCE: 空間索引の許容値。許容値は、2つの点が同じ点とみなされるためにどの程度近接している必要があるかを示す正数です。この値の単位は、使用されるSRIDのデフォルト単位によって決定されます(たとえば、WGS84経度/緯度の場合はメートル)。許容値の詳細は、Oracle Spatial開発者ガイドを参照してください。

  • DIMENSIONS - 空間索引のテキスト文字列エンコーディングの次元情報。各次元は、カンマ区切りの一連の3つの値(名前、最小値および最大値)で表現されます。各次元をカッコで囲み、それらの次元のセットを外側のカッコで囲みます。

例1-90 RDFデータ上の空間データ型索引の追加

例1-90では、RDFネットワーク上の空間データ型索引を追加し、この座標系を使用する空間データの索引付けに関する、WGS84経度-緯度空間参照システム、0.1の許容値、推奨次元を指定しています。TOLERANCE、SRIDおよびDIMENSIONSキーワードでは大/小文字が区別され、サポートされる任意のジオメトリ・リテラル・タイプ(<http://xmlns.oracle.com/rdf/geo/WKTLiteral><http://www.opengis.net/ont/geosparql#wktLiteral> <http://www.opengis.net/ont/geosparql#gmlLiteral><http://www.opengis.net/ont/geosparql#geoJSONLiteral>または<http://www.opengis.net/ont/geosparql#kmlLiteral>)に対してデータ型索引を作成すると、サポートされるすべてのジオメトリ・リテラル・タイプに対して索引が作成されます。たとえば、ogc:wktLiteralの索引を作成すると、orageo:WKTLiteralogc:gmlLiteralogc:geoJSONLiteralおよびogc:kmlLiteralジオメトリ・リテラルも索引付けされます。

EXECUTE sem_apis.add_datatype_index('http://www.opengis.net/ont/geosparql#wktLiteral',  
                    options=>'TOLERANCE=0.1 SRID=8307 DIMENSIONS=((LONGITUDE,-180,180) (LATITUDE,-90,90))', 
                    network_owner=>'RDFUSER', network_name=>'NET1');

RDFネットワークについては1つの空間データ型索引のみサポートされます。RDFネットワークに格納されるジオメトリ・リテラル値は、索引に使用される空間参照システムに自動的に正規化されるため、単一の空間索引では複数の空間参照システムからのジオメトリ・リテラル値を同時にサポートできます。この座標変換は、索引付けと空間の計算に対して透過的に行われます。ジオメトリ・リテラル値がSEM_MATCH問合せから戻されるときは、元の未変換のジオメトリが戻されます。

空間索引の詳細は、Oracle Spatial開発者ガイドの空間データの索引付けと問合せに関する章を参照してください。

例1-91 RDFデータでの空間データ型の実体化された索引の追加

空間データを操作する際、ジオメトリ・リテラルからジオメトリ・オブジェクトへの変換が必要になる場合がありますが、変換によってはパフォーマンスが低下することがあります。このような状況を回避するため、格納されているすべてのジオメトリ・リテラルを、索引の作成時にSDO_GEOMETRYオブジェクトに変換して実体化できます。

これは、空間データ型索引の追加時にMATERIALIZE=Tオプションを使用すると実現できます。索引付けするジオメトリ・リテラルの量が大量の場合は、オプションINS_AS_SEL=Tを使用すると、実体化された索引の作成の高速化に役立つことがあります。

次の例に、実体化された空間索引の作成を示します。

EXECUTE sem_apis.add_datatype_index('http://www.opengis.net/ont/geosparql#wktLiteral',  
             options=>'TOLERANCE=0.1 SRID=8307 DIMENSIONS=((LONGITUDE,-180,180) (LATITUDE,-90,90)) MATERIALIZE=T ');

例1-92 RDFデータでの3D空間データ型索引の追加

Oracle Spatialでは、3つの座標を持つ空間索引を作成できます。3D索引を作成するには、SEM_APIS.ADD_DATATYPE_INDEXプロシージャのoptions引数でSDO_INDX_DIMS=3オプションを指定する必要があります。

次の例に、3Dデータの作成および索引付けを示します。座標は(X, Y, Z)の順に指定され、外側のポリゴン境界の線形の輪は反時計回りに指定されていることに注意してください。

ノート: 制限を含め、3Dデータでのジオメトリ操作のサポートの詳細は、3次元空間オブジェクトに関する項を参照してください。

conn rdfuser/<password>;

create table geo3d_tab(tri sdo_rdf_triple_s);

exec sem_apis.create_sem_model('geo3d','geo3d_tab','tri');

-- 3D Polygon
insert into geo3d_tab(tri) values(sdo_rdf_triple_s('geo3d','<http://example.org/ApplicationSchema#A>', 
                                  '<http://example.org/ApplicationSchema#hasExactGeometry>', 
                                  '<http://example.org/ApplicationSchema#AExactGeom>'));
insert into geo3d_tab(tri) values(sdo_rdf_triple_s('geo3d','<http://example.org/ApplicationSchema#AExactGeom>', 
                                  '<http://www.opengis.net/ont/geosparql#asWKT>', 
                                  '"<http://xmlns.oracle.com/rdf/geo/srid/31468> Polygon ((4467504.578 5333958.396 513.9, 
                                                                  4467508.939 5333956.379 513.9, 
                                                                  4467509.736 5333958.101 513.9, 
                                                                  4467505.374 5333960.118 513.9, 
                                                                  4467504.578 5333958.396 513.9))"^^<http://www.opengis.net/ont/geosparql#wktLiteral>'));

-- 3D Point at same elevation as Polygon
insert into geo3d_tab(tri) values(sdo_rdf_triple_s('geo3d','<http://example.org/ApplicationSchema#B>', 
                                                   '<http://example.org/ApplicationSchema#hasExactGeometry>', 
                                                   '<http://example.org/ApplicationSchema#BExactGeom>'));
insert into geo3d_tab(tri) values(sdo_rdf_triple_s('geo3d','<http://example.org/ApplicationSchema#BExactGeom>', 
                                                   '<http://www.opengis.net/ont/geosparql#asWKT>', 
                                                   '"<http://xmlns.oracle.com/rdf/geo/srid/31468> Point (4467505.000 5333959.000 513.9)"^^<http://www.opengis.net/ont/geosparql#wktLiteral>'));

-- 3D Point at different elevation from Polygon
insert into geo3d_tab(tri) values(sdo_rdf_triple_s('geo3d','<http://example.org/ApplicationSchema#C>', 
                                                   '<http://example.org/ApplicationSchema#hasExactGeometry>', 
                                                   '<http://example.org/ApplicationSchema#CExactGeom>'));
insert into geo3d_tab(tri) values(sdo_rdf_triple_s('geo3d','<http://example.org/ApplicationSchema#CExactGeom>', 
                                                   '<http://www.opengis.net/ont/geosparql#asWKT>', 
                                                   '"<http://xmlns.oracle.com/rdf/geo/srid/31468> Point (4467505.000 5333959.000 13.9)"^^<http://www.opengis.net/ont/geosparql#wktLiteral>'));
commit;

-- Create 3D index
conn system/manager;
exec sem_apis.add_datatype_index('http://www.opengis.net/ont/geosparql#wktLiteral' ,
                                  options=>'TOLERANCE=0.1 SRID=3148 
                                  DIMENSIONS=((x,4386596.4101,4613610.5843) (y,5237914.5325,6104496.9694) (z,0,10000)) 
                                  SDO_INDX_DIMS=3 ');

conn rdfuser/rdfuser;
-- Find geometries within 200 M of my:A
-- Returns only one point because of 3D index
SELECT aGeom, f, fGeom, aWKT, fWKT
FROM TABLE(SEM_MATCH(
 '{ my:A my:hasExactGeometry ?aGeom .
     ?aGeom ogc:asWKT ?aWKT .
     ?f my:hasExactGeometry ?fGeom .
     ?fGeom ogc:asWKT ?fWKT .
     FILTER (orageo:withinDistance(?aWKT, ?fWKT,200,"M") &&
             !sameTerm(?aGeom,?fGeom))
   }',
 SEM_Models('geo3d'),
 null,
 SEM_ALIASES(
  SEM_ALIAS('my','http://example.org/ApplicationSchema#')),
 null));

1.7.11.5 空間データの問合せ

SEM_MATCHで空間問合せを実行するために、複数のSPARQL拡張関数を使用できます。たとえば、空間RDFデータでは、ジオメトリの領域と境界線(長さ)、2つのジオメトリ間の距離、およびジオメトリの重心と最小外接矩形を検出することや、ジオメトリ間の様々な位相関係を確認することができます。

「空間問合せのSEM_MATCHサポート」には、次を含めて使用可能な関数のリファレンスおよび使用方法に関する情報が記載されています。

  • GeoSPARQLの関数

  • Oracle固有の関数

1.7.11.6 GeoSPARQL問合せとのロング・リテラルの使用

ジオメトリ・リテラルは非常に長くなることがあり、SQLインタフェースを使用する際にそれらを表すのにCLOBの使用が必要になります。CLOB定数は、SEM_MATCH問合せで直接使用することはできません。しかし、ユーザー定義のSPARQL関数を使用してCLOB定数をSEM_MATCH問合せにバインドできます。SPARQLの実行にJavaまたはRESTインタフェースを使用する際、SPARQL問合せ文字列で長いジオメトリ・リテラルを直接使用できます。

次の例では、ユーザー定義のSPARQL関数を一時表と組み合せて使用して、SEM_MATCH問合せでCLOBジオメトリを許可します。

例1-93 SPARQL問合せへのCLOB定数のバインド

conn rdfuser/<password>;

-- Create temporary table
create global temporary table local_value$(
 VALUE_TYPE 	 VARCHAR2(10),
 VALUE_NAME     VARCHAR2(4000),
 LITERAL_TYPE	 VARCHAR2(1000),
 LANGUAGE_TYPE	 VARCHAR2(80),
 LONG_VALUE 	 CLOB)
on commit preserve rows;

-- Create user-defined function to transform a CLOB into an RDF term
CREATE OR REPLACE FUNCTION myGetClobTerm
RETURN SDO_RDF_TERM
AS
  term SDO_RDF_TERM;
BEGIN
  select sdo_rdf_term(
      value_type,
      value_name,
      literal_type,
      language_type,
      long_value)
  into term
  from local_value$
  where rownum < 2;

  RETURN term;
END;
/

-- Insert a row with CLOB geometry
insert into local_value$(value_type,value_name,literal_type,language_type,long_value)
values ('LIT','','http://www.opengis.net/ont/geosparql#wktLiteral','','Some_CLOB_WKT');

-- Use the CLOB constant in a SEM_MATCH query
SELECT cdist
FROM table(sem_match(
'{ ?cdist ogc:asWKT ?cgeom 
   FILTER (
     orageo:withinDistance(?cgeom, oraextf:myGetClobTerm(), 200, "M")) }'
,sem_models('gov_all_vm')
,null, null, null, null, ' ALLOW_DUP=T ', null, null
,'RDFUSER', 'NET1'));

1.7.12 フラッシュバック問合せのサポート

フラッシュバック問合せを使用して、過去のデータを返すSEM_MATCH問合せを実行できます。TIMESTAMPまたはシステム変更番号(SCN)の値が、AS_OFヒントを介してSEM_MATCHへ渡されます。AS_OFヒントは、次のいずれかの書式で指定できます。

  • AS_OF[TIMESTAMP,<TIMESTAMP_VALUE>] (ここで、<TIMESTAMP_VALUE>は「YYYY/MM/DD HH24:MI:SS.FF」という形式の、有効なタイムスタンプ文字列です。)

  • AS_OF[SCN,<SCN_VALUE>] (ここで<SCN_VALUE>は有効なSCNです。)

AS_OFヒントは、指定したRDFグラフのトリプルを格納している問合せ対象の表またはビューに対してフラッシュバック問合せ(SELECT AS OF)を実行するために、内部変換されます。これにより、それ以前に存在していたグラフに対する問合せが可能になります。この機能が機能するためには、問合せ対象メタデータ表またはビュー(ネイティブRDFグラフの場合はRDFM_RDF-graph-nameビュー、RDFグラフ・コレクションの場合はSEMU_RDF-collection--nameおよびSEMV_RDF-collection-name、RDFビュー・グラフの場合は基礎となるリレーショナル表)に対するフラッシュバック権限が必要です。たとえば: grant flashback on RDFUSER.NET1#RDFM_FAMILY to scott

RDFデータでフラッシュバック問合せを使用する際の制限

パーティション表に対して、パーティションの追加や削除を行うと、以前のバージョンのパーティション表に対するフラッシュバック問合せが無効化されます。その結果、ネイティブRDFグラフを作成または削除、あるいは推論グラフを作成または削除すると、RDFネットワーク内の以前のバージョンのすべてのネイティブRDFグラフのフラッシュバック問合せが無効になります。したがって、RDFネットワークでフラッシュバック問合せを使用している場合、そうした操作は確実に管理する必要があります。

例1-94 TIMESTAMPを使用したフラッシュバック問合せ

次の例では、AS_OF句を使用してTIMESTAMPを定義しています。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * 
     WHERE { ?x :name ?name }',
    SEM_Models('family'),
    null, null,
    null,null,' AS_OF=[TIMESTAMP,2016/05/02 13:06:03.979546]', 
    null, null,
    'RDFUSER', 'NET1'));

例1-95 SCNを使用したフラッシュバック問合せ

次の例では、AS_OF句を使用してSCNを指定しています。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * 
     WHERE { ?x :name ?name }',
    SEM_Models('family'),
    null, null,
    null,null,' AS_OF=[SCN,1429849]', 
    null, null,
    'RDFUSER', 'NET1'));

1.7.13 問合せパフォーマンスのベスト・プラクティス

この項では、SEM_MATCH表関数を使用してRDFデータを問い合せる場合に推奨される方法について説明します。次のサブセクションが含まれます:

1.7.13.1 xsd:dateTime、xsd:dateおよびxsd:timeを含むFILTER構成要素

デフォルトでは、SEM_MATCHは、xsd:date、xsd:timeおよびxsd:dateTimeの値の比較についてXMLスキーマ標準に準拠しています。この標準に従って2つのカレンダ値のc1とc2を比較すると(c1には明示的にタイムゾーンが指定され、c2にはタイムゾーンが指定されていません)、c2は[c2-14:00, c2+14:00]という間隔に変換されます。c2-14:00 <= c1 <= c2+14:00である場合、比較は未定義となり、常にfalseに評価されます。c1がこの間隔の外部にある場合、比較は定義されます。

ただし、このような比較(タイムゾーンを持つ値とタイムゾーンを持たない値)の評価に必要な追加のロジックによって、カレンダ値が関係するFILTER構成要素を含む問合せの速度が大幅に低下する可能性があります。問合せパフォーマンスを向上させるには、SEM_MATCH表関数のoptionsパラメータにFAST_DATE_FILTER=Tを指定することによって、この追加ロジックを無効にできます。FAST_DATE_FILTER=Tを指定すると、タイムゾーンのないカレンダ値については、すべてグリニッジ標準時(GMT)と想定されます。

FAST_DATE_FILTER=Tを使用すると、(1)データセットのすべてのカレンダ値がタイムゾーンを持つ場合も、(2)データセットのすべてのカレンダ値がタイムゾーンを持たない場合も、問合せの正確性には影響ありません

1.7.13.2 型付きリテラルを含むFILTER構成要素の索引

FILTER構成要素を含むSEM_MATCH問合せの評価では、RDF_VALUE$表の順序列を使用することがよくあります。たとえば、フィルタ(?x < "1929-11-16Z"^^xsd:date)は、ORDER_DATE列を使用します。

索引を使用すると、型付きリテラルを含むフィルタ条件を含む問合せのパフォーマンスを向上させることができます。たとえば、xsd:date索引によって、フィルタ(?x < "1929-11-16Z"^^xsd:date)の評価の速度が向上する場合があります。

これらの索引をオーダー列用に作成、変更および削除するための便利なインタフェースが用意されています。詳細は、「データ型索引の使用」を参照してください。

ただし、RDF_VALUE$表にこれらの索引が存在することで、バルク・ロード操作の速度は大幅に低下する可能性があります。多くの場合、索引付きのままバルク・ロードを実行する場合と比較すると、索引を削除し、バルク・ロードを実行してから索引を再作成する方が高速です。

1.7.13.3 関係式を含むFILTER構成要素

関係式を含むFILTER構成要素には次の推奨事項が適用されます。

  • orardf:sameCanonTerm拡張関数は、すべての場合にIDベースの比較ができるので、2つのRDF用語の同一性を比較する最も効率的な方法です。

  • 標準のSPARQL機能を利用している場合、FILTER句内の2つの変数を比較するには、=または!=よりもsameTerm組込み関数の方が効率が良いため、(たとえば)可能なかぎり(?a = ?b)ではなくsameTerm(?a, ?b)を使用し、(?a != ?b)ではなく(!sameTerm(?a, ?b))を使用します。

  • FILTER式で値を比較するときは、否定の使用を減らすことによってパフォーマンスが向上する場合があります。たとえば、(?x <= "10"^^xsd:int)を評価する方が、式(!(?x > "10"^^xsd:int))を評価するよりも効率的です。

1.7.13.4 オプティマイザ統計と動的サンプリング

問合せオプティマイザに十分な統計を確保することは、優れた問合せパフォーマンスのために非常に重要です。通常は、SEM_PERF.GATHER_STATSプロシージャを使用して、RDFネットワークの基本的な統計が収集されていることを確認する必要があります(「SEM_PERFパッケージのサブプログラム」を参照)。

RDFグラフ本来の柔軟性のため、静的情報ではSEM_MATCH問合せの最適実行計画が生成されない場合があります。通常、動的サンプリングでは、非常によい問合せ実行プランを生成できます。動的サンプリング・レベルは、optimizer_dynamic_samplingパラメータを使用してセッションまたはシステム・レベルで設定することも、dynamic_sampling(level) SQL問合せヒントを使用して個別の問合せレベルで設定することもできます。通常は3から6の間の動的サンプリング・レベルで試すことをお薦めします。動的サンプリングの統計の見積りの詳細は、『Oracle Database SQLチューニング・ガイド』を参照してください。

例1-96では、動的サンプリング・レベルが6のSQLヒントを使用しています。

例1-96 動的サンプリングのSQLヒント

SELECT /*+ DYNAMIC_SAMPLING(6) */ x, y
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * 
     WHERE {
      ?x :grandParentOf ?y . 
      ?x rdf:type :Male . 
      ?x :birthDate ?bd }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null, null, '', null, null,
    'RDFUSER', 'NET1'));

1.7.13.5 複数パーティションの問合せ

複数のRDFグラフ、RDFグラフと推論グラフ、RDFグラフ・コレクションの使用には、次の推奨事項が適用されます。

  • 複数のRDFグラフに対して、またはRDFグラフと推論グラフに対してSEM_MATCH問合せを実行する場合、問い合せるすべてのRDFグラフおよび推論グラフを含むRDFグラフ・コレクション(RDFグラフ・コレクションを参照)を作成してから、この単一のRDFグラフ・コレクションを問い合せると、問合せのパフォーマンスが向上する可能性があります。

  • ALLOW_DUP=T問合せオプションを使用します。このオプションを使用しない場合は、RDFデータの設定済セマンティクを保持するために、問合せ処理中に高コストな(処理に関して)重複除去ステップが必要になります。ただし、このオプションを使用した場合、重複除去ステップは実行されず、パフォーマンスが大幅に向上します。

1.7.13.6 OLTP索引圧縮によるシステムの圧縮

OLTP索引圧縮がサポートされるシステム(Exadataなど)では、RDFネットワークによって使用される一部のBツリー索引の圧縮率を向上させる機能を利用できます。

たとえば、DBAまたはスキーマプライベート・ネットワークの所有者は、次のコマンドを使用して、RDF_VAL_NAMETYLITLNG_IDX索引での圧縮スキームを接頭辞圧縮からOLTP索引圧縮に変更できます。

SQL> alter index rdfuser.net1#RDF_VAL_NAMETYLITLNG_IDX rebuild compress for oltp high;

1.7.13.7 無制限のプロパティ・パス表現

+および*プロパティ・パス演算子では、可能な場合には常に深度制限検索を使用する必要があります。*および+の深度制限実装のパフォーマンスは、大規模なグラフや関連性が高いグラフにおいてはCONNECT BYベースの実装を大幅に上回ります。深度制限10がデフォルトで使用されます。どのグラフでもグラフの直径を超えた深度制限は役立ちません。深度制限の設定の詳細は、「プロパティ・パス」を参照してください。

クラス階層が非常に深いオントロジに対してrdfs:subClassOf+を使用する後方連鎖スタイルの推論は、このルールの例外になることがあります。このようなケースでは、無制限のCONNECT BYベース評価のパフォーマンスが、非常に大きな深度制限(たとえば50)の深度制限評価よりもよくなることがあります。

1.7.13.8 ネストしたループによるプロパティ・パスのプッシュダウン

あるプロパティ・パスに対して無制限のCONNECT BY評価が実行される場合で、しかもそのプロパティ・パスのトリプル・パターンの主語が変数の場合、使用される可能性が最も高いのは、CONNECT BY WITHOUT FILTERING操作です。主語になっているその変数が、問合せ実行時に限られた数の値にバインドされているだけであれば、問合せの実行時にネストしたループを用いる方法(「過負荷のサービスにおけるネストしたループによるプッシュダウン」を参照)を選ぶと良い場合があります。その場合、プロパティ・パスをSERVICE句にプッシュダウンすることができます。またOVERLOADED_NL=Tヒントを使用できます。

たとえば、次に示すような問合せを考えてみます。ここで、無制限のプロパティ・パス検索{ ?s :hasManager+ ?x }はあるものの、トリプル{ ?s :ename "ADAMS" }?sに対して取り得る値の数は限られているものとします。

select s, x
from table(sem_match(
'PREFIX : <http://scott-hr.org#>
 SELECT *
 WHERE {
   ?s :ename "ADAMS" .
   ?s :hasManager+ ?x .
 }',
sem_models('scott_hr_data'),
null,null,null,null,'  ALL_MAX_PP_DEPTH(0) ', null, null,
'RDFUSER', 'NET1'));

この問い合わせは、ネストしたループで実行されるように書き換えることができます。SERVICEグラフで指定されたRDFグラフは、SEM_MATCHコールで指定されたRDFグラフと同じであることに注意してください。

select s, x
from table(sem_match(
'PREFIX : <http://scott-hr.org#>
 SELECT *
 WHERE {
   ?s :ename "ADAMS" .
   service oram:scott_hr_data { ?s :hasManager+ ?x . }
 }',
sem_models('scott_hr_data'),
null,null,null,null,'  ALL_MAX_PP_DEPTH(0) OVERLOADED_NL=T ', null, null,
'RDFUSER', 'NET1'));

ネストしたループを用いたこの例では、{ ?s :hasManager_ ?x }?sの値ごとに1回ずつ評価され、評価のたびに定数が?sに代入されます。定数が主語の位置にあることで、CONNECT BY WITH FILTERING操作が可能になります。この操作により、通常はパフォーマンスが大幅に向上します。

1.7.13.9 グループ化と集計

MINMAXおよびGROUP_CONCAT集計では、不均一なタイプ(たとえば、MAX(?x))の入力についてSPARQLセマンティクを完全にキャプチャするために特別なロジックが必要です。均一入力タイプをコンパイル時に判別できるケース(たとえば、MAX(STR(?x)) - プレーン・リテラル入力)では、組込みSQL集計の最適化を使用できます。通常は、このような最適化によってパフォーマンスが1桁向上します。次のケースは最適化されます。

  • MIN/MAX(<plain literal>)

  • MIN/MAX(<numeric>)

  • MIN/MAX(<dateTime>)

  • GROUP_CONCAT(<plain literal>)

図1-97ではMIN/MAX(<numeric>)最適化を使用しています。

例1-97 集計の最適化

SELECT dept, minSal, maxSal
  FROM TABLE(SEM_MATCH(
    'SELECT ?dept (MIN(xsd:decimal(?sal)) AS ?minSal) (MAX(xsd:decimal(?sal)) AS ?maxSal)
     WHERE
       {?x :salary ?y . 
        ?x :department ?dept }
     GROUP BY ?dept',
    SEM_Models('hr_data'),
    null, null, null, null, '', null, null,
    'RDFUSER', 'NET1'));

1.7.13.10 バインド変数の使用によるコンパイル時間の短縮

問合せによっては、問合せの実行よりも問合せのコンパイルにコストがかかることがあり、小規模な問合せでは、所定の作業量に対するスループットがこれにより制限を受ける場合があります。ワークロードの問合せが、使用される定数でのみ異なる場合、セッションのコンテキストに依存するバインド変数を使用して、SEM_MATCH問合せのコンパイル・ステップを省略できます。JDBCバインド変数およびPL/SQLバインド変数をSPARQL問合せとともに使用する方法の詳細は、SEM_APIS.SPARQL_TO_SQLによるバインド変数の使用も参照してください。

次の例では、セッション・コンテキストをユーザー定義のSPARQL関数と組み合わせて使用し、SEM_MATCH問合せを1回コンパイルしてからその問合せを異なる定数で実行する方法を示します。ここでの基本的な考え方は、セッション・コンテキストからRDF語句を読み取り、それを返すユーザー定義の関数を作成することにあります。この関数では、実行時にSEM_MATCH問合せによりRDF語句の値が読み取られます。したがって、セッション・コンテキスト変数が変化すると、まったく同じSEM_MATCH問合せでも、異なる値が生成されることになります。

conn / as sysdba;
grant create any context to testuser;

conn testuser/testuser;

create or replace package MY_CTXT_PKG as  
  procedure set_attribute(name varchar2, value varchar2);  
  function get_attribute(name varchar2) return varchar2;  
end MY_CTXT_PKG;  
/

create or replace package body MY_CTXT_PKG as  
  procedure set_attribute(  
    name varchar2,  
    value varchar2  
  ) as  
  begin  
    dbms_session.set_context(namespace => 'MY_CTXT',  
                             attribute => name,  
                             value     => value );
  end;  

  function get_attribute(  
    name varchar2  
  ) return varchar2 as  
  begin  
    return sys_context('MY_CTXT', name);  
  end;  
end MY_CTXT_PKG;  
/

create or replace function myCtxFunc(  
  params in SDO_RDF_TERM_LIST  
) return SDO_RDF_TERM  
as  
  name varchar2(4000);  
  arg  SDO_RDF_TERM;  
begin  
  arg := params(1);  
  name := arg.value_name;  
  return SDO_RDF_TERM(my_ctxt_pkg.get_attribute(name));  
end;  
/  

CREATE OR REPLACE CONTEXT MY_CTXT using TESTUSER.MY_CTXT_PKG;

-- Set a value
exec MY_CTXT_PKG.set_attribute('value','<http://www.example.org/family/Martha>');

-- Query using the function
-- Note the use of HINT0={ NON_NULL } to allow the most efficient join
SELECT s, p, o
  FROM TABLE(SEM_MATCH(
    'SELECT ?s ?p ?o
     WHERE {
       BIND (oraextf:myCtxFunc("value") # HINT0={ NON_NULL } 
             AS ?s)
       ?s ?p ?o }',
    SEM_Models('family'),
    null,
    null,
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

-- Set another value
exec MY_CTXT_PKG.set_attribute('value','<http://www.example.org/family/Sammy>');

-- Now the same query runs for Sammy without recompiling
SELECT s, p, o
  FROM TABLE(SEM_MATCH(
    'SELECT ?s ?p ?o
     WHERE {
       BIND (oraextf:myCtxFunc("value") # HINT0={ NON_NULL } 
             AS ?s)
       ?s ?p ?o }',
    SEM_Models('family'),
    null,
    null,
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

1.7.13.11 非NULL式ヒント

共通の変数を持つ複数のグラフ・パターンを用いて無制限になる可能性のある結合を行う場合、パフォーマンスの低下を防ぐために、NULL値を処理するより複雑な結合条件が必要になります。無制限な値は、SELECT式、バインド、OPTIONAL句およびUNIONで発生する可能性があります。多くの場合、SELECT式でNULL値が発生することは考えられません。そのような場合には、インラインのHINT0={ NON_NULL }ヒントを用いて特定のSELECT式がNULL値にならないことを明示するか、DISABLE_NULL_EXPR_JOIN問合せオプションを使用して、すべてのSELECT式でNULL以外の値が生成されることを示すことで、問合せのパフォーマンスが大幅に向上します。

次の例では、変数?fulltitleが常に結合の両端で制限されていることが、グローバルなDISABLE_NULL_EXPR_JOINヒントにより明示されています。(「インライン問合せオプティマイザ・ヒント」も参照してください。)

SELECT s, t
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * WHERE {
       { SELECT ?s (CONCAT(?title, ". ", ?fullname) AS ?fulltitle)
         WHERE { ?s :fullname ?fullname .
                 ?s :title ?title }
       }
       { SELECT ?t (CONCAT(?title, ". ", ?fname, " ", ?lname) AS ?fulltitle)
         WHERE { 
         ?t :fname ?fname .
         ?t :lname ?lname . 
         ?t :title ?title } 
       } 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null,
    null,
    null,
    ' DISABLE_NULL_EXPR_JOIN ', null, null,
    'RDFUSER', 'NET1'));

1.7.13.12 自動結合のヒント

SQLエンジンがHASH結合を使用してトリプル・パターン間の結合を評価する場合、選択性が非常に低いSEM_MATCH問合せの実行は、通常、より高速になります。SEM_MATCHで使用されるSPARQLからSQLへの問合せトランスレータは、このような問合せの自動検出を試行し、オプションの引数文字列に文字列AUTO_HINTS=Tが指定されている場合は、適切なUSE_HASHヒントを自動的に追加しようとします。

次のSEM_MATCH問合せは、AUTO_HINTS=Tを使用してUSE_HASHヒントを自動的に生成します。

SELECT f, l, n, e
  FROM table(sem_match(
        'PREFIX : <http://www.example.com#> 
         SELECT ?f ?l ?n ?e
          WHERE { ?s :fname ?f . ?s :lname ?l . ?s :nickName ?n . ?s :email ?e }',
                sem_models('m1'),
                null,null,null,null,
                ' AUTO_HINTS=T ')
          );

1.7.13.13 RDFネットワーク索引

RDFネットワーク索引(RDFネットワーク索引の使用を参照)は、RDF_LINK$表の一意でないBツリー索引です。ネットワーク所有者およびDBAは、様々なSEM_APISプロシージャを使用してこれらの索引を管理できます。RDF_LINK$で索引付けする列は、索引コードによって識別されます。索引コードは、次の文字の順序です(繰返しなし): PCSGMHindex_codeで使用されたこれらの文字は、RDF_LINK$の次の列に対応しています: P_VALUE_ID (述語)、CANON_END_NODE_ID (目的語)、START_NODE_ID (主語)、G_ID (グラフ)、MODEL_IDおよびH - 関数ベースの索引(MODEL_ID、GID)。

問合せワークロードに適したRDFネットワーク索引のセットを持つことが重要です。バージョン19c以前では、デフォルトの索引設定はPCSGMPSCGMです。バージョン21c以降では、デフォルトの索引設定はPCSGMSPCGMCMHです。

RDFネットワーク索引の一般的な推奨事項は、次のとおりです。

  • ほとんどのSPARQL問合せには、述語がバインドされたトリプル・パターンがあるため、索引セット全体でPPCおよびPSの組合せを先行列としてカバーすることをお薦めします。このような組合せは、デフォルトの索引設定(19cではPCSGMPSCGM、21cではPCSGMSPCGM)によって取得されます。
  • バインドされていない述語({ ?s :ssn 1234 . ?s ?p ?o }など)を含む問合せがある場合、P以外の先頭列を持つネットワーク索引が必要になることがあります。SPCGM索引は、主語になっている変数?sに対する結合のため、この例に適しています。
  • { { <urn:abc> ?p1 ?o1 } UNION { ?s2 ?p2 <urn:abc> } }などのDESCRIBE問合せまたはDESCRIBEスタイル・パターンを実行する場合、先行するS列を持つ索引に加えて、先行するC列(CMなど)を持つネットワーク索引が必要になることがあります。
  • 選択的なFROM、FROM NAMEDまたはGRAPH句を指定したグラフ問合せがある場合、先頭にG列を持つネットワーク索引(GPCSMなど)が必要になることがあります。
  • H索引は、スキーマプライベート・ネットワークでの効率的なSPARQL更新GRAPH操作(DROP GRAPHなど)に必要です。
  • PSCGM索引は、接頭辞圧縮が優れているために通常SPCGM索引よりも小さいので、バインドされていない述語がワークロードに含まれていない場合には、SPCGM索引をPSCGM索引に置き換えると、パフォーマンスが向上する可能性があります。

1.7.13.14 Oracle Database In-MemoryでのRDFの使用

RDF_LINK$表およびRDF_VALUE$表に格納されているRDFデータは、Oracle Database In-Memoryを使用してメモリーにロードできます。SEM_APISプロシージャを使用してRDFデータをメモリーにロードする方法の詳細は、Oracle Database In-MemoryのRDFサポートを参照してください。

一般的に、Oracle Database In-Memoryで最も一貫したパフォーマンスを得るには、RDF_VALUE$のRDF_LINK$ (RDFネットワーク索引)およびRDF_VALUE$表の索引を非表示にすることをお薦めします。ただし、<NETWORK_NAME>#C_PK_VIDおよび<NETWORK_NAME>#RDF_VAL_NAMETYLITLNG_IDX索引は例外です。これらの索引設定は、次のSQLコマンドで実現できます(たとえば、NET1というRDFネットワークがRDFUSERによって所有されている場合)。

exec sem_apis.alter_rdf_indexes('VISIBILITY','N', network_owner=>'RDFUSER', network_name=>'NET1');

alter index NET1#C_PK_VID visible;

alter index NET1#RDF_VAL_NAMETYLITLNG_IDX visible;

非常に選択的な問合せのパフォーマンスは、RDF_LINK$索引が非表示になる場合があるため、問合せワークロードに応じて索引の表示を試す必要がある場合があることに注意してください。

Oracle Database In-Memoryでは、このような索引設定に加えて、パラレル問合せ実行を使用することをお薦めします。多くの場合、パラレル化によるスピードアップが大幅に向上する可能性があるためです。

大規模なデータセット(100Mの3倍以上)の場合、Oracle Database In-Memoryでハッシュ・サブパーティション化されたRDFネットワークを使用することもお薦めします。ハッシュ・サブパーティション化については、「RDFネットワーク」を参照してください。

1.7.13.15 FILTER式での言語タグの使用

言語タグに基づいて問合せ結果をフィルタリングする場合、できるかぎり、LANGMATCHESではなくLANGを使用する方が効率的です。たとえば、単純なフィルタlangMatches(lang(?x), "en")は、より効率的な評価のためにlang(?x) = "en"に置き換えることができます。格納されたRDFリテラルの言語タグは小文字に正規化されるため、このようなフィルタでは、小文字の言語タグ定数を使用する必要があります。

1.7.13.16 より効率的なFILTER評価のための型キャスト

等価以外の演算子(?x < ?yなど)を使用して2つの変数を比較するSPARQL FILTERでは、SPARQLでの型付けが弱いためにパフォーマンスが低下する可能性があります。?xおよび?yのデータ型は問合せのコンパイル時に決定できないため、実行時に複数のデータ型を比較するための複雑なロジックを使用する必要があります。

?xおよび?yがバインドされる値のデータ型がわかっている場合は、式のそれらのデータ型に?xおよび?yをキャストして、問合せコンパイル時に型がわかるようにすることをお薦めします。たとえば、次の問合せでは、より効率的な単一データ型比較のために、FILTER句で給与値をxsd:decimalにキャストします。

SELECT ?y
WHERE { 
  :emp1 :salary ?s1 . 
  ?y :salary ?s2 .
  FILTER (xsd:decimal(?s2) < xsd:decimal(?s1))
}

1.7.13.17 GeoSPARQL問合せの空間索引付け

空間索引の作成時に使用されるオプションは、GeoSPARQL問合せのパフォーマンスに大きな影響を与える可能性があります。

最も重要な2つのオプションは次のとおりです。

  • 索引のタイプ: 関数ベースまたはマテリアライズド
  • 空間参照システム: 索引に使用されるSRID

SEM_APIS.ADD_DATATYPE_INDEXは、デフォルトで関数ベースの空間索引を作成します。関数ベース索引は単純なポイント・ジオメトリには十分ですが、データセットにポリゴンまたは線ジオメトリが含まれている場合は、マテリアライズド空間索引を使用する必要があります。マテリアライズド空間索引は、SEM_APIS.ADD_DATATYPE_INDEXのオプション引数にMATERIALIZE=Tを指定することで作成できます。

空間索引に使用されるSRIDもパフォーマンスにとって重要です。オラクル社のGeoSPARQL実装は、様々な空間参照システムでエンコードされたジオメトリ・リテラルをロードできるという点で非常に柔軟です。これらのジオメトリは、索引付けおよび問合せ評価のために単一のSRIDに正規化する必要があります。索引の作成時にこの正規SRIDを指定できます。最適なパフォーマンスを得るには、ジオメトリ・リテラル間で最も一般的なSRIDを選択して、必要な座標変換を最小限に抑える必要があります。

空間索引の作成の詳細は、空間データの索引付けを参照してください。

1.7.14 SEM_MATCH使用時の特別な考慮事項

次の考慮事項は、SEM_MATCHを使用して実行されるSPARQL問合せに適用されます。

  • 値の割当て

    • 値割り当てのソースで未定義の変数が参照されると、コンパイル時にエラーが発生します。

  • グループ化と集計

    • 非グループ化変数(グループ化に使用されないため、射影には妥当でない問合せ変数)は、値割り当てのターゲットとして再利用できません。

    • 数値以外の値は、AVGおよびSUM集計によって無視されます。

    • デフォルトでは、SEM_MATCHは、グラフ・パターンが一致しない集計問合せの場合に行を返しません。W3C仕様では、このケースでは1つのnull行が必要です。STRICT_AGG_CARD=T問合せオプションを使用すると動作がW3Cに準拠しますが、パフォーマンスがわずかに低下します。

  • ORDER BY

    • SEM_MATCHでSPARQL ORDER BYを使用する場合、取り囲んでいるSQLブロック全体を通じて目的の順序を維持するためには、格納側のSQL問合せをSEM$ROWNUMで並べ替える必要があります。

  • 数値計算

    • ネイティブのOracleのNUMBER型はすべての演算処理のために内部的に使用され、すべての算術演算の結果はxsd:decimalとしてシリアライズされます。ネイティブのOracleのNUMBER型は、BINARY_FLOATおよびBINARY_DOUBLEよりも正確です。組込みデータ型NUMBERの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

    • ゼロで除算した場合は、バインドされていない値が生成されるのではなく、ランタイム・エラーが発生します。

  • 否定

    • 潜在的にバインドされていない変数を参照するEXISTSおよびNOT EXISTSフィルタは、次のコンテキストではサポートされません。

      • GROUP BY内の別名のない式

      • 集計への入力

      • ORDER BY内の式

      • OPTIONALグラフ・パターン内に出現しない変数も参照するOPTIONALグラフ・パターン内のFILTER式

      最初の3つのケースは、BIND句またはSELECT式を使用して変数にEXISTSまたはNOT EXISTSフィルタの結果を最初に割り当てることで実現できます。

      これらの制限は、明確にバインドされた変数のみを参照するEXISTSおよびNOT EXISTSフィルタには、当てはまりません

  • 空白ノード

    • 空白ノードは、グラフ・パターン内ではサポートされません。

    • BNODE(literal)関数は、同じリテラル引数でコールされるたびに、同じ空白ノード値を戻します。

  • プロパティ・パス

    • 無制限の演算子+および*は、パフォーマンスの理由からデフォルトでは10ホップの深度制限を使用します。深度制限を0に設定すると、この動作を完全に無制限の検索に変更できます。詳細は、「プロパティ・パス」を参照してください。

  • ロング・リテラル(CLOB)

    • SPARQLの関数と集計は、デフォルトではロング・リテラルをサポートしていません。

    • CLOB_EXP_SUPPORT=T問合せオプションを指定すると、SPARQL関数(IF、COALESCE、STRLANG、STRDT、SUBSTR、STRBEFORE、STRAFTER、CONTAINS、STRLEN、STRSTARTS、STRENDS)でのロング・リテラルのサポートが有効になります。

    • CLOB_AGG_SUPPORT=T問合せオプションを指定すると、集計(MIN、MAX、SAMPLE、GROUP_CONCAT)でのロング・リテラルのサポートが有効になります。

  • RDFリテラルの正規化

    • デフォルトでは、SPARQL関数から返されるRDFリテラルと、値割当て文(BIND、SELECT式、GROUP BY式)で使用される定数RDFリテラルは正規化されます。この動作は、SPARQL 1.1の「D-Entailment Regime」と一致しています。

    • 正規化を無効にするにはPROJ_EXACT_VALUES=T問合せオプションを使用します。