10 RDFビュー: RDFとしてのリレーショナル・データ

RDFセマンティク・グラフのリレーショナル・データ上にRDFビューを作成し、使用できます。

リレーショナル・データは、W3Cドキュメントに説明のあるRDB2RDFマッピングの2つのフォームのうちの1つを使用して、直接マッピングとR2RMLマッピングで仮想RDFトリプルとして表示されます。

この章では、次の項目について説明します。

10.1 リレーショナル・データに対してRDFビューを使用する理由

リレーショナル・データに対してRDFビューを使用することで、SPARQLを使用してリレーショナル・データを問い合せたり、様々なソースからのデータを統合することができます。

リレーショナル・データと一致するRDFトリプルを物理的に格納しなくても、リレーショナル・データの長所を利用することができます。

RDFデータにリレーショナル・データのマッピングを作成する最も単純な方法は、SEM_APIS.CREATE_RDFVIEW_MODELプロシージャをコールしてRDFビュー・モデルを作成し、RDFとして表示する内容の表またはビューのリストを指定することです。これが、それらのリレーショナル表またはビューの直接マッピングになります。

よりカスタマイズされたマッピングを取得するには、SEM_APIS.CREATE_RDFVIEW_MODELプロシージャをコールしてRDFビュー・モデルを作成し、r2rml_stringパラメータで(TurtleまたはN-Triple構文を使用して)R2RMLマッピングを指定します。

10.2 RDFビューのAPIサポート

SEM_APISパッケージには、RDFビューの作成、削除およびエクスポート(つまりRDFビューの実体化)を行うサブプログラムが含まれています。

RDFビュー・モデルはRDFモデルとして作成されますが、物理的にはマッピング・メタデータのみが含まれています。実際のデータは、RDFビュー・モデルが作成されたリレーショナル表に残ります。(SEM_APISサブプログラムの詳細は、「SEM_APISパッケージ・サブプログラム」を参照してください。)

RDFビュー・モデルが作成されると、SEM_APIS.EXPORT_RDFVIEW_MODELサブプログラムを使用して、RDFトリプルをステージング表に実体化することもできます。

この章の例では、リレーショナル表EMPおよびDEPTTESTUSERスキーマに存在するとします(これら2つの表の定義については、10.3項を参照)。また、RDFUSERスキーマが所有するNET1という名前のスキーマプライベート・ネットワークがすでに存在し、RDFUSERがこの2つの表に対するREAD権限を持っているとします。

RDFトリプル・エクスポートの使用を示す例では、マテリアライズドRDFトリプルが格納されるステージング表がTESTUSERによって所有され、ネットワーク所有者がその表に対するINSERT権限を持っているとします。

10.2.1 直接マッピング・モデルによるRDFビュー・モデルの作成

例10-1では、EMPとDEPTの2つの表(これら2つの表の定義については第10.3項を参照)の直接マッピングに、スキーマプライベート・ネットワークでベース接頭辞http://empdb/を使用してRDFビュー・モデルを作成しています。(仮想)RDF語句は、A Direct Mapping of Relational Data to RDF、W3C勧告に従って作成されます。

例10-1 スキーマプライベート・ネットワークでの直接マッピングによるRDFビュー・モデルの作成

BEGIN
  sem_apis.create_rdfview_model(
    model_name => 'empdb_model',
    tables => SYS.ODCIVarchar2List('"TESTUSER"."EMP"', '"TESTUSER"."DEPT"'),
    prefix => 'http://empdb/',
    options => 'KEY_BASED_REF_PROPERTY=T',
    network_owner=>'RDFUSER',
    network_name=>'NET1'
  );
END;
/

生成されたプロパティを表示するには、次の問合せを入力します。

SELECT p
  FROM TABLE(SEM_MATCH(
    'SELECT DISTINCT ?p {?s ?p ?o} ORDER BY ?p',
    SEM_Models('empdb_model'),
    NULL, NULL, NULL, NULL,
    NULL, NULL, NULL,
   'RDFUSER', 'NET1'));
