CouchDB

  • 投稿者:
  • 投稿カテゴリー:NoSQL

概要

@ITのcouchDB記事を利用して、いろいろやってみた
http://www.atmarkit.co.jp/ait/articles/0909/04/news105.html

CouchDBとは

・2009年3月にApache Software Foudationの正式なプロジェクトとして最初のリリース
・主にErlangというプログラミング言語で実装されている
・JSON形式を介してデータの入出力を実施
・各ドキュメントに対して一意なURIを割り当てる。つまりドキュメント操作にHTTPメソッドを利用できる
・データをリビジョン管理しておりCompactionを実行するまでは、履歴が削除されない
・レプリケーションの機能が標準で組み込まれており、利用者の任意のタイミングでレプリケーションを実行する
 レプリケーションは、最新のリビションのみが対象となる
 この機能を利用して、オフラインでCouchDBを利用して、オンラインになるとレプリケーションで同期、といった動きも可能
・Design Documentという特別なドキュメントがあり、ドキュメントの検索や集計処理、ドキュメントの表示を動的に処理することが可能

インストール

root@hostname:/home/shimizu# aptitude show couchdb
パッケージ: couchdb
状態: インストールされていません
バージョン: 1.2.0-5
優先度: 任意
セクション: misc
メンテナ: Laszlo Boszormenyi (GCS) <gcs@debian.hu>
アーキテクチャ: amd64
展開サイズ: 2,713 k
依存: adduser, erlang-base (>= 1:15.b.1-dfsg) | erlang-base-hipe (>=
        1:15.b.1-dfsg), libjs-jquery (>= 1.4.2), libjs-jquery-form (>= 2.36),
        lsb-base, procps, erlang-crypto (>= 1:15.b.1-dfsg), erlang-inets (>=
        1:15.b.1-dfsg), erlang-xmerl (>= 1:15.b.1-dfsg), erlang-eunit (>=
        1:15.b.1-dfsg), erlang-os-mon (>= 1:15.b.1-dfsg), erlang-ssl (>=
        1:15.b.1-dfsg), erlang-syntax-tools (>= 1:15.b.1-dfsg), erlang-tools (>=
        1:15.b.1-dfsg), libc6 (>= 2.4), libcurl3 (>= 7.16.2), libgcc1 (>=
        1:4.1.1), libicu48 (>= 4.8-1), libmozjs185-1.0 (>= 1.8.5-1.0.0+dfsg),
        libstdc++6 (>= 4.4.0)
説明: REST を活用したドキュメント指向データベース
 Apache CouchDB は分散型で、耐故障性があり、スキーマフリーのドキュメント指向
 データベースで、REST を活用した HTTP/JSON API でアクセスできます。
 そのほかの特徴としては、ロバスト性、双方向衝突を検知して解決できる差分複製
 機能があり、また、デフォルトのビュー定義言語である JavaScript を用いてテー
 ブル指向のビューエンジンを使った探索および索引作成が可能です。

 CouchDB は Erlang で書かれていますが、HTTP リクエストを発行できる環境ならど
 こからでも簡単にアクセスすることができます。いろいろなプログラミング言語や
 環境において、より簡単にアクセスできるようにするためのたくさんのサードパー
 ティ製クライアントライブラリがあります。
ホームページ: http://couchdb.apache.org/

root@hostname:/home/shimizu# aptitude install couchdb
以下の新規パッケージがインストールされます:
  couchdb erlang-asn1{a} erlang-base{a} erlang-crypto{a} erlang-eunit{a} erlang-inets{a} erlang-mnesia{a}
  erlang-os-mon{a} erlang-public-key{a} erlang-runtime-tools{a} erlang-snmp{a} erlang-ssl{a}
  erlang-syntax-tools{a} erlang-tools{a} erlang-webtool{a} erlang-xmerl{a} libjs-jquery-form{a}
  libmozjs185-1.0{a} libsctp1{a} lksctp-tools{a}
