むかしむかし、MSSQLでストアドプロシージャ、トリガー、カーソルの作成を練習していたとき、すべてのビジネスロジックがデータベースレベルで回転し、プレゼンテーション層がデータベースをプルし、結果の描画を担当するアプリケーションの考えに悩まされていました。 私の開発年の多くはそれ以来過ぎましたが、CouchDBに出会うまで、このアイデアを実装する機会に会いませんでした。
Couch DBを含むNoSQLデータベースについては、すでに多くの人が聞いたことがあると思います。 ここでは、CouchAppと呼ばれるCouchDBにJavaScriptアプリケーションを埋め込む絶好の機会についてお話したいと思います。
CouchAppは
、CouchDBブックサイトでは「CouchDBからブラウザに直接配信されるJavascriptおよびHTML5アプリケーション」と説明され
ています。 HTMLはこの場合ブラウザに渡され、どのHTMLが渡されるかはサーバー上で実行されるJavaScriptによって決定されるため、このような定義は完全に正確ではないと思います。 サイトのスキームは、このアイデアをもう少し良く示しています。
Browser (UI and links between pages)
-------------- HTTP ---------------
CouchDB (persistence, business logic, and templating)
CouchDBはWebサーバーです(またはWebサーバーを含みます)。 JSON形式の結果をREST要求に返す機能を実行します。これは、あらゆる操作中にデータベースと通信する主な方法です(データに対するCRUD操作からデータベース自体の作成と削除まで)。 サーバーとクライアント間のデータはそれぞれHTTPプロトコルを通過し、HTMLの送信を妨げるものは何もありません。 これを行うには、適切な方法で彼にそれを伝える必要があります。
CouchDBのアプリケーションは、「設計ドキュメント」で始まります。 CouchDBのデータを含むすべてのものはドキュメントと呼ばれ、JSON形式で指定されているため、ドキュメントのデザインに違いはありません。 もちろん、特別な方法で呼び出され、特定の構造を持つ必要があります。 ドキュメント自体には、アプリケーションコードが含まれています。
最も単純なベースドキュメントは次のようになります。
{
"_id" : "my_doc" ,
"_rev" : "1-7a8b01193c8798fa555243b354d1e9d7"
}
設計ドキュメントには、
_design/app_name
という形式の_idが必要
_design/app_name
。 アプリケーションのJavaScriptコードは、ドキュメントのデザインを定義するJSONオブジェクトのフィールドに広がります(適切なシールド付き)。 また、ファイルリンク(添付ファイル)、アプリケーションマニフェストなど、他のアプリケーション属性も示します。 アプリケーションの展開では、ドキュメントのデザインとファイルリソース(添付ファイル)をデータベースに読み込みます。
お気に入りのエディターでJSコードを正常に動作させるために、設計フォルダーのアプリケーションフォルダーから少しずつ収集するのではなく、
couchappユーティリティがあります。 Pythonで書かれており、アプリケーションリソースを単一のjsonドキュメントに収集してサーバーに送信することを約束しています;添付ファイルは別々に注がれます。 また、アプリケーションの初期フォルダー構造を生成し、そこからリソースを収集することもできます。
したがって、最初にすべきことはcouchappユーティリティをインストールすることです。 インストールプロセスについては説明しませんが、
wikiによく書かれてい
ます 。
さらに、ベースに慣れるために、ベースを自分で置くか
、無料のCouchDBホスティングに登録することができます。 最後の選択肢を選びました。 その中のすべては問題ありません(制限については何も言いません)。ただし、そこでログを見ることができず、それに応じてアプリケーションをデバッグするのが難しい場合があります。
これで、すべての準備が整いました。
開始する
私は「Hello world」よりも多く、各教科書で開発されているブログとは異なる何かを書きたいと思っていましたが、同時に、ドキュメントの例を見て、コードの移植にあまり夢中にならないようにアプリのチュートリアル。 実践が示すように、これにより、新しいテクノロジーの取り扱いのニュアンスをすぐに理解できます。
説明するアプリケーションは、外国語を学習するためのいわゆるフラッシュカードです。 原則は単純です-人生では、カードの片側に単語がターゲット言語で書かれており、反対側にその翻訳があります。 したがって、アプリケーションでは、ユーザーはカードのセット(セット)のリストを表示するためのインターフェース、カード上の単語を追加および変更してセットを編集する機能、およびカードを実行するためのインターフェースが必要です。
データベース内の一連のカードのドキュメントは次のようになります。
{
"_id": "my set",
"_rev": "1-7a8b01193c8798fa555243b354d1e9d6",
"type": "set",
"cards": [
{
"front": "front_text",
"back": "back_text"
},
{
"front": "front_text second",
"back": "back_text second"
}
]
}
「_id」-セットの一意の識別子、同時にその名前(簡単にするため)
「_rev」はセットのリビジョン番号です。 ドキュメントを保存または作成するときに省略でき、自動的に入力されます。
フィールド「_id」および「_rev」は、ドキュメントの必須属性です。
「タイプ」-ドキュメントのタイプ。 CouchDBにはテーブルがなく、すべてのドキュメントはデータベース内で隣り合っているため、選択中に特別なフィールドを使用して単純に区別するのが便利です。
「カード」-カードを定義するオブジェクトの配列。 「カード」タイプのドキュメントに各カードを個別に保存できますが、単純なアプリケーションでは、これを行わないことにしました。
新しいセットを作成するか、既存のセットを編集するためのフォームでページを作成します。
ページを編集
CouchAppには「表示機能」という概念があります。 この関数は、ベースドキュメント、つまり これを別の構造に変換します。たとえば、HTML出力を生成できます。
ショー関数はjsファイルに保存され、showsフォルダーに配置する必要があります。 アドレスhttp://// _ design / flashcards / _show / edit /およびhttp://// _ design / flashcards / _show / edit / <document_id>にアクセスすると、編集関数の呼び出しが発生します。
ファイルのコードは、\ページの\ edit.jsを示しています。
function (doc, req) {
//!json shows._edit
var Mustache = require( "vendor/couchapp/lib/mustache" ),
path = require( "vendor/couchapp/lib/path" ).init(req);
var data = {
assets : path.asset(),
indexPath : path.list( 'sets' , 'all-sets' , {descending: true , limit:10})
};
data.doc = doc || {};
return Mustache.to_html(shows._edit, data);
}
Show関数は、要求されたドキュメント(要求され、見つかった場合)、および着信要求を記述するオブジェクトを要求されたパラメーターとして受け入れます。 最初のケースでは、ドキュメントは存在しません。
次はコメントで、これはファイルの内容を書き込むスクリプト(マクロと呼ばれる)のcouchappディレクティブです\ショー\ _edit *変数「shows._edit」に。 つまり、拡張子に関係なく、フォルダーには_editという名前のファイルを複数含めることはできません。 この場合、_edit.htmlファイルがそこにあります。これには、フォームを含むページのコードが含まれています。 後で戻ります。
次は2つのモジュールのインポートです。 CouchDBは、サーバー側のJavaScriptを開発するためにCommonJSの規則に従っているため、Node.js開発者にとって
インポート機能はおなじみかもしれません。 私はNode.jsを使用していなかったため、CouchDBで使用可能な機能に関するドキュメントを見つけることができませんでした。 CouchDBのコードを見て、例を理解する必要がありました。
最初のモジュールはMustacheで、すべてのレンダリングを担当します。 準備するデータでhtmlページをレンダリングするために必要です。 2つ目はパスです。これにより、データベースを操作するためのjsスクリプトなど、アプリケーションおよびリソースの他のページへのリンクを生成できます(一部はプロジェクトの初期化時にcouchappによって生成され、一部はデータベースのWebサーバーで既に利用可能です)。
次に、モデルオブジェクトが作成されます(MVCパターンから)。 アセットフィールドは、スクリプトが配置されるディレクトリのURLプレフィックスです。indexPathは、セットのリストを含むページのURLです。 文書のリストの表示は、後で説明するリスト関数によって行われます。 .listメソッドは、sets関数へのリンクを提供し、sets関数はall-setsビュー関数の結果を渡します。
以下は、ドキュメント自体のモデルへの追加です。 カードのセット。 すでに書いたように、ドキュメントのIDを使用して、またはドキュメントを使用せずに、編集機能にアクセスできます。 ドキュメントが見つかった場合、docパラメーターに含まれます。 見つからなかった場合は、セットの空のオブジェクトを作成します。 したがって、セット編集ページを開くと、新しいセットまたは既存のセットが編集されます。
セットのレンダリングを担当するページのhtmlコードの一部:
< form id = "new-post" method = "post" >
{{#doc}}
< label > Set name < / label > < input type = "text" size = "20" name = "_id" value = "{{_id}}" >
< ul class = "cards" >
{{#cards}}
< li >
< label > Front < / label > < input type = "text" size = "20" name = "front" value = "{{front}}" >
< label > Back < / label > < input type = "text" size = "20" name = "back" value = "{{back}}" >
< / li >
{{/cards}}
< li >
< label > Front < / label > < input type = "text" size = "20" name = "front" >
< label > Back < / label > < input type = "text" size = "20" name = "back" >
< / li >
< / ul >
< button id = "add" > Add < / button >< br / >< br / >
{{/doc}}
< input type = "submit" value = "Save →" / >
< span id = "saved" style = "display:none;" > Saved < / span >
< br / >< br / >
< / form >
特別なことは何もありません。 すべて
口ひげに従って。
フォームを表示した後、フォームを保存する機能を記述する必要があります。 これを行うには、一連のカードのJSONドキュメントを含むPOSTリクエストを送信します。 これを行うために、次のスクリプトがページに追加されます:/_utils/script/jquery.jsおよび/_utils/script/jquery.couch.js。 1つ目はjQuery、2つ目はCouchDBのクエリを整理するjQueryプラグインです。
次に、スクリプト:
( function ( $ ) {
$ ( '#new-post' ) . submit ( function ( ) {
var self = $ ( this ) , setName = $ ( 'input[name=_id]' , this ) . val ( ) ,
oldSet , newSet = { } , db = $. couch . db ( 'flashcards' ) ;
function saveDoc ( set ) {
db. saveDoc ( set ) , {
success : function ( resp ) {
window. location . reload ( true ) ;
}
} ) ;
}
//collect cards array
newSet. cards = $ ( 'ul.cards input' ) . toArray ( ) . reduce ( function ( arr , el , idx ) {
if ( ! ( idx % 2 ) ) { arr [ arr. length ] = { } ; }
arr [ arr. length - 1 ] [ ! ( idx % 2 ) ? "front" : "back" ] = el. value ;
return arr ;
} , [ ] ) ;
//retrieve old set if found or create new
db. openDoc ( setName , {
error : function ( code ) {
oldSet = { } ;
if ( setName. length ) {
oldSet._id = setName ;
}
saveDoc ( $. extend ( oldSet , newSet ) ;
} ,
success : function ( response ) {
oldSet = response ;
saveDoc ( $. extend ( oldSet , newSet ) ;
}
} ) ;
return false ;
} ) ;
} ) ( jQuery ) ;
主なデータベース操作は次のとおりです。
1.
var db = $. couch . db ( 'flashcards' )
var db = $. couch . db ( 'flashcards' )
var db = $. couch . db ( 'flashcards' )
-save、openなどを呼び出すためのデータベースオブジェクトの取得
2.
db. openDoc ( id , callback )
db. openDoc ( id , callback )
データベースからドキュメントを取得します。 ドキュメントの最新バージョンを取得するために使用されます。 最新のリビジョンを含むドキュメントをサーバーに送信する必要があります。そうしないと、ドキュメントは拒否されます。 CouchDBは、リソース共有の共有というこの原則のみを実装しています。 ドキュメントが見つからない場合、新しいセットが作成されたと見なされます。 次に、セットオブジェクト全体がデータベースに保存されます。
3.
db. saveDoc ( doc , callback )
db. saveDoc ( doc , callback )
-ドキュメントをデータベースに保存します。 すべてが成功すると、ページがリロードされます。 何かがうまくいかなかった場合、古いリビジョンが送信された場合にこれが発生する可能性があるので、考慮しません。
これで、マップセットを作成および編集するためのすべての機能を使用できます。 セットのリストの表示に移りましょう。
リスト表示
リストを表示する前に、選択する必要があります。 サンプリングはビューを使用して行われます。 クエリを動的に構築し、テーブル内のデータを処理できるSQLとは異なり、ビューの動作は少し異なります。 HTTP要求からビューにパラメーターを渡す方法はありませんが、ビューから受信した結果に適用できます。
ビューは、データベース内の各ドキュメントに適用される機能です。 これを使用して、このフィルタリングの結果にインデックスを課すために、ドキュメントのフィルタリングが実行されます。 ビューは、マップ機能とオプションのリデュースで構成されます。 すべてのセットを表示するには、関数\ビュー\すべてのセット\ map.js(すべてのセットはビューと呼ばれます)は次のとおりです。
function ( doc ) {
if ( doc. type === 'set' && doc. cards ) {
emit ( doc._id , null ) ;
}
}
ここでは、ドキュメントがセットタイプに準拠しているかどうか、およびカードを含むアレイが存在するかどうかがチェックされます。 一致する場合、emit関数が呼び出されます。これは、キーと値の2つの引数を取ります。 セットリストを表示するには、2番目のパラメーターの値は役割を果たしません。 必要なのは、セットの名前を表すキーだけです。 また、結果を並べ替えます。 取得したキーのセットに基づいて、インデックスが構築されます。
表示するには、選択範囲を絞り込むクエリを作成できます。 一部のクエリでは、重要なキー生成スキームが必要であり、他のクエリでは、追加のリデュース機能が必要です。 それについてのドキュメントはそれについてよく書かれているので、私はこれに焦点を合わせません。
ビューを定義したら、結果の表示を設定できます。 ドキュメントを表示するためにshow関数が使用された場合、ここでリスト関数が必要です。 関数\リスト\ sets.js:
function ( head , req ) {
// !json lists._sets
var Mustache = require ( "vendor/couchapp/lib/mustache" ) ,
path = require ( "vendor/couchapp/lib/path" ) . init ( req ) ;
provides ( 'html' , function ( ) {
var data = {
assets : path. asset ( ) ,
createNewLink : path. show ( 'edit' )
} ;
data. sets = ( function ( ) {
var row , set , arr = [ ] ;
while ( row = getRow ( ) ) {
set = row. value ;
arr. push ( {
title : row. id ,
showView : path. show ( 'set' , row. id ) ,
editLink : path. show ( 'edit' , row. id ) ,
runsetLink : path. asset ( 'flashcards_zeptojs.html' ) + '#' + row. id
} ) ;
}
return arr ;
} ) ( ) ;
return Mustache. to_html ( lists._sets , data ) ;
} ) ;
}
show関数の顕著な特徴は、ビューの行を返す要求のcontent-typeとgetRow()が一致した場合にコールバックを呼び出す、提供(content_type、コールバック)関数がここで利用できることです。 文字列を表示するビューは、URLで決定されます:http://// _ design / flashcards / _list / sets / <view-name>? ビューのパラメーターは、関数のheadパラメーターと、reqの多数のHTTP要求パラメーターに書き込まれます。 残りについては、show関数と同じ方法で進めます。テンプレートを取得し、そこに結果のモデルを渡し、結果を返します。
記事の範囲外で、カードのセットと実行インターフェース自体のプレビューを含む2つのページがありましたが、それらはまったく簡単で、上記の同じ機能のセットによって実装されています。
これはおそらく、CouchAppを理解するために必要だと思うすべてです。 その後、安全にドキュメントに目を向け、意味のある何かを実装できます。
おわりに
CouchAppでCouchDBを学習した経験の残りの部分:
1.非常に漏れやすいドキュメント。
CouchDB Bookは、その2つのバージョン(1.0とドラフト)でもパブリックドメインにあり、データベース自体の基本概念を詳細に明らかにしていますが、couchAppの説明は非常に複雑でスペースがあります。 すべてがどのように機能するかの一般的な図を取得するには、さまざまなブログエントリを調べる必要があります。 300ページを読んで高度な理解を得るのは私には少し大変なように思えますが、本全体を読むことで完全に理解できるとは限りません。 一方、神聖な碑文のみを表示し、深くは行かないという小さなhelloworldの記事がありますが、これはほとんど利点がありません。
面白いのは、CouchAppにJavaScript APIの記述がないことです。 さらに、
couchone.com 、
wiki.apache.org/couchdb 、または
couchapp.orgの公式Webサイトでも、このようなAPIへの参照は見つかりませんでした。
CouchDBの本では、GitHubにあるSofaの例(ブログ)を参照することを推奨しています。 これまでのところ、このアプリケーションのコードはなくなっているため、遠くにある類似点のみを見つけることができる場所でのみです。 さらに、本のアプリケーションコードがかなり基本的なものを使用している場合、リポジトリのアプリケーションはすでに高レベルの構造を使用しています。 何がわかるかはそれほど怖くないですが、CouchAppを開いたばかりの人にとっては、あまりにも難しいと思います。 これはサーバーサイドJSでの経験の利用可能性によって促進されるかもしれません、私は知りません、私はそのような経験を持っていませんでした。
また、提供されているjavascriptライブラリのドキュメントが不足していることも憂鬱です。 それらがどこにあるのかは明らかではありません(一部のライブラリはcouchappスクリプトによって提供され、一部は既にサーバー上にあることをすぐには知りませんでしたが、それ以外の場所はまだ把握しなければなりませんでした)。 たとえば、CouchDBリードの妻のブログで、JavaScriptライブラリ(1つはプレーンjs、もう1つはjqueryベース)のテストケースの説明があり、データベースへのajaxクエリを実行します。 ただし、これらのライブラリはSofaアプリケーションでは使用されません。 そこで別のライブラリが使用され、その機能が拡張されますが、何らかの理由で、最初の要求でアプリケーションの設計ドキュメント全体を引き出して、そこからURLを正しく構築します。 そして、私の小さなアプリケーションであっても、デザインドキュメントのサイズは約1メガバイトです。
一般的に、ドキュメントから判断すると、プロジェクトは非常に深刻な学生の卒業証書でいっぱいですが、製品が深刻であるという事実にもかかわらず、商用製品ではありません。
2.セキュリティアプリケーション。
最初は、絶対にすべてのユーザーがデータベースクエリを実行できます。 これは、データベースユーザーを指定することにより禁止されています。 しかし、CouchAppは1つのデータベース内で回転しているため、ユーザーがCouchAppにアクセスできる場合、すべてのドキュメントに完全にアクセスできます。 また、関数の検証レベルで書き込みを禁止できる場合、読み取りは機能しません。 承認されたユーザーは、ビルトインリクエスト/ _all_docsを作成し、データベース内のすべてのドキュメントを受信できます。
これを回避するには、Apacheの上にそれをねじ込み、不要なURLをすべて閉じ、きれいなURLの質問(ユーザーは/ _lists / sets / ...?に移動しません)を解決しますが、私はそれを試しませんでした。同じcouchapp.orgは機能しますが。
このすべてから、セキュリティを処理し、フォームからのPOSTリクエストを処理する何らかの種類のアプリケーションの背後にCouchDBを置く方が落ち着くと結論付けることができます。 しかし、プロジェクトは開発中であり、生活を簡素化する革新について正気の文書が書かれているなら、私の意見を再考することができます。
ありがとう、私はそれが面白かったと思います