2015年8月12日水曜日

Cloudant(CouchDB)を操作する際の最低限のおさえどころ


CouchDBはJSON形式でデータの入出力が行えるNoSQLである。
CloudantはCouchDBをベースに作られたクラウドで利用できるDBaaS(distributed database as a service)である。
現在CloudantはIBMが提供しているbluemixのサービスとして利用できる。

ここではCloudantの使い方をまとめておく。
アカウントは取得済みであることを前提とする。

登録が終わるとusernameとpasswordが払い出される。
以下手順内では${username}、${password}変数部分は各自のものに読み替えていただきたい。



◆ WEBコンソール
ブラウザを開いてアクセスできることを確認する。
https://${username}:${password}@${username}.cloudant.com/dashboard.html"



◆ データベースの操作
WEBのコンソールからも操作はできるが、REST経由で操作できるためコマンドラインで手順を残しておく。

(全データベースの取得)
$ curl -X GET "https://${username}:${password}@${username}.cloudant.com/_all_dbs"


(データベースの新規作成)
$ db="testdb"
$ curl -X PUT "https://${username}:${password}@${username}.cloudant.com/${db}"


(削除)
$ curl -X DELETE "https://${username}:${password}@${username}.cloudant.com/${db}"



◆ jsonデータ(ドキュメント)の操作
リレーショナルなデータベースではないためid検索が基本である。
サーチインデックスを付与しない場合、直接それ以外の属性(下記例ではname, ageなど)による検索はできない。
投入する値がユニークであれば、"_id"キーにデータを入れるのも手だろう。
idやサーチインデックスについては後述。

(1ドキュメントを投入する場合)
$ doc='{
"name": "aaa",
"age": "20",
"hobbies": {
"1st": "computer",
"2nd": "ferret"
},
"timestamp": "1438354800"
}'

$ curl -v \
-H "Content-type: application/json" \
-X POST \
-d "${doc}" \
https://${username}:${password}@${username}.cloudant.com/${db}/


(2つ以上のドキュメントはbulk投入できる)
jsonをここではdoc.jsonというファイル名で保存したとする。
{
    "docs": [
        {
            "name": "aaa",
            "age": "20",
            "hobbies": {
                "1st": "computer",
                "2nd": "ferret"
            },
            "timestamp": "1438354800"
        },
        {
            "name": "bbb",
            "age": "30",
            "hobbies": {
                "1st": "food",
                "2nd": "book"
            },
            "timestamp": "1438354860"
        },
        {
            "name": "ccc",
            "age": "40",
            "hobbies": {
                "1st": "car",
                "2nd": "movie"
            },
            "timestamp": "1438354920"
        }
    ]
}

$ curl -v \
-H "Content-type: application/json" \
-X POST \
-d @doc.json \
"https://${username}:${password}@${username}.cloudant.com/${db}/_bulk_docs"



◆ ドキュメントの操作

(全てのドキュメントを取得)
$ curl -X GET "https://${username}:${password}@${username}.cloudant.com/${db}/_all_docs"

結果にはidだけ渡される。ドキュメントその物を含んで欲しいときはinclude_docsフラグを付与する。
$ curl -X GET "https://${username}:${password}@${username}.cloudant.com/${db}/_all_docs?include_docs=true"

?limit=***
を付与することで取得するドキュメント数を制限できる。


(個別のドキュメントの取得)
$ curl -X GET "https://${username}:${password}@${username}.cloudant.com/${db}/${_id}"


(更新)
まずidとrev番号を確認する。
先の個別のドキュメントの取得時の結果の_id、_rev属性の値として確認できる。
それをjsonファイルに追加して対応する。それ以外は更新も新規投入と同じである。
revision番号は更新のたびに変わるため、その都度確認すること。

$ doc='{
"_id": "***",
"_rev": "***",
"name": "aaa",
"age": "20",
"hobbies": {
"1st": "computer",
"2nd": "ferret"
},
"timestamp": "1438354800"
}'

$ curl -v \
-H "Content-type: application/json" \
-X POST \
-d "${doc}" \
https://${username}:${password}@${username}.cloudant.com/${db}/


