Design Documents

デザインドキュメント

Design documents are a special type of CouchDB document that contains application code. Because it runs inside a database, the application API is highly structured. We’ve seen JavaScript views and other functions in the previous chapters. In this section, we’ll take a look at the function APIs, and talk about how functions in a design document are related within applications.

デザインドキュメントはアプリケーションコードを格納する特別なドキュメントです。データベース内部で動作するため、APIは構造化されています。前のチャプターで、javascriptのビューとその他の関数に触れました。この章では、アプリケーションに関連するdesign ドキュメントについて、またその関数についてみていきます。

This part (Part II, “Developing with CouchDB”, Chapters Chapter 5, Design Documents through Chapter 9, Transforming Views with List Functions) lays the foundation for Part III, “Example Application”, where we take what we’ve learned and build a small blog application to further develop an understanding of how CouchDB applications are built. The application is called Sofa, and on a few occasions we discuss it this part. If you are unclear on what we are referring to, do not worry, we’ll get to it in Part III, “Example Application”.

このパートはパート3のサンプルアプリケーション(couchdb アプリの構成の仕方を理解するためのブログアプリ)に基づいています。このアプリケーションはsofaと呼ばれるもので、何度かこのパートでふれることになります。もし、何のことだか分からなくても心配はいりません。パート3のサンプルアプリケーションで確認できます。

Document Modeling

ドキュメントモデリング

In our experience, there are two main kinds of documents. The first kind is like something a word processor would save, or a user profile. With that sort of data, you want to denormalize as much as you possibly can. Basically, you want to be able to load the document in one request and get something that makes sense enough to display.

我々の経験によれば、ドキュメントは2つの種類があります。一つ目は、何かのワードプロセッサーで作るものや、ユーザプロファイルのようなものです。データをソートするとき、可能な限りカスタマイズしたいでしょう。基本的に、一回のリクエストで、ドキュメントを読み込むことができ、十分に表示できるものを得られます。

A technique exists for creating “virtual” documents by using views to collate data together. You could use this to store each attribute of your user profiles in a different document, but I wouldn’t recommend it. Virtual documents are useful in cases where the presented view will be created by merging the work of different authors; for instance, the reference example, a blog post, and its comments in one query. A blog post titled “CouchDB Joins,” by Christopher Lenz, covers this in more detail.

"仮想的な"ドキュメントを作成するためのテクニックとして、データを順に並べるためのviewsを使うことができます。これを使うことで、異なるドキュメントでのユーザプロファイルの属性をストアできますが、それは推奨される使い方ではありません。;仮想的なドキュメントは別々の作者のドキュメントを結合するために作成されるビューのときに有効です。例えば、参照サンプルや、ブログのポストやそのコメントなどです。より詳しい情報は、Chirstopher Lenzの"CouchDB Joins"というブログで見ることができます。

This virtual document idea takes us to the other kind of document—the event log. Use this in cases where you don’t trust user input or where you need to trigger an asynchronous job. This records the user action as an event, so only minimal validation needs to occur at save time. It’s when you load the document for further work that you’d check for complex relational-style constraints.

仮想的なドキュメントというアイデアは、我々にイベントログといった別の種類のドキュメントをもたらします。ユーザの入力が信頼できない場合や非同期のジョブをトリガーする必要がある場合などに使えます。これはイベントとしてユーザのアクションを記録するため、保存の時に最小限の確認が生じます。さらにドキュメントをロードする時には複雑なリレーショナルスタイルの制約をチェックすることになるでしょう。

You can treat documents as state machines, with a combination of user input and background processing managing document state. You’d use a view by state to pull out the relevant document—changing its state would move it in the view.

ドキュメントはユーザ入力とドキュメント状態を管理するバックグラウンド処理の状態機械として扱えます。ドキュメントを引き出すための状態でビューを使うでしょう、それはビューの中でその状態が移動することを変化させます。

This approach is also useful for logging—combined with the batch=ok performance hint, CouchDB should make a fine log store, and reduce views are ideal for finding things like average response time or highly active users.

この方法はログをとるのに便利です。CouchDBが良いログストアとなるbatch=okのパフォーマンスヒントと合わせて、平均的なレスポンスタイムもしくはとてもアクティブなユーザのようなことを見つけるのに適しているでしょう。

The Query Server

CouchDB’s default query server (the software package that executes design document functions) is written in JavaScript, but there are views servers available for nearly any language you can imagine. Implementing a new language is a matter of handling a few JSON commands from a simple line-based program.

