LoginSignup
9
4

More than 5 years have passed since last update.

【MarkLogic Server】MarkLogic9の新機能TDEを使ってみた

Last updated at Posted at 2017-12-20

はじめに

MarkLogicを利用していると、データベースに格納したデータをSQLで参照したい場合があります。
今回はMarkLogic9の新機能であるTDEを使ってみたので紹介します。

TDEとは

TDE(Template Driven Extraction)とは、MarkLogicに格納されている非構造化データに対してRDBのような表形式のビューに変換することで、RDBのように検索することができる機能です。
テンプレートと呼ばれる表形式のビューに変換するルールをXML形式またはJSON形式で作成します。
テンプレートを作成し、スキーマデータベースへテンプレートを挿入することでビューが作成され、行やトリプルが生成できます。
1つのスキーマに対して一意のビューを作成できます。また、スキーマが異なる場合、同名のビューをそれぞれのスキーマに作成することができます。

image.png

TDEについて詳しい内容は以下の公式ドキュメント参照ください。
https://docs.marklogic.com/guide/app-dev/TDE
http://jp.marklogic.com/wp-content/uploads/2017/05/MarkLogic-Whitepaper-Whats-New-in-MarkLogic-9_ja_JP.pdf

TDEの使用例

テンプレートの使用例について説明します。

デフォルトでは、テンプレート1つに対して1つのビューが作成されます。
例えば、テンプレートを次のように定義します。
・対象ノードの値を指定した列に設定します。
・テンプレートで定義したノードがドキュメントに存在しない場合、そのドキュメントのビューを作成しません。

以下のドキュメントに対してテンプレートを適用します。

documentA.xml
<ROOT>
  <ID>0001</ID>
  <NAME>TANAKA</NAME>
  <AGE>20</AGE>
</ROOT>

テンプレートは以下のように記載します。

テンプレート
<template xmlns="http://marklogic.com/xdmp/tde">
  <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード -->
  <context>/ROOT</context>
  <rows> 
    <row>
      <!-- スキーマ名 -->
      <schema-name>TEST_Schema</schema-name> 
      <!-- ビュー名 -->
      <view-name>TEST_View</view-name>
      <columns>
        <!-- ID -->
        <column>
          <name>ID_I</name>
          <scalar-type>string</scalar-type>
          <val>ID</val>
          <invalid-values>ignore</invalid-values>
        </column>
        <!-- 名前 -->
        <column>
          <name>NAME_I</name>
          <scalar-type>string</scalar-type>
          <val>NAME</val>
          <invalid-values>ignore</invalid-values>
        </column>
        <!-- 年齢 -->
        <column>
          <name>AGE_I</name>
          <scalar-type>string</scalar-type>
          <val>AGE</val>
          <invalid-values>ignore</invalid-values>
        </column>
      </columns>
    </row>
  </rows>
</template>

作成されるビューは以下の通りです。

ID_I NAME_I AGE_I
0001 TANAKA 20

また、テンプレートの設定により、複数のテンプレートから1つのビューを作成することもできます。

image.png

上記の図ではテンプレートを次のように定義しています。
・複数のテンプレートで1つのビューを作成できるようにします。
・対象ノードの値を指定した列に設定します。
・テンプレートが適用されたドキュメントで定義されていない列についてはNullが設定されます。

テンプレートAとテンプレートBはそれぞれ以下のように記載します。

テンプレートA
<template xmlns="http://marklogic.com/xdmp/tde">
  <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード -->
  <context>/ROOT</context>
 <!-- テンプレートを適用するディレクトリ(documentA.xmlの格納ディレクトリを指定) -->
  <directories>
    <directory>/CompanyA/</directory>
  </directories>
  <rows> 
    <row>
      <!-- スキーマ名 -->
      <schema-name>TEST_Schema</schema-name> 
      <!-- ビュー名 -->
      <view-name>TEST_View</view-name>
      <!-- 複数のテンプレートを1つのビューにするためsparseを設定 -->
      <view-layout>sparse</view-layout>
      <columns>
        <!-- ID -->
        <column>
          <name>ID_I</name>
          <scalar-type>string</scalar-type>
          <val>ID</val>
          <nullable>true</nullable>
        </column>
        <!-- 名前 -->
        <column>
          <name>NAME_I</name>
          <scalar-type>string</scalar-type>
          <val>NAME</val>
          <nullable>true</nullable>
        </column>
      </columns>
    </row>
  </rows>
