【MarkLogic Server】Collection検索入門

はじめに
===
ドキュメント型データベースには、コレクションによる検索が機能として備わっている場合があります。今回はMarkLogicを使いつつコレクションの有用性や使い方を確認しましょう。
(厳密にはDB製品ごとでコレクションの扱いが異なったりすることがあります。[こちら](https://developer.marklogic.com/blog/how-is-marklogic-different-from-mongodb "こちら")もご参考にお願いします。)

背景
===
以前の[記事](https://qiita.com/JucoML/items/6af0573b96304db8a026 "記事")にも示した通り、コーディングの上でデータの中身を見ずに検索対象を絞り込むことは重要です。ディレクトリやドキュメントURIといった条件設定と合わせてコレクションによる絞り込みもまた大きな効果を発揮します。

コレクションとは？
===
図のサンプルデータを見てください。この例では/shopというディレクトリの下に、各店舗ごとのディレクトリが店番号(例 /shop00001)で区切られ、さらにその下に複数のXMLファイル(店舗基本情報(例 basic.xml)、売上合計、チェック結果)が存在します。各ドキュメントはディレクトリによってカテゴライズされます。
これに対して、コレクションはディレクトリとは異なるカテゴライズを提供することになります。図にはありませんが、1つのドキュメントが複数のコレクションに属することも可能です。

![abstractCollection.png](https://qiita-image-store.s3.amazonaws.com/0/188643/83898b1e-3f95-c938-788b-485c9954d9c1.png)

図のディレクトリ関係は一見して違和感のないものです。しかし、全ての店舗の基本情報のみを出力する場合、/shopディレクトリ内の全てのドキュメントURIを取り上げて、"basic.xml"かどうかという文字列照合を行うことになります。

解決方法の一つは、ディレクトリをより大まかな単位から作っていくことです。すなわち/shopの直下は店番号によるディレクトリ区分ではなく、店舗基本情報といったより大まかディレクトリ配下に店番号単位のディレクトリorドキュメントを作るようにします。
しかし、ディレクトリ構成の変更は他のクエリへの影響などで二の足を踏むことが多いですね。こんなときに役立つのがコレクションです。コレクションは挿入時に設定だけでなく、後から付加することも可能です。

DB設定
===
コレクションの利用にあたっては、DB設定の変更をしましょう。ポート8001番の管理者画面からConfigure→Databases→[対象のDB名]→Configureタブにて「collection lexicon」をtrueにしましょう。

コレクションを用いた関数
===
主要なものを挙げます。

| 関数 | 説明 |
|---|---|
| fn:collection | 指定コレクションURIに属するドキュメント内容を返す |
| cts:collection-query | 他のcts検索関数に用いられるcts検索条件 |
| cts:collections | コレクションURIの一覧を返す |
| cts:collection-delete | 指定コレクションURIに属する"ドキュメント"を削除する |
| xdmp:document-set-collections | 指定ドキュメントにコレクションを設定する |
| xdmp:document-add-collections | 指定ドキュメントにコレクションを追加する |
| xdmp:document-remove-collections | 指定ドキュメントからコレクションを削除する |

☆利用例

```
cts:uris((), (), cts:collection-query("collection/basic"))
```

[補足]挿入クエリにおけるコレクションの設定
===
ドキュメント挿入時にコレクションを設定できます。ただし[ver8](https://docs.marklogic.com/8.0/xdmp:document-insert "ver8")以前と[ver9](https://docs.marklogic.com/xdmp:document-insert "ver9")で記述方法が大きく変わっていますのでご注意ください。
☆ver8の場合
コレクションは第４引数で指定していました。

```
xdmp:document-insert("/shop/shop01/basic.xml", <test>a</test>, (),
  "collection/basic"
)
```

☆ver9の場合
コレクションは第３引数に要素の形で指定します。

```
xdmp:document-insert("/shop/shop01/basic.xml", <test>a</test>, 
  <options xmlns="xdmp:document-insert">  
    <collections>
      <collection>collection/basic</collection>
    </collections>
  </options>
)
```

[補足]Content Pumpによるコレクション設定
===
[Content Pump](https://docs.marklogic.com/guide/mlcp.pdf "Content Pump")による挿入時にもコレクションを設定することが可能です。「-output_collections」というパラメータに設定します。複数のコレクションを設定したい場合は、カンマ区切りの文字列を引数とします。

[補足]挿入ユーザ・ロールのデフォルトコレクションによる設定
===
実行ユーザにデフォルトコレクションを設定することで、そのユーザによる挿入時に自動的にコレクションを設定できます。管理画面(ポート8001)よりConfigure→Security→RolesまたはUsersを選択すると、「default collections」という設定から挿入時のコレクションを設定できます。

おわりに
===
ディレクトリと比べて、コレクションは目に見えないため慣れるのに時間がかかるかもしれません。しかし使いこなせば、NoSQLDBが苦手とするデータの内外部結合を補完できる可能性があると思います。例えば、より細かく店舗単位でのコレクションを付加すれば、店番号での内外部結合をコレクションへの検索で実現できるといった具合です。
是非皆様も活用してみてください。


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

------------------------------------------------------------------------

**免責事項**

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