The Core API

コアAPI

This chapter explores the CouchDB in minute detail. It shows all the nitty-gritty and clever bits. We show you best practices and guide you around common pitfalls.

この章では、CouchDBの大事なところを中心に、ベストプラクティスやよくある落とし穴を説明します。少し細かい内容となります。

We start out by revisiting the basic operations we ran in the last chapter, looking behind the scenes. We also show what Futon needs to do behind its user interface to give us the nice features we saw earlier.

まずは前章での基本的な操作を復習しながら、その背後で何が起きているかを見ていきましょう。また、Futonのユーザーインターフェイスの背後で何が起きているかをみれば、これまで見てきたCouchDBの素敵な特徴がみえてくることでしょう。

This chapter is both an introduction to the core CouchDB API as well as a reference. If you can’t remember how to run a particular request or why some parameters are needed, you can always come back here and look things up (we are probably the heaviest users of this chapter).

この章は、CouchDBのコアAPIの入門ですが、リファレンスにもなります。もし、リクエストの出し方や、そのパラメータが必要な理由を覚えられなくても、ここに戻って見直せば思い出せるでしょう(多分、私たちがこの章の一番のヘビーユーザーでしょう)。

While explaining the API bits and pieces, we sometimes need to take a larger detour to explain the reasoning for a particular request. This is a good opportunity for us to tell you why CouchDB works the way it does.

APIを説明しようとするときに、リクエストを理解するために回り道の説明が必要になるかもしれません。しかし、これもCouchDBの動作を理解するためのよい機会となるでしょう。

The API can be subdivided into the following sections. We’ll explore them individually:

APIはいくつかのセクションに分けることができます。順にみていきましょう:

Server

サーバ

This one is basic and simple. It can serve as a sanity check to see if CouchDB is running at all. It can also act as a safety guard for libraries that require a certain version of CouchDB. We’re using the curl utility again:

これは基本となるAPIで、とてもシンプルです。CouchDBが正常に動いているかどうかのヘルスチェックに使います。特定のバージョンのCouchDBが必要なライブラリには、バージョンなどの安全性チェックにも使えるでしょう。またcurlを使います:::

curl http://127.0.0.1:5984/

CouchDB replies, all excited to get going:

CouchDBは元気に返事してくれます:

{"couchdb":"Welcome","version":"0.10.1"}

You get back a JSON string, that, if parsed into a native object or data structure of your programming language, gives you access to the welcome string and version information.

JSON文字列を受け取って、あなたのプログラミング言語のネイティブオブジェクトやデータ構造に変換して、ようこそ文やバージョンを表示するのに使うことができます。

This is not terribly useful, but it illustrates nicely the way CouchDB behaves. You send an HTTP request and you receive a JSON string in the HTTP response as a result.

これがとても便利ということはありませんが、HTTPリクエストを送って、JSON文字列が入ったHTTPレスポンスを受け取るという、CouchDBの基本的な振る舞いが端的に現れています。

Databases

データベース

Now let’s do something a little more useful: create databases. For the strict, CouchDB is a database management system (DMS). That means it can hold multiple databases. A database is a bucket that holds “related data.” We’ll explore later what that means exactly. In practice, the terminology is overlapping—often people refer to a DMS as “a database” and also a database within the DMS as “a database.” We might follow that slight oddity, so don’t get confused by it. In general, it should be clear from the context if we are talking about the whole of CouchDB or a single database within CouchDB.

さて、もう少し実用的なことをしてみましょう。データベースを作成します。厳密には、CouchDBはデータベース管理システム(DMS)です。これは、CouchDBはデータベースを複数保持することができるということを意味します。データベースは「関連するデータ」を保持するバケツです。これが正確には何を意味するのか、ということについては後で見ていきます。実際には、この専門用語は重なりあっています。人々はしばしばDMSのことを「データベース」と言いますし、DMSの中のデータベースを「データベース」とも言います。私たちがこのような少し奇妙な言い回しに従うことがあるかも知れませんが、それによって混乱しないようにしてください。一般的には、CouchDB全体について話をしている場合や、CouchDBの中のひとつのデータベースについて話をしている場合には文脈から明らかでしょう。

Now let’s make one! We want to store our favorite music albums, and we creatively give our database the name albums. Note that we’re now using the -X option again to tell curl to send a PUT request instead of the default GET request:

さて、ひとつ作ってみましょう!私たちはお気に入りの音楽アルバムを保存したいと思います。独創的に、データベースの名前はalbumsとします。今、curlがデフォルトのGETリクエストの代わりにPUTリクエストを送信するように、-Xオプションをまた使っていることに注意してください。

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

CouchDB replies:

CouchDBは次のように返答します。:

{"ok":true}

That’s it. You created a database and CouchDB told you that all went well. What happens if you try to create a database that already exists? Let’s try to create that database again:

これだけです。あなたはデータベースを作成し、CouchDBはすべてがうまくいったことを知らせます。もし、既に存在するデータベースを作成しようとしたら、何が起きるでしょうか。もう一度このデータベースを作ってみましょう。

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

CouchDB replies:

CouchDBは次のように返答します。

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

We get back an error. This is pretty convenient. We also learn a little bit about how CouchDB works. CouchDB stores each database in a single file. Very simple. This has some consequences down the road, but we’ll skip the details for now and explore the underlying storage system in Appendix F, The Power of B-trees.

エラーが返ってきました。これはかなり便利です。CouchDBがどのように動作しているのかについて、少し学習します。CouchDBは各データベースをひとつのファイルに保存します。非常に単純です。このことは、将来的にいくつかの結果をもたらしますが、今のところ詳細は飛ばして、基礎となるストレージシステムは「付録F 強力なB木」で探索します。

Let’s create another database, this time with curl’s -v (for “verbose”) option. The verbose option tells curl to show us not only the essentials—the HTTP response body—but all the underlying request and response details:

もうひとつ、データベースを作りましょう。今度はcurlの-vオプション(「verbose」の意)を使います。この冗長オプションを使うと、curlはHTTPレスポンスの本文のような重要な情報以外の、基礎となるすべてのリクエストとレスポンスの詳細を表示します。

