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

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

タグ:bluemix

NoSQL な DBaaS である IBM Cloudant を使うようになり、単に「管理/環境構築の手間がない」とか「クラスタリングされてる」という以上に便利な機能がいくつもあることが分かってきました。そのいくつかを実際のサンプルを使って動かす形で紹介しようと思います。今回はいわゆる「バルクインサート」の API で、複数のドキュメントを1回の API でまとめて作成する方法です。


以下の内容を読み進めるにあたり、「実際に自分でも試してみたい」という人は是非 IBM Cloudant のアカウントを取得して、サービスインスタンスを作って動かしてみてください。まだ環境をお持ちでない場合、IBM Bluemix のアカウントを登録して、"Cloudant NoSQL DB" を選択してサービスを作成してください。加えて API の実行には curl コマンドを使うので、curl の実行環境を用意してください(Windows であればこちら、他はおそらく標準のはず):
2017100401


サービス作成の際に利用プランを選択します。1GB かつ 30 日利用がないと削除されるという条件であれば無料の Lite プランを選択することも可能です。利用用途や目的に合わせて選択してください:
2017100402


IBM Cloudant のサービスインスタンスを作成したら(或いは既にお持ちであれば)、作成済みのサービスインスタンスの「サービス接続情報」から「資格情報の表示」を選択して、IBM Cloudant に接続するための情報を確認します。具体的にはここで表示される username と password の値を後で利用することになるので、メモしておいてください:
2017100403


また(今回はあまり使いませんが)IBM Cloudant はウェブのダッシュボード機能があり、データを確認したり、一部の操作をこのダッシュボードから行ったりすることができます。ダッシュボードにアクセスするにはサービスインスタンスの「管理」から「LAUNCH」ボタンをクリックすることで移行できます(或いは上記の「資格情報の表示」の中に表示されている "url" の値をウェブブラウザで指定して開きます。この場合はユーザー名とパスワードを聞かれるので、上記でメモした username と password を指定して開きます):
2017100404


IBM Cloudant のダッシュボード画面です。左ペインの上から2つ目がデータベース一覧タブになっており、ここから現在作成済みのデータベースを一覧できます(下図ではまだ1つもありません)。この後の作業用に1つデータベースを作っておきます。画面右上の「Create Database」をクリックします:
2017100405


適当な名前(以下例では "mydb")を入力して「Create」ボタンをクリックします:
2017100406


指定した名前(mydb)のデータベースができました。この時点ではまだ1つもドキュメント(データ)が入っていないので空の状態です。再度画面左のデータベースアイコンをクリックして、データベース一覧に戻ります:
2017100407


