概要
MarkLogicで実行できるXQueryの関数は、W3C標準のものに加えてMarkLogic独自の関数が用意されています。W3C標準の関数はfn:docのような検索やfn:replaceのような変換を行います。これに対して本稿ではMarkLogic独自の関数のうち更新処理を行うものを取り上げます。
ドキュメント挿入クエリ
ドキュメントの挿入はxdmp:document-insertを使います。この関数は第1引数に挿入先、第2引数に挿入内容を設定します。第3引数はオプションです。コレクションやアクセス権を任意に設定したいときに用います。これらは後々設定するよりも、挿入時にこの関数で決めておいた方が良いと思います。ver9から第3引数の記入方法が大きく変わっていますので、ver9へのバージョンアップではくれぐれもご注意ください。
下記のサンプルは異なる記述方法で同じ挿入内容を作り、それぞれ別々のドキュメントURIで挿入を行うというものです。最もやりやすい記述方法を選んでいただければと思います。なおxdmp:document-insertは戻り値を返しません。
サンプルコードはクエリコンソール(ポート8000番)などで試してみて下さい。
xquery version "1.0-ml";
(: 挿入先URIヘッダ :)
let $dir := "/insTest/"
(: 挿入内容 :)
let $content1 := element {"root"}{element {"a"}{"x"}}
let $content2 := <root><a>x</a></root>
let $content3 := xdmp:unquote("<root><a>x</a></root>")
let $content-seq := ($content1, $content2, $content3)
(: 挿入 :)
for $content at $cnt in $content-seq
let $uri := fn:concat($dir, $cnt, ".xml")
return xdmp:document-insert($uri, $content)
挿入されたドキュメントは、いずれもこんな感じになります。
<root><a>x</a></root>
ドキュメント更新クエリ
ドキュメントの部分更新は、xdmp:node-replaceなどを使います。他の関数も含めて表にまとめます。経験的には一旦入れたドキュメントを更新するよりも、同じURIにxdmp:document-insertなどで上書き挿入した方が性能が良いような気がします。
関数 | 説明 |
---|---|
xdmp:node-insert-before | 指定した要素の前に要素を挿入する |
xdmp:node-insert-after | 指定した要素の後ろに要素を挿入する |
xdmp:node-insert-child | 指定した要素の子供として要素を挿入する |
xdmp:node-replace | 指定した要素を取り換える |
xdmp:node-delete | 指定した要素を削除する |
xdmp:node-insert-beforeでサンプルを作ってみました。URI名に設定した数字を基にno要素を追加していきます。
xquery version "1.0-ml";
(: 更新対象URIヘッダ :)
let $dir := "/insTest/"
(: 更新対象の確認 :)
let $uri-seq := cts:uris((), (), cts:directory-query("/insTest/", "1"))
(: 更新 :)
for $uri in $uri-seq
let $doc := fn:doc($uri)
let $uriTokenized := fn:tokenize($uri, "/")[fn:last()]
let $cnt := fn:substring-before($uriTokenized, ".xml")
let $nodeInserted := element {"no"}{$cnt}
return xdmp:node-insert-before($doc/root/a, $nodeInserted)
更新されたドキュメントのうち/insTest/1.xmlはこんな感じになります。
<root><no>1</no><a>x</a></root>
このクエリ自体は挿入クエリ内を書き換えることで、挿入クエリに統一できますが、何らかの形で既存データの修正を求められる場合には必要になると思います。大量のデータを処理する場合は、このようなforループではなく、AP側のマルチスレッド処理かxdmp:spawn系関数でタスクサーバを使うなどの並列処理をお奨めします。
ドキュメント削除クエリ
ドキュメントの削除は、xdmp:document-deleteを使います。ここで挿入・更新してみた3つのドキュメントを削除するサンプルを作りました。cts:urisという関数を使って削除対象となるURIシーケンスを作成して、forループで1個ずつ削除しています。大量のデータを対象にする場合は、やはり並列処理を視野に入れておくべきです。
xquery version "1.0-ml";
(: 削除対象URIヘッダ :)
let $dir := "/insTest/"
(: 削除対象URI :)
let $uri-seq := cts:uris((), (), cts:directory-query($dir, "1"))
(: 削除 :)
for $uri in $uri-seq
return xdmp:document-delete($uri)
雑感
W3C標準関数を補完する形で存在するこれらの関数は、単に検索だけでなくCRUDを備えたデータベースとしての機能を整えるものです。一方で製品独自の関数というのは個別の勉強が必要となり取っ付きにくくなる要因です。ひとまずここにある関数ぐらいは記憶しておきたいですね。