まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

タグ:design

こちらの続きです:
ノーツデータベースの設計変更履歴を git で管理する(1)

↑のブログエントリを書いた時点では未完成だったインポート機能が使えるようになったので、続きのエントリとして紹介します。

上述の記事内で紹介した dxl_export.vbs ツールでエクスポートした XML データを元の NSF ファイルにインポートするのがもう一つのファイルである dxl_import.vbs です。以下のようにして使います(XML ファイルはフルパス指定が必要な点に注意してください):
> c:\Windows\SysWOW64\CScript //nologo dxl_import.vbs C:\Users\username\dev_mydb.nsf\mydb.xml

成功すると指定した XML ファイルと同じフォルダ内に拡張子が .xml から .nsf になったノーツデータベースが復元されます。復元元のデータ(設計要素と文書)は XML ファイルです:
2023051601


復元されたデータベースをドミノデザイナーで開くと、設計要素も元の(dxl_exporter.vbs でエクスポートされる前の)状態で復元されているはずです:
2023051600


このツールの便利なところは XML データを git でバージョン管理できるという点にあります。つまり元のデータベースが変更される度に dxl_exporter.vbs を実行しておくことで、 git の履歴(ログ)を見て、必要に応じて過去のコミットに戻り(チェックアウトし)、過去の状態の NSF データベースに復元することもできるようになる、という点です。この dxl_importer.vbs が正しく動くようになったことでこちらの機能も動くようになりました。





ノーツのデータベース(アプリケーション)はノーツクライアントやドミノサーバーが無いと開くことができないため、内容を確認したりデータ文書を追加したり、あるいはデータベースそのものの設計を変更したりする際には、原則的にこれらがセットアップ済みの環境が必要です。

特に設計に変更を加える場合、ドミノデザイナーという専用クライアントアプリが必要になります。Eclipse RCP をベースとしたツールとして提供されていますが、データベースそのものがバイナリファイルになっていることもあり、(例えば git などを利用してソースコードの変更履歴管理をする場合と比較して)設計の変更履歴を管理することが難しいのでした。

そんな背景の中、「じゃあノーツデータベースの変更履歴を git で管理できるようにならないか」というアイデアネタを思いつき、実現可能性のありそうな方法を見つけて試しに作ってみました。まだ理想形には至っていないのですが、当初の目的であった「git による変更履歴管理」はできそうな目途が立っているので公開します:
https://github.com/dotnsf/dxl.vbs

で、↑このページ内でも(英語で)使い方の説明をしているのですが、このブログエントリでは図を含めて日本語で紹介します。


【前提条件】
上記コードは MIT ライセンスのオープンソースとして公開しますが、正しく動作させる上での前提条件がいくつかあります:
  • Windows 64bit 環境(32bit でも多分動くが未検証)
  • Windows 版 git がインストール済み
  • ノーツがセットアップ済み
  • 対象データベースに対する設計者以上の権限がある

前提条件について補足します。まずこのツール自体が VBScript で出来ています。実現可能性や使っていただく上での条件をいろいろ考慮した結果、最もハードルが低そうなものを選択しました(これはこれで文字コードが Shift-JIS になってしまう制約があって苦労しました。が、他よりはマシだったと思っています)。この VBScript を動かすため Windows 環境が必要となります。変更管理ツールとしての git も Windows 環境下で動かす必要があります※。

※ WSL を併用している場合であれば、このツールを使って出力した結果のフォルダに WSL のターミナルを移動して WSL の git を使う、ということができないわけではありません。ただこのツール自体が Windows の CLI で動くものなので、コマンドプロンプトを起動して、ツールを実行して、実行結果をそのまま git で管理する、、という使い方が便利で、その場合は(WSL の git ではなく)Windows 環境で動く git 環境が必要です。 また Windows 版で GUI を提供する git もあるようですが、今回のツールを使う場合はコミット ID を指定しての差分比較などを行えることが便利だと思っていて、そういった操作までができる GUI 版 git であればいいのですが、私が軽く調べた限りではそこまでの GUI を持ったものがなかったので、CLI 版の利用をお勧めします。

