はじめに
NoSQLドキュメント指向データベースであるCouchbase Serverの優れた点として、クライアントからデータベースに対して、JSONデータの一部に対する操作(取得・変更)をリクエストできることがあります。これを「サブドキュメント操作」と呼びます。
レコードの一部に対する操作(取得・変更)をリクエストできることは、SQLでは珍しくないことですが、SQL文の構築、解析、実行というフェーズを経ずに、KVストアとしての特性、ミリ秒以下の応答速度、を活かすことができるという利点があります。
今年(2021年)に発表した、以下の拙著では、サブドキュメント操作については、基本的な説明に留まっていました。
本来、サブドキュメント操作は、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}}
5秒待ってから、ドキュメント取得を試みます。
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"}