PHP 開発者のための CouchDB の基本

PHP 開発者の視点から CouchDB を調べる

著者の Thomas Myer が、経験豊富な PHP 開発者の技術ツールボックスに CouchDB を追加する方法について説明します。

Thomas Myer, Principal, Triple Dog Dare Media

author Thomas Myer はオースチンを拠点に活動するコンサルタントであり、著作者であり、講演者です。彼は Triple Dog Dare Media を運営しており、また Twitter では @myerman としてツイートしています。



2010年 3月 23日

皆さんが典型的な PHP 開発者であるなら、過去のプロジェクトを隅から隅まで見返さなくても PHP を使った明らかなパターンを見出せるはずです。つまり皆さんは (すべてとは言えないまでも) ほとんどの場合、PHP を使ってデータベース・バックエンドと通信し、あらゆる動的データを処理します。そしてそうした場合の 99 パーセントは MySQL を使っています。

リレーショナル・データベースを使うことは、悪いことではありません。関係を大量に持ち、高度に構造化されたデータを扱う場合には、まさにリレーショナル・データベースが適しています。リレーショナル・データベースによって、皆さんは苦労なく (あるいは、SQL に対する理解が不十分な場合や SQL に慣れていない場合には苦労しながら)、スキーマの作成や、データ相互の関係の正規化、テーブルのセットアップ等々のプロセスを処理することができます。

しかし皆さんは時によると、「なぜ私はこうした作業をしているのだろう」と自問するようなプロジェクトに従事することがあります。そうしたプロジェクトには、非常に単純なちょっとしたデータが含まれているだけであったり、予測困難なデータが含まれていたりする場合があり、得られるデータ・フィールドは日によって異なったり、さらにはトランザクションごとに異なったりします。取得されるデータを想定したスキーマを作成しようとすると、空のフィールドを大量に持つ、あるいはマッピング・テーブルを大量に持つテーブルが作成されてしまう羽目になります。

よく使われる頭字語

  • Ajax: Asynchronous JavaScript + XML
  • API: Application programming interface
  • GUID: Globally Unique Identifier
  • HTTP: Hypertext Markup Language
  • JSON: JavaScript Object Notation
  • REST: Representational State Transfer
  • SQL: Structured Query Language
  • UUID: Universal Unique Identifier

そうしたプロジェクトでは、従来とは異なる、リレーショナル・データベースを使用しない手法が必要です。リレーショナル・データベースを使用しない手法では、ドキュメント・ベースでスキーマ不要、そして必要な場合に随時作成される、フラットなアドレス空間を持つデータベースが必要になります。要するに、Apache CouchDB が必要なのです。

CouchDB とは何か

Apache CouchDB の Web サイトによれば、CouchDB は以下の特徴を持ちます。

  • RESTful な JSON API を使ってアクセス可能な文書データベース・サーバーです。
  • 随時作成され、スキーマは不要であり、アドレス空間はフラットです。
  • 分散型であり、堅牢でインクリメンタルな複製を特徴とし、競合の検出と管理を双方向で行うことができます。
  • クエリーおよび索引付けが可能であり、問い合わせ言語に JavaScript を使用するテーブル指向のレポート・エンジンを備えています。

これはつまり、CouchDB データベースを作成すると JSON 文書を受け付けられるということです。各文書は固有のリビジョン ID を取得して独自の構造を持ち、すべての文書は同じフラットな集合の中に格納されます。例えば履歴書の集合をデータベースに格納して扱うようにするとします。1 番目の履歴書には、苗字、名前、電話番号、E メール・アドレス、Twitter アカウント、資格リスト、そして詳細な職歴が含まれています。2 番目の履歴書には、苗字、名前、E メール・アドレスが含まれ、さらに職歴が別リストとして含まれています。2 つの履歴書の間の違いはリレーショナル・データベースで扱おうとすると非常に面倒ですが、CouchDB で扱えばどうってことありません。

簡単に言えば、CouchDB 文書は名前付きフィールドで構成されるオブジェクトです。これらのフィールドの値は、ストリングの場合もあれば、ブール値、数字、日付、発注リスト、連想マップなどの場合もあります。リスト 1 は履歴書の文書の例を示しています。

リスト 1. 単純な CouchDB 文書の例
{
"Firstname": "Tom"
"Lastname": "Myer"
"Twitter": "@myerman"
"Email": "tom@example.com"
"Skills": ["php","couchdb","xml","json"]
"Work History": ....
}