また「ノーツが不要」というわけではありません。ツールを使って設計をテキストにエクスポートした後は git だけで使えますが、ツール利用時にはノーツが必要で、かつ対象となるデータベースに対して設計者権限または管理者権限がないと設計内容にアクセスできません。設計変更履歴を管理しようとすると何回もこのツールを利用することになると思っていますが、仮に「1回だけ利用して中身をテキスト化する」という目的であったとしても、実行時にはセットアップ済みノーツ環境が必要です。


【ツールの使い方】
ツールは Github のこのリポジトリで公開しています。git clone するか、zip download で README.md ごと取得してください:
https://github.com/dotnsf/dxl.vbs


リポジトリには dxl_export.vbs と dxl_import.vbs の2つのツールが含まれています。が、dxl_import.vbs はまだ開発途中で、期待通りの挙動は実現できていないので、2023年5月の現時点では実質的に dxl_export.vbs だけがリリースされている、とご理解ください。

ツールはコマンドラインツールなので、実行する上では Windows のコマンドプロンプトを使います(管理者権限は不要です)。コマンドプロンプトを開き、dxl_export.vbs を保存したフォルダに移動します:
2023051101


ここで CScript.exe (VBScript のコマンド)を実行して del_export.vbs を動かします。パラメータの最後に設計変更履歴を管理したいノーツデータベースを相対パスで指定します(下の例だと dev/mydb.nsf というデータベースを指定しています)。注意点として CScript.exe は必ず指定のフルパス(c:\\Windows\\SysWOW64\\CScript)を指定して実行する必要があります(64bit Windows ではパスを指定せずに CScript を実行すると 32bit 版の VBScript が実行されてしまいます。64bit 版 Windows では 64bit 版 VBScript を実行するためにこのフルパスを指定して実行してください:
> c:\Windows\SysWOW64\CScript //nologo dxl_export.vbs dev/mydb.nsf

このようなダイアログが表示された場合は、表示されているノーツ ID のパスワードを入力してください(一度入力しておくと次回からしばらくパスワードなしで使えるはずです):
2023051001


dxl_export.vbs が正しく実行されると以下のような出力になります(この例だと dev_mydb.nsf/mydb.xml にエクスポート結果が出力されていることになります):
2023051001


この出力された XML がパラメータで指定したデータベースファイル(dev/mydb.nsf)の設計情報を DXL(Domino XML Language) というフォーマットで出力したファイルになっています:
2023051001


本ツールでは、このバイナリデータベースが XML でテキスト化された状態を git でコミットすることを想定しています。具体的にはこんな感じ:
> git add dev_mydb.nsf\mydb.xml

> git commit -m "first comment"

これでこの状態の設計情報が(テキスト形式で)git に格納され、コミットされました。git はコミット単位で履歴を追ったり、比較できるようになるツールなので、まずはその履歴の1つが記録された状態になりました。

その後、このノーツデータベースになんらかの設計変更が加わったとします。例えば "myForm" という名前のフォーム要素を新たに追加したとします:
2023051101


何らかの設計変更が加わった状態で、再度この dxl_export.vbs ツールを実行します(コマンド自体は最初に実行したものと全く同じです):
> c:\Windows\SysWOW64\CScript //nologo dxl_export.vbs dev/mydb.nsf

するとこの時点での設計情報が dev_mydb.nsf\\mydb.xml ファイルに記録(正確には上書き)されます。この結果をやはり同様に git でコミットします:
> git add dev_mydb.nsf\mydb.xml

> git commit -m "myForm added"

コミットの履歴は "git log" で確認することができます。↓の例では1回目の "first commit" というコメントの付いたコミットと、2回目の "myForm added" というコメントのついたコミットの2つを確認することができます:
$ git log

2023051102


2つのコミットログを並べて "git diff" を実行すると、コミット間の差分を表示することができます(以下の例では "myForm" に相当する設計要素が追加されたことがわかります:
$ git diff (変更前のコミットID) (変更後のコミットID)

2023051103


同様にしてデータベースに設計を加え、ツールを使って XML ファイルにエクスポートして、git でコミットし、git diff で比較することができます。以下の例では LotusScript プログラムの内容が表示できていることわかり、そのプログラムに後からコメントを追加している様子がコミット間比較によって視覚化されています:
2023051104


このように、
・データベースの設計を変更
・dxl_export.vbs ツールを実行
・git で差分をコミット
を繰り返すことで、バイナリデータであるノーツデータベースの設計変更履歴を git で管理することができるようになります。

(2023/05/12 追記 裏技の紹介)
dxl_export.vbs は VBScript なのでテキストファイルです。テキストエディタで開くことでカスタマイズもできます。

例えば 76 行目の
nc.SelectDocuments = selDocs           'Documents

となっている部分。これは「(データベースからエクスポートする要素として)各文書データは対象外とする」ことを指定しています。なので dxl_export.vbs をそのまま使った場合、設計要素のみが対象となって、文書データはエクスポート対象外となります。

ここを、
nc.SelectDocuments = True           'Documents

と無理やり変更して保存すると、文書データもエクスポート対象に含まれるようになります(ただし文書データも含めてエクスポートする場合はメモリ不足のエラーが発生する確率が高くなります)。テキストファイルとして読める形でアーカイブしておきたい場合などに使ってください。


(2023/05/16 追記)
続きはこちらです:
ノーツデータベースの設計変更履歴を git で管理する(2)


これらの記事の続きです(シリーズとしては今回が最終回です):
Cloudant の便利な API (1) : バルクインサート
Cloudant の便利な API (2) : View Design Document
Cloudant の便利な API (3) : List Design Document

DBaaS である IBM Cloudant の便利で特徴的な API を紹介しています。前回までは Design Document の1つである View Design Document と List Design Document を紹介して、データベース内の特定の条件を満たすドキュメントデータだけを「ビュー」としてまとめ、かつそのビューの UI も格納ドキュメントの一部として定義する、という内容を紹介しました(47都道府県のドキュメントデータから海なし県だけを取り出して HTML の UI で表示する、というところまでを作りました):
2017100602

↑ https://username.cloudant.com/mydb/_design/nosea/_list/nosea/nosea にアクセスした結果(username は Cloudant インスタンスに接続するための username です)

最終回である今回は、この一覧からクリックした各ドキュメントも HTML で表示するための Show Design Document と、その API を紹介します。

前回のおさらいとして、このビューで表示される各ドキュメントをクリックすると、以下の URL に移動します(現時点ではエラーになります):
https://username.cloudant.com/mydb/_design/nosea/_show/nosea/(doc.id)

これは doc.id で示される id 値を持つドキュメントデータを nosea という Show Design Document の設計内容を使って表示する際の URL です(そして現時点では nosea という Show Design Document を定義していないためエラーになります)。

ではこの nosea Show Design Document を定義します。前回までに紹介した View Design Document と List Design Document を含む JSON の内容に赤字部分を加えて以下のようなドキュメント(nosea_show.json)を作ります:
{
 "language": "javascript",
 "views": {
  "nosea": {
   "map": "function(doc){ if( doc.code && [9,10,11,19,20,21,25,29].indexOf(doc.code) > -1 ){ emit( doc._id, {code:doc.code,prefecture:doc.prefecture,capital:doc.capital,lat:doc.lat,lng:doc.lng} ); } }"
  }
 },
 "lists": {
  "nosea": "function( head, row ){ start( { 'headers': { 'content-type': 'text/html' } } ); send( '<ul>' ); var row; while( row = getRow() ){  var url = '../../_show/nosea/';  send( ' <li><a href=\"' + url + row.id + '\">' + row.value.prefecture + '(' + row.value.capital + ')</a></li>' ); } send( '</ul>' );}"
 },
 "shows": {
  "nosea": "(function( doc, req ){ if( doc ){  var str = '<h2>' + doc.prefecture + '</h2><h3>' + doc.capital + '</h3><hr/>緯度: ' + doc.lat + '<br/>経度: ' + doc.lng;  return str; }else{  return 'empty'; }})"
 }
}

赤字部分が Show Desgin Document に相当する部分です。この中では同ファイル内の上位部分で定義された nosea ビューからクリックされた各ドキュメントが表示する際に実行される処理が記載されています。上記例では理解しやすさを優先して、ドキュメントの各属性(県名、県庁所在地名、緯度、経度)を単純に HTML で表示する内容にしています。

なお、この内容と同じファイル(nosea_show.json)をこちらからダウンロードできるよう用意しました:
https://raw.githubusercontent.com/dotnsf/samples/master/nosea_show.json


前回同様に、この JSON ファイルを指定して Design Document を更新します。まずは API で現在の Design Document を確認し、現在のリビジョンを確認します:
$ curl -u "username:password" -XGET "https://username.cloudant.com/mydb/_design/nosea"

{"_id":"_design/nosea","_rev":"YYYY..YYYY","language":"javascript", ... }

この例の場合の YYYY..YYYY 部分("_rev" の値)が現在のリビジョン ID なので、この値をダウンロードした nesea_show.json ファイルに追加します:
{
 "_rev": "YYYY..YYYY",
 "language": "javascript",
 "views": {
  "nosea": {
   "map": "function(doc){ if( doc.code && [9,10,11,19,20,21,25,29].indexOf(doc.code) > -1 ){ emit( doc._id, {code:doc.code,prefecture:doc.prefecture,capital:doc.capital,lat:doc.lat,lng:doc.lng} ); } }"
  }
 },
 "lists": {
  "nosea": "function( head, row ){ start( { 'headers': { 'content-type': 'text/html' } } ); send( '<ul>' ); var row; while( row = getRow() ){  var url = '../../_show/nosea/';  send( ' <li><a href=\"' + url + row.id + '\">' + row.value.prefecture + '(' + row.value.capital + ')</a></li>' ); } send( '</ul>' );}"
 },
 "shows": {
  "nosea": "(function( doc, req ){ if( doc ){  var str = '<h2>' + doc.prefecture + '</h2><h3>' + doc.capital + '</h3><hr/>緯度: ' + doc.lat + '<br/>経度: ' + doc.lng;  return str; }else{  return 'empty'; }})"
 }
}

これで更新用の nosea_show.json ファイルが完成しました。改めてこのファイルを指定して Design Document を更新します:
$ curl -u "username:password" -XPUT -H "Content-Type: application/json" "https://username.cloudant.com/mydb/_design/nosea" -d@nosea_show.json

{"ok":true, "id":_design/nosea", "rev":"ZZZZ..ZZZZ"}

これで Design Document が更新されました。改めてウェブブラウザで https://username.cloudant.com/mydb/_design/nosea/_list/nosea/nosea にアクセスすると、List Design Document で定義された内容に従って nosea ビューが表示されます(ここまでは前回と同様):
2017100602


そしていずれかのドキュメント(県名)をクリックすると、そのドキュメントデータが Show Design Document に定義された内容で表示されます。これで一覧から詳細情報まで表示するアプリケーションとして繋がりました!:
2017100604


先程は Design Document の理解のため比較的シンプルな Show Design Document を使いましたが、少し UI にも凝ったバージョンも用意しました:
https://raw.githubusercontent.com/dotnsf/samples/master/nosea_show2.json

こちらの JSON ファイルをダウンロードして、上記同様にリビジョン ID を調べて追加し、API で PUT すると、少しだけ凝った UI で海なし県の一覧と詳細画面を確認することができます(View Design Document は変更せずに、List Design Document と Show Design Document を変更したものです)。

nosea_show2.json を PUT した場合、ビューはテーブル形式で表示されます。県名または県庁所在地名がクリック可能になっています:
2017100605


クリックすると OpenStreetMap API を使って、その県庁所在地周辺の地図が表示されます。海なし県の海までの遠さを視覚的にも確認できる UI にしました(笑):
2017100606



4回に渡って IBM Cloudant の特徴的な Design Document とその API を中心に紹介してきました。以前にも触れましたが、IBM Cloudant のベースとなった CouchDB は IBM Notes/Domino と似た生まれであり、その設計思想などにも似た部分が多くあると感じています。私自身がノーツ大好きということもあってそんな Cloudant の特徴的な機能をまとめて紹介してみました。


これらの記事の続きです:
Cloudant の便利な API (1) : バルクインサート
Cloudant の便利な API (2) : View Design Document


DBaaS である IBM Cloudant の便利で特徴的な API を紹介しています。前回は Design Document の1つである View Design Document とその API を紹介して、データベース内の特定の条件を満たすドキュメントデータだけを「ビュー」としてまとめる方法を紹介しました。

今回紹介するのはやはり Design Document の1つで、「ビューの見た目を定義する」List Design Document です。前回の「ビュー」がドキュメント集合の条件を定義していたのに対して、今回の「リスト」は「ビューの見た目」を定義します。


一般的にデータベースを使ったウェブアプリケーションを作る場合、データベースサーバーにデータを格納した上で、そのデータを読み/書き/更新/検索して画面に表示する部分はアプリケーションサーバーに実装されることが多いです。しかし(HTTP をベースとした) REST API で動かす Cloudant は、その HTTP 部分を更に活用してデータの見た目に関わる部分までを定義・実装することができます。特に今回紹介する List Design Document ではデータの集合体であるビューの見た目を実装して格納します。個別の文書の見た目を実装する Show Design Document については次回紹介する予定です。


※余談ですが、この「見た目を定義する情報がドキュメントの一部として格納される」という点も「ノーツのビューやフォーム」に近い考え方や設計だと思っています。

このリスト(List)も Design Document の1つなので、ビューと同様に設計文書を用意します。前回紹介した View Design Document の JSON の内容に赤字部分を加えて以下のようなドキュメント(nosea_list.json)を作ります:

{
 "language": "javascript",
 "views": {
  "nosea": {
   "map": "function(doc){ if( 

doc.code && [9,10,11,19,20,21,25,29].indexOf(doc.code) > -1 ){ emit( doc._id, 

{code:doc.code,prefecture:doc.prefecture,capital:doc.capital} ); } }"
  }
 },
 "lists": {
  "nosea": "function( head, row ){ 

start( { 'headers': { 'content-type': 'text/html' } } ); send( '<ul>' ); var row; while( row = getRow() ){  var url = 

'../../_show/nosea/';  send( ' <li><a href=\"' + url + row.id + '\">' + row.value.prefecture + '(' + row.value.capital + ')

</a></li>' ); } send( '</ul>' );}"
 }
}

赤字部分が List Desgin Document に相当する部分です。この中では同ファイル内の上位部分で定義された nosea ビューを表示する際に実行される処理が記載されています。

なお、この内容と同じファイル(nosea_list.json)をこちらからダウンロードできるよう用意しました:
https://raw.githubusercontent.com/dotnsf/samples/master/nosea_list.json


赤字部分について簡単に内容を紹介すると、まず HTTP レスポンスヘッダとして 'Content-Type: text/html' を指定し、全体が HTML として返されるよう宣言しています。次に <ul> と </ul> の間が while でループ処理され、このビューに含まれる各文書(doc)の値を row として取り出します。そして
  <li><a href="../../_show/nosea/(doc.id)">県名(県庁所在地名)</a></li>
という <li> 要素を動的に作って <ul> と </ul> の間に挿入し、最後に全体を返しています。 要するに nosea ビューに含まれる海無し県の一覧を <ul> タグを使ってリスト表示している、というものです。

この JSON ファイルを指定して API を実行すれば List Design Document が作成される、、、のですが、もう1つだけ準備が必要です。今回作成する Design Document は前回作成した Design Document を上書きして保存する必要があります。そのため単にこのままのファイルを指定して API を実行しても(同一 ID への新規作成コマンドと解釈され)コンフリクトを起こしてしまい、更新できません。Cloudant の既存ドキュメントを更新する場合は既存ドキュメントのリビジョン ID を明示して実行する必要があるのでした。

というわけで、まずは API で現在の Design Document を確認し、現在のリビジョンを確認します。前回同様、コマンド内の username, password はそれぞれ Cloudant インスタンスに接続するための username, password で、実行結果を青字で表しています(以下同様):
$ curl -u "username:password" -XGET "https://username.cloudant.com/mydb/_design/nosea"

{"_id":"_design/nosea","_rev":"XXXX..XXXX","language":"javascript","views":{"nosea":{"map":"function(doc){ if( doc.code && [9,10,11,19,20,21,25,29].indexOf(doc.code) > -1 ){ emit( doc._id, {code:doc.code,prefecture:doc.prefecture,capital:doc.capital} ); } }"}}}

この例の場合の XXXX..XXXX 部分("_rev" の値)が現在のリビジョンIDです。nosea_list.json をテキストエディタで開いて、この値を使って以下のように書き換えます:
{
 "_rev": "xxxx..xxxx",
"language": "javascript", "views": { "nosea": { "map": "function(doc){ if( doc.code && [9,10,11,19,20,21,25,29].indexOf(doc.code) > -1 ){ emit( doc._id, {code:doc.code,prefecture:doc.prefecture,capital:doc.capital} ); } }" } }, "lists": { "nosea": "function( head, row ){ start( { 'headers': { 'content-type': 'text/html' } } ); send( '<ul>' ); var row; while( row = getRow() ){ var url = '../../_show/nosea/'; send( ' <li><a href=\"' + url + row.id + '\">' + row.value.prefecture + '(' + row.value.capital + ') </a></li>' ); } send( '</ul>' );}" } }

これで更新用の nosea_list.json ファイルが完成しました。改めてこのファイルを指定して Design Document を更新します:
$ curl -u "username:password" -XPUT -H "Content-Type: application/json" "https://username.cloudant.com/mydb/_design/nosea" -d@nosea_list.json

{"ok":true, "id":_design/nosea", "rev":"YYYY..YYYY"}

これで Design Document が更新されました。この時点でダッシュボードの nosea ビューを確認すると・・・一見、何も変わっていないようにみえます:
2017100601


しかしウェブブラウザで https://username.cloudant.com/mydb/_design/nosea/_list/nosea/nosea にアクセスすると、List Design Document で定義された内容に従って nosea ビューが表示されます。結果としてこのような画面が表示されます:
2017100602


これが Cloudant(CouchDB) の特徴ともいえる Design Document の機能です。通常であれば別途アプリケーションサーバーを用意した上で UI やロジックを実現するのですが、Cloudant の場合は Design Document を使うことで Cloudant の REST API(HTTP) の機能を使って UI を実現することができるようになるのでした。 ただ上のUIはシンプルすぎるので実用段階ではもう少しちゃんとしたほうがいいとは思います(苦笑)。

なお、この結果表示されている画面の各海なし都道府県へのリンクをクリックすると、以下のようなエラーになります:
2017100603


これはビューの UI とリンクまでは作成したのですが、各ドキュメントの内容(UI)を表示する Design Document についてはまだ作成していないために(リンク先が見当たらずに)エラーとなっているのでした。というわけで、次回は各ドキュメントの UI を定義する Show Design Document とその API について紹介し、各ドキュメントの内容まで表示できるようなアプリケーションを完成させる予定です。



こちらの続きです:
Cloudant の便利な API (1) : バルクインサート


NoSQL な DBaaS である IBM Cloudant の便利で特徴的な API を紹介しています。前回は1回の POST API 呼び出しでまとめて複数のドキュメントデータを登録するバルクインサート機能を紹介しました。この登録したドキュメントデータを使って、今回からは Cloudant のユニークな API を紹介すると共に、このドキュメントデータを使った参照アプリケーションを作っていきます。

今回紹介する便利な API は View Design Document API です。Cloudant には Design Document と呼ばれる特殊なドキュメントを格納することができます。一般的なドキュメントはいわば「データとしてのドキュメント」であるのに対し、Design Document は「設計情報としてのドキュメント」です。特に今回紹介する View Design Document は複数のドキュメントの集合である「ビュー」の定義情報を保持するドキュメントです。具体的にはどのような条件を満たすドキュメントがビューに含まれるのか、その条件を満たすドキュメントのどの要素をビューに格納するのか、、といった情報を保持する、(ドキュメントデータとは異なる)特殊なドキュメントです。

なお、Cloudant の Design Document に関する API のリファレンスはこちらを参照ください:
https://docs.cloudant.com/design_documents.html


では前回作った47都道府県ドキュメントデータに View Design Document を使ってビューを作ってみます。今回はこの47ドキュメントから、いわゆる「海無し県(=栃木県、群馬県、埼玉県、山梨県、長野県、岐阜県、滋賀県、奈良県)」だけを抜き出して集めた nosea ビューを定義してみます。

まず海無し県は上述の8県です。海無し県に含まれる条件は各ドキュメントデータ(doc)の code (都道府県コード)の値が「9か、10か、11か、19か、20か、21か、25か、29のいずれかであれば海無し県」ということになります。これを JavaScript で表現すると、以下のようになります:
if( doc.code && [9,10,11,19,20,21,25,29].indexOf( doc.code ) > -1 ){
    //. doc.code が存在していて、かつその値が [9,10,11,19,20,21,25,29] のいずれかであった場合、
        :
}

この条件を満たしたドキュメントデータの各値を nosea ビューに含める、という処理の場合に指定するデータは以下のような内容になります:
{
  "language": "javascript",
  "views": {
    "nosea": {
      "map": "function( doc ){ if( doc.code && [9,10,11,19,20,21,25,29].indexOf( doc.code ) > -1 ){ emit( doc._id, {code:doc.code,prefecture:doc.prefecture,capital:doc.capital} ); } }"
    }
  }
}

JSON 内の views.nosea(ビュー名).map に、このビューへのマッピングの関数を記述します。function のパラメータである doc がデータベース内の各ドキュメントを示しており、全ドキュメントがこの関数によってマッピングされ、条件を満たしたものだけがビューに含まれるよう定義されています。

関数内で使われている emit() 関数は第一パラメータがキー、第二パラメータがデータの値となります。第二パラメータに全データを含める必要はなく、今回は code, prefecture, capital という3つのデータだけを取り出して表示するようにアプリ化するので、これらの値だけを含めるようにしました。なお、上記の定義ファイル nosea_view.json はこちらからダウンロード可能です:
https://raw.githubusercontent.com/dotnsf/samples/master/nosea_view.json


ではこの(ダウンロードした)nosea_view.json と View Design Document API を使って、実際に海無し県ビューを作ってみましょう。前回同様に、nosea_view.json を保存したディレクトリで以下のコマンドを実行します(青字は実行結果、成功した時の例です):
$ curl -u "username:password" -XPUT "https://username.cloudant.com/mydb/_design/nosea" -H "Content-Type: application/json" -d @nosea_view.json

{"ok":true, "id":"_design/nosea", "rev":"XXXX..XXXX"}

前回作成した mydb データベースの中に nosea という名前のビューを、nosea_view.json で定義された内容で作成する、という API を実行しています。username および password は Cloudant に接続するためのユーザー名およびパスワードです。詳しくは前回の記事を参照してください。

このコマンドを実行後、改めてダッシュボードの画面をリロードすると、まずドキュメントデータそのものが1つ増えて 47 データから 48 データになっていることが分かります。つまりこのコマンドでデータベース内のドキュメントが1つ追加されたことが分かります(追加されたドキュメントの id は:"_design/nosea" です):
2017100504
2017100504


また mydb データベースに nosea という Design Document が追加されていることがわかります:
2017100501


nosea を更に展開し、Views の中にある nosea を選択すると、この nosea ビューで選別されたドキュメントデータが一覧できます。想定通りの8つの海無し県が並んでいれば成功です:
2017100502


value の部分が途中で切れてみれなくなっている場合は、その部分にマウスカーソルを置いてみると value の結果がオーバーレイして表示されます。JSON ファイルで指定した通りに3つの値が取得できていることが確認できます:
2017100503


なお、ビューの一覧結果は API からも参照できます:
$ curl -u "username:password" -XGET "https://username.cloudant.com/mydb/_design/nosea/_view/nosea"

{"total_rows":8, "offset":0, "rows":[
 { "id": "aaaa..aaaa", "key": "aaaa..aaaa", "value": { "code":9, "prefecture":"栃木県", "capital": "宇都宮市" } },
 { "id": "bbbb..bbbb", "key": "bbbb..bbbb", "value": { "code":10, "prefecture":"群馬県", "capital": "前橋市" } },
    :
 { "id": "cccc..cccc", "key": "cccc..cccc", "value": { "code":29, "prefecture":"奈良県", "capital": "奈良市" } }
]}


今回は Cloudant の View Design Document を使うことで特定条件を満たすドキュメントデータだけを選別してビューにする例を紹介しました。このようなドキュメント集合体の定義が1つのドキュメントデータとしてデータベース内に格納される、という所が Cloudant のユニークな点であると同時に、その集合体が「ビュー」と呼ばれている点などがなんとなくノーツっぽい※ところもあって、個人的には親和性を感じます。

※ちなみに Cloudant のベースとなっている CouchDB を開発した Damien Katz さんは元 Lotus のエンジニアです。
https://www.linkedin.com/in/damienkatz/


なお、次回は今回紹介した View Design Document を使って定義したビューを「どのような UI で見せるか」という情報を定義するための List Design Document を紹介する予定です。

このページのトップヘ