Cloudant – Bluemix で作る Node.jsで動く クラウダント・サンプル

Bluemix のクラウド上で、代表的な NoSQLデータベースの Cloudant を使う簡単な Node.js の サンプルを作ってみましょう。まだの人はまず以下で Bluemix環境と Node.js アプリを準備してください。

⇒ Bluemixで作る Node.jsで動く 簡単サンプル

Cloudantの準備

ここではまず、Bluemix にCloudantのデータベースを用意します。ダッシュボードの以下の画面から、[+ サービスまたはAPIの追加] をクリックしてください。

1.BMSample

画面を下にスクロールして、[データおよび分析] から [Cloudant NoSQL DB] をクリック。

1.Cloudant サービス

月平均20GBの無料枠などを確認して、[作成] をクリックして作成します。[再ステージ] をクリックすると、環境を立ち上げ直して、少しすると [アプリは稼動しています] になり稼動開始します。[概要] に戻り追加された以下の Cloudantをクリックしてセットアップします。

1.Cloudant追加

以下の右上の [Launch] (起動)をクリックして Cloudantの設定画面に。

1.Cloudant起動

以下の設定画面で右上の [Create Database] をクリックし、以下の例(cldb)のようにデータベース名を半角の英小文字や数字で入力します。(全角にならないように注意)

2.CloudantCreate

次にその cldb でデータを見つける(検索する)ための索引(キーのIndex)を作成。[All Design Docs +] で、[New Search Index] をクリックすることで索引を追加できます。

2.CloudantIndex

右に入力画面が表示されたら、以下のように [_design] に 「items」、[index name] に 「items_index」 とします。ここでは、キーを日付の「date」にしましょう。[Search Index Function] を以下のようにname 二箇所を 「date」 に変更し、[Save & Build Index] をクリックします。これで 「date」 をこキーにしての検索が可能になります。

2.CloudantIndexName

次にその cldb で検索するためのビュー(取得する項目の定義)を作成。[All Design Docs +] で、[New View] をクリックすることでビューを追加できます。

2.CloudantView

以下のように既に作った 「items」 に対して、Index name 「items_view」 を追加し、その Map function (返す列のオブジェクト)を以下のように記述し [Save & Build Index] で保存してください。

2.CloudantViewDefinition

 

function(doc) {
 var row = { id: doc._id,
 date: doc.date,
 item1: doc.item1 };
 emit(doc._id, row);
}

これで、これらの索引(Index)やビューで検索可能になります。

プログラムのCloudant対応

ダッシュボードに戻って [コードの編集] (EDIT CODE) の左のファイルから 「package.json」を選択し、以下のように変更。Cloudant にアクセスするために、Cloudantと互換性のある CouchDB 用のアクセス・モジュールである 「cradle」 を追加しています。(ここに記入することでBluemix上では自動的にモジュールがダウンロードされ組み込まれます)

{
 "name": "NodejsStarterApp",
 "version": "0.0.1",
 "description": "A sample nodejs app for Bluemix",
 "scripts": {
 "start": "node app.js"
 },
 "dependencies": {
 "express": "4.12.x",
 "cfenv": "1.0.x",
 "body-parser": "*",
 "date-utils": "*",
 "cradle": "0.6.x"
 },
 "repository": {},
 "engines": {
 "node": "0.12.x"
 } 
}

次に、Node.jsサーバー・アプリの、「app.js」 を以下のように変更します。。[/***ここから追加***/] のところからが、初期のサンプル・コードに対して追加した部分です。その中の青字の部分は、このページの最初のリンク先の前サンプル・アプリケーションに対して追加した部分です。Cloudantへのアクセス・モジュールである、「cradle」 を組み込み、Cloudantへの接続情報である、‘cloudantNoSQLDB’ の credentials を環境変数より取得します(後述)。
cradle.Connection を new してDBへの接続を確立し、db.save でデータ追加、db.view で全件表示、db.remove で全件削除します。

// This application uses express as its web server
// for more info, see: http://expressjs.com
var express = require('express');

// cfenv provides access to your Cloud Foundry environment
// for more info, see: https://www.npmjs.com/package/cfenv
var cfenv = require('cfenv');

// create a new express server
var app = express();

// serve the files out of ./public as our main files
app.use(express.static(__dirname + '/public'));

// get the app environment from Cloud Foundry
var appEnv = cfenv.getAppEnv();

/***ここから追加***/
// POSTパラメータ取得用 body-parser設定 (express4から必要)
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

// Date()で現在時刻を取得するためのユーティリティ
var dateutil = require('date-utils');

// Cloudant用アクセス・モジュール「cradle」設定
var cradle = require('cradle');

// Cloudant DB接続情報取得
var services = JSON.parse(process.env.VCAP_SERVICES);
var credentials = services['cloudantNoSQLDB'][0].credentials;
var host = credentials.host;
var port = credentials.port;
var options = {
 cache : true,
 raw : false,
 secure : true,
 auth : {
 username : credentials.username,
 password : credentials.password
 }
};

// データベース接続
var db = new (cradle.Connection)(host, port, options).database('cldb');
 
app.post('/', function(req, res){
 var date = new Date();
 var now = date.toFormat("YYYY/MM/DD HH24:MI:SS");
 req.body.date = now;

 // 項目の保存
 db.save(now, req.body);
  res.send(req.body);
});