ここまでの説明は、JSON の処理に慣れている読者とっては特別なものではありません。JSON の処理に慣れていない読者であっても、この文書を PHP の配列のような使い慣れたものに対応させることは容易なはずです。実際、JSON エンコード/デコード用の組み込み関数を使って CouchDB を操作したり、オブジェクト指向の手法を使ったりすることもできるということがわかると思います。

集合の情報を照会する方法としては、RESTful な JSON API による使いやすい各種クエリー手法を使用することができます。JSON を扱えばよいため、多くの問題が単純になります。例えば、JavaScript、Ajax、JSON をよく理解した Web 開発者であれば、SQL を知らなくてもどんな処理でも行うことができます。

先に進む前にいったん立ち止まり、いくつかのポイントを強調することにしましょう。CouchDB はリレーショナル・データベースではありません。この点については先ほど触れましたが、重要なポイントとして強調しておく価値があります。リレーショナル・データベースの流儀で CouchDB を使おうとしてはなりません。例えば、文書間の関係を明確するために ID フィールドを挿入しようとしてはなりません。関係を作成する代わりに、必要な内容を文書の中に追加して作業を続ければよいのです。

また、CouchDB はオブジェクト指向のデータベースでもありません。CouchDB はネイティブ・オブジェクトの類いではなく、オブジェクト指向構造の土台として使用可能な永続データ・レイヤーではありません。そうした使い方で CouchDB を使ってはなりません。


CouchDB をインストールする

Mac OS X を使用している場合には、CouchDB のインストール・プロセスは以下のように非常に単純です。

Linux でのインストール

developerWorks の編集者は Ubuntu Linux が動作するラップトップ・コンピューターに対し、下記の 2 つのステップで CouchDB をインストールすることができました。

sudo apt-get install couchDB
sudo /etc/init.d/couchdb start

このステップを実行したところ、CouchDB は既にリポジトリーにあり、何の問題もなくロードされました。

  1. ターミナル・ウィンドウを開き、sudo port install couchdb と入力します。
  2. パスワードの入力を要求する画面が表示されたら、root パスワードを入力します。
  3. MacPorts を起動し、必要な CouchDB パッケージをインストールします。
  4. ターミナル・ウィンドウからコマンド sudo port upgrade couchdb を実行し、ごく最近追加された変更や依存関係を入手します。
  5. CouchDB を起動して実行するためには、ターミナル・ウィンドウに以下のコマンドを入力します。
    sudo launchctl load -w /opt/local/Library/LaunchDaemons/org.apache.couchdb.plist

    このコマンドによって CouchDB サーバーが起動し、永続的に実行されます。そのため、Mac を再起動すると必ず CouchDB サーバーが起動します。

CouchDB の動作を調べるためには、ブラウザーのアドレスバーに http://127.0.0.1:5984/_utils/index.html と入力します。すると図 1 のような Futon ユーティリティーが表示されます。

図 1. Futon ユーティリティー
Futon ユーティリティー

Windows® システムでは、このプロセスはもっと複雑です。Cygwin や Microsoft® C コンパイラー、その他さまざまな前提条件 (cURL、ICU、SeaMonkey など) をインストールする必要があり、また Erlang と Couch のソース・コードをダウンロードしてインストールし、それらを README ファイルに従って構成してから完全なインストールを行う必要があります。このプロセスは CouchDB のウィキ (「参考文献」を参照) に説明されています。またそのウィキには Linux®、BSD (Berkeley Software Distribution)、その他の環境へのインストール方法についても説明されています。


CouchDB の API を使用する

PHP の話題に移る前に、CouchDB の API の感覚をつかんでおきましょう。CouchDB の API を利用するためには HTTP の GET リクエストと PUT リクエストを使用します。すると CouchDB の API は JSON フォーマットでデータを返します。そのため、どのような言語を使用するかによらず、Web アプリケーションから容易にデータの保存や取得を行うことができます (使用する言語としては、PHP、Microsoft ASP (Active Server Pages)、Ruby、Python、さらには jQuery による単純な Ajax 関数なども考えられます)。

このセクションでは、cURL コマンドライン・ツールを利用して CouchDB に GETPOSTPUTDELETE リクエストを送信する方法を説明します。いったん CouchDB の API の感覚をつかめると、特定の PHP ラッパーを使うことで開発作業を単純化することができます。

