Couchbase
NoSQL データベース。
環境構築
Docker で動かす方がおすすめ。
インストールして動かす
Windows 用インストーラ
https://www.couchbase.com/downloads
インストール後、PowerShell
で以下のコマンドを実行すると起動、停止ができる。
# Couchbase Serverの起動
net start CouchbaseServer
# 停止
net stop CouchbaseServer
起動後、ブラウザからlocalhost:8091
にアクセスすると WebUI が表示される。
Docker で動かす
以下のコマンドを実行
winpty docker run -it -d --name db -p 8091-8093:8091-8093 -p 11210:11210 couchbase
couchbase
イメージは最新の EnterPrise エディション(開発、テスト、検証は無料)となっているので、本番環境で無料版を使いたい場合は代わりに couchbase:community-4.0.0
を使用する。
ref: https://hub.docker.com/_/couchbase
起動後、ブラウザからlocalhost:8091
にアクセスすると WebUI が表示される。
削除する場合
docker rm db
N1QL
インデックス作成
https://docs.couchbase.com/server/6.0/getting-started/try-a-query.html
インデックスがないとSELECT name FROM users
みたいなN1QLは使えない。
# 名前なしインデックスを作成する
create primary index on users
# 名前なしインデックスを削除する
drop primary index on users
ref:
DROP PRIMARY INDEX
バケット内のドキュメント数を取得
SELECT COUNT(*) AS size FROM `users`
Rubyの例。
require 'couchbase'
c = Couchbase.connect('http://localhost:8091', :bucket => "users", :username => nil, :password => 'password')
size = c.query('SELECT COUNT(*) AS size FROM `users`')
p size[:rows].size
バケットの全ドキュメント取得
ドキュメントIDはmeta([buketName]).id
で指定できる。
res = c.query('SELECT meta(users).id, name, age FROM users')
# IDの昇順でソートしてオブジェクトに変換
rows = res[:rows].sort {|a, b| a['id'] <=> b['id']}.map {|row|
{
'id'=> row['id'],
'name'=> row['name'],
'age'=> row['age'],
}
}
WHERE句でドキュメントIDを使った検索
res = c.query('SELECT meta(u).id, name, age FROM users u WHERE meta(u).id = "12345"')
p res
Couchbase CLI
docker で起動している場合はまずコンテナに入る。
docker exec -it db bash
クラスタ作成
https://docs.couchbase.com/server/6.0/cli/cbcli/couchbase-cli-cluster-init.html#host-formats
hostname -i
は自分の IP アドレス。
--services
にquery
を設定しないとN1QLが使えない。
couchbase-cli cluster-init \
--cluster=`hostname -i` \
--cluster-username=admin \
--cluster-password=password \
--services data,index,query,fts,analytics
容量が足りない的なエラーが出たら--services
をdata,query
だけにするか、--cluster-ramsize
の設定を追加してみる。
バケット作成
--cluster
に設定する IP アドレスは、WebUI の Servers から確認できる。
--bucket-ramsize
は MB 単位
couchbase-cli bucket-create \
--cluster=`hostname -i`
--username=admin \
--password=password \
--bucket=myBucket \
--bucket-type=couchbase \
--bucket-ramsize=100 \
--enable-flush=0 # 1にするとSDKなどからflush(全ドキュメント削除)ができる
ユーザー作成
https://docs.couchbase.com/server/6.0/cli/cbcli/couchbase-cli-user-manage.html
couchbaseの5.0
からはバケット名と同じ名前のユーザーがいないとSDKからアクセスできない。
GUIから確認するにはSecurity -> Users
。
couchbase-cli user-manage \
--cluster=`hostname -i` \
--username=Administrator \
--password=password \
--set \
--roles=admin \
--auth-domain=local \
--rbac-username=users \
--rbac-password=password
バケットアクセス用のユーザ作成
アプリからアクセスするとき用のユーザを作る。
--roles=bukcet_full_access[<バケット名>]
オプションで指定したバケットへのアクセス権を指定する。
couchbase-cli user-manage \
--cluster `hostname -i` \
--username=Administrator \
--password=password \
--set \
--roles=bucket_full_access[mybucket] \
--auth-domain=local \
--rbac-username=mybucket \
--rbac-password=mybucketpassword
Ref:
https://docs.couchbase.com/server/current/cli/cbcli/couchbase-cli-user-manage.html
Json をインポート
json ファイルをインポートする場合、ファイル名が ID、ファイル中身が Value となる。
https://docs.couchbase.com/server/6.0/tools/cbimport-json.html
https://docs.couchbase.com/server/5.5/cli/cbdocloader-tool.html
cbdocloader \
--cluster `hostname -i` \
--username admin \
--password password \
--bucket myBucket \
--bucket-quota 100 \
[json or zip file]
ex) test.json
{
"hoge": 123
}
cbimport
コマンドでも似たようなことができる。
cbimport json \
--cluster `hostname -i` \
--username admin \
--password password \
--bucket permission \
--dataset file://initdata.json \
--format list \
--generate-key %email%
CLIでN1QL
cbqを使う。
Running N1QL queries from a command line
# cbq開始
/opt/couchbase/bin/cbq -engine=http://localhost:8093 -c Administrator:password
# クエリを直接実行
/opt/couchbase/bin/cbq -engine=http://localhost:8093 -c Administrator:password -script "create primary index on users"
# help
cbq -h
REST API
REST API 経由でいろいろ設定できる。
https://docs.couchbase.com/server/6.0/rest-api/rest-endpoints-all.html
バケットの情報を取得する例
# -uオプションはBASIC認証
curl -u [ユーザ名]:[パスワード] http://localhost:8091/pools/default/buckets/[バケット名]
クラスタ設定
https://docs.couchbase.com/server/6.0/rest-api/rest-node-set-username.html
curl -u [admin]:[password] -d username=[new_admin] \
-d password=[new_password] \
-d port=8091 \
http://[localhost]:8091/settings/web
バケット作成
エンドポイント
POST /pools/default/buckets
content-type
application/x-www-form-urlencoded応答 application/json
認証 BASIC 認証が必要
{
"authType": "",
"bucketType": "couchbase",
"name": "b1",
"ramQuotaMB": 100
}
Dockerfile
FROM couchbase
SDK
Java(Kotlin)
Bucket
にデータを登録する例。
@Service
class CouchService {
lateinit var bucket: Bucket
init {
val cluster =CouchbaseCluster.create()
bucket = cluster.openBucket("user", "password")
}
fun insert() {
val user = JsonObject.empty()
.put("firstname", "Walter")
.put("lastname", "White")
.put("job", "chemistry teacher")
.put("age", 50)
val stored = bucket.upsert(JsonDocument.create("walter", user))
}
}
バケット名と同じユーザを作成しておき、openBucket()
でそのユーザ名、パスワードを入れる必要がある。
FAQ
java.lang.RuntimeException: java.util.concurrent.TimeoutException
アプリがリソース不足なせいで接続するまで時間がかかっている。
Nodejs
yarn add couchbase
Dockerで動かす場合はイメージによってyarn install
でコケるので、node:8
イメージを使う。
node:8.9.4-alpine
だとダメでした。
Ruby
apk add gcc libcouchbase-dev
apk add libcouchbase
apk add make
gem install couchbase
yajl
が入れれないエラーが出た場合(alpine)、makeできるようにするため以下コマンド実行
apk add --virtual build-dependencies build-base gcc wget git
https://github.com/gliderlabs/docker-alpine/issues/24#issuecomment-411117124
事前にバケットに対応するユーザを作っておく必要がある。
require 'couchbase'
# usernameは`nil`かバケット名と同じ文字列が入る
c = Couchbase.connect('http://localhost:8091', :bucket => "users", :username => nil, :password => 'password')
# ドキュメント取得
res = c.get('key')
# 全ドキュメント削除
c.query('drop primary index on users') # flushの前にインデックスを削除しないといけない
c.flush
# DELETE文ならインデックス削除しなくていい(むしろ必要
c.query('delete from users')
# ドキュメント追加(更新)
c.set('id', {:email => "hoge@example.com", :name => "hoge"})
# N1QL
c.query('create primary index on users') # selectの前にインデックスを追加しないといけない
res = c.query('SELECT meta(users).id, email, name FROM users')
p res[:rows].map {|row|
{
'id'=> row['id'],
'email'=> row['email'],
'name'=> row['name'],
}
}