</template>
テンプレートB
<template xmlns="http://marklogic.com/xdmp/tde">
  <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード -->
  <context>/ROOT</context>
 <!-- テンプレートを適用するディレクトリ(documentB.xmlの格納ディレクトリを指定) -->
  <directories>
    <directory>/CompanyB/</directory>
  </directories>
  <rows> 
    <row>
      <!-- スキーマ名 -->
      <schema-name>TEST_Schema</schema-name> 
      <!-- ビュー名 -->
      <view-name>TEST_View</view-name>
      <!-- 複数のテンプレートを1つのビューにするためsparseを設定 -->
      <view-layout>sparse</view-layout>
      <columns>
        <!-- ID -->
        <column>
          <name>ID_I</name>
          <scalar-type>string</scalar-type>
          <val>ID</val>
          <nullable>true</nullable>
        </column>
        <!-- 名前 -->
        <column>
          <name>NAME_I</name>
          <scalar-type>string</scalar-type>
          <val>NAME</val>
          <nullable>true</nullable>
        </column>
         <!-- 性別 -->
        <column>
          <name>SEX_I</name>
          <scalar-type>string</scalar-type>
          <val>SEX</val>
          <nullable>true</nullable>
        </column>
      </columns>
    </row>
  </rows>
</template>

実施内容

2つのテンプレートを使用して1つのビューを作成します。
実施内容は以下の通りです。

1.ドキュメント(パターン1)のテンプレートを作成
  1-1.テンプレートの作成
  1-2.テンプレートを検証
  1-3.テンプレートを適用
2.ドキュメント(パターン2)のテンプレートを作成
  2-1.テンプレートの作成
  2-2.テンプレートを検証
  2-3.テンプレートを適用
3.SQLでビューを確認

実施環境は以下の通りです。

対象MarkLogicバージョン 対象OS・バージョン
9.0-3.1 Windows7

事前準備

実施に必要なデータベースの作成とドキュメントの追加を行います。
TDEのテンプレートはスキーマデータベースに格納されるため、スキーマデータベースも作成します。

データベース作成

MarkLogicの管理画面よりデータベースを作成します
データベース名とフォレスト名は以下で作成します。

データベース名 フォレスト名
TDE_Database TDE_DBForest

1.「Configure」→「Databases」に遷移
2.「Create」タブをクリック
3.「triple index」がtrueに設定されていることを確認
4.「database name」に「TDE_Database」を入力し「OK」ボタンをクリック
5.「Database->Forests」のリンクをクリック
6.「Create a Forest」のリンクをクリック
7.「forest name」に「TDE_DBForest」と入力し「OK」ボタンをクリック
8.「Summary」タブをクリック
9.作成した「TDE_DBForest」フォレストのDatabaseを「TDE_Database」に設定し「OK」ボタンをクリック

スキーマデータベース作成

MarkLogicの管理画面よりスキーマデータベースを作成します
データベース名とフォレスト名は以下で作成します。

スキーマデータベース名 フォレスト名
TDE_SchemaDatabase TDE_SDBForest

1.「Configure」→「Databases」に遷移
2.「Create」タブをクリック
3.「database name」に「TDE_SchemaDatabase 」を入力し「OK」ボタンをクリック
4.「Database->Forests」のリンクをクリック
5.「Create a Forest」のリンクをクリック
6.「forest name」に「TDE_SDBForest 」と入力し「OK」ボタンをクリック
7.「Summary」タブをクリック
8.作成した「TDE_SDBForest 」フォレストのDatabaseを「TDE_SchemaDatabase 」に設定し「OK」ボタンをクリック
9.「Configure」→「Databases」→「TDE_Database」に遷移
10.「schema database」で「TDE_SchemaDatabase 」を選択し「OK」ボタンをクリック

ドキュメント(パターン1)

以下のXMLドキュメントをデータベースに追加します。