CouchDBのデフォルトのQuery server (デザインドキュメントの関数を実行するソフトウェアパッケージ)はJavaScriptで記述されています。しかし、あなたがイメージする何かの言語に近いものを有効にするview サーバーもあります。新しい言語の導入は単純なコマンドラインからJSONコマンドを扱う一つの方法です。

In this section, we’ll review existing functionality like MapReduce views, update validation functions, and show and list transforms. We’ll also briefly describe capabilities available on CouchDB’s roadmap, like replication filters, update handlers for parsing non-JSON input, and a rewrite handler for making application URLs more palatable. Since CouchDB is an open source project, we can’t really say when each planned feature will become available, but it’s our hope that everything described here is available by the time you read this. We’ll make it clear in the text when we’re talking about things that aren’t yet in the CouchDB trunk.

このセクションでは、MapReduceビューやアップデート検証関数, show, list変換のような存在する関数についてレビューします。私たちはまた、CouchDBのロードマップにあるレプリケーションフィルターや、non-JSONの入力への対応、より細かくアプリケーションURLを作るためのrewriteハンドラによるCouchDBの能力を明確に述べます。CouchDBがオープンソースプロジェクトになって以来、予定されている機能がいつ使えるようになるのか明確に言うことができませんが、あなたがここで読むすべてのことが私たちの望んでいることです。私たちがCouchDBのtrunkリポジトリにまだ存在しないことについて話し、文字として明確にします。

Applications Are Documents

ドキュメントの集まりであるアプリケーション

CouchDB is designed to work best when there is a one-to-one correspondence between applications and design documents.

CouchDBはアプリケーションとデザインドキュメントが一対一のような場合に良く動くように出来ています。

A design document is a CouchDB document with an id that begins with _design/. For instance, the example blog application, Sofa, is stored in a design document with the ID _design/sofa (see Figure 1, “Anatomy of our design document”). Design documents are just like any other CouchDB document—they replicate along with the other documents in their database and track edit conflicts with the rev parameter.

design documentid_designから始まるドキュメントです。例えば、ブログアプリケーションのSofaでは_design/sofaというIDでデザインドキュメントが保存されています。 (see Figure 1, “Anatomy of our design document”) デザインドキュメントは他のCouchDBドキュメントと同じです。データベース内の他のドキュメントと一緒にレプリカされたり、revパラメータで編集の競合を追跡します。

As we’ve seen, design documents are normal JSON documents, denoted by the fact that their DocID is prefixed with _design/.

ここまで見てきたように、デザインドキュメントは普通のJSONドキュメントで、DocIDが_design/で始まることで決定されています。

CouchDB looks for views and other application functions here. The static HTML pages of our application are served as attachments to the design document. Views and validations, however, aren’t stored as attachments; rather, they are directly included in the design document’s JSON body.

CouchDBはviewと他のアプリケーション機能をここで探します。アプリケーション内の静的なHTMLはデザインドキュメントの添付として提供されます。しかし、viewと認証系は添付としては保管されず、直接デザインドキュメントの内容として組み込まれます。

Figure 1. Anatomy of our design document

CouchDB’s MapReduce queries are stored in the views field. This is how Futon displays and allows you to edit MapReduce queries. View indexes are stored on a per–design document basis, according to a fingerprint of the function’s text contents. This means that if you edit attachments, validations, or any other non-view (or language) fields on the design document, the views will not be regenerated. However, if you change a map or a reduce function, the view index will be deleted and a new index built for the new view functions.

CouchDBのMapReduceクエリは、viewに保管されます。これはFutonがどのように表示やMapReduceクエリを編集可能にするかを表しています。viewインデックスは、関数のテキスト内容の署名に従い、基本的にデザインドキュメント毎に保管されます。これはデザインドキュメントの添付ファイルや認証、他のviewや言語ではないフィールドを編集しても、viewが再作成されないことを意味しています。しかし、もしmapやreduceの内容を変更した場合は、viewインデックスは削除され、新しいviewのためにインデックスが再作成されます。

CouchDB has the capability to render responses in formats other than raw JSON. The design doc fields show and list contain functions used to transform raw JSON into HTML, XML, or other Content-Types. This allows CouchDB to serve Atom feeds without any additional middleware. The show and list functions are a little like “actions” in traditional web frameworks—they run some code based on a request and render a response. However, they differ from actions in that they may not have side effects. This means that they are largely restricted to handling GET requests, but it also means they can be cached by HTTP proxies like Varnish.