まず、(この場合もターミナル・ウィンドウから) コマンド curl http://127.0.0.1:5984/ を実行する必要があります。すると {"couchdb":"Welcome","version":"0.10.0"} のようなレスポンスが表示されるはずです。これは単純に、CouchDB が起動され、稼働中であること、そしてどのバージョンが使われているかを示しています。このメッセージが表示されない場合には、インストールと構成のプロセスを再度繰り返し、CouchDB を稼働させます。

今度は、CouchDB の中に格納されたすべての集合を一覧表示します。curl -X GET http://127.0.0.1:5984/_all_dbs を実行します。

初めて CouchDB をインストールした場合には、レスポンスとして [] が表示されるはずです。これは集合やデータベースが何もないことを意味します (二重の角括弧は空の JavaScript 配列を意味します)。この cURL コマンドの場合、-X オプションを使用して GET 操作を明示的に指定していることに注意してください。

では、データベースがないという問題を解決するために、データベースを作成しましょう。

curl -X PUT http://127.0.0.1:5984/songs

このコマンドを実行すると、{"ok":true} というレスポンスが表示されます。このことから、ok 属性を調べればコマンドが成功したかどうかを確認できることがわかります。再度 curl -X GET http://127.0.0.1:5984/_all_dbs を実行すると、空ではない配列 ["songs"] が得られます。もっと具体的に言えば、この CouchDB インスタンスには songs という 1 つのデータベースがあります。

今度は、もう 1 つ songs というデータベースを作成してみます。再度 curl -X PUT http://127.0.0.1:5984/songs を実行すると、下記のエラー・メッセージが表示されます。

