ブラウザ から Ajaxで送ったデータを、Node.js 経由で代表的な NoSQLデータベースの一つである Cloudant に格納する簡単サンプルです。
=> まだの方はこの前回のサンプルを見て、まず Node.jsで Ajaxと連携するアプリを作ってください。
Node.jsアプリの Cloudant 対応
前回のサンプルを手順どおり Bluemix 上で稼動させ、ブラウザで名称を入力して 「追加」 ボタンを押すと、上の表に名称がリストされます。しかし、他のブラウザで同様に画面を表示してもそのリストは表示されません。また、サーバーを立ち上げ直すと、その入力データは消えてしまいます。これは、ブラウザ上にデータを保持しているだけで、サーバー側のデータベース (DB) に保存していないためです。
そこで今回は、前回のサンプルに手を加え、「追加」 したらJSONをそのまま Cloudant の DB に保管し、DBの中身を 「全件表示」 したり、「全件削除」 したりできるように機能追加してみましょう。追加した結果は、以下のような画面になります。
最初に、Node.js のサーバー側 JavaScriptアプリケーションである 「app.js」 に手を加えて、Cloudant DBにデータを格納するよう機能追加します。
そのために以下のように、Cloudant のベースとなっている、CouchDB 用のアクセス・モジュールである、「cradle」 を以下のように 「package.json」 に追加し、[実行] [npm install] で導入します。
{ "name": "Nodejs_Start", "version": "1.0.0", "description": "Sample nodejs + ajax app for Bluemix", "scripts": { "start": "node app.js" }, "dependencies": { "express": "4.12.x", "body-parser": "*", "date-utils": "*", "cradle": "0.6.x" }, "repository": {} }
次に、Node.jsサーバー・アプリの、「app.js」 を以下のように変更します。
Cloudantへのアクセス・モジュールである、「cradle」 を組み込み、Cloudantへの接続情報である、‘cloudantNoSQLDB’ の credentials を環境変数より取得します(後述)。
cradle.Connection を new してDBへの接続を確立し、db.save でデータ追加、db.view で全件表示、db.remove で全件削除します。
// expressアプリ・フレームワークの設定
var express = require('express');
var app = express();
// POSTパラメータ取得用 body-parser設定 (express4からurlencoded()とjson()必要)
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// index.htmlの /public ディレクトリ設定
app.use(express.static(__dirname + '/public'));
// 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('itemsdb');
// 「追加」ボタンの id=add, ui_item.jsの url:'/add'でcall
app.post('/add', 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);
console.log('app.js saved: ' + JSON.stringify(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);
});
};
//環境変数にポート番号が無ければ、port=3000 設定
var port = (process.env.VCAP_APP_PORT || 3000);
// サーバー開始
app.listen(port);
console.log('App started on port ' + port);
Bluemix上の Cloudantの設定
次に、=>リンク先のBluemixにログイン し、ダッシュボード画面からCloudant DBの設定を行います。対象のアプリケーションの画面(このサンプルでは「BMSampleC」)で以下の画面で、[Cloudant NoSQL DB] をクリックしてください。
すると Cloudant の初期画面が表示されるため、下の右にある、[起動] アイコンをクリックして Cloudant のコンソール(操作画面)を起動してください。(うまく起動しない場合はしばらくして再実行)
すると、以下のような Cloudant コンソールが表示されるはずです。ここで右上の [Add New Database] をクリックし、新しいデータベース名 「itemsdb」 を入力して、[Create] をクリックしデータベースを作成します。
次にそのitemsdbで検索するための索引(キーのIndex)を作成します。[All Design Docs +] で、[New Search Index] をクリックすることで索引を追加できます。
右に入力画面が表示されたら、以下のように [_design] に 「items」。[index name] に 「items_index」 とします。ここでは、キーを日付の「date」にしましょう。[Search Index Function] を以下のように 「date」 に変更し、[Save & Build Index] をクリックします。これで 「date」 をこキーにしての検索が可能になります。
次にそのitemsdbで検索するためのビュー(返す列を決められる)を作成します。[All Design Docs +] で、[New View] をクリックすることでビューを追加できます。
以下のように既に作った 「_design/items」 に対して、Index name 「items_view」 を追加し、その Map function (返す列のオブジェクト)を以下のように記述し [Save & Build Index] で保存してください。
function(doc) {
var row = { id: doc._id,
date: doc.date,
item1: doc.item1 };
emit(doc._id, row);
}
これで、これらの索引(Index)やビューで検索可能になります。
Bluemixの Cloudant用環境変数の変更
メニューの [ダッシュボードに戻る] をクリックし、ダッシュボード(上の最初の画面)に戻り、左のメニューから [環境変数] をクリックすると、環境変数エディターになります。(左にメニューが表示されていない場合は、[ダッシュボードに戻る] の右側の [∧] をクリック)
このエディターに表示されている、「 { 」 から始まるテキストを全てコピーし、テキスト・エディターやメモ帳で、改行を削除して一行の文字列にしてください。
(「 { “cloudantNoSQLDB”: [ { “name”: “Cloudant NoSQL DB-qn”,”label”: “cloudantNoSQLDB”,”plan”: “Shared”,”credentials”: { “username”: ・・・」 となります)
次に、Eclipseの 「app.js」 を右クリックし、[実行] [実行の構成] を選びます。左のリストの中から、「Node Application」 の下の自分のNode.jsプロジェクトの、「-app.js」 が付いているものを選んでください。右にダイアログが出ますので、[環境] タブを選び [新規] ボタンを押してください。
そこの [名前] に 「VCAP_SERVICES」 を入力し、下の [値] に、先ほどの一行にした文字列 「 { “cloudantNoSQLDB”: [ { “name”: “Cloudant NoSQL DB-qn”, ・・・」 をコピーしてください。
これで、ローカルでもBluemixのクラウド上でも、同じ Cloudantアクセス用環境変数を取得できるようになりました。
画面の機能追加
画面 「index.html」 は以下のように変更し、「全件表示 (getAll)」 や 「全件削除 (removeAll)」 のボタンを加えます。index.html はシンプルなままにしておきました。
<html>
<head>
<title>Node.js Ajax Cloudant Sample</title>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="js/ui_item.js"></script>
</head>
<body>
<table id="dataTable" border="1">
<thead>
<tr>
<th>時間</th><th>項目</th>
</tr>
</thead>
<tbody id='tableItems'></tbody>
</table><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>
<button value="追加" id="add"> 追加 </button>
<br>
</div>
</body>
</html>
ブラウザ側 JavaScript として作成した、「ui_item.js」は以下のように、$.ajax のサーバー呼び出しに、追加の「/add」、全件表示の「/getAll」、全件削除の「/removeAll」 の3つの機能を追加しました。
いずれも、画面上部の表 「#tableItems」 に結果を表示するようになっています。
// ui_item.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: '/add',
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();
});
});
前回同様、Eclipseで、「app.js」を右クリックし、[実行] [Node Application] を実行することで、Node.js サーバーを立ち上げて、ブラウザで 「http://localhost:3000/」 をアクセスすると、最初に貼り付けた画面のイメージが表示されるはずです。項目の「追加」や、「全件表示」、「全件削除」ができるはずです。
これらのソースコードは、Eclipseでは以下のような構成になります。