/CompanyA/document_A.xml
<?xml  version="1.0" encoding="UTF-8"?>
<root>
  <!-- ID -->
  <ID>0001</ID>
  <!-- 名前(姓) -->
  <LAST_NAME>田中</LAST_NAME>
  <!-- 名前(名) -->
  <FIRST_NAME>太郎</FIRST_NAME>
  <!-- 年齢 -->
  <AGE>20</AGE>
  <!-- 住所 -->
  <ADDRESS>東京都台東区上野 ABCアパート</ADDRESS>
</root>

クエリコンソール画面から以下のXQueryを実行します。

xquery version "1.0-ml";

let $xmlData := 
<root>
  <!-- ID -->
  <ID>0001</ID>
  <!-- 名前(姓) -->
  <LAST_NAME>田中</LAST_NAME>
  <!-- 名前(名) -->
  <FIRST_NAME>太郎</FIRST_NAME>
  <!-- 年齢 -->
  <AGE>20</AGE>
  <!-- 住所 -->
  <ADDRESS>東京都台東区上野 ABCアパート</ADDRESS>
</root>

let $uri := "/CompanyA/document_A.xml"

return xdmp:document-insert($uri, $xmlData)

ドキュメント(パターン2)

以下のXMLドキュメントをデータベースに追加します。

/CompanyB/document_B.xml
<?xml  version="1.0" encoding="UTF-8"?>
<root>
  <!-- 住所 -->
  <ADDRESS>千葉県佐倉市</ADDRESS>
  <items>
    <!-- データ1 -->
    <item>
      <!-- ID -->
      <ID>0004</ID>
      <!-- 名前 -->
      <NAME>千葉次郎</NAME>
      <!-- 性別 -->
      <SEX></SEX>
      <!-- アパート名 -->
      <APARTMENT_NAME>DEFアパート</APARTMENT_NAME>
    </item>
    <!-- データ2 -->
    <item>
      <!-- ID -->
      <ID>0007</ID>
      <!-- 名前 -->
      <NAME>臼井花子</NAME>
      <!-- 性別 -->
      <SEX></SEX>
      <!-- アパート名 -->
      <APARTMENT_NAME>GHIアパート</APARTMENT_NAME>
    </item>
  </items>
</root>

クエリコンソール画面から以下のXQueryを実行します。

xquery version "1.0-ml";

let $xmlData := 
<root>
  <!-- 住所 -->
  <ADDRESS>千葉県佐倉市</ADDRESS>
  <items>
    <!-- データ1 -->
    <item>
      <!-- ID -->
      <ID>0004</ID>
      <!-- 名前 -->
      <NAME>千葉次郎</NAME>
      <!-- 性別 -->
      <SEX>男</SEX>
      <!-- アパート名 -->
      <APARTMENT_NAME>DEFアパート</APARTMENT_NAME>
    </item>
    <!-- データ2 -->
    <item>
      <!-- ID -->
      <ID>0007</ID>
      <!-- 名前 -->
      <NAME>臼井花子</NAME>
      <!-- 性別 -->
      <SEX>女</SEX>
      <!-- アパート名 -->
      <APARTMENT_NAME>GHIアパート</APARTMENT_NAME>
    </item>
  </items>
</root>

let $uri := "/CompanyB/document_B.xml"

return xdmp:document-insert($uri, $xmlData)

作成したいビュー

今回、TDEを利用して作成したいビューは以下の通りです。

スキーマ名 ビュー名
IntegratedInfo PersonalInfo

作成するビューの項目は以下の通りです。

項目名 説明
NAME_I 名前(姓+名)を設定します。
AGE_I 年齢を設定します。
ADDRESS_I 住所を設定します。アパート名がある場合は結合します。
SEX_I 性別を設定します。

実施手順

追加した2つのドキュメントは構造体が異なるため、テンプレートを2つ作成し1つのビューを作成します。
本手順はクエリコンソール画面上で行っています。

1.ドキュメント(パターン1)のテンプレートを作成

ドキュメント(パターン1)のテンプレートを作成します。

1-1.テンプレートの作成

作成するビューの項目を確認すると、名前が姓と名で結合されているため、LAST_NAMEタグとFIRST_NAMEタグを結合して1つの項目にします。
不足している項目はドキュメント(パターン2)のテンプレートを作成することで追加されるため無視します。

テンプレートは以下のようになります。