P
--------------------------------------------------------------------------------
http://empdb/TESTUSER.EMP#EMPNO
http://empdb/TESTUSER.EMP#JOB
http://empdb/TESTUSER.EMP#ENAME
http://empdb/TESTUSER.EMP#DEPTNO
http://www.w3.org/1999/02/22-rdf-syntax-ns#type
http://empdb/TESTUSER.EMP#ref-DEPTNO
http://empdb/TESTUSER.DEPT#DEPTNO
http://empdb/TESTUSER.DEPT#DNAME
http://empdb/TESTUSER.DEPT#LOC

9 rows selected.

10.2.2 R2RMLマッピングによるRDFビュー・モデルの作成

2つの表EMPとDEPTを使用してRDFビュー・モデルを独自のカスタマイズで作成するには、Turtleを使用して指定したR2RMLマッピング・ドキュメントを作成します。次に例を示します。

@prefix rr: <http://www.w3.org/ns/r2rml#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix ex: <http://example.com/ns#>.
 
ex:TriplesMap_Dept
    rr:logicalTable [ rr:tableName "TESTUSER.DEPT" ];
    rr:subjectMap [
        rr:template "http://data.example.com/department/{DEPTNO}";
        rr:class ex:Department;
    ];
    rr:predicateObjectMap [
        rr:predicate ex:deptNum;
        rr:objectMap [ rr:column "DEPTNO" ; rr:datatype xsd:integer ];
    ];
    rr:predicateObjectMap [
        rr:predicate ex:deptName;
        rr:objectMap [ rr:column "DNAME" ];
    ];
    rr:predicateObjectMap [
        rr:predicate ex:deptLocation;
        rr:objectMap [ rr:column "LOC" ];
    ].
 
ex:TriplesMap_Emp
    rr:logicalTable [ rr:tableName "TESTUSER.EMP" ];
    rr:subjectMap [
        rr:template "http://data.example.com/employee/{EMPNO}";
        rr:class ex:Employee;
    ];
    rr:predicateObjectMap [
        rr:predicate ex:empNum;
        rr:objectMap [ rr:column "EMPNO" ; rr:datatype xsd:integer ];
    ];
    rr:predicateObjectMap [
        rr:predicate ex:empName;
        rr:objectMap [ rr:column "ENAME" ];
    ];
    rr:predicateObjectMap [
        rr:predicate ex:jobType;
        rr:objectMap [ rr:column "JOB" ];
    ];
    rr:predicateObjectMap [
        rr:predicate ex:worksForDeptNum;
        rr:objectMap [ rr:column "DEPTNO" ; rr:dataType xsd:integer ];
    ];
    rr:predicateObjectMap [
        rr:predicate ex:worksForDept;
        rr:objectMap [ 
          rr:parentTriplesMap ex:TriplesMap_Dept ; 
          rr:joinCondition [ rr:child "DEPTNO"; rr:parent "DEPTNO" ]]].

例10-2 R2RMLマッピング文字列によるRDFビュー・モデルの作成

次の例では、前述のR2RMLマッピングを使用して、R2RML文字列から直接RDFビュー・モデルを作成します。

DECLARE
  r2rmlStr CLOB;