更新: 0 個、新規インストール: 20 個、削除: 0 個、保留: 2 個。
16.2 M バイトのアーカイブを取得する必要があります。展開後に 31.1 M バイトのディスク領域が新たに消費されます。
先に進みますか? [Y/n/?] y
...
couchdb (1.2.0-5) を設定しています ...
[ ok ] Starting database server: couchdb.
libsctp1 (1.0.11+dfsg-2) を設定しています ...
lksctp-tools (1.0.11+dfsg-2) を設定しています ...

root@hostname:/home/shimizu# ps afx | grep "ouch"
29221 ?        S      0:00 /bin/sh -e /usr/bin/couchdb -a /etc/couchdb/default.ini -a /etc/couchdb/local.ini -b -r 5 -p /var/run/couchdb/couchdb.pid -o /dev/null -e /dev/null -R
29243 ?        S      0:00  \_ /bin/sh -e /usr/bin/couchdb -a /etc/couchdb/default.ini -a /etc/couchdb/local.ini -b -r 5 -p /var/run/couchdb/couchdb.pid -o /dev/null -e /dev/null -R
29244 ?        Sl     0:00      \_ /usr/lib/erlang/erts-5.9.1/bin/beam.smp -Bd -K true -A 4 -- -root /usr/lib/erlang -progname erl -- -home /var/lib/couchdb -- -noshell -noinput -os_mon start_memsup false start_cpu_sup false disk_space_check_interval 1 disk_almost_full_threshold 1 -sasl errlog_type error -couch_ini /etc/couchdb/default.ini /etc/couchdb/local.ini /etc/couchdb/default.ini /etc/couchdb/local.ini -s couch -pidfile /var/run/couchdb/couchdb.pid -heart

root@hostname:/home/shimizu# vi /etc/couchdb/default.ini
=====
[httpd]
port = 5984
bind_address = 0.0.0.0
=====
root@hostname:/home/shimizu# /etc/init.d/couchdb restart
[ ok ] Restarting database server: couchdb.

外部からアクセスすると
2014-12-20_213921

CouchDBの管理ツールであるFutonユーティリティを利用する
2014-12-20_213944

test_suite_foobar内のドキュメントを閲覧する
2014-12-20_214850

test_suite_foobar内のドキュメントは以下URLでアクセス可能
http://49.212.204.46:5984/test_suite_foobar/doc1
2014-12-20_215310

データベース操作

root@hostname:/home/shimizu# mkdir couchdb
root@hostname:/home/shimizu# cd couchdb/
root@hostname:/home/shimizu/couchdb# git clone git://github.com/z-ohnami/cocktail-sample.git
Cloning into 'cocktail-sample'...
remote: Counting objects: 27, done.
remote: Total 27 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (27/27), 28.83 KiB, done.
Resolving deltas: 100% (6/6), done.
root@hostname:/home/shimizu/couchdb# cd cocktail-sample/
root@hostname:/home/shimizu/couchdb/cocktail-sample# ./upload-all.sh 127.0.0.1
{"ok":true}
{"ok":true,"id":"matini","rev":"1-f58be22e6c517a3740432c096331a30f"}
{"error":"bad_content_type","reason":"Content-Type must be application/json"}
{"error":"bad_content_type","reason":"Content-Type must be application/json"}
{"ok":true,"id":"_design/d01","rev":"1-ed539ac0b127da44904226819196fbf3"}
{"ok":true,"id":"_design/d02","rev":"1-a48d76a64eaeaec52305bf3452f1e79b"}
{"ok":true,"id":"_design/d03","rev":"1-9a3317be70ecc076e136f4d17c6fbaa0"}
{"ok":true,"id":"_design/d04","rev":"1-17df994bc036dc89be2e14472effb4ae"}
finished ...,be relaxed !!

### データベースを作成する ###
root@hostname:/home/shimizu/couchdb/cocktail-sample# curl -X PUT 'http://127.0.0.1:5984/test'
{"ok":true}
root@hostname:/home/shimizu/couchdb/cocktail-sample# curl -X GET 'http://127.0.0.1:5984/test'
{"db_name":"test","doc_count":0,"doc_del_count":0,"update_seq":0,"purge_seq":0,"compact_running":false,"disk_size":79,"data_size":0,"instance_start_time":"1419082712784379","disk_format_version":6,"committed_update_seq":0}