<template xmlns="http://marklogic.com/xdmp/tde">
  <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード -->
  <context>/root</context>
  <!-- テンプレートを適用するディレクトリ -->
  <directories>
    <directory>/CompanyA/</directory>
  </directories>
  <rows> 
    <row>
      <!-- スキーマ名 -->
      <schema-name>IntegratedInfo</schema-name> 
      <!-- ビュー名 -->
      <view-name>PersonalInfo</view-name>
      <!-- 複数のテンプレートを1つのビューにするためsparseを設定 -->
      <view-layout>sparse</view-layout>
      <columns>
        <!-- 名前 -->
        <column>
          <name>NAME_I</name>
          <scalar-type>string</scalar-type>
          <val>fn:concat(LAST_NAME, FIRST_NAME)</val>
          <nullable>true</nullable>
        </column>
        <!-- 年齢 -->
        <column>
          <name>AGE_I</name>
          <scalar-type>integer</scalar-type>
          <val>AGE</val>
          <nullable>true</nullable>
        </column>
        <!-- 住所 -->
        <column>
          <name>ADDRESS_I</name>
          <scalar-type>string</scalar-type>
          <val>ADDRESS</val>
          <nullable>true</nullable>
        </column>
      </columns>
    </row>
  </rows>
</template>

1-2.テンプレートを検証

tde:validate関数を利用して作成したテンプレートが正しい内容であるか確認します。
XQueryで以下のクエリを実行します。

xquery version "1.0-ml";

(: テンプレート :)
let $template_pattern1 :=
<template xmlns="http://marklogic.com/xdmp/tde">
  <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード -->
  <context>/root</context>
  <!-- テンプレートを適用するディレクトリ -->
  <directories>
    <directory>/CompanyA/</directory>
  </directories>
  <rows> 
    <row>
      <!-- スキーマ名 -->
      <schema-name>IntegratedInfo</schema-name> 
      <!-- ビュー名 -->
      <view-name>PersonalInfo</view-name>
      <!-- 複数のテンプレートを1つのビューにするためsparseを設定 -->
      <view-layout>sparse</view-layout>
      <columns>
        <!-- 名前 -->
        <column>
          <name>NAME_I</name>
          <scalar-type>string</scalar-type>
          <val>fn:concat(LAST_NAME, FIRST_NAME)</val>
          <nullable>true</nullable>
        </column>
        <!-- 年齢 -->
        <column>
          <name>AGE_I</name>
          <scalar-type>integer</scalar-type>
          <val>AGE</val>
          <nullable>true</nullable>
        </column>
        <!-- 住所 -->
        <column>
          <name>ADDRESS_I</name>
          <scalar-type>string</scalar-type>
          <val>ADDRESS</val>
          <nullable>true</nullable>
        </column>
      </columns>
    </row>
  </rows>
</template>


(: テンプレートの検証 :)
return tde:validate($template_pattern1)

実行結果よりmap:valueタグの値がtrueであることを確認します。
image.png

tde:node-data-extract関数を利用し、指定したドキュメントのリストから行データの抽出結果を確認します。

xquery version "1.0-ml";

(: テンプレート :)
let $template_pattern1 :=
<template xmlns="http://marklogic.com/xdmp/tde">
  <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード -->
  <context>/root</context>
  <!-- テンプレートを適用するディレクトリ -->
  <directories>
    <directory>/CompanyA/</directory>
  </directories>
  <rows> 
    <row>
      <!-- スキーマ名 -->
      <schema-name>IntegratedInfo</schema-name> 
      <!-- ビュー名 -->
      <view-name>PersonalInfo</view-name>
      <!-- 複数のテンプレートを1つのビューにするためsparseを設定 -->
      <view-layout>sparse</view-layout>
      <columns>
        <!-- 名前 -->
        <column>
          <name>NAME_I</name>
          <scalar-type>string</scalar-type>
          <val>fn:concat(LAST_NAME, FIRST_NAME)</val>
          <nullable>true</nullable>
        </column>
        <!-- 年齢 -->
        <column>
          <name>AGE_I</name>
          <scalar-type>integer</scalar-type>
          <val>AGE</val>
          <nullable>true</nullable>
        </column>
        <!-- 住所 -->
        <column>
          <name>ADDRESS_I</name>
          <scalar-type>string</scalar-type>
          <val>ADDRESS</val>
          <nullable>true</nullable>
        </column>
      </columns>
    </row>
  </rows>