BEGIN

  r2rmlStr := 
   '@prefix rr: <http://www.w3.org/ns/r2rml#>. '||
   '@prefix xsd: <http://www.w3.org/2001/XMLSchema#>. '||
   '@prefix ex: <http://example.com/ns#>. '||'

    ex:TriplesMap_Dept
        rr:logicalTable [ rr:tableName "TESTUSER.DEPT" ];
        rr:subjectMap [
            rr:template "http://data.example.com/department/{DEPTNO}";
            rr:class ex:Department;
        ];
        rr:predicateObjectMap [
            rr:predicate ex:deptNum;
            rr:objectMap [ rr:column "DEPTNO" ; rr:datatype xsd:integer ];
        ];
        rr:predicateObjectMap [
            rr:predicate ex:deptName;
            rr:objectMap [ rr:column "DNAME" ];
        ];
        rr:predicateObjectMap [
            rr:predicate ex:deptLocation;
            rr:objectMap [ rr:column "LOC" ];
        ].'||'

    ex:TriplesMap_Emp
        rr:logicalTable [ rr:tableName "TESTUSER.EMP" ];
        rr:subjectMap [
            rr:template "http://data.example.com/employee/{EMPNO}";
            rr:class ex:Employee;
        ];
        rr:predicateObjectMap [
            rr:predicate ex:empNum;
            rr:objectMap [ rr:column "EMPNO" ; rr:datatype xsd:integer ];
        ];
        rr:predicateObjectMap [
            rr:predicate ex:empName;
            rr:objectMap [ rr:column "ENAME" ];
        ];
        rr:predicateObjectMap [
            rr:predicate ex:jobType;
            rr:objectMap [ rr:column "JOB" ];
        ];
        rr:predicateObjectMap [
            rr:predicate ex:worksForDeptNum;
            rr:objectMap [ rr:column "DEPTNO" ; rr:dataType xsd:integer ];
        ];
        rr:predicateObjectMap [
            rr:predicate ex:worksForDept;
            rr:objectMap [ 
              rr:parentTriplesMap ex:TriplesMap_Dept ; 
              rr:joinCondition [ rr:child "DEPTNO"; rr:parent "DEPTNO" ]]].';

  sem_apis.create_rdfview_model(
    model_name => 'empdb_model',
    tables => NULL,
    r2rml_string => r2rmlStr,
    r2rml_string_fmt => 'TURTLE',
    network_owner=>'RDFUSER',   
    network_name=>'NET1'
  );

END;
/

10.2.3 RDFビュー・モデルの削除

例10-3に示すように、RDFビュー・モデルは、SEM_APIS.DROP_RDFVIEW_MODELプロシージャを使用して削除できます。

例10-3 RDFビュー・モデルの削除

BEGIN
  sem_apis.drop_rdfview_model(
    model_name => 'empdb_model',
    network_owner=>'RDFUSER',   
    network_name=>'NET1'
  );
END;
/

10.2.4 ステージング表へのRDFビュー・モデルの仮想内容のエクスポート

RDFビュー・モデルの内容は仮想、つまり直接マッピングまたはR2RMLマッピングによってマップされ、基礎となるリレーショナル・データに対応するRDFトリプルであり、実体化されず、どこにも格納されていません。SEM_APIS.EXPORT_RDFVIEW_MODELサブプログラムは、RDFビュー・モデルの仮想RDFトリプルをステージング表に実体化します。その後、ステージング表を使用してRDFモデルへロードすることができます。

例10-4 スキーマプライベート・ネットワークでのRDFビュー・モデルのエクスポート

例10-4では、RDFビューempdb_modelの内容をステージング表TESTUSER.R2RTABに実体化(N-Triples形式)します。

BEGIN
  sem_apis.export_rdfview_model(
    model_name => 'empdb_model',
    rdf_table_owner => 'TESTUSER',
    rdf_table_name => 'R2RTAB',
    network_owner => 'RDFUSER',
    network_name => 'NET1'
  );
END;
PL/SQL procedure successfully completed.

10.3 例: 直接マッピングによるRDFビュー・モデルの使用

この項では、直接マッピングによるRDFビュー・モデルの使用例を示します。

