これらの記事の続きです(シリーズとしては今回が最終回です):
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 の特徴的な機能をまとめて紹介してみました。