</template>

(: テンプレート確認用データ :)
let $docs :=
(
  fn:doc("/CompanyA/document_A.xml"),
  fn:doc("/CompanyB/document_B.xml")
)
return tde:node-data-extract($docs, $template_pattern1)

上記のクエリを実行すると以下の結果となります。
「/CompanyA」配下のドキュメントにテンプレートが適用され、「/CompanyB」の配下のドキュメントにテンプレートが適用されていないことがわかります。
image.png

1-3.テンプレートを適用

作成したテンプレートをtde:template-insert関数を利用してデータベースに適用します。
テンプレートはスキーマデータベースに格納されますが、tde:template-insert関数はスキーマデータベースをアタッチしているデータベースに対して実行する必要があるので注意が必要です。

image.png

以下のクエリを実行します。

xquery version "1.0-ml";
import module "http://marklogic.com/xdmp/tde" at "/MarkLogic/tde.xqy";

(: テンプレート :)
let $template_pattern1 :=
<template xmlns="http://marklogic.com/xdmp/tde">
  <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード -->
  <context>/root</context>
  <!-- テンプレートを適用するディレクトリ -->
  <directories>
    <directory>/CompanyA/</directory>
  </directories>
  <rows> 
    <row>
      <!-- スキーマ名 -->
      <schema-name>IntegratedInfo</schema-name> 
      <!-- ビュー名 -->
      <view-name>PersonalInfo</view-name>
      <!-- 複数のテンプレートを1つのビューにするためsparseを設定 -->
      <view-layout>sparse</view-layout>
      <columns>
        <!-- 名前 -->
        <column>
          <name>NAME_I</name>
          <scalar-type>string</scalar-type>
          <val>fn:concat(LAST_NAME, FIRST_NAME)</val>
          <nullable>true</nullable>
        </column>
        <!-- 年齢 -->
        <column>
          <name>AGE_I</name>
          <scalar-type>integer</scalar-type>
          <val>AGE</val>
          <nullable>true</nullable>
        </column>
        <!-- 住所 -->
        <column>
          <name>ADDRESS_I</name>
          <scalar-type>string</scalar-type>
          <val>ADDRESS</val>
          <nullable>true</nullable>
        </column>
      </columns>
    </row>
  </rows>
</template>

(: ビューを生成する :)
return tde:template-insert("/tde_統合_パターン1.xml", $template_pattern1)

スキーマデータベースにテンプレートが格納されていることを確認します(Databaseでスキーマデータベースを選択し「Explore」ボタンをクリックする)。
image.png

2.ドキュメント(パターン2)のテンプレートを作成

ドキュメント(パターン2)のテンプレートを作成します。

2-1.テンプレートの作成

ドキュメント(パターン2)は1ドキュメントの中に複数データ設定されています。
そのため、templetesタグを利用して1データを1レコードとなるようテンプレートを作成します。
また、住所を変数で定義して利用してみます。

テンプレートは以下のようになります。

<template xmlns="http://marklogic.com/xdmp/tde">
  <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード -->
  <context>/root</context>
  <!-- 変数を定義 -->
  <vars>
    <!-- 住所を格納する変数を定義 -->
    <var>
      <name>var_address</name>
      <val>./ADDRESS</val>
    </var>
  </vars>
  <!-- テンプレートを適用するディレクトリ -->
  <directories>
    <directory>/CompanyB/</directory>
  </directories>
  <templates>
    <template>
      <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード(/root以降のパスを指定) -->
      <context>items/item</context>
      <rows> 
        <row>
          <!-- スキーマ名 -->
          <schema-name>IntegratedInfo</schema-name> 
          <!-- ビュー名 -->
          <view-name>PersonalInfo</view-name>
          <!-- 複数のテンプレートを1つのビューにするためsparseを設定 -->
          <view-layout>sparse</view-layout>
          <columns>
            <!-- 名前 -->
            <column>
              <name>NAME_I</name>
              <scalar-type>string</scalar-type>
              <val>NAME</val>
              <nullable>true</nullable>
            </column>
            <!-- 性別 -->
            <column>
              <name>SEX_I</name>
              <scalar-type>string</scalar-type>
              <val>SEX</val>
              <nullable>true</nullable>
            </column>
            <!-- 住所 -->
            <column>
              <name>ADDRESS_I</name>
              <scalar-type>string</scalar-type>
              <!-- 変数を使い住所とアパート名を結合する -->
              <val>fn:concat($var_address, " ", APARTMENT_NAME)</val>
              <nullable>true</nullable>
            </column>
          </columns>
        </row>
      </rows>
    </template>
  </templates>