直接マッピングによるRDFビュー・モデルを作成および使用するには、次のステップを実行します。

  1. TESTUSERスキーマにEMPおよびDEPTという2つのリレーショナル表を作成し、これらの2つの表に対するREAD権限をRDFUSERに付与します。
    -- Use the following relational tables.
    CREATE TABLE TESTUSER.dept (
      deptno NUMBER CONSTRAINT pk_DeptTab_deptno PRIMARY KEY,
      dname VARCHAR2(30),
      loc VARCHAR2(30)
    );
     
    CREATE TABLE TESTUSER.emp ( 
      empno NUMBER PRIMARY KEY,
      ename VARCHAR2(30),
      job VARCHAR2(20),
      deptno NUMBER REFERENCES dept (deptno)
    );
    
    GRANT READ ON TESTUSER.dept TO RDFUSER;
    
    GRANT READ ON TESTUSER.emp TO RDFUSER;
  2. 表にデータを挿入します。
    -- Insert some data.
     
    INSERT INTO TESTUSER.dept (deptno, dname, loc)
      VALUES (1, 'Sales', 'Boston');
    INSERT INTO TESTUSER.dept (deptno, dname, loc)
      VALUES (2, 'Manufacturing', 'Chicago');
    INSERT INTO TESTUSER.dept (deptno, dname, loc)
      VALUES (3, 'Marketing', 'Boston');
     
    INSERT INTO TESTUSER.emp (empno, ename, job, deptno)
      VALUES (1, 'Alvarez', 'SalesRep', 1);
    INSERT INTO TESTUSER.emp (empno, ename, job, deptno)
      VALUES (2, 'Baxter', 'Supervisor', 2);
    INSERT INTO TESTUSER.emp (empno, ename, job, deptno)
      VALUES (3, 'Chen', 'Writer', 3);
    INSERT INTO TESTUSER.emp (empno, ename, job, deptno)
      VALUES (4, 'Davis', 'Technician', 2);
  3. RDFUSERとして接続し、前のステップで作成および移入された2つの表の直接マッピングを使用して、RDFビュー・モデルempdb_modelを作成します。
    -- Create an RDF view model using direct mapping of two tables, EMP and DEPT, 
    -- with a base prefix of http://empdb/.
    -- Specify KEY_BASED_REF_PROPERTY=T for the options parameter.
    
    
    BEGIN
      sem_apis.create_rdfview_model(
        model_name => 'empdb_model',
        tables => SYS.ODCIVarchar2List('"TESTUSER"."EMP"', '"TESTUSER"."DEPT"'),
        prefix => 'http://empdb/',
        options => 'KEY_BASED_REF_PROPERTY=T'
        network_owner=>'RDFUSER',
        network_name=>'NET1'
      );
    END;
    /
  4. SEM_MATCHベースのSQL問合せを使用して、新しく作成したRDFビュー・モデルを問い合せます。
    SELECT emp
      FROM TABLE(SEM_MATCH(
        'PREFIX dept: <http://empdb/TESTUSER.DEPT#>
         PREFIX emp: <http://empdb/TESTUSER.EMP#>
         SELECT ?emp {?emp emp:ref-DEPTNO ?dept . ?dept dept:LOC "Boston"}',
        SEM_Models('empdb_model'),
        NULL,
        NULL,
        NULL, NULL,NULL, NULL,NULL, 'RDFUSER', 'NET1'));
    
    EMP
    --------------------------------------------------------------------------------
    http://empdb/TESTUSER.EMP/EMPNO=1
    http://empdb/TESTUSER.EMP/EMPNO=3

    このステップに示されている問合せは、機能的に次のものと同等です。

    SQL> SELECT e.empno FROM emp e, dept d WHERE e.deptno = d.deptno AND d.loc = 'Boston';
    
         EMPNO
    ----------
             1
             3

10.4 ネイティブRDFデータと仮想RDB2RDFデータの組合せ

SERVICEキーワードを使用して、ネイティブ・トリプル・データと仮想RDB2RDFトリプル・データ(RDFビュー・モデルからの)を、1つのSEM_MATCH問合せで組み合せることができます。

SERVICEキーワード(「グラフ・パターン: SPARQL 1.1のフェデレーテッド問合せのサポート」を参照)は、ローカル(仮想)のRDFデータを示す特別なSERVICE URLの使用を通じてオーバーロードされます。特別なSERVICE URLを表すために次の接頭辞が使用されます。

  • ネイティブ・モデル - oram: <http://xmlns.oracle.com/models/>

  • ネイティブ仮想モデル - oravm: <http://xmlns.oracle.com/virtual_models/>

  • RDB2RDFモデル - orardbm: <http://xmlns.oracle.com/rdb_models/>