//「全件削除」ボタンの id=removeAll, ui_item.jsの url:'/removeAll'でcall
app.post('/removeAll', function(req, res){

 // 全件検索を、作成したview名 items_view にて実行
 db.view('items/items_view', function (err, rows) {
 if (!err) {
 rows.forEach(function (id, row) {
 db.remove(id);
 console.log("removed key is: %s", id);
 });
 } else { console.log("app.js db.remove error: " + err); }

 });

 res.send({});
});


//「全件表示」ボタンの id=getAll, ui_item.jsの url:'/getAll'でcall
app.post('/getAll', function(req, res){
 returnTable(res);
});

var returnTable = function(res) {
 // 全件検索を、作成したview名 items_view にて実行
 db.view('items/items_view', function (err, rows) {
 if (!err) {
 rows.forEach(function (id, row) {
 console.log("key: %s, row: %s", id, JSON.stringify(row));
 });
 } else { console.log("app.js returnTable error: " + err); }

 res.send(rows);
 });
}
/***ここまで追加***/

// start server on the specified port and binding host
app.listen(appEnv.port, '0.0.0.0', function() {

 // print a message when the server starts listening
 console.log("server starting on " + appEnv.url);
});

画面の機能追加

画面 「index.html」 は以下のように変更し、「全件表示 (getAll)」 や 「全件削除 (removeAll)」 のボタンを加えます。index.html はシンプルなままにしておきました。

<!DOCTYPE html>
<html>

 <head>
 <title>NodeJS Starter Application</title>
 <meta charset="utf-8">
 <!--ここから追加-->
 <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
 <script type="text/javascript" src="js/ui_table.js"></script>
 <!--ここまで追加-->
 </head>

 <body>
 <!--ここから追加-->
 <table id="dataTable" border="1">
 <thead>
 <tr><th>時間</th><th>項目</th></tr>
 </thead>
 <tbody id='tableItems'></tbody>
 </table><br><br>

 <div id="form">
 <br>
 <button value="全件表示" id="getAll"> 全件表示 </button>
 <button value="全件削除" id="removeAll"> 全件削除 </button>
 <br><br>
 <span>項目名: </span><span><input type="text" id="item1"></span><br>
 <button value="追加" id="add">追加</button>
 </div>
 <!--ここまで追加-->
 </body>

</html>

[public] [js] フォルダの下にブラウザ側 JavaScript として作成した、「ui_table.js」は以下のように、$.ajax のサーバー呼び出しに、追加の「/add」、全件表示の「/getAll」、全件削除の「/removeAll」 の3つの機能を追加しました。
いずれも、画面上部の表 「#tableItems」 に結果を表示するようになっています。

// ui_table.js ブラウザUI用 JavaScript (index.htmlより呼ばれる)

 $(function(){
 console.log('ui_item.js in');

 // サーバから取得したデータを、htmlテーブルに追加
 var showTable = function(data) {
 $("#tableItems").append("<tr></tr>")
 .find("tr:last")
 .append("<td>" + data.date + "</td>")
 .append("<td>" + data.item1 + "</td>")
 };

 // 追加ボタン(index.htmlのid=add)押下時 実行
 $("#add").click(function(e){ e.preventDefault();
 var param = {};
 param.item1 = $("#item1").val() || "";

 // POSTでのajaxコールで、サーバーのapp.jsのapp.post /add呼び出し
 $.ajax({
 type: 'POST',
 data: JSON.stringify(param),
 contentType: 'application/json',
 url: '/',
 success: function(data) {
 console.log('success add: ' + JSON.stringify(data));
 showTable(data);
 },
 error: function(data) { console.log('error add: ' + JSON.stringify(data)); }
 });

 // 入力項目名を空白に
 $("#item1").val('');
 });

 // 全件表示ボタン(index.htmlのid=getAll)押下時 実行
 $("#getAll").click(function(e){ e.preventDefault();
 $("#tableItems").empty();

 // POSTでのajaxコールで、サーバーのapp.jsのapp.post /getAll呼び出し
 $.ajax({
 type: 'POST',
 data: {},
 contentType: 'application/json',
 url: '/getAll',
 success: function(rows) {
 for(var i=0; i<rows.length; i++) {
 console.log(' row '+ i +": "+ JSON.stringify(rows[i]));
 showTable(rows[i].value);

 }
 },
 error: function(data) { console.log('error getAll: ' + JSON.stringify(data)); }
 });
 });

 // 全件削除ボタン(index.htmlのid=removeAll)押下時 実行
 $("#removeAll").click(function(e){ e.preventDefault();

 // POSTでのajaxコールで、サーバーのapp.jsのapp.post呼び出し
 $.ajax({
 type: 'POST',
 data: {},
 contentType: 'application/json',
 url: '/removeAll',
 success: function(data) { console.log('success removeAll'); },
 error: function(data) { console.log('error getAll: ' + JSON.stringify(data)); }
 });

 $("#tableItems").empty();
 });
 });

稼動確認

一通りのコードが完成しましたので、以下の「デプロイ」ボタン 3.bm_deployB をクリックして、サーバーで稼動させます。

3.bm_deploy

次に 「アプリケーションを開く」 ボタン 3.bm_appliB をクリックして、Web画面を表示してください。以下の画面が開きますので、項目名に文字を入れて追加すると、Node.js の app.js にアクセスし日時を取得した上で、以下のように上の表に動的に追加されます。

2.CloudantUI

全件を表示し直したり、全件のデータを削除するボタンも使えます。

 

⇒次は、Eclipseと連携して Bluemix開発する方法

 

 

nikami.org – デジタル時代の自分デジタル化の軌跡