CouchDBはそのままのJSON以外のフォーマットでのレスポンスを戻す機能も持っています。デザインドキュメントフィールドのshowやlistはJSONをHTMLやXML, 他のContent-Typeへ変換するのに使われます。これにより、CouchDBに新たなミドルウェアを追加することなく、Atomフィードを提供する仕組みを持たせることができます。showlistはリクエストとレスポンスの描画に基づいてコードを実行する古典的なwebのフレームワークの"actions"のようなものです。しかし、"actions"とは違い、副作用を起こしません。これはGETリクエストを扱うことに強く制限されていることを意味しています。しかし、これはまた、VarnishなどのHTTPプロキシによってキャッシュすることができることも意味しています。

Because application logic is contained in a single document, code upgrades can be accomplished with CouchDB replication. This also opens the possibility for a single database to host multiple applications. The interface a newspaper editor needs is vastly different from what a reader desires, although the data is largely the same. They can both be hosted by the same database, in different design documents.

アプリケーションロジックは一つのドキュメント内にあるため、コードのアップグレードはCouchDBレプリケーションで成し遂げられます。また、これは一つのデータベースで複数のアプリケーションをホストすることも可能にします。新聞の編集者が必要とするものと、読者が必要とするインタフェースは違えど、データはほとんどが同じ場合などです。それらは、両者とも同じデータベースに配置され、異なるデザインドキュメントで管理します。

A CouchDB database can contain many design documents. Example design DocIDs are:

CouchDBはたくさんのデザインドキュメントを格納することができます。デザインのDocIDの例は以下です。

_design/calendar
_design/contacts
_design/blog
_design/admin

In the full CouchDB URL structure, you’d be able to GET the design document JSON at URLs like:

完全なCouchDBのURLで表現すると以下のようなURLで、デザインドキュメントのJSONをGETできます。

http://localhost:5984/mydb/_design/calendar
http://127.0.0.1:5984/mydb/_design/contacts
http://127.0.0.1:5984/mydb/_design/blog
http://127.0.0.1:5984/mydb/_design/admin

We show this to note that design documents have a special case, as they are the only documents whose URLs can be used with a literal slash. We’ve done this because nobody likes to see %2F in their browser’s location bar. In all other cases, a slash in a DocID must be escaped when used in a URL. For instance, the DocID movies/jaws would appear in the URL like this: http://127.0.0.1:5984/mydb/movies%2Fjaws.

私たちはここでデザインドキュメントが持つ特殊なケースについて注意を述べます。それらは、ドキュメントのURLにスラッシュを使うことが出来ることです。誰もブラウザのロケーションバーに%2Fを見たくないでしょうからやってみました。すべての他のケースで、DocIDのスラッシュはURLに使われる時にエスケープされている必要があります。例えば、DocID movies/jawsはこのようなURLで表現されます。http://127.0.0.1:5984/mydb/movies%2Fjaws

We’ll build the first iteration of the example application without using show or list, because writing Ajax queries against the JSON API is a better way to teach CouchDB as a database. The APIs we explore in the first iteration are the same APIs you’d use to analyze log data, archive assets, or manage persistent queues.

私たちは、サンプルアプリケーションの最初の反復をshowもしくはlistを使わずに構築します。なぜならJSON APIに逆らってAjaxクエリを書くことはデータベースとしてのCouchDBを教えるためには良い方法だからです。私たちが最初の反復で切り開いたAPIは、あなたがログデータの解析やアセットの保管、永続クエリの管理に使うであろうAPIと同じです。

In the second iteration, we’ll upgrade our example blog so that it can function with client-side JavaScript turned off. For now, sticking to Ajax queries gives more transparency into how CouchDB’s JSON/HTTP API works. JSON is a subset of JavaScript, so working with it in JavaScript keeps the impedance mismatch low, while the browser’s XMLHttpRequest (XHR) object handles the HTTP details for us.

二つ目の反復では、私たちはサンプルのblogをアップグレードし、クライアント側のJavaScriptを無くした。そして今は、CouchDBのJSONやHTTP APIがどのように動作するかについてAjaxクエリが更に透過性を提供することに着目している。JSONはJavaScriptのサブセットであり、JavaScriptの中で動くことが、ブラウザのXMLHttpRequest (XHR)オブジェクトがHTTPの詳細を扱っている間のミスマッチとなる抵抗を低く保っている。