### データベースの一覧をJSON形式で取得する ###
root@hostname:/home/shimizu/couchdb/cocktail-sample# curl -X GET 'http://127.0.0.1:5984/_all_dbs'
["_replicator","_users","cocktail-book","test","test_suite_db","test_suite_db/with_slashes","test_suite_db_a","test_suite_db_b","test_suite_db_c","test_suite_foobar","test_suite_reports","test_suite_users"]

### ドキュメントを登録する(POSTだとidがuuidで自動採番される) ###
root@hostname:/home/shimizu/couchdb/cocktail-sample# curl -X PUT  -d '{"name":"mimosa","proof":32}' 'http://127.0.0.1:5984/cocktail-book/mimosa'
{"ok":true,"id":"mimosa","rev":"1-3c1c87c4524329789538e73bce534f61"}
root@hostname:/home/shimizu/couchdb/cocktail-sample# curl -X GET http://127.0.0.1:5984/cocktail-book/mimosa
{"_id":"mimosa","_rev":"1-3c1c87c4524329789538e73bce534f61","name":"mimosa","proof":32}

### ドキュメントを更新する。部分更新を実行することはできない。リビジョン管理される ###
root@hostname:/home/shimizu/couchdb/cocktail-sample# cat document/mimosa.txt
{
"_rev":"1-3c1c87c4524329789538e73bce534f61",
"name":"ミモザ",
"proof":32,
"howto":"ステア",
"base":"シャンパン",
"recipe":{
    "シャンパン":"60ml",
    "オレンジジュース":"60ml"
  },
"situation":["食前","食後","007","ナイトキャップ","デザート"]
}

root@hostname:/home/shimizu/couchdb/cocktail-sample# curl -X PUT -d @'./document/mimosa.txt' 'http://127.0.0.1:5984/cocktail-book/mimosa'
{"ok":true,"id":"mimosa","rev":"2-a8188c791fed7f4f96e82f71c77a66f3"}
root@hostname:/home/shimizu/couchdb/cocktail-sample# curl -X GET http://127.0.0.1:5984/cocktail-book/mimosa
{"_id":"mimosa","_rev":"2-a8188c791fed7f4f96e82f71c77a66f3","name":"ミモザ","proof":32,"howto":"ステア","base":"シャンパン","recipe":{"シャンパン":"60ml","オレンジジュース":"60ml"},"situation":["食前","食後","007","ナイトキャップ","デザート"]}

### 検索する。"_all_docs"APIでkeyに指定できるのは"_id"のみ ###
root@hostname:/home/shimizu/couchdb/cocktail-sample# curl -X GET 'http://127.0.0.1:5984/cocktail-book/_all_docs?startkey="ma"'
{"total_rows":6,"offset":4,"rows":[
{"id":"matini","key":"matini","value":{"rev":"1-f58be22e6c517a3740432c096331a30f"}},
{"id":"mimosa","key":"mimosa","value":{"rev":"2-a8188c791fed7f4f96e82f71c77a66f3"}}
]}

### 一覧取得する ###
root@hostname:/etc/couchdb# curl -X GET 'http://127.0.0.1:5984/cocktail-book/_all_docs'
{"total_rows":6,"offset":0,"rows":[
{"id":"_design/d01","key":"_design/d01","value":{"rev":"3-0f090673dd5b44d4d4698c98575260b5"}},
{"id":"_design/d02","key":"_design/d02","value":{"rev":"1-a48d76a64eaeaec52305bf3452f1e79b"}},
{"id":"_design/d03","key":"_design/d03","value":{"rev":"1-9a3317be70ecc076e136f4d17c6fbaa0"}},
{"id":"_design/d04","key":"_design/d04","value":{"rev":"3-088c86f5c242e9b5f3ca7cb14c99910b"}},
{"id":"matini","key":"matini","value":{"rev":"1-f58be22e6c517a3740432c096331a30f"}},
{"id":"mimosa","key":"mimosa","value":{"rev":"2-a8188c791fed7f4f96e82f71c77a66f3"}}
]}