</template>

2-2.テンプレートを検証

tde:validate関数を利用して作成したテンプレートが正しい内容であるか確認します。
XQueryで以下のクエリを実行します

xquery version "1.0-ml";

let $template_pattern2 :=
<template xmlns="http://marklogic.com/xdmp/tde">
  <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード -->
  <context>/root</context>
  <!-- 変数を定義 -->
  <vars>
    <!-- 住所を格納する変数を定義 -->
    <var>
      <name>var_address</name>
      <val>./ADDRESS</val>
    </var>
  </vars>
  <!-- テンプレートを適用するディレクトリ -->
  <directories>
    <directory>/CompanyB/</directory>
  </directories>
  <templates>
    <template>
      <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード(/root以降のパスを指定) -->
      <context>items/item</context>
      <rows> 
        <row>
          <!-- スキーマ名 -->
          <schema-name>IntegratedInfo</schema-name> 
          <!-- ビュー名 -->
          <view-name>PersonalInfo</view-name>
          <!-- 複数のテンプレートを1つのビューにするためsparseを設定 -->
          <view-layout>sparse</view-layout>
          <columns>
            <!-- 名前 -->
            <column>
              <name>NAME_I</name>
              <scalar-type>string</scalar-type>
              <val>NAME</val>
              <nullable>true</nullable>
            </column>
            <!-- 性別 -->
            <column>
              <name>SEX_I</name>
              <scalar-type>string</scalar-type>
              <val>SEX</val>
              <nullable>true</nullable>
            </column>
            <!-- 住所 -->
            <column>
              <name>ADDRESS_I</name>
              <scalar-type>string</scalar-type>
              <!-- 変数を使い住所とアパート名を結合する -->
              <val>fn:concat($var_address, " ", APARTMENT_NAME)</val>
              <nullable>true</nullable>
            </column>
          </columns>
        </row>
      </rows>
    </template>
  </templates>
</template>

(: テンプレートの検証 :)
return tde:validate($template_pattern2)

実行結果よりmap:valueタグの値がtrueであることを確認します。
image.png

tde:node-data-extract関数を利用し、指定したドキュメントのリストから行データの抽出結果を確認します。

xquery version "1.0-ml";

let $template_pattern2 :=
<template xmlns="http://marklogic.com/xdmp/tde">
  <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード -->
  <context>/root</context>
  <!-- 変数を定義 -->
  <vars>
    <!-- 住所を格納する変数を定義 -->
    <var>
      <name>var_address</name>
      <val>./ADDRESS</val>
    </var>
  </vars>
  <!-- テンプレートを適用するディレクトリ -->
  <directories>
    <directory>/CompanyB/</directory>
  </directories>
  <templates>
    <template>
      <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード(/root以降のパスを指定) -->
      <context>items/item</context>
      <rows> 
        <row>
          <!-- スキーマ名 -->
          <schema-name>IntegratedInfo</schema-name> 
          <!-- ビュー名 -->
          <view-name>PersonalInfo</view-name>
          <!-- 複数のテンプレートを1つのビューにするためsparseを設定 -->
          <view-layout>sparse</view-layout>
          <columns>
            <!-- 名前 -->
            <column>
              <name>NAME_I</name>
              <scalar-type>string</scalar-type>
              <val>NAME</val>
              <nullable>true</nullable>
            </column>
            <!-- 性別 -->
            <column>
              <name>SEX_I</name>
              <scalar-type>string</scalar-type>
              <val>SEX</val>
              <nullable>true</nullable>
            </column>
            <!-- 住所 -->
            <column>
              <name>ADDRESS_I</name>
              <scalar-type>string</scalar-type>
              <!-- 変数を使い住所とアパート名を結合する -->
              <val>fn:concat($var_address, " ", APARTMENT_NAME)</val>
              <nullable>true</nullable>
            </column>
          </columns>
        </row>
      </rows>
    </template>
  </templates>