例10-5 複数のデータセットの問合せ

例10-5は複数のデータセットを問い合せます。この問合せでは、最初のトリプル・パターン{ ?x rdf:type :Person }は通常どおりネイティブ・モデルm1に対応しますが、{ ?x :name ?name }はローカル・ネイティブ・モデルm2に対応し、{ ?x emp:JOB ?job }はローカルRDB2RDFモデルempdb_modelに対応します。

SELECT * FROM TABLE (SEM_MATCH(
'PREFIX    : <http://people.org/> 
 PREFIX emp: <http://empdb/TESTUSER.EMP#> 
 SELECT ?x ?name ?job 
 WHERE {
   ?x rdf:type :Person .   
   OPTIONAL { SERVICE oram:m2 { ?x :name ?name } }   
   OPTIONAL { SERVICE orardbm:empdb_model { ?x emp:JOB ?job } } 
 }',
 SEM_MODELS('m1'), NULL, NULL, NULL, NULL, ' ', NULL, NULL, 'RDFUSER', 'NET1'));

オーバーロードされたSERVICEの使用は、SEM_MATCHのmodels引数に指定された1つのモデルのみで許可されます。オーバーロードされたSERVICE問合せでは、複数のモデルまたは入力としてのルールベースは許可されません。そのような組合せのかわりに、複数のモデルまたは伴意(あるいは両方)を含む仮想モデルを使用する必要があります。また、SEM_MATCHのindex_status引数は、modelsパラメータで入力として渡された仮想モデルに含まれる伴意のみをチェックします。つまり、オーバーロードされたSERVICEコールで参照される伴意のステータスはチェックされません。

例10-6は、2つのデータセットを問い合せます。「例: 直接マッピングによるRDFビュー・モデルの使用」empdb_modelと、peopleという名前のネイティブ・モデルです。

例10-6 スキーマプライベート・ネットワークでの仮想RDB2RDFデータとネイティブRDFデータの問合せ

-- Create native model people --
 EXECUTE SEM_APIS.CREATE_SEM_MODEL('people', NULL, NULL, network_owner=>'rdfuser', network_name=>'net1');
 