データベース操作-Design Document

view

特定の条件に合致するドキュメントの検索やドキュメントの集計処理ができる

root@hostname:/home/shimizu/couchdb/cocktail-sample# cat ./design/d01.txt
{
  "language": "javascript",
  "views": {
    "gin-by-proof" : {
      "map": "function(doc) {
        if (doc.proof && doc.base == \"ジン\") {
            emit(doc.proof, doc.name);
          }}"
       },
   "all-by-base" : {
      "map": "function(doc) {
        if (doc.name) {
            emit(doc.base, doc.name);
          }}"
       }
   }
}

root@hostname:/home/shimizu/couchdb/cocktail-sample# curl -X PUT -H'Content-Type: application/json' -d @'./design/d01.txt' 'http://127.0.0.1:5984/cocktail-book/_design/d01'
{"ok":true,"id":"_design/d01","rev":"3-0f090673dd5b44d4d4698c98575260b5"}
root@hostname:/home/shimizu/couchdb/cocktail-sample# curl -X GET 'http://127.0.0.1:5984/cocktail-book/_design/d01/_view/gin-by-proof?descending=true'
{"total_rows":1,"offset":0,"rows":[
{"id":"matini","key":35,"value":"マティーニ"}
]}

show , list

JSON形式のデータを任意の書式で出力できる

root@hostname:/home/shimizu/couchdb/cocktail-sample# cat design/d03.txt
{
  "language": "javascript",
  "views": {
    "gin-by-proof" : {
      "map": "function(doc) {
        if (doc.proof && doc.base == \"ジン\") {
            emit(doc.proof, doc.name);
          }}"
       }
   },
  "shows": {
     "show-detail": "(function (doc, req) {
        if (doc) {
           var str;
           str = \"<h2>\" + doc.name + \"</h2><ul>\";
           str = str + \"<li>度数:\" + doc.proof + \"</li>\";
           str = str + \"<li>ベースのお酒:\" + doc.base + \"</li>\";
           str = str + \"<li>作り方:\" + doc.howto + \"</li>\";

           str = str + \"<li>レシピ:<ul>\";
           for(var r in doc.recipe) {
              str = str + \"<li>\" + r + \":\" +doc.recipe[r] + \"</li>\";
           }
           str = str + \"</ul></li>\";

           str = str + \"<li>シチュエーション:\";
           for(var i in doc.situation) {
              if (i > 0) str = str + \",\";
              str = str + doc.situation[i];
           }
           str = str + \"</li></ul>\";

           if (doc._attachments) {

              str = str + \"<img src=\\\"../../../../\" + doc._id + \"/\" + doc._id + \".jpg\\\">\";

           }

           return str;

      } else {
        if (req.docId) {
           return \"Undefined Document...\";
        } else {
           return \"docId is empty...\";
        }
      }
    })"
  }
}

root@hostname:/home/shimizu/couchdb/cocktail-sample# curl -X PUT -H'Content-Type: application/json' -d @'./design/d04.txt' 'http://127.0.0.1:5984/cocktail-book/_design/d04'
{"ok":true,"id":"_design/d04","rev":"3-088c86f5c242e9b5f3ca7cb14c99910b"}

http://49.212.204.46:5984/cocktail-book/_design/d03/_show/show-detail/mimosa
にアクセスすると
2014-12-21_002551

スケールアウト

CouchDBをノードとして登録する
dumbproxyというNginxをもとにしたリバースプロキシが受けて、対象ノードに振り分ける
すべてのノードが対象になる処理はsmartproxyというTwistedを利用したリバースプロキシに処理が引き継がれる
パッチを当てないとCouchDBをノードとして登録できない点が運用面としてのネック
2014-12-21_191646

参考URL

“動物図鑑”で知るCouchDBの特徴
http://www.atmarkit.co.jp/ait/articles/0909/04/news105.html