</template>

(: テンプレート確認用データ :)
let $docs :=
(
  fn:doc("/CompanyA/document_A.xml"),
  fn:doc("/CompanyB/document_B.xml")
)
return tde:node-data-extract($docs, $template_pattern2)

上記のクエリを実行すると以下の結果となります。
「/CompanyB」配下のドキュメントにテンプレートが適用され、「/CompanyA」の配下のドキュメントにテンプレートが適用されていないことがわかります。
image.png

2-3.テンプレートを適用

作成したテンプレートをtde:template-insert関数を利用してデータベースに適用します。
ドキュメント(パターン1)の時と同様、tde:template-insert関数はスキーマデータベースをアタッチしているデータベースに対して実行する必要があるので注意が必要です。

以下のクエリを実行します。

xquery version "1.0-ml";
import module "http://marklogic.com/xdmp/tde" at "/MarkLogic/tde.xqy";

let $template_pattern2 :=
<template xmlns="http://marklogic.com/xdmp/tde">
  <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード -->
  <context>/root</context>
  <!-- 変数を定義 -->
  <vars>
    <!-- 住所を格納する変数を定義 -->
    <var>
      <name>var_address</name>
      <val>./ADDRESS</val>
    </var>
  </vars>
  <!-- テンプレートを適用するディレクトリ -->
  <directories>
    <directory>/CompanyB/</directory>
  </directories>
  <templates>
    <template>
      <!-- テンプレートのアクティブ化とデータ抽出に使用される参照ノード(/root以降のパスを指定) -->
      <context>items/item</context>
      <rows> 
        <row>
          <!-- スキーマ名 -->
          <schema-name>IntegratedInfo</schema-name> 
          <!-- ビュー名 -->
          <view-name>PersonalInfo</view-name>
          <!-- 複数のテンプレートを1つのビューにするためsparseを設定 -->
          <view-layout>sparse</view-layout>
          <columns>
            <!-- 名前 -->
            <column>
              <name>NAME_I</name>
              <scalar-type>string</scalar-type>
              <val>NAME</val>
              <nullable>true</nullable>
            </column>
            <!-- 性別 -->
            <column>
              <name>SEX_I</name>
              <scalar-type>string</scalar-type>
              <val>SEX</val>
              <nullable>true</nullable>
            </column>
            <!-- 住所 -->
            <column>
              <name>ADDRESS_I</name>
              <scalar-type>string</scalar-type>
              <!-- 変数を使い住所とアパート名を結合する -->
              <val>fn:concat($var_address, " ", APARTMENT_NAME)</val>
              <nullable>true</nullable>
            </column>
          </columns>
        </row>
      </rows>
    </template>
  </templates>
</template>

(: ビューを生成する :)
return tde:template-insert("/tde_統合_パターン2.xml", $template_pattern2)

スキーマデータベースにテンプレートが格納されていることを確認します(Databaseでスキーマデータベースを選択し「Explore」ボタンをクリックする)。
image.png

3.SQLでビューを確認

作成されたビューを確認します。
クエリコンソール上で以下を実行します。

select * from PersonalInfo

SQLを実行するとビューの内容が表示されます。
PersonalInfoビューにドキュメント(パターン1)とドキュメント(パターン2)の内容がテンプレートで定義した内容で追加されていることを確認します。
image.png

以上でビューの作成が完了です。

おわりに

TDEを利用することでデータ統合が容易に行えます。
また、作成されたビューは、MarkLogicが提供しているオプティックAPIと呼ばれるJavaScript、XQuery、Java、REST APIで利用できるクエリインターフェースからも実行可能です。
非構造化データをRDBのように利用できるようになるのはとても便利ですね。

\def\textsmall#1{%
  {\rm\scriptsize #1}
}

免責事項

​​​​​$\textsmall{当ユーザ会は本文書及びその内容に関して、いかなる保証もするものではありません。}$
​​​​​$\textsmall{万一、本文書の内容に誤りがあった場合でも当ユーザ会は一切責任を負いかねます。}$
​​​​​$\textsmall{また、本文書に記載されている事項は予告なしに変更または削除されることがありますので、予めご了承ください。}$

9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4