Couchbase Serverのサブドキュメント操作: cbc subdocコマンド実行例


## はじめに

NoSQLドキュメント指向データベースであるCouchbase Serverの優れた点として、クライアントからデータベースに対して、JSONデータの一部に対する操作（取得・変更）をリクエストできることがあります。これを「サブドキュメント操作」と呼びます。
レコードの一部に対する操作（取得・変更）をリクエストできることは、SQLでは珍しくないことですが、SQL文の構築、解析、実行というフェーズを経ずに、KVストアとしての特性、ミリ秒以下の応答速度、を活かすことができるという利点があります。

今年(2021年)に発表した、以下の拙著では、サブドキュメント操作については、基本的な説明に留まっていました。

https://www.amazon.co.jp/-/en/%E6%B2%B3%E9%87%8E-%E6%B3%B0%E5%B9%B8/dp/429560030X/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=1636588872&sr=1-1


本来、サブドキュメント操作は、APIを介してアプリケーション開発に活用するためのものですが、Couchbase Serverは、コマンドラインでも実行できる手段を提供しています。この`cbc subdoc`コマンドの実行例を使って、サブドキュメント操作のイメージを掴んでいただくことができるかと思われます。

## cbc subdocコマンド実行例


サーバーに接続し、コマンドプロンプトを表示します。

```
cbc subdoc -u Administrator -P password -U couchbase://192.168.33.101/a_bucket
subdoc>
```

「foo」というキー（ドキュメントID）で、新しい空のJSONドキュメントを作成します。

```
subdoc> upsert foo {}
foo                  CAS=0x14d766f19a720000
```


ドキュメント（まだ内容は空のため`{}`と表示されます）をメタデータと共にフェッチします。

```
subdoc> get -x $document foo
foo                  CAS=0x14d766f19a720000
0. Size=194, RC=0x00 Success (Not an error)
{"CAS":"0x14d766f19a720000","vbucket_uuid":"0x0000ef56295d9206",
"seqno":"0x0000000000000021","exptime":0,"value_bytes":2,
"datatype":["json","xattr"],"deleted":false,"last_modified":"1501782188"}
1. Size=2, RC=0x00 Success (Not an error)
{}
```


パス`site.hits`の値をカウンター操作で2回インクリメントし、ドキュメントの有効期限を5秒に設定します。JSONオブジェクト`site`を自動的に作成するための`-i`オプションを指定しています。

```
subdoc> counter -e 5 -i -p site.hits=1 foo
foo                  CAS=0x14d76764f3b60000
0. Size=1, RC=0x00 Success (Not an error)
1
subdoc> counter -e 5 -p site.hits=1 foo
foo                  CAS=0x14d76765ea2b0000
0. Size=1, RC=0x00 Success (Not an error)
2
subdoc> get foo
foo                  CAS=0x14d76765ea2b0000
0. Size=19, RC=0x00 Success (Not an error)
{"site":{"hits":2}}
```

５秒待ってから、ドキュメント取得を試みます。

```
subdoc> get foo
foo                  The key does not exist on the server (0xd)
```


パス`ratings`に値`5`を配列の要素として追加します。`-u`オプションは、ドキュメントが存在しない場合、サーバーにドキュメントの作成を要求します。

```
subdoc> array-add-first -u -p ratings=5 foo
foo                  CAS=0x14d76814fbb00000
0. Size=0, RC=0x00 Success (Not an error)
subdoc> get foo
foo                  CAS=0x14d76814fbb00000
0. Size=15, RC=0x00 Success (Not an error)
{"ratings":[5]}
```

一度に複数のオブジェクトを`ratings`配列に追加します。

```
subdoc> array-add-last -p ratings=4,6,7 foo
foo                  CAS=0x14d7687097c50000
0. Size=0, RC=0x00 Success (Not an error)
subdoc> get foo
foo                  CAS=0x14d7687097c50000
0. Size=21, RC=0x00 Success (Not an error)
{"ratings":[5,4,6,7]}
```

`ratings`配列のインデックス「2」の要素（3番目の要素）を削除します。

```
subdoc> remove -p ratings[2] foo
foo                  CAS=0x14d76885efd90000
0. Size=0, RC=0x00 Success (Not an error)
subdoc> get foo
foo                  CAS=0x14d76885efd90000
0. Size=19, RC=0x00 Success (Not an error)
{"ratings":[5,4,7]}
```

Insert new rating instead of removed one:

`ratings`配列のインデックス「2」の要素（3番目の要素）に、別の値を設定します。

```
subdoc> array-insert -p ratings[2]=10 foo
foo                  CAS=0x14d768a6daee0000
0. Size=0, RC=0x00 Success (Not an error)
subdoc> get foo
foo                  CAS=0x14d768a6daee0000
0. Size=22, RC=0x00 Success (Not an error)
{"ratings":[5,4,10,7]}
```


`ratings`配列内の要素の数を取得します。

```
subdoc> size -p ratings foo
foo                  CAS=0x14d768a6daee0000
0. Size=1, RC=0x00 Success (Not an error)
4
```


スペースを含むJSONコンテンツを（コマンドライン上で）指定して、ドキュメントを作成する場合は、JSONコンテンツをシングルクォートで囲みます（シングルクォートがコンテンツに含まれる場合は、バックスラッシュでエスケープします）。

```
subdoc> upsert bar ´{"text": "hello world"}´
bar                  CAS=0x14d768bc25270000
subdoc> get bar
bar                  CAS=0x14d768bc25270000
0. Size=23, RC=0x00 Success (Not an error)
{"text": "hello world"}
```

## 関連情報

[cbc-subdoc manpage](https://www.mankier.com/1/cbc-subdoc¥)