{"error":"file_exists","reason":"The database could not be created, 
    the file already exists."}

つまり、error 属性を調べることで、何か問題が起きたかどうかを容易に調べることができます。

foobar という 2 番目のデータベースを下記のように作成します。

curl -X PUT http://127.0.0.1:5984/foobar

もし curl -X GET http://127.0.0.1:5984/_all_dbs を実行したとすると、レスポンスは ["songs","foobar"] のようになります。この 2 番目のデータベースを削除するためには、DELETE 呼び出しを渡します。

curl -X DELETE http://127.0.0.1:5984/foobar

curl -X GET http://127.0.0.1:5984/_all_dbs を実行すると、["songs"] のみの状態に戻ったことがわかります。

今度は songs データベースの中にいくつかの文書を作成します。ごく普通の処理として、このデータベースの中に何曲かを保存します。各曲にはフィールドとして、曲のタイトル、アーティストの名前、アルバムの名前があります。文書を作成するためには、以下のパターンに従います。

curl -X PUT http://127.0.0.1:5984/songs/*id* -d '{ *json_data* }'

データベースの名前を呼び出していること、それに続いて何らかの ID (この CouchDB インスタンスで一意であるだけではなく、できればすべての CouchDB インスタンスで一意である必要があります) があり、その後に JSON データがあることに注目してください。

わざわざ一意の ID を用意する必要はありません。一意の ID として UUID (または GUID) を使うことや、多様なデータを組み合わせた何らかの自然キー (例えば曲の名前とタイムスタンプとを、空白の代わりにアンダーバーでつなげたもの) を作成すること、あるいは一意の ID を CouchDB に作成させることもできます (このプロセスは低速です)。これらのどの方法も適切ですが、MySQL 環境の場合のようにオート・インクリメントされるような値を使ってはなりません。

今度は、下記のようにデータベースに曲を入力します。

curl -X PUT http://localhost:5984/songs/whatever_you_like -d \
	'{"title":"Whatever You Like", "artist":"T.I.","album":"Paper Trail"}'

{"ok":true,"id":"whatever_you_like","rev":"1-1d915e4c209a2e47e5cf05594f9f951b"}

ここでは一意の ID として非常に単純な手法を使っていることに注目してください (曲名には単純な形式を使い、空白の代わりにアンダーバーを使っています)。この単純な方式でも、とりあえず OK でしょう。幸いなことに、この後で PHP によるラッパーを使うことで、もっと適切な ID が作成されます。また、ここでは即座に「ok」レスポンスを受信しており、そのレスポンスには文書の ID と、設定されたリビジョン番号を示す rev 属性が含まれていることにも注意してください。

今ここで追加した文書を表示するためには、下記を実行します。

curl -X GET http://localhost:5984/songs/whatever_you_like

{"_id":"whatever_you_like","_rev":"1-1d915e4c209a2e47e5cf05594f9f951b", 
	"title":"Whatever You Like", "artist":"T.I.", "album":"Paper Trail"}

Futon ユーティリティーを使って作業を進めていれば、songs というデータベース名をクリックすることができ、これにより文書リストの中に whatever_you_like が表示されるはずです。そのリンクをクリックすると、この文書の詳細が表示されます (図 2)。

図 2. 文書の詳細
曲に関して入力された内容の一覧を示すスクリーン・ショット。すべてのフィールドにデータが追加されたものが表示されています。

これで、感覚がつかめてきたことと思います。つまり JSON を使って RESTful なリクエストを行うと、求める結果が得られるのです。

さて、これらはどれも非常に素晴らしいのですが、皆さんが PHP 開発者であるなら、これらを皆さんが慣れ親しんだものとどう関連付けるのかと思うかもしれません。そこで次のセクションでは、CouchDB のための PHP ラッパーを紹介します。


PHP を使う

次のステップとして、Github から PHP-on-Couch をダウンロードする必要があります (「参考文献」を参照)。解凍した /lib フォルダーの内容を開発領域に置きます。作業領域を設定したら、先ほど作成した CouchDB データベース (曲のコレクション) と通信する簡単な PHP アプリケーションを作成します。新しいファイルを作成し、そのファイルに index.php という名前を付けます。そのファイルの中にリスト 2 のコードを追加します。

リスト 2. CouchDB への接続設定
<?php
$couch_dsn = "http://localhost:5984/";
$couch_db = "songs";

require_once "./lib/couch.php";
require_once "./lib/couchClient.php";
require_once "./lib/couchDocument.php";


$client = new couchClient($couch_dsn,$couch_db);
?>

このコードは CouchDB への接続コードとして機能し、このデータベースを扱うために必要となる、関連するクラスをすべて含んでいます。早速、先ほどのデータベースに関するすべての情報をリストアップします (リスト 3)。

リスト 3. データベースの情報を取得する
try {
	$info = $client->getDatabaseInfos();
} catch (Exception $e) {
	echo "Error:".$e->getMessage()." (errcode=".$e->getCode().")\n";
	exit(1);
}
print_r($info);

その結果、リスト 4 のようなものが得られるはずです。

リスト 4. データベースの情報
stdClass Object 
( 
	[db_name] => songs 
	[doc_count] => 2 
	[doc_del_count] => 0 
	[update_seq] => 2 
	[purge_seq] => 0 
	[compact_running] => 
	[disk_size] => 8281 
	[instance_start_time] => 1266082749089965 
	[disk_format_version] => 4 
)

次に、曲のデータベースから 1 つの文書を取得します。リスト 5 はそのためのコードを示しています。

リスト 5. データベースから曲を取得する
try {
	$doc = $client->getDoc('whatever_you_like');
} catch (Exception $e) {
	if ( $e->code() == 404 ) {
		echo "Document not found\n";
	} else {
		echo "Error: ".$e->getMessage()." (errcode=".$e->getCode().")\n";
	}
	exit(1);
}
print_r($doc);

リスト 6 は、そのレスポンスを示しています。

リスト 6. 取得された曲
stdClass Object
(
    [_id] => whatever_you_like
    [_rev] => 1-1d915e4c209a2e47e5cf05594f9f951b
    [title] => Whatever You Like
    [artist] => T.I.
    [album] => Paper Trail
)

素晴らしい結果ですが、文書を更新したい場合にはどうすればよいのでしょう?更新の方法には、既存のフィールド値を変更する方法、または独自の値を持つ新しいフィールドを追加する方法、という 2 種類があります。更新を行うためには矢印表記を使い (例えば $doc->new_field など)、storeDoc() を使って変更をコミットします。リスト 7 は文書を更新するためのコードを示しています。

リスト 7. 文書を更新する
$doc->genre = 'hip-hop';
$doc->year = 2008;
try {
        $response = $client->storeDoc($doc);
} catch (Exception $e) {
        echo "Error: ".$e->getMessage()." (errcode=".$e->getCode().")\n";
        exit(1);
}

このコードを実行すると、文書の ID を取得することができ、リスト 8 のレスポンスが得られます。

リスト 8. 更新された文書
stdClass Object
(
    [_id] => whatever_you_like
    [_rev] => 2-12513a362693b300928aa45f82faed83
    [title] => Whatever You Like
    [artist] => T.I.
    [album] => Paper Trail
    [genre] => hip-hop
    [year] => 2008
)

_rev 属性が 2-xxxx にインクリメントされていることに注意してください。更新前の値は 1-xxxx でした。_rev 属性によって、どんなリビジョンがあるのかを容易に知ることができます。

新しい文書をデータベースに保存したい場合にはどうすればよいのでしょう?その場合には、新しいオブジェクトをインスタンス化し、矢印表記を使って文書のフィールドにデータを追加します。リスト 9 のコードはその方法を示しています。

リスト 9. 新しい文書を作成する
$song = new stdClass();
$song->_id = "in_the_meantime";
$song->title = "In the Meantime";
$song->album = "Resident Alien";
$song->artist = "Space Hog";
$song->genre = "Alternative";
$song->year = 1995;

try {
	$response = $client->storeDoc($song);
} catch (Exception $e) {
	echo "Error: ".$e->getMessage()." (errcode=".$e->getCode().")\n";
	exit(1);
}
print_r($response);

このレスポンスはリスト 10 のようになります。

リスト 10. 新しい文書を作成した場合のレスポンス
stdClass Object
(
    [ok] => 1
    [id] => in_the_meantime
    [rev] => 1-d65b03a9fe2f3c8095b08883e7cd97df
)

まとめ

ここまで読むと、CouchDB と PHP を使い始める上で十分すぎるほどの情報が得られたことになります。皆さんは基本的な更新フォームを簡単に作成できるはずであり、そのフォームを使ってデータベースの中で文書を作成したり既存の文書を更新したりできるはずです。また PHP-on-Couch パッケージを使用すると、データベースの作成や削除、CouchDB のビューの処理、等々に他の手法を使えるようになります。運が良ければ、この記事の中には適切な出発点として利用できる十分な情報があるはずです。

参考文献

学ぶために

  • CouchDB プロジェクトのサイトを訪れてください。
  • CouchDB: The Definitive Guide の無料のオンライン版は CouchDB に関して最も信頼のおけるガイドです。
  • CouchDB のウィキを調べ、CouchDB に関する疑問への答えを見つけてください。
  • Windows プラットフォームに CouchDB をインストールする方法については Installing CouchDB on Windows を読んでください。
  • Installing CouchDB on Linux/BSD を訪れ、Linux または BSD を実行するコンピューターに CouchDB をインストールする方法を学んでください。
  • The CouchDB API Reference を調べ、この記事で使用した CouchDB の API について学んでください。
  • CouchDB を探る」を読み、CouchDB の特徴について学んでください。
  • PHP.net には PHP 開発者のためのリソースが集まっています。
  • Recommended PHP reading list」を調べてみてください。
  • developerWorks には他にも PHP に関する記事が豊富に用意されています。
  • developerWorks を Twitter でフォローしてください。
  • IBM developerWorks の PHP project resources を利用して PHP のスキルを磨いてください。
  • developerWorks podcasts ではソフトウェア開発者のための興味深いインタビューや議論を聞くことができます。
  • PHP でデータベースを使うのであれば、Zend Core for IBM を調べてみてください。これはシームレスでそのまま使用でき、インストールも容易な、IBM DB2 V9 をサポートする PHP の開発環境であり本番環境でもあります。
  • My developerWorks コミュニティーは広範な話題を網羅した全般的なコミュニティーとして成功している一例です。
  • developerWorks の Technical events and webcasts で最新情報を入手してください。
  • IBM オープンソース開発者にとって関心のある、世界中で今後開催される会議や業界展示会、ウェブキャスト、その他のイベントについて調べてみてください。
  • developerWorks の Open source ゾーンをご覧ください。オープンソース技術を使った開発や、IBM 製品でオープンソース技術を使用するためのハウ・ツー情報やツール、プロジェクトの更新情報など、豊富な情報が用意されています。また最も人気のあった記事やチュートリアルもご覧ください。
  • IBM とオープンソース技術、そして製品機能を調べ、学ぶために、無料の developerWorks On demand demos をご覧ください。

製品や技術を入手するために

  • Github から PHP-on-Couch ライブラリーをダウンロードしてください。
  • 皆さんの次期オープンソース開発プロジェクトを IBM ソフトウェアの試用版を使って革新してください。ダウンロード、あるいは DVD で入手することができます。
  • IBM 製品の評価版をダウンロードするか、あるいは IBM SOA Sandbox のオンライン試用版で、DB2®、Lotus®、Rational®、Tivoli®、WebSphere® などが提供するアプリケーション開発ツールやミドルウェア製品を試してみてください。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source
ArticleID=483224
ArticleTitle=PHP 開発者のための CouchDB の基本
publish-date=03232010