curl -vX PUT http://127.0.0.1:5984/albums-backup

curl elaborates:

curlは詳しく説明します。

* About to connect() to 127.0.0.1 port 5984 (#0)
*   Trying 127.0.0.1... connected
* Connected to 127.0.0.1 (127.0.0.1) port 5984 (#0)
> PUT /albums-backup HTTP/1.1
> User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
> Host: 127.0.0.1:5984
> Accept: */*
>
< HTTP/1.1 201 Created
< Server: CouchDB/0.9.0 (Erlang OTP/R12B)
< Date: Sun, 05 Jul 2009 22:48:28 GMT
< Content-Type: text/plain;charset=utf-8
< Content-Length: 12
< Cache-Control: must-revalidate
<
{"ok":true}
* Connection #0 to host 127.0.0.1 left intact
* Closing connection #0

What a mouthful. Let’s step through this line by line to understand what’s going on and find out what’s important. Once you’ve seen this output a few times, you’ll be able to spot the important bits more easily.

何て長い言葉でしょう。何が起きているかを理解し、重要なことを見付けるために、一行づつ追ってみましょう。この出力を何度か見れば、あなたはより簡単に重要な部分を見付けることができるようになるでしょう。

* About to connect() to 127.0.0.1 port 5984 (#0)

This is curl telling us that it is going to establish a TCP connection to the CouchDB server we specified in our request URI. Not at all important, except when debugging networking issues.

これは、curlがリクエストURIで指定したCouchDBサーバーへのTCP接続を確立しようとしていることを示しています。まったく重要ではありませんが、ネットワークの問題をデバッグしているときは別です。

*   Trying 127.0.0.1... connected
* Connected to 127.0.0.1 (127.0.0.1) port 5984 (#0)

curl tells us it successfully connected to CouchDB. Again, not important if you aren’t trying to find problems with your network.

curlがCouchDBに正常に接続したことを示しています。繰り返しますが、あなたがネットワークについての問題を見付けようとしているのでなければ、重要ではありません。

The following lines are prefixed with > and < characters. > means the line was sent to CouchDB verbatim (without the actual >). < means the line was sent back to curl by CouchDB.

次の行は、><という文字で始まります。>は、その行が(実際の>を除いて)そのままの形でCouchDBに送信されたということを意味します。<はその行がCouchDBからcurlに送り返されたということを意味します。

> PUT /albums-backup HTTP/1.1

This initiates an HTTP request. Its method is PUT, the URI is /albums-backup, and the HTTP version is HTTP/1.1. There is also HTTP/1.0, which is simpler in some cases, but for all practical reasons you should be using HTTP/1.1.

これは、HTTPリクエストを開始しています。そのメソッドはPUTで、URIは/albums-backup、そしてHTTPバージョンはHTTP/1.1です。場合によってはより単純になるHTTP/1.0もありますが、すべての実用的な理由からは、HTTP/1.1を使うべきです。

Next, we see a number of request headers. These are used to provide additional details about the request to CouchDB. > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3

The User-Agent header tell CouchDB which piece of client software is doing the HTTP request. We don’t learn anything new: it’s curl. This header is often useful in web development when there are known errors in client implementations that a server might want to prepare the response for. It also helps to determine which platform a user is on. This information can be used for technical and statistical reasons. For CouchDB, the User-Agent header is irrelevant. > Host: 127.0.0.1:5984

The Host header is required by HTTP 1.1. It tells the server the hostname that came with the request.

HostヘッダーはHTTP 1.1のために必要です。これは、リクエストとともに来たホスト名をサーバーに知らせます。

> Accept: */*

The Accept header tells CouchDB that curl accepts any media type. We’ll look into why this is useful a little later.

AcceptヘッダーはCouchDBに、curlがどんなメディアタイプでも受け取ることを知らせます。少し後に、何故これが便利なのかを見ていきます。

>

An empty line denotes that the request headers are now finished and the rest of the request contains data we’re sending to the server. In this case, we’re not sending any data, so the rest of the curl output is dedicated to the HTTP response.

空の行は、リクエストヘッダーがここで終わりであり、残りのリクエストがサーバーに送信されたデータを含んでいることを表します。このケースでは、私たちは何もデータを送っていないので、残りのcurlの出力にはHTTPレスポンスだけが含まれています。

< HTTP/1.1 201 Created

The first line of CouchDB’s HTTP response includes the HTTP version information (again, to acknowledge that the requested version could be processed), an HTTP status code, and a status code message. Different requests trigger different response codes. There’s a whole range of them telling the client (curl in our case) what effect the request had on the server. Or, if an error occurred, what kind of error. RFC 2616 (the HTTP 1.1 specification) defines clear behavior for response codes. CouchDB fully follows the RFC.

CouchDBのHTTPレスポンスの最初の行はHTTPバージョンの情報(繰り返しになりますが、リクエストされたバージョンが処理できたことを知らせます)、HTTPステータスコード、そしてステータスコードメッセージです。異なったリクエストには異なったレスポンスコードが返されます。これらのすべてが、リクエストがサーバーにどのような影響を与えるのかをクライアント(私たちのケースではcurlです)に知らせます。また、エラーが起きた場合には、どのような種類のエラーかを知らせます。RFC 2616(HTTP 1.1の仕様)はレスポンスコードの振る舞いについて明確に定義します。CouchDBはRFCに完全に従います。

The 201 Created status code tells the client that the resource the request was made against was successfully created. No surprise here, but if you remember that we got an error message when we tried to create this database twice, you now know that this response could include a different response code. Acting upon responses based on response codes is a common practice. For example, all response codes of 400 or larger tell you that some error occurred. If you want to shortcut your logic and immediately deal with the error, you could just check a >= 400 response code.

201 Createdステータスコードはクライアントに、リクエストが作成されたリソースが正常に作成されたことを知らせます。何も驚くことはありませんが、このデータベースを2回作成しようとしたとき、エラーメッセージを見たことを思い出せば、そのレスポンスは異なったレスポンスコードを含んでいたことが今は分かります。レスポンスコードに基づいたレスポンスに従うことは、一般的な慣習です。例えば、400以上のすべてのレスポンスコードは、何らかのエラーが起こったことを知らせます。もし、ロジックをショートカットし、すぐにエラーに対処したいのであれば、単に>= 400レスポンスコードをチェックすることができます。

< Server: CouchDB/0.10.1 (Erlang OTP/R13B)

The Server header is good for diagnostics. It tells us which CouchDB version and which underlying Erlang version we are talking to. In general, you can ignore this header, but it is good to know it’s there if you need it.

Serverヘッダーは診断に有用です。これは、通信しているCouchDBのバージョンとその基礎となるErlangのバージョンを知らせます。一般的に、あなたはこのヘッダーを無視することができますが、必要なときにここにあるということを知っておくのは良いことです。

< Date: Sun, 05 Jul 2009 22:48:28 GMT

The Date header tells you the time of the server. Since client and server time are not necessary synchronized, this header is purely informational. You shouldn’t build any critical application logic on top of this! < Content-Type: text/plain;charset=utf-8

The Content-Type header tells you which MIME type the HTTP response body is and its encoding. We already know CouchDB returns JSON strings. The appropriate Content-Type header is application/json. Why do we see text/plain? This is where pragmatism wins over purity. Sending an application/json Content-Type header will make a browser offer you the returned JSON for download instead of just displaying it. Since it is extremely useful to be able to test CouchDB from a browser, CouchDB sends a text/plain content type, so all browsers will display the JSON as text.

Content-TypeヘッダーはHTTPレスポンスの本文がどのMIMEタイプなのか、とそのエンコーディングを知らせます。私たちはすでにCouchDBがJSON文字列を返すことを知っています。適切なContent-Typeヘッダーはapplication/jsonです。何故text/plainになっているのでしょう?ここは現実主義が純粋性に勝利するところです。application/json Content-Typeヘッダーを送ると、ブラウザーはそれを単純に表示する代わりに返されたJSONをダウンロードさせようとするでしょう。CouchDBをブラウザーからテストするためには非常に便利なので、すべてのブラウザーがJSONをテキストとして表示するように、CouchDBはtext/plainコンテンツタイプを送信します。

There are some browser extensions that make your browser JSON-aware, but they are not installed by default.

ブラウザーのJSON対応にするためのブラウザー拡張もありますが、それらは標準でインストールされてはいません。

Do you remember the Accept request header and how it is set to \*/\* -> */* to express interest in any MIME type? If you send Accept: application/json in your request, CouchDB knows that you can deal with a pure JSON response with the proper Content-Type header and will use it instead of text/plain.

Acceptリクエストヘッダーと、任意のMIMEタイプへの関心を表現するためにそれを\\\*/\\\* -> \*/\*に設定する方法を覚えているでしょうか。リクエストをAccept: application/jsonとして送信した場合、CouchDBはあなたが適切なContent-Typeの付いた純粋なJSONレスポンスを扱うことができると理解し、text/plainの代わりにそれを使うでしょう。

< Content-Length: 12

The Content-Length header simply tells us how many bytes the response body has.

Content-Lengthヘッダーは単にレスポンスの本文が何バイトであるかを知らせます。

< Cache-Control: must-revalidate

This Cache-Control header tells you, or any proxy server between CouchDB and you, not to cache this response.

このCache-Controlヘッダーは、あなたやCouchDBとあなたとの間にあるプロキシーサーバーにこのレスポンスをキャッシュしないよう指示します。

<

This empty line tells us we’re done with the response headers and what follows now is the response body.

この空の行はレスポンスヘッダーが終了したことと、この後にレスポンスの本文が続くことを知らせます。

{"ok":true}

We’ve seen this before.

これは前に見ました。

* Connection #0 to host 127.0.0.1 left intact
* Closing connection #0

The last two lines are curl telling us that it kept the TCP connection it opened in the beginning open for a moment, but then closed it after it received the entire response.

最後の2行はcurlに、最初に開いたTCP接続をしばらく維持していたが、すべてのレスポンスを受け取った後でこれを閉じたということを知らせます。

Throughout the book, we’ll show more requests with the -v option, but we’ll omit some of the headers we’ve seen here and include only those that are important for the particular request.

この本を通して、私たちはより多くのリクエストを-vオプション付きで示しますが、ここで見たヘッダーのいくつかは省略し、特定のリクエストについて重要なもののみを含みます。

Creating databases is all fine, but how do we get rid of one? Easy—just change the HTTP method:

データベースの作成はすべて成功しましたが、削除はどのようにするのでしょうか。簡単です。単にHTTPメソッドを次のように変更します。

> curl -vX DELETE http://127.0.0.1:5984/albums-backup

This deletes a CouchDB database. The request will remove the file that the database contents are stored in. There is no “Are you sure?” safety net or any “Empty the trash” magic you’ve got to do to delete a database. Use this command with care. Your data will be deleted without a chance to bring it back easily if you don’t have a backup copy.

これはCouchDBのデータベースを削除します。このリクエストはデータベースの内容が保存されているファイルを削除します。データベースを削除するとき、「本当に削除しますか」というセーフティーネットや、「ゴミ箱を空にする」のような魔法はありません。このコマンドは注意して使用してください。バックアップコピーを持っていなければ、あなたのデータは簡単に元に戻すチャンスなしに削除されるでしょう。

This section went knee-deep into HTTP and set the stage for discussing the rest of the core CouchDB API. Next stop: documents.

このセクションではHTTPについて膝の深さまで行き、コアCouchDB APIの残りを議論するための足場を組みました。次の停留所は、ドキュメントです。

Documents

ドキュメント

Documents are CouchDB’s central data structure. The idea behind a document is, unsurprisingly, that of a real-world document—a sheet of paper such as an invoice, a recipe, or a business card. We already learned that CouchDB uses the JSON format to store documents. Let’s see how this storing works at the lowest level.

ドキュメントはCouchDBの中心をなすデータ構造です。ドキュメントの背後にある考え方は、当然、現実世界の文書、つまり請求書、レシピや名刺などの紙1枚です。私たちはすでにCouchDBがドキュメントを保存するためにJSON形式を使っていることを学びました。この保存が最も下のレベルではどのように動作しているのかを見てみましょう。

Each document in CouchDB has an ID. This ID is unique per database. You are free to choose any string to be the ID, but for best results we recommend a UUID (or GUID), i.e., a Universally (or Globally) Unique IDentifier. UUIDs are random numbers that have such a low collision probability that everybody can make thousands of UUIDs a minute for millions of years without ever creating a duplicate. This is a great way to ensure two independent people cannot create two different documents with the same ID. Why should you care what somebody else is doing? For one, that somebody else could be you at a later time or on a different computer; secondly, CouchDB replication lets you share documents with others and using UUIDs ensures that it all works. But more on that later; let’s make some documents:

CouchDBの各ドキュメントはIDを持ちます。このIDはデータベースごとに一意です。IDには任意の文字列を自由に選ぶことができますが、最良の結果を得るために、私たちはUUID(またはGUID)、すなわちUniversal(またはGlobally) Unique IDentifierを推奨します。UUIDは、衝突する確率の非常に低いランダムな数字です。その確率は、100万年間すべての人が1分間に1000個のUUIDを重複することなく生成し続けることができるほどです。これは2つの独立した人が2つの異なったドキュメントを同じIDでつくることができないということを確実にするために最適な方法です。何故他の誰かが行うことを気にしなければならないのでしょうか。第1に、その他の誰かというのが後のあなた自身、または違うコンピューターを使うあなたであるかも知れないからです。第2に、CouchDBのレプリケーションを使うと他の人とドキュメントを共有することになり、UUIDを使うとそれが完全に動作することを確実にできるからです。しかし詳細は後にしましょう。いくつかドキュメントを作成してみましょう。

curl -X PUT http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af -d '{"title":"There is Nothing Left to Lose","artist":"Foo Fighters"}'

CouchDB replies:

CouchDBは次のように返答します。

{"ok":true,"id":"6e1295ed6c29495e54cc05947f18c8af","rev":"1-2902191555"}

The curl command appears complex, but let’s break it down. First, -X PUT tells curl to make a PUT request. It is followed by the URL that specifies your CouchDB IP address and port. The resource part of the URL /albums/6e1295ed6c29495e54cc05947f18c8af specifies the location of a document inside our albums database. The wild collection of numbers and characters is a UUID. This UUID is your document’s ID. Finally, the -d flag tells curl to use the following string as the body for the PUT request. The string is a simple JSON structure including title and artist attributes with their respective values.

curlコマンドは複雑に見えますが、分解してみましょう。まず、-X PUTはcurlにPUTリクエストを送信するよう指示します。その後にあなたのCouchDBのIPアドレスとポートを指定するURLが続きます。/albums/6e1295ed6c29495e54cc05947f18c8afというURLのリソース部分は、私たちのalbumsデータベースの中でのドキュメントの場所を指定します。数字と文字の羅列はUUIDです。このUUIDはあなたのドキュメントのIDです。最後に、-dフラグはcurlに、続く文字列をPUTリクエストの本文として使うよう指示します。この文字列は単純なJSONの構造で、title属性とartist属性をそれぞれの値として含んでいます。

If you don’t have a UUID handy, you can ask CouchDB to give you one (in fact, that is what we did just now without showing you). Simply send a GET request to /_uuids:

もしUUIDを簡単に用意することができなければ、CouchDBにUUIDを要求することができます(実際、これが先程私たちがあなたに見せずに行ったことです)。単純にGETリクエストを/_uuidsに送ります。

curl -X GET http://127.0.0.1:5984/_uuids

CouchDB replies:

CouchDBは次のように返答します。

{"uuids":["6e1295ed6c29495e54cc05947f18c8af"]}

Voilá, a UUID. If you need more than one, you can pass in the ?count=10 HTTP parameter to request 10 UUIDs, or really, any number you need.

はい、これがUUIDです。もしあなたが1個より多く欲しいのであれば、10個のUUIDを要求するためにHTTPパラメータとして?count=10を渡すことができ、実際には必要な任意の数を使うことができます。

To double-check that CouchDB isn’t lying about having saved your document (it usually doesn’t), try to retrieve it by sending a GET request:

CouchDBがドキュメントを保存したということについて嘘をついていないかをダブルチェックするために、GETリクエストを送ってドキュメントを取得してみましょう。

curl -X GET http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af

We hope you see a pattern here. Everything in CouchDB has an address, a URI, and you use the different HTTP methods to operate on these URIs.

私たちは、あなたがここにパターンを見付けることを期待しています。CouchDBの中のすべてのものはアドレス、URIを持っていて、これらのURIを操作するために異なったHTTPメソッドを使います。

CouchDB replies:

CouchDBは次のように返答します。

{"_id":"6e1295ed6c29495e54cc05947f18c8af","_rev":"1-2902191555","title":"There is Nothing Left to Lose","artist":"Foo Fighters"}

This looks a lot like the document you asked CouchDB to save, which is good. But you should notice that CouchDB added two fields to your JSON structure. The first is _id, which holds the UUID we asked CouchDB to save our document under. We always know the ID of a document if it is included, which is very convenient.

これはあなたがCouchDBに保存するよう指示したドキュメントに良く似ていて、問題ありません。しかし、CouchDBが2つのフィールドをJSONの構造に追加していることに気付いたでしょう。1つは、_idで、これは私たちがCouchDBにドキュメントをここに保存するようにと指示したUUIDを保持するものです。私たちはIDが含まれている限り、いつもドキュメントのIDを知っています。これはとても便利です。

The second field is _rev. It stands for revision.

2つ目のフィールドは、_revです。これはrevisionの略です。

Revisions

リビジョン

If you want to change a document in CouchDB, you don’t tell it to go and find a field in a specific document and insert a new value. Instead, you load the full document out of CouchDB, make your changes in the JSON structure (or object, when you are doing actual programming), and save the entire new revision (or version) of that document back into CouchDB. Each revision is identified by a new _rev value.

もしあなたがCouchDBのドキュメントを変更したいと思ったなら、そこに行って特定のドキュメントからフィールドを探し、新しい値を挿入するよう指示することはできません。代わりに、CouchDBからドキュメント全体を読み込んで、JSONの構造(あなたが実際のプログラミングを行っているのであれば、オブジェクト)に変更を加えて、全体をそのドキュメントの新しいリビジョン(またはバージョン)をCouchDBに保存します。各リビジョンは、新しい_revの値で識別されます。

If you want to update or delete a document, CouchDB expects you to include the _rev field of the revision you wish to change. When CouchDB accepts the change, it will generate a new revision number. This mechanism ensures that, in case somebody else made a change unbeknownst to you before you got to request the document update, CouchDB will not accept your update because you are likely to overwrite data you didn’t know existed. Or simplified: whoever saves a change to a document first, wins. Let’s see what happens if we don’t provide a _rev field (which is equivalent to providing a outdated value):

もしドキュメントを更新したり削除したいのであれば、CouchDBは変更したいリビジョンの_revフィールドが含まれていることを期待します。CouchDBが変更を受け入れると、新しいリビジョン番号が生成されます。この仕組みは、あなたがドキュメントの更新のリクエストを行う前に、他の誰かがあなたにとって未知の変更を行った場合に、CouchDBがあなたの更新を受け入れないことを確実にします。これは、あなたが存在を知らないデータを上書きしてしまう可能性があるためです。単純に言えば、先にドキュメントへの変更を保存した人が勝つということです。_revフィールドを与えなかった場合(これは期限切れの値を与えた場合と同じです)に、何が起きるかを見てみましょう。

curl -X PUT http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af -d '{"title":"There is Nothing Left to Lose","artist":"Foo Fighters","year":"1997"}'

CouchDB replies: {"error":"conflict","reason":"Document update conflict."}

If you see this, add the latest revision number of your document to the JSON structure:

これを見たら、あなたのドキュメントの最新のリビジョン番号をJSONの構造に追加してください。

curl -X PUT http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af -d '{"_rev":"1-2902191555","title":"There is Nothing Left to Lose", "artist":"Foo Fighters","year":"1997"}'

Now you see why it was handy that CouchDB returned that _rev when we made the initial request. CouchDB replies:

これで何故最初のリクエストを送信したときにCouchDBがその_revを返すことが役に立つのかが分かりました。CouchDBは次のように返答します。

{"ok":true,"id":"6e1295ed6c29495e54cc05947f18c8af","rev":"2-2739352689"}

CouchDB accepted your write and also generated a new revision number. The revision number is the md5 hash of the transport representation of a document with an N- prefix denoting the number of times a document got updated. This is useful for replication. See Chapter 17, Conflict Management for more information.

CouchDBはあなたの書き込みを受け入れ、新しいリビジョン番号を生成しました。リビジョン番号は、先頭にドキュメントが更新された回数を示すN-を付けた、ドキュメントの移動用の表現のmd5ハッシュです。これはレプリケーションに便利です。詳細については「< href="conflicts.html">17章 衝突の管理」を参照してください。

There are multiple reasons why CouchDB uses this revision system, which is also called Multi-Version Concurrency Control (MVCC). They all work hand-in-hand, and this is a good opportunity to explain some of them.

何故CouchDBがMulti-Version Concurrency Control(MVCC)とも呼ばれるこのリビジョンシステムを使っているのかには、複数の理由があります。これらはすべて協力して動作するのですが、これらのいくつかについてはこれが説明する良い機会です。

One of the aspects of the HTTP protocol that CouchDB uses is that it is stateless. What does that mean? When talking to CouchDB you need to make requests. Making a request includes opening a network connection to CouchDB, exchanging bytes, and closing the connection. This is done every time you make a request. Other protocols allow you to open a connection, exchange bytes, keep the connection open, exchange more bytes later—maybe depending on the bytes you exchanged at the beginning—and eventually close the connection. Holding a connection open for later use requires the server to do extra work. One common pattern is that for the lifetime of a connection, the client has a consistent and static view of the data on the server. Managing huge amounts of parallel connections is a significant amount of work. HTTP connections are usually short-lived, and making the same guarantees is a lot easier. As a result, CouchDB can handle many more concurrent connections.

CouchDBが使用しているHTTPプロトコルの一面として、ステートレスであるということが挙げられます。それはどういう意味でしょうか。CouchDBと通信するときに、あなたはリクエストを送信する必要があります。リクエストの送信にはCouchDBへのネットワーク接続を開き、バイト列を交換し、接続を閉じることが含まれます。あなたがリクエストを送信する度に、これが毎回行われます。他のプロトコルには、接続を開いて、バイト列を交換して、接続を開いたままで、後で更にバイト列(それは最初に交換したバイト列に依存しているかも知れません)を交換し、最後に接続を閉じることのできるものもあります。後で使うために接続を開いたままにしておくには、サーバーに余分な作業を行わせなければなりません。ひとつの一般的なパターンは、接続の存続期間中、クライアントがデータの一貫性のある静的なビューをサーバーに持っている場合です。膨大な量の並行した接続を管理することは、かなりの量の作業です。HTTP接続は通常、存続期間が短く、同じ保証をするのもずっと簡単です。結果として、CouchDBはより多くの同時接続を処理することができます。

Another reason CouchDB uses MVCC is that this model is simpler conceptually and, as a consequence, easier to program. CouchDB uses less code to make this work, and less code is always good because the ratio of defects per lines of code is static.

CouchDBがMVCCを使用するもうひとつの理由は、このモデルが概念的に単純であり、結果としてプログラミングが簡単になるということです。CouchDBのこの作業を行うためのコードは少なく、コード1行当たりの欠陥の比率はほとんど変化しないことから、コードが少ないということはいつも良いことです。

The revision system also has positive effects on replication and storage mechanisms, but we’ll explore these later in the book.

また、このリビジョンシステムは、レプリケーションやストレージ機構にプラスの効果をもたらしますが、それについてはこの本の後半で見ていきます。

The terms version and revision might sound familiar (if you are programming without version control, drop this book right now and start learning one of the popular systems). Using new versions for document changes works a lot like version control, but there’s an important difference: CouchDB does not guarantee that older versions are kept around.

バージョンという用語やリビジョンという用語はおなじみでしょう(もしあなたがバージョン管理をせずにプログラミングをしているのであれば、この本はすぐに投げ捨てて、人気のあるバージョン管理システムのどれかの学習を始めてください)。ドキュメントのために新しいバージョンを使うことは、バージョン管理のように作業を変えてくれます。しかし、そこには重要な違いがあります。CouchDBは古いバージョンのドキュメントが保持されることを保証しないのです。

Documents in Detail

ドキュメントの詳細

Now let’s have a closer look at our document creation requests with the curl -v flag that was helpful when we explored the database API earlier. This is also a good opportunity to create more documents that we can use in later examples.

さて、先程データベースAPIを調べるときに便利だったcurlの-vを使って、ドキュメント作成リクエストを詳しく見てみましょう。これは後の例で使うことができるより多くのドキュメントを作る良い機会でもあります。

We’ll add some more of our favorite music albums. Get a fresh UUID from the /_uuids resource. If you don’t remember how that works, you can look it up a few pages back.

私たちのお気に入りの音楽アルバムをもう少し追加します。新しいUUIDを/_uuidsリソースから取得します。もし、どのように作業を行うのかを思い出せないのであれば、数ページ戻れば調べることができます。

curl -vX PUT http://127.0.0.1:5984/albums/70b50bfa0a4b3aed1f8aff9e92dc16a0 -d '{"title":"Blackened Sky","artist":"Biffy Clyro","year":2002}'

By the way, if you happen to know more information about your favorite albums, don’t hesitate to add more properties. And don’t worry about not knowing all the information for all the albums. CouchDB’s schema-less documents can contain whatever you know. After all, you should relax and not worry about data.

ところで、もしあなたのアルバムについてもっと多くの情報を知りたいのであれば、ためらうことなくより多くのプロパティを追加してください。そして、すべてのアルバムのすべての情報について知っているわけではないことは心配しないでください。CouchDBのスキーマレスドキュメントには、あなたが知っている情報を何でも含めることができます。結局、あなたはリラックスするべきであって、データについて心配すべきではありません。

Now with the -v option, CouchDB’s reply (with only the important bits shown) looks like this:

今、-vオプションを付けたので、(表示される重要な部分のみを含んだ)CouchDBの返答はこのようになります。

> PUT /albums/70b50bfa0a4b3aed1f8aff9e92dc16a0 HTTP/1.1
>
< HTTP/1.1 201 Created
< Location: http://127.0.0.1:5984/albums/70b50bfa0a4b3aed1f8aff9e92dc16a0
< Etag: "1-2248288203"
<
{"ok":true,"id":"70b50bfa0a4b3aed1f8aff9e92dc16a0","rev":"1-2248288203"}

We’re getting back the 201 Created HTTP status code in the response headers, as we saw earlier when we created a database. The Location header gives us a full URL to our newly created document. And there’s a new header. An Etag in HTTP-speak identifies a specific version of a resource. In this case, it identifies a specific version (the first one) of our new document. Sound familiar? Yes, conceptually, an Etag is the same as a CouchDB document revision number, and it shouldn’t come as a surprise that CouchDB uses revision numbers for Etags. Etags are useful for caching infrastructures. We’ll learn how to use them in Chapter 8, Show Functions.

私たちが以前データベースを作成したときと同じように、201 Created HTTPステータスコードがレスポンスの中で返されました。Locationヘッダーは新しく作成されたドキュメントへの完全なURLを示しています。そして、新しいヘッダーがあります。HTTP通信におけるEtagは、リソースの特定のバージョンを識別します。この場合、これは新しいドキュメントの特定の(今回は最初の)バージョンを識別します。おなじみでしょうか。そう、概念的には、EtagはCouchDBにおけるドキュメントリビジョン番号と同じであり、CouchDBがEtagにリビジョン番号を使っているということは驚くことではないはずです。Etagはキャッシュインフラのために役立ちます。これらをどのように使うのかは、8章 ショウ機能で学びます。

Attachments
添付ファイル

CouchDB documents can have attachments just like an email message can have attachments. An attachment is identified by a name and includes its MIME type (or Content-Type) and the number of bytes the attachment contains. Attachments can be any data. It is easiest to think about attachments as files attached to a document. These files can be text, images, Word documents, music, or movie files. Let’s make one. Attachments get their own URL where you can upload data. Say we want to add the album artwork to the 6e1295ed6c29495e54cc05947f18c8af document (“There is Nothing Left to Lose”), and let’s also say the artwork is in a file artwork.jpg in the current directory:

添付ファイルはデータをアップロードできる場所として固有のURLを持ちます。仮に、私たちはアルバムアートワークを6e1295ed6c29495e54cc05947f18c8afドキュメント(「There is Nothing Left to Lose」)に追加したいとして、そのアートワークはカレントディレクトリのartwork.jpgファイルにあるとしましょう。

> curl -vX PUT http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af/ artwork.jpg?rev=2-2739352689 --data-binary @artwork.jpg -H "Content-Type: image/jpg"

The -d@ option tells curl to read a file’s contents into the HTTP request body. We’re using the -H option to tell CouchDB that we’re uploading a JPEG file. CouchDB will keep this information around and will send the appropriate header when requesting this attachment; in case of an image like this, a browser will render the image instead of offering you the data for download. This will come in handy later. Note that you need to provide the current revision number of the document you’re attaching the artwork to, just as if you would update the document. Because, after all, attaching some data is changing the document.

-d@オプションはcurlに、ファイルの内容をHTTPリクエストの本文に読み込むよう指示します。CouchDBに、JPEGファイルをアップロードしていることを知らせるために、-Hオプションを使用しています。CouchDBはこの情報を保持し、この添付ファイルが要求された場合には適切なヘッダーを送信します。このように画像の場合には、ブラウザーはデータをダウンロードさせる代わりに画像をレンダリングします。これは後で役に立つことになるでしょう。ちょうどドキュメントをアップデートするときと同じように、アートワークを添付するドキュメントの現在のリビジョン番号を渡す必要があることに注意してください。何故なら、結局、データを添付するということはドキュメントを変更するということだからです。

You should now see your artwork image if you point your browser to http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af/artwork.jpg.

あなたがブラウザでhttp://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af/artwork.jpgにアクセスすれば、アートワークの画像が見えるはずです。

If you request the document again, you’ll see a new member:

ドキュメントをもう一度要求すると、新しいメンバーが見えるでしょう。

curl http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af

CouchDB replies:

CouchDBは次のように返答します。

{"_id":"6e1295ed6c29495e54cc05947f18c8af","_rev":"3-131533518","title": "There is Nothing Left to Lose","artist":"Foo Fighters","year":"1997","_attachments":{"artwork.jpg":{"stub":true,"content_type":"image/jpg","length":52450}}}

_attachments is a list of keys and values where the values are JSON objects containing the attachment metadata. stub=true tells us that this entry is just the metadata. If we use the ?attachments=true HTTP option when requesting this document, we’d get a Base64-encoded string containing the attachment data.

_attachmentsはキーと値のリストで、その値は添付ファイルのメタデータを含むJSONオブジェクトです。stub=trueはこのエントリーが単なるメタデータであることを示します。このドキュメントを要求するときに?attachments=true HTTPオプションを使うと、添付ファイルのデータを含むBase64エンコードされた文字列を取得できます。

We’ll have a look at more document request options later as we explore more features of CouchDB, such as replication, which is the next topic.

ドキュメントリクエストオプションについては後で、次のトピックであるレプリケーションのようなCouchDBのより多くの機能を探索するときに詳細を見ましょう。

Replication

レプリケーション

CouchDB replication is a mechanism to synchronize databases. Much like rsync synchronizes two directories locally or over a network, replication synchronizes two databases locally or remotely.

CouchDBのレプリケーションはデータベースを同期する仕組みです。rsyncが2つのディレクトリをローカルで、またはネットワーク越しで同期するのとちょうど同じように、レプリケーションは2つのデータベースをローカルで、またはリモートで同期します。

In a simple POST request, you tell CouchDB the source and the target of a replication and CouchDB will figure out which documents and new document revisions are on source that are not yet on target, and will proceed to move the missing documents and revisions over.

単純なPOSTリクエストにおいて、CouchDBにレプリケーション対象のsourceとtargetを与えると、CouchDBはどのドキュメントと新しいドキュメントリビジョンがsourceにあってtargetにはないのかを判断し、存在しないドキュメントとリビジョンのコピーを進めます。

We’ll take an in-depth look at replication later in the book; in this chapter, we’ll just show you how to use it.

この本の後半では、レプリケーションについてより深く見ていきます。この章では、どのように使うのかだけを示します。

First, we’ll create a target database. Note that CouchDB won’t automatically create a target database for you, and will return a replication failure if the target doesn’t exist (likewise for the source, but that mistake isn’t as easy to make):

まず、ターゲットデータベースを作成します。CouchDBはあなたのために自動的にターゲットデータベースを作成してはくれないということ、そしてもしターゲットが存在しなければレプリケーションは失敗するということに注意してください(ソースの場合も同様ですが、ターゲットの場合の失敗は気付きにくいものです)。

curl -X PUT http://127.0.0.1:5984/albums-replica

Now we can use the database albums-replica as a replication target:

今回は、albums-replicaデータベースをレプリケーションターゲットに使います。

curl -vX POST http://127.0.0.1:5984/_replicate -d '{"source":"albums","target":"albums-replica"}'

As of version 0.11, CouchDB supports the option "create_target":true placed in the JSON POSTed to the _replicate URL. It implicitly creates the target database if it doesn’t exist.

バージョン0.11現在、CouchDBは_replicate URLにPOSTするJSONの中で"create_target":trueオプションをサポートしています。これはターゲットデータベースが存在しない場合に、暗黙的にターゲットデータベースを作成します。

CouchDB replies (this time we formatted the output so you can read it more easily):

CouchDBは次のように返答します(今はより読みやすいように出力を整形しています)。

{
  "history": [
    {
      "start_last_seq": 0,
      "missing_found": 2,
      "docs_read": 2,
      "end_last_seq": 5,
      "missing_checked": 2,
      "docs_written": 2,
      "doc_write_failures": 0,
      "end_time": "Sat, 11 Jul 2009 17:36:21 GMT",
      "start_time": "Sat, 11 Jul 2009 17:36:20 GMT"
    }
  ],
  "source_last_seq": 5,
  "session_id": "924e75e914392343de89c99d29d06671",
  "ok": true
}

CouchDB maintains a session history of replications. The response for a replication request contains the history entry for this replication session. It is also worth noting that the request for replication will stay open until replication closes. If you have a lot of documents, it’ll take a while until they are all replicated and you won’t get back the replication response until all documents are replicated. It is important to note that replication replicates the database only as it was at the point in time when replication was started. So, any additions, modifications, or deletions subsequent to the start of replication will not be replicated.

CouchDBはレプリケーションのセッション履歴を管理します。レプリケーションリクエストに対するレスポンスには、このレプリケーションセッションの履歴エントリーが含まれます。レプリケーションのリクエストがレプリケーションが閉じるまで開き続けるということには大きな価値があります。もしあなたがたくさんのドキュメントを持っているのであれば、それらすべてが複製されるのにはしばらく時間が掛かりますし、すべてのドキュメントが複製されるまではレプリケーションレスポンスは返ってこないでしょう。レプリケーションはデータベースをレプリケーションの始まったその時点の状態で複製するということに注意することは大切です。そのため、レプリケーションの開始後に行われた追加、変更、または削除については複製されません。

We’ll punt on the details again—the "ok": true at the end tells us all went well. If you now have a look at the albums-replica database, you should see all the documents that you created in the albums database. Neat, eh?

もう一度詳細を説明しましょう。最後の"ok": trueはすべてがうまくいったということを示します。もしあなたが今、albums-replicaデータベースを見たのならば、あなたがalbumsデータベースに作成したすべてのドキュメントが見えたはずです。すっきりしているでしょう。

What you just did is called local replication in CouchDB terms. You created a local copy of a database. This is useful for backups or to keep snapshots of a specific state of your data around for later. You might want to do this if you are developing your applications but want to be able to roll back to a stable version of your code and data.

あなたが行ったことは、CouchDBの用語でローカルレプリケーションと言います。あなたはデータベースのローカルコピーを作成しました。これは、バックアップのためや、後のためにあなたのデータの特定の状態のスナップショットを取るために役立ちます。あなたがアプリケーションを開発しているのであれば、これを使ってコードとデータとを安定版にロールバックできるようにしたいと思うかも知れません。

There are more types of replication useful in other situations. The source and target members of our replication request are actually links (like in HTML) and so far we’ve seen links relative to the server we’re working on (hence local). You can also specify a remote database as the target:

レプリケーションにはその他の状況で便利なもっと多くのタイプがあります。レプリケーションリクエストのsourceメンバーとtargetメンバー は実際には(HTMLのものと同じ)リンクであり、私たちは今まで、私たちが作業をしているサーバー(従ってlocal)への相対リンクを見てきました。リモートデータベースをターゲットとして指定することもできます。

curl -vX POST http://127.0.0.1:5984/_replicate -d '{"source":"albums","target":"http://127.0.0.1:5984/albums-replica"}'

Using a local source and a remote target database is called push replication. We’re pushing changes to a remote server.

ローカルのsourceデータベースとリモートのtargetデータベースを使うレプリケーションは、プッシュレプリケーションと呼ばれます。変更をリモートサーバーへプッシュします。

Since we don’t have a second CouchDB server around just yet, we’ll just use the absolute address of our single server, but you should be able to infer from this that you can put any remote server in there.

私たちはまだ2台目のCouchDBサーバーを持っていないので、単に1台のサーバーの絶対アドレスを使いますが、このことから、ここにどのリモートサーバーでも当てはめることができるということを推論できるでしょう。

This is great for sharing local changes with remote servers or buddies next door.

これはローカルでの変更をリモートサーバーや隣の仲間と共有するために最適です。

You can also use a remote source and a local target to do a pull replication. This is great for getting the latest changes from a server that is used by others:

プルレプリケーションを行うために、リモートのsourceとローカルのtargetを使うこともできます。これは他の人が使っているサーバーから最新の変更を取得するために最適です。

curl -vX POST http://127.0.0.1:5984/_replicate -d '{"source":"http://127.0.0.1:5984/albums-replica","target":"albums"}'

Finally, you can run remote replication, which is mostly useful for management operations:

最後に、主に操作の管理のために役立つリモートレプリケーションを実行することができます。

curl -vX POST http://127.0.0.1:5984/_replicate -d '{"source":"http://127.0.0.1:5984/albums","target":"http://127.0.0.1:5984/albums-replica"}'

CouchDB and REST

CouchDBとREST

CouchDB prides itself on having a RESTful API, but these replication requests don’t look very RESTy to the trained eye. What’s up with that? While CouchDB’s core database, document, and attachment API are RESTful, not all of CouchDB’s API is. The replication API is one example. There are more, as we’ll see later in the book.

CouchDBはRESTful APIを持っていることを誇りとしていますが、これらのレプリケーションリクエストは訓練された目には非常にREST的とは見えません。どうなっているのでしょうか。CouchDBのコアデータベース、ドキュメント、そして添付ファイルのAPIはRESTfulですが、すべてのCouchDBのAPIがそうという訳ではありません。レプリケーションAPIはその一例です。この本の後半で見るように、もっとたくさんあります。

Why are there RESTful and non-RESTful APIs mixed up here? Have the developers been too lazy to go REST all the way? Remember, REST is an architectural style that lends itself to certain architectures (such as the CouchDB document API). But it is not a one-size-fits-all. Triggering an event like replication does not make a whole lot of sense in the REST world. It is more like a traditional remote procedure call. And there is nothing wrong with this.

何故RESTfulなAPIとRESTfulでないAPIとが混ざっているのでしょうか。開発者が全部RESTにするのを面倒だと思ったからでしょうか。思い出してください、RESTは(例えばCouchDBのドキュメントAPIのような)特定のアーキテクチャに役立つアーキテクチャの形式です。しかし、それは万能ではありません。レプリケーションのようなイベントを発生させることは、RESTの世界では全く意味がありません。それは、伝統的なリモートプロシージャーコールにより似ています。そのため、これで何の問題もありません。

We very much believe in the “use the right tool for the job” philosophy, and REST does not fit every job. For support, we refer to Leonard Richardson and Sam Ruby who wrote RESTful Web Services (O’Reilly), as they share our view.

私たちは「仕事に対して適切な道具を使う」という哲学を大変信じていて、RESTはすべての仕事に適しているのではありません。サポートとして、私たちの視点を共有している、RESTful Webサービス(オライリー)を書いたLeonard RichardsonとSam Rubyに言及しておきます。

Wrapping Up

まとめ

This is still not the full CouchDB API, but we discussed the essentials in great detail. We’re going to fill in the blanks as we go. For now, we believe you’re ready to start building CouchDB applications.

これはまだCouchDB APIのすべてではありませんが、主要な点については非常に詳細に議論しました。先へ進み、空白を埋めていきます。とりあえず、あなたはCouchDBアプリケーションを構築し始める準備ができたと私たちは信じています。