先程の画面に戻りました。mydb というデータベースが追加されて、現在のサイズやデータ数(# of Docs)などが確認できる状態になっています:
2017100408


ではこのデータベースに対して、バルクインサート API を実行してみます。まずはインサートするドキュメントデータのサンプル(prefs.json)をここからダウンロードします:
https://raw.githubusercontent.com/dotnsf/samples/master/prefs.json


prefs.json の内容は以下のようになっています。"docs" 内に日本の47都道府県のコード(code)と名前(prefecture)、都道府県庁所在地名(capital)、そしてその緯度(lat)経度(lng)が JSON オブジェクトで定義されており、その配列を docs としています:
{
  "docs": [
    { "code": 1, "prefecture": "北海道", "capital": "札幌市", "lat": 43.06417, "lng": 141.34694 },
    { "code": 2, "prefecture": "青森県", "capital": "青森市", "lat": 40.82444, "lng": 140.74 },
    { "code": 3, "prefecture": "岩手県", "capital": "盛岡市", "lat": 39.70361, "lng": 141.1525 },
       :
    { "code": 46, "prefecture": "鹿児島県", "capital": "鹿児島市", "lat": 31.56028, "lng": 130.55806 },
    { "code": 47, "prefecture": "沖縄県", "capital": "那覇市", "lat": 26.2125, "lng": 127.68111 }
  ]
}

これが Cloudant のバルクインサート API で使う場合のデータフォーマットになります。挿入したい複数のドキュメントデータを { "docs": [ .. ] } という形式で、"docs" の配列として定義します。

ではこのドキュメントデータ(prefs.json)を上記で作成した mydb データベースにまとめて格納します。curl を使って以下のように実行します:
$ curl -u "username:password" -XPOST "https://username.cloudant.com/mydb/_bulk_docs" -H "Content-Type: application/json" -d @prefs.json

※↑青字usernamepassword の部分には IBM Cloudant の資格情報で確認した値をそのまま指定します。またデータファイル prefs.json はコマンド実行時のカレントディレクトリに存在しているものとします。


コマンド実行後にダッシュボード画面を(リロードして)確認すると、mydb データベースに 47 件の(47都道府県の)ドキュメントデータが格納されていることが分かります。詳しく見るために mydb を選択します:
2017100401


先程は空だった mydb に 47 件のドキュメントデータが格納されていることが確認できます。個々のドキュメントデータの中身はこの(デフォルトの "Metadata" の)画面だとわかりにくいので、表示形式を "Table" か "JSON" に切り替えてみます(ここでは JSON を選択します):
2017100402


ドキュメントデータが JSON フォーマットで、実際に格納した中身(doc)まで含めて表示されます。画面では北海道の1ドキュメントデータしか表示されていませんが、下にスクロールすると他のドキュメントデータも確認することができます:
2017100403


なお、データベースのドキュメントデータ一覧は curl で以下のコマンドを実行した結果でも確認することができます:
$ curl -u "username:password" -XGET "https://username.cloudant.com/mydb/_all_docs?include_docs=true"

include_docs=true のパラメータを付けて実行すると doc の中身まで、付けずに実行すると id と key の一覧のみ取得します。


今回は1回の API 実行で複数のドキュメントデータをまとめて Cloudant に格納するバルクインサート API を紹介しました。バルクインサート自体は必ずしも Cloudant の特徴というわけではなく、他のデータベースシステムにも存在している機能だと思いますが、今後 Cloudant の特徴でもある Design Document API を紹介していくつもりで、その時には今回作成した都道府県データを使ったサンプルを紹介する予定です。


なお、IBM Cloudant の REST API リフェレンスはこちらを参照ください:
https://console.bluemix.net/docs/services/Cloudant/api/http.html
 

最近メインの業務が変わって、ずっと勉強モードだったこともあってブログの更新が滞ってました。やっと心に余裕がでてきたので、しばらくシリーズで(比較的簡単な)エントリを続けてみようと思います。

というわけで、今回紹介するのは「Node-RED で REST API を作る」というものです。Node-RED をある程度使っている人ならば「何それ簡単じゃん」と思う程度のことですが、今後引き続いて紹介しようと思ってる内容の導入部分として読んでいただければと。

まず最近話題(になってると感じる)の Node-RED はビジュアルフローエディタです:
2017090801


「ノード」と呼ばれる組み合わせ可能なブロックを順番に配置/接続して、データのフローを定義し、実行します。一通りの作業をブラウザ上の GUI で行うことができる手軽さとわかりやすさが素晴らしいと思っています。Node-RED はラズベリーパイの標準 OS である Raspbian OS にも標準搭載されていますが、IBM Bluemix 環境を使ってすぐにクラウド上の環境を用意することもできます(以下は Bluemix 環境前提で紹介します):
2017090802


Node-RED は基本的に GUI でデータのフローを定義するものであって、ここで作ったものの動きをそのまま視覚化できるわけではありません。ただノードの中にはデータを受け取って HTML ベースのダッシュボードを作るようなものがあったり、HTTP のリクエスト/レスポンスのノードも用意されているので、データを HTML で出力する(そしてそれをブラウザで表示する)といった応用もすぐにできます。今回はこの HTTP リクエスト/レスポンスノードを使って REST API を作ってみます。

Node-RED 画面左のキャンバス部分から、ノードパレットから HTTP リクエストfunctionHTTP レスポンスノードを1つずつドラッグ&ドロップでキャンバスに配置します。この時点でこのような画面になります:
2017090803


これら3つのノードの左右の端をドラッグ&ドロップして以下のように接続します。Node-RED ではデータは左から右に向かって流れていきます。つまりこの場合だと「HTTP リクエスト → function → HTTP レスポンス」という順にデータが送られていくようなフローができました:
2017090804


配置した3つのノードそれぞれの属性を(ダブルクリックして)変更してみましょう。まずは HTTP リクエストノードです。ここは「どのような HTTP リクエストに対して反応するか」を属性で指定します。今回は GET /getDate という日付時刻を返す REST API を作ってみましょう。メソッドは GET 、そして URL には /getDate を指定します。これでこのサーバー上の /getDate に対して GET リクエストが送られてきた場合にこのノードから始まる一連のフローの実行が開始するようになります。編集が終わったら右上の「完了」ボタンをクリックします:
2017090805



なお GET リクエストの場合、URL パラメータで指定された値は msg.req.query 内に格納されます。例えば /getDate?a=x&b=y というリクエストを処理した場合には msg.req.query.a = x, msg.req.query.b = y という値が格納された状態で次のノードが実行されます(といったような情報が画面右の「情報」タブに表示されます。キャンバスで選択中のノードに関する説明はここから参照できます):
2017090801


その次のノードである function ノードは JavaScript を記述することができます。ある意味でビジュアルフローっぽくないというか、一般的なプログラミングに近い処理を行うノードです。今回はこのノードを使って API として返す値(今回の例であれば日付時刻)を生成します。以下のような内容に書き換えます(緑文字部分は処理に関係のないコメントなので不要です):
var dt = new Date();  //. 現在時刻
if( msg.req.query.timestamp ){
  //. timestamp パラメータが指定されていた場合は、そのタイムスタンプの時刻に設定する
  dt.setTime( msg.req.query.timestamp );
}
msg.payload = dt;   //. ペイロードに時刻文字列を設定
return msg;

2017090806




今回作成する API は時刻の文字列を返すようにしました。特にパラメータ指定なしで実行した場合は現在時刻を、timestamp というパラメータが指定された場合はその値をタイムスタンプ値(1970年1月1日午前0時からの経過ミリ秒)と見なして、その日時の時刻を返すようにしています。


そして最後に HTTP レスポンスノードの属性を設定します。普通に動かすだけであれば何も設定しなくても(このままでも)動きます。が、今回は後でこの API を外部の JavaScript からも呼び出せるような設定を加えます(外部からの呼び出しを許可するため、HTTP レスポンスヘッダにクロスオリジンを許可する項目を加えます。詳しくはこちらを参照)。HTTP レスポンスノードのヘッダに Access-Control-Allow-Origin という項目を追加し、その値を * に指定します:
2017090807


これでこの HTTP リクエストは、外部のサーバーから AJAX などで呼び出しても利用できるようになりました。


こうして Node-RED 上に作成したフローを画面右上のボタンから「デプロイ」します:
2017090808


デプロイが成功することを確認します:
2017090802


デプロイが成功したら、ウェブブラウザで http(s)://(Node-RED の動いているサーバー)/getDate にアクセスしてみます。画面に現在時刻が表示されれば成功です(実際には Node-RED が稼働している環境の言語設定などに依存するので日本時間で表示されたり、外国の時間で表示されたりしますが、同じユニバーサル時刻が表示されるはずです。下図では GMT 時間で表示されています):
2017090803


今度は timestamp パラメータを指定して、 http(s)://(Node-RED の動いているサーバー)/getDate?timestamp=1 にアクセスしてみます。これは 1970/01/01 00:00:00 から1ミリ秒経過したタイミングを指定しているので、このような表示になるはずです:
2017090804


と、まずは単純な GET アクセスだけの API を1つだけ作ってみました。Node-RED を使うと最小で3つのノードを組み合わせるだけで簡単に作れることが分かりました。同様にして POST メソッドに対応させたりすることもできますので、興味ある方はチャレンジしてみてください。


なお、Node-RED に関しては最近たて続けに日本語書籍が発表されています。Node-RED そのものに関する情報はこれらの書籍も参考にしてください(↓アマゾンへのリンクです):




 

自分はラズパイ(Raspberry Pi 3B)をリモートの開発環境として使っています。自宅内ネットワークで常時起動させ、OpenVPN 経由で外からもアクセスできるようにしています。その辺りの設定についてはこちらを参照してください:
OpenVPN でローカル(自宅)ネットワークに VPN 接続する


そんなラズパイに各種開発環境やら docker やら TensorFlow やら、、を導入しています。これで外からも利用できる開発環境を構築しています:
http://dotnsf.blog.jp/tag/raspberrypi


さて、コーディングして動かすところまではこういったツールだけで問題ないのですが、1点だけ不便に感じる点がありました。それが「cf ツール」です。作ったアプリケーションを IBM Bluemix (Cloud Foundry) 環境上にデプロイする際に使うツールなのですが、公式にはラズパイ用のバイナリは提供されていません。なのでラズパイで開発して、動かして、テスト&デバッグして、、というところまではこの環境でできるのですが、作ったアプリを IBM Bluemix 上で動かす、という最後のステップの際に別の(cf ツールの導入された)環境に切り替えて行う、というちと面倒な手順をとる必要がありました:
Releases cloudfoundry/cli

2017080601


これをラズパイ環境のままで行えるようにする、というのが今回の目的です。実はこれまでにも IBM LinuxONE 環境などで同様の経験はしていて、その時は自分でソースからビルドして対応したりしていました:
IBM LinuxONE コミュニティクラウド上で cf コマンドを動かす

2017080602
(↑メインフレーム上で cf を動かしたのは、もしかすると世界中で自分だけかも・・)


で、同様の問題がラズパイで発生しているということです。というわけで、ラズパイ環境でも同様に cf ツールをビルドしてみました。以下はその手順紹介ですが、基本的には上記の LinuxONE 環境と同じことをしています。

まず cf ツールは go 言語で書かれているため、ビルドには go 言語が必要です。ラズパイ用の go 言語導入については以下を参照して、go 言語が動く環境を作っておいてください:
ラズパイに go 1.8 をインストールする

go 言語が動くようになったら次はソースコードの入手です。以下のコマンドを実行します:
$ go get code.cloudfoundry.org/cli

これで $GOPATH/src/code.cloudfoundry.org/cli 以下にソースコードが展開されます。これをビルドします:
$ cd $GOPATH/src/code.cloudfoundry.org/cli
$ bin/build

ビルドが成功すると $GOPATH/src/code.cloudfoundry.org/cli/out/ 以下に cf コマンドが生成されます。試しに動くかテストしてみます:
$ cd $GOPATH/src/code.cloudfoundry.org/cli/out
$ ./cf -v
cf version 6.29.0+35e54cd.2017-08-06

バージョン番号が表示され、ちゃんと動くことが確認できました。後はこのコマンドを PATH の通った所に移動すれば完成です。
$ sudo mv $GOPATH/src/code.cloudfoundry.org/cli/out/cf /usr/local/bin
$ sudo chown root.staff /usr/local/bin/cf


なお、このラズパイ版の cf コマンドについては困っていた方が他にもいたようで、たまに有志でビルドされたものが見つかります。僕が動作確認しているわけではないし、動作保証もできないのですが、こういった所から入手して使うという手段もありそうです:

https://github.com/mmb/cf-cli-pi
https://cf-cli-pi.s3.amazonaws.com/index.html


最近、従来種ではなかったはずの猛毒アリである「火蟻(ヒアリ)」が日本で見つかった、というニュースを耳にします:
ヒアリ、東京で発見 ついに関東上陸 大井埠頭のコンテナから


外来種かつ毒虫という特徴から、素手で捕まえたり、触ったりするのが非常に危険なアリです。とはいえ、この季節は普通のアリを見かけることも多いので、ヒアリかどうかを判断するのが難しい問題もあります。

さて、最近話題の画像認識を使って蟻の画像を識別させて、「それがヒアリかどうか?」を判断することはできるでしょうか? IBM WatsonVisual Recognition API を使って試してみました。

当初は「まずはヒアリを学習させて・・・」と思っていたのですが、調べてみたら IBM Watson の Visual Recognition V3 では標準機能でヒアリを識別する機能を持っているようでした(これに気付いた時はちと驚きました)。というわけで普通に公開されているデモ用ページを使い、カスタマイズなしの標準機能だけで試してみました。
Visual Recognition Demo

2017070701


標準機能で画像認識を試す場合は、ブラウザで上記ページにアクセスして、赤枠部分をクリックし識別させたい画像を PC 内から指定するだけです。非常に簡単です。


今回、まずはこのヒアリの画像を指定してみました:
fire1


しばらく考えて・・・
2017070702


はい、結果がでました!"pharaoh ant"(ファラオ蟻、何それ?)とかに混じって "fire ant"(ヒアリ)という識別結果が表示されています!検索スコアも 0.80 と中々高い結果になっています(赤枠部分参照):
2017070703


では次はこの「黒蟻」の画像を指定してみます:

kuro1


結果はこうでした。"carpenter ant" は日本では「黒蟻」と呼ばれているものです(ちなみに "sanguinary ant" は「銀蟻」です)。そして "fire ant" とは識別されませんでした。これも正解です:
2017070704


いくつかの画像で試してみたので、その結果を表にしておきます:
画像正解識別結果スコア成否
 fire1
ヒアリファラオ蟻
ヒアリ

銀蟻
0.81
0.80
0.60
 fire2
ヒアリヒアリ0.60
 fire3
ヒアリヒアリ
軍隊アリ
0.83
0.50
 kuro1
黒蟻黒蟻
銀蟻
0.81
0.50
 kuro2
黒蟻黒蟻0.93
 gin1
銀蟻銀蟻0.51
 gin2
銀蟻銀蟻
黒蟻
0.64
0.60


おおーっ! 適当に集めた画像で試してみただけですが、それなりの精度で検索できているように思えます。 カスタマイズなしの標準機能だけでもいい感じでした。ぶっちゃけ想定以上です(笑)。


皆さんもアリ画像を使って上記サイトで色々試してみてください。なかなかの精度で調べてくれそうですよ。

#最初は学習させるつもりで蟻の画像を大量に集めて見ていたので、気持ち悪くなってきた・・・

IBM Bluemix からも提供されている IBM の DBaaS サービスである dashDB に Node.js からアクセスする方法を紹介します。実際には dashDB だけでなく、DB2 のサービスやオンプレミスデータベースへも同様に応用できますが、今回は Bluemix 上の DB2/dashDB 関連サービスを例に紹介します:
2017063002


dashDB は行指向/列指向型のテーブルをどちらも作成することができるリレーショナル・データベースのサービスですが、そのデータベースシステムとしての実体は IBM DB2 です。というわけで、このライブラリを使ってアクセスします:
https://www.npmjs.com/package/ibm_db

2017063001


まず以下のコマンドを実行して ibm_db をインストールします(このコマンドだけで DB2 ODBC Driver ごとインストールされます):
$ npm install ibm_db


そして以下のようなコードを用意して dashDB にアクセスします:

(settings.js)
exports.db_host = 'dashdb-entry-yp-XXXXXXXX.services.dal.bluemix.net';
exports.db_port = 50000;
exports.db_name = 'BLUDB';
exports.db_username = 'dashNNNN';
exports.db_password = 'PASSWORD';

(sample.js)
var ibm_db = require( 'ibm_db' );
var settings = require( './settings' );

var db_str = "DATABASE=" + settings.db_name
  + ";HOSTNAME=" + settings.db_host
  + ";UID=" + settings.db_username
  + ";PWD=" + settings.db_password
  + ";PORT=" + settings.db_port
  + ";PROTOCOL=TCPIP";
var sql = "select OBJECTID, NAME from SAMPLES.GEO_CUSTOMER limit 10";

ibm_db.open( db_str, function( err, conn ){
  if( err ) return console.log( err );

  conn.query( sql, function( err, data ){
    if( err ) console.log( err );
    else console.log( data );

    conn.close( function(){
      console.log( 'done.' );
    });
  });
});

settings.js の中身はユーザー名やパスワードといった dashDB に接続するためのサービス資格情報です。IBM Bluemix の画面から取得できる値を使って、実際の値で書き換えて使ってください:

2017063003


アプリケーションの実体は sample.js です。今回の例ではシンプルに接続して、サンプルデータとして GEO_CUSTOMER テーブルから OBJECTID と NAME の値を 10 件だけ取得する、という SQL (青字部分)を実行しました。また settings.js で定義した情報を取り出して接続文字列(赤字部分)を生成しています。

node コマンドで sample.js を実行して、以下のような結果が表示されれば成功です:
$ node sample.js
[ { OBJECTID: 1322, NAME: 'Kami Labarbera' },
  { OBJECTID: 1323, NAME: 'Johnathon Tunney' },
     :
  { OBJECTID: 1587, NAME: 'Althea Alcazar' } ]
done.







 

このページのトップヘ