CouchDB uses the validate_doc_update function to prevent invalid or unauthorized document updates from proceeding. We use it in the example application to ensure that blog posts can be authored only by logged-in users. CouchDB’s validation functions also can’t have any side effects, and they have the opportunity to block not only end user document saves, but also replicated documents from other nodes. We’ll talk about validation in depth in Part III, “Example Application”.

CouchDBは処理における許可されないドキュメントアップデートや無効なアップデートを防ぐためにvalidate_doc_update functionを利用している。私たちはサンプルアプリケーションの中で、ログインした管理ユーザだけがblogを投稿できるようにすることを確実にするために、この方法を使っている。CouchDBの validation functionはまた、副作用を持つことがなく、エンドユーザドキュメントの保管のブロックや他のノードからのドキュメントの複製もブロックするための機会を持つ。

The raw images, JavaScript, CSS, and HTML assets needed by Sofa are stored in the _attachments field, which is interesting in that by default it shows only the stubs, rather than the full content of the files. Attachments are available on all CouchDB documents, not just design documents, so asset management applications have as much flexibility as they could need. If a set of resources is required for your application to run, they should be attached to the design document. This means that a new user can easily bootstrap your application on an empty database.

イメージやJavaScirpt, CSSやHTMLは _attachmentsフィールドに保管されたSofaによって必要とされます。デフォルトでは、そこにはファイルの完全な内容ではなくスタブだけが見えます。Attachmentsはデザインドキュメントだけではなく、すべてのCouchDBドキュメントで有効です。そして、アセット管理のアプリケーションはそれらが必要とされるぐらいとても柔軟です。もし、リソースのセットがあなたのアプリケーションを動かすのに必要とされるなら、それらはデザインドキュメントのattachmentとして追加されるべきです。これは、新しいユーザがあなたのアプリケーションを空のデータベースに簡単に配置することができることを示しています。

The other fields in the design document shown in Figure 1, “Anatomy of our design document” (and in the design documents we’ll be using) are used by CouchApp’s upload process (see Chapter 10, Standalone Applications for more information on CouchApp). The signatures field allows us to avoid updating attachments that have not changed between the disk and the database. It does this by comparing file content hashes. The lib field is used to hold additional JavaScript code and JSON data to be inserted at deploy time into view, show, and validation functions. We’ll explain CouchApp in the next chapter.

Figure 1, “Anatomy of our design document”に示しているデザインドキュメントの他のフィールド (そして、デザインドキュメントで私たちが使っている)はCouchAppのアップロードプロセスで使われています。(CouchApについての詳しい情報はChapter 10, スタンドアローンアプリケーションを参照) signaturesフィールドは、ディスクとデータベースとの間で変更のない添付ファイルをアップロードすることを回避させてくれます。それはファイルコンテンツのハッシュを比較することで行っています。libフィールドは追加のJavaScriptコードや、view, show , validation functionとして挿入されたJSONデータを保持するのに利用されます。次の章でCouchAppについて説明します。

A Basic Design Document

デザインドキュメントの基本

In the next section we’ll get into advanced techniques for working with design documents, but before we finish here, let’s look at a very basic design document. All we’ll do is define a single view, but it should be enough to show you how design documents fit into the larger system.

次のセクションでは、デザインドキュメントを動かす上での一歩進んだ技術を紹介します。しかし、ここで完了する前に、とても単純なデザインドキュメントを見てみましょう。一つのビユーで定義していますが、大きなシステムへ適用するデザインドキュメントをどう作ればよいかを見せるには十分でしょう。

First, add the following text (or something like it) to a text file called mydesign.json using your editor:

まず、以下のテキストをmydesign.jsonファイルとしてエディターで作成します。

{
  "_id" : "_design/example",
  "views" : {
    "foo" : {
      "map" : "function(doc){ emit(doc._id, doc._rev)}"
    }
  }
}

Now use curl to PUT the file to CouchDB (we’ll create a database first for good measure):

さて、curlを使って、CouchDBへファイルをPUTします。(まずは基本となるデータベースを作成します)

curl -X PUT http://127.0.0.1:5984/basic
curl -X PUT http://127.0.0.1:5984/basic/_design/example -data-binarymydesign.json

From the second request, you should see a response like:

二つ目のリクエストの返答として、以下のようなものが戻ってくるでしょう。