(削除)
idをurlパスに、rev番号をurlパラメータにしてdeleteメソッドを呼ぶ。

$ curl -X DELETE https://${username}:${password}@${username}.cloudant.com/${db}/${_id}?rev=${_rev}



◆ インデックスの作成と検索
cloudantはLuceneベースの検索ができる。ランク付き検索、強力な照会タイプ、結果のブックマーキング、ファセット検索、フィールド検索などの機能も備えている。


(作成)
WEBコンソールから
Databases -> testdb
All Design Docs -> New Search Index

入力ボックスで指示していく(_design配下でインデックスは管理される)。
・ Save to Design Document: _design/index ※indexは任意の名称である

・ index name: info ※任意の名称である

・ Search index function: 
function (doc) {
  if (doc.name && doc.hobbies) {
    index("name", doc.name, {"store":true});
    index("hobbiy_1st", doc.hobbies["1st"], {"store":true});
    index("hobbiy_2nd", doc.hobbies["2nd"], {"store":true});
    index("timestamp", doc.timestamp, {"store":true});
    return
  }
}

・ Analyzer: Single

・ Type: Standard

インデックスは既に投入済みのドキュメントにも有効である。


(検索)
$ curl -X GET "https://${username}:${password}@${username}.cloudant.com/${db}/_design/index/_search/info?q=name:aaa"

$ curl -X GET "https://${username}:${password}@${username}.cloudant.com/${db}/_design/index/_search/info?q=hobby_1st:computer"

$ curl -X GET "https://${username}:${password}@${username}.cloudant.com/${db}/_design/index/_search/info?q=timestamp:1438354*"


storeオプションの有無で検索結果に値を含むかどうかが変わる。
デフォルトではfalseである。
trueに数rことで、include_docsを使わずに欲しい情報を取得することができるようになる。 

nameキーで検索した結果をそれぞれ見てみる。

・storeがtrue場合
{"total_rows":1,"bookmark":"g2wAAAABaANkAB9kYmNvcmVAZGIxMi5pYm0wMDkuY2xvdWRhbnQubmV0bAAAAAJuBAAAAADAbgQA____32poAkY_06N6AAAAAGEAag","rows":[{"id":"3f8705b307d03b42a4fd027d49b58436","order":[0.3068528175354004,0],"fields":{"name":"aaa"}}]}

・storeがfalse場合
{"total_rows":1,"bookmark":"g2wAAAABaANkAB9kYmNvcmVAZGIxMi5pYm0wMDkuY2xvdWRhbnQubmV0bAAAAAJuBAAAAADAbgQA____32poAkY_06N6AAAAAGEAag","rows":[{"id":"3f8705b307d03b42a4fd027d49b58436","order":[0.3068528175354004,0],"fields":{}}]}



◆ map/reduceの利用
map/reduceを使うためにはmap関数で指定するキーとしてセカンダリインデックス、またはビューと呼ばれるキーを設定しなければならない。

(作成)
WEBコンソールから
Databases -> testdb
All Design Docs -> New View

入力ボックスで指示していく。
・ Design Document: _design/index ※すでに作成済みのものを利用

・ index name: info ※任意の名称である

・ Map function
function(doc) {
  emit(doc._id, 1);
}

mapフェーズでは"doc._id"をキーとして数字1を出力し、
reduceフェーズでそれを集約する("doc._name"でも構わない。目的に応じてmap対象を選べばよい)。

・ Reduce function: _stat
statはsum, count, min, max, sumsqrをまとめて出力する。

例えばsumは実質以下と同じ。
function (keys, values, rereduce) {
  return values.length;
}


(検索)
$ curl -X GET "https://${username}:${password}@${username}.cloudant.com/${db}/_design/index/_view/info"
{"rows":[
{"key":null,"value":{"sum":3,"count":3,"min":1,"max":1,"sumsqr":3}}
]}




~参考~
IBM Cloudant 公式マニュアル

CloudantDBとSQL系DBの違い



0 件のコメント:

コメントを投稿