BEGIN
  sem_apis.update_model('people',
   'PREFIX peop: <http://people.org/> 
    INSERT DATA {
       <http://empdb/TESTUSER.EMP/EMPNO=1> peop:age 35 .
       <http://empdb/TESTUSER.EMP/EMPNO=2> peop:age 39 .
       <http://empdb/TESTUSER.EMP/EMPNO=3> peop:age 30 .
       <http://empdb/TESTUSER.EMP/EMPNO=4> peop:age 42 .
    } ');
END;
/
COMMIT;
 
-- Querying multiple datasets --
SELECT emp, age
  FROM TABLE(SEM_MATCH(
    'PREFIX dept: <http://empdb/TESTUSER.DEPT#>
     PREFIX emp: <http://empdb/TESTUSER.EMP#>
     PREFIX peop: <http://people.org/>
     SELECT ?emp ?age WHERE {
       ?emp peop:age ?age
       SERVICE orardbm:empdb_model { ?emp emp:ref-DEPTNO ?dept . ?dept dept:LOC "Boston" }
    }',
    SEM_Models('people'),
    NULL,
    NULL,
    NULL, NULL, NULL, NULL, NULL, 'RDFUSER', 'NET1'));

問合せの出力は次のようになります。

EMP                                                AGE
-------------------------------------------------- --------------------------------------------------
http://empdb/TESTUSER.EMP/EMPNO=1                   35
http://empdb/TESTUSER.EMP/EMPNO=3                   30

10.4.1 オーバーロードしたサービスによるネストされたループのプッシュダウン

シナリオによっては、ネストしたループのサービスを使用することで、パフォーマンスが向上することがあります。スキーマプライベート・ネットワークの複数のデータセットに対する問合せの例を考えてみます。問合せでは、35歳の人がいるすべての部門のプロパティが検索されます。

–- Query example for a schema-private network.

SELECT emp, dept, p, o
  FROM TABLE(SEM_MATCH(
    'PREFIX dept: <http://empdb/TESTUSER.DEPT#>     
     PREFIX emp: <http://empdb/TESTUSER.EMP#>
     PREFIX peop: <http://people.org/>
     SELECT * WHERE{
       ?emp peop:age 35
       SERVICE orardbm:empdb_model{ ?emp emp:ref-DEPTNO ?dept . ?dept ?p ?o }
     }',
     SEM_Models('people'),
     NULL,
     NULL,
     NULL, NULL, NULL, NULL, NULL, 'RDFUSER', 'NET1'));

この問合せの出力は次のようになります。

EMP                                DEPT                                P                                                 O
---------------------------------- ----------------------------------- ------------------------------------------------  --------------------------
http://empdb/TESTUSER.EMP/EMPNO=1   http://empdb/TESTUSER.DEPT/DEPTNO=1  http://empdb/TESTUSER.DEPT#DEPTNO                1
http://empdb/TESTUSER.EMP/EMPNO=1   http://empdb/TESTUSER.DEPT/DEPTNO=1  http://empdb/TESTUSER.DEPT#DNAME                 Sales
http://empdb/TESTUSER.EMP/EMPNO=1   http://empdb/TESTUSER.DEPT/DEPTNO=1  http://empdb/TESTUSER.DEPT#LOC                   Boston
http://empdb/TESTUSER.EMP/EMPNO=1   http://empdb/TESTUSER.DEPT/DEPTNO=1  http://www.w3.org/1999/02/22-rdf-syntax-ns#type  http://empdb/TESTUSER.DEPT

与えられたグラフ・パターンと一致するすべての結果を得るために、最初にモデルpeopleに対してトリプル・パターン{ ?emp peop:age 35 }の照合が行われ、次にモデルempdb_modelに対してトリプル・パターン{ ?emp emp:ref-DEPTNO ?d . ?d dept:DNAME ?dept }の照合が行われ、最後に2つの照合結果が結合されます。ここで、モデルpeopleには35歳の人が1人しかいないものの、部に関する情報を含むトリプルは10万個あるとします。明らかに、すべての結果を抽出する方法は最も効率的とはいえず、問合せのパフォーマンスも悪いと考えられます。これは、問合せの残りの部分と結合する前に、大量の結果を処理する必要があるためです。

この例では、ネストしたループのサービスでパフォーマンスが向上する可能性があります。ヒントOVERLOADED_NL=Tが使用されると、問合せの最初の部分で得られる結果が計算され、SERVICEパターンが、ルート・トリプル・パターンから得られる?emp値ごとに1回ずつ、ネストしたループで順番に実行されます。実行のたびに、SERVICEパターンの主語値?empが、ルート・トリプル・パターンの定数に置き換えられます。これにより、結合条件が効率的にSERVICE句へプッシュ・ダウンされます。

次の例では、先の問合せに対してヒントOVERLOADED_NL=Tが使用されています。

SELECT emp, dept, p, o
  FROM TABLE(SEM_MATCH(
    'PREFIX dept: <http://empdb/TESTUSER.DEPT#>     
     PREFIX emp: <http://empdb/TESTUSER.EMP#>
     PREFIX peop: <http://people.org/>
     SELECT * WHERE{
       ?emp peop:age 35
       SERVICE orardbm:empdb_model { ?emp emp:ref-DEPTNO ?dept . ?dept ?p ?o }
     }',
     SEM_Models('people'),
     NULL,
     NULL,
     NULL, NULL,' OVERLOADED_NL=T ', NULL, NULL, 'RDFUSER', 'NET1'));

ヒントOVERLOADED_NL=Tは、SEM_MATCHオプションや、与えられたSERVICEグラフのインライン・コメントで指定することができます。