{"ok":true,"id":"_design/example","rev":"1-230141dfa7e07c3dbfef0789bf11773a"}

Now we can query the view we’ve defined, but before we do that, we should add a few documents to the database so we have something to view. Running the following command a few times will add empty documents:

今、先ほど定義したビューをクエリできました。しかし、そのビューを実行するまえに、ビューするための対象であるいくつかのドキュメントをデータベースに追加するべきです。以下のコマンドを何回か実行して空のドキュメントを追加しましょう。

curl -X POST http://127.0.0.1:5984/basic -d '{}'

Now to query the view:

さて、ビューを見てみましょう。

curl http://127.0.0.1:5984/basic/_design/example/_view/foo

This should give you a list of all the documents in the database (except the design document). You’ve created and used your first design document!

これによりデータベースのすべてのドキュメントのリストが得られます。(デザインドキュメントを除く)これで、初めてのデザインドキュメントを作って利用しました!

Looking to the Future

There are other design document functions that are being introduced at the time of this writing, including _update and _filter that we aren’t covering in depth here. Filter functions are covered in Chapter 20, Change Notifications. Imagine a web service that POSTs an XML blob at a URL of your choosing when particular events occur. PayPal’s instant payment notification is one of these. With an _update handler, you can POST these directly in CouchDB and it can parse the XML into a JSON document and save it. The same goes for CSV, multi-part form, or any other format.

この文章の中で何度か別のデザインドキュメントの関数について紹介してきました。たとえば、_update_filterです。これらはここでは深くは触れません。Filter functionはChapter 20, Change Notificationsで述べます。特別なイベントが起きる時に選択するURLでXML blobをPOSTsするWebサービスをイメージしてください。PayPalの"instant payment notification"はその一つです。_updateハンドラーによって、これらを直接CouchDBへPOSTすることができ、XMLをパースした後にJSONドキュメントとしてそれを保存できます。これはCSVやmulti-part form、他のフォーマットにも言えます。

The bigger picture we’re working on is like an app server, but different in one crucial regard: rather than let the developer do whatever he wants (loop a list of DocIDs and make queries, make queries based on the results of other queries, etc.), we’re defining “safe” transformations, such as view, show, list, and update. By safe, we mean that they have well-known performance characteristics and otherwise fit into CouchDB’s architecture in a streamlined way.

私たちが動かした概要はアプリケーションサーバのようなものです。しかし、一つ決定的に違うものがあります。開発者が望むものはなんでもできます。(DocIDのリストをループさせ、クエリをつくり、他のクエリの結果に基づいたクエリを作り、など)私たちは"安全な"変換を定義しています。それは、viewやshow, listやupdateです。これによって、開発者は良く知られたパフォーマンスの特徴を持ち、さもなくば合理化された手段でのCouchDBのアーキテクチャーにフィットさせることを示しています。

The goal here is to provide a way to build standalone apps that can also be easily indexed by search engines and used via screen readers. Hence, the push for plain old HTML. You can pretty much rely on JavaScript getting executed (except when you can’t). Having HTML resources means CouchDB is suitable for public-facing web apps.

ここでのゴールは、サーチエンジンでの簡単なインデックス作成やスクリーンリーダーを通して利用されることを可能にするためのスタンド アローンアプリケーションを構築する方法を提供することです。ゆえに、プレーンテキストのHTMLを進めます。JavaScriptで実行されることを>当てにしても構いません(出来ない時を除いて)。HTMLリソースを持つことは、CouchDBが一般的なWebアプリケーションの表向きとしても適し>ていることを意味しています。

On the horizon are a rewrite handler and a database event handler, as they seem to flesh out the application capabilities nicely. A rewrite handler would allow your application to present its own URL space, which would make integration into existing systems a bit easier. An event handler would allow you to run asynchronous processes when the database changes, so that, for instance, a document update can trigger a workflow, multi-document validation, or message queue.

平行して、アプリケーションの機能を良い方向に具体化するような rewriteハンドラーやデータベースイベントハンドラーがあります。rewriteハンドラーは、アプリケーションをそれ自身のURLスペースで表現することを可能にします。既に動作するシステムの一部として簡単に統合できます。イベントハンドラーはデータベースが変更された時に非同期でプロセスを実行することを可能にします。例えば、ドキュメントのアップデートでワークフローをトリガーしたり、マルチドキュメントの認証を実施したりメッセージをキューしたりなどです。