Node-REDでCloudantのWarehouse連携機能を使わず直接Db2 Warehouse on Cloudに書き込みする方法


Bluemix、改め IBM cloudでは、Cloudantから Db2 Warehouse on Cloud(旧dashDB)にデータを連携する機能がありました。

IoTデータのJSONデータを自動的に表形式のRDBに格納してくれるので、便利だったのですが、この機能が2018/4/30にSunsetしてしまうようです。

案内(2018/2/13) → Feature Retirement – IBM Cloudant’s Warehousing feature

「案内」には、代替案リンクがついているのですが、そこに飛ぶと現在の方法しか紹介されていないですね、、

「案内」(Feature Retirement」

  • IBM Cloud has several alternatives to the Warehouse feature. We have documented alternative approaches using Spark SQL, which you can read here .

上記の「here.」から行ける「deprecations」のリストの記載

  • You can find a schedule and alternatives to IBM® Db2® Warehouse on Cloud here.

上記の「here.」から行けるサイトはこちら
Spark SQLの説明はなく、現行機能の説明があるのみです。(2018/3/11時点)

ちなみに IBM cloudで使えるSparkはApache Sparkで、こちらは今のとこ Liteプランで2個無料で使えるようです。
ただ、コーディングが必要で、ちょっと敷居が高いですね。2018/4/30までにできるのかな。

やりたいことは、JSONデータをRDBに保存するだけ なのに、、

というわけで、今現在、上記の機能を使っている人向けに、もっと簡単にデータ書き込みできる方法を紹介します。

前提

  • IBM CloudのNode-RED上で、Cloudantを使っている
  • Cloudantから、Db2 Warehouse on Cloudへの連携機能を使っている
    • なお、この連携機能の新規作成機能は、2018/1/16で止まっています。新しく作ることはできません。
  • Node-REDで、dashDBのノードを使える状態である
    • 最新のNode-RED 0.18.4だと、dashDBのノードがなく、パレットから追加しようとすると失敗します。 (2018/3/11現在) ← 本日実施したら 0.18.4でも追加できました 。(2018/3/23)
    • Node-RED 0.17.xだと、dashDBノードがありませんが、パレットから追加できます。
    • Node-REDのバージョン0.16.xだと、dashDBノードがはじめからついてます。

手順概要

Node-REDとDb2 Warehouse on Cloudを接続し、ノードを2個追加するだけです。
なお、手順の過程で Node-REDが再ステージ(再起動)しますので、フローのバックアップを取得することをおすすめします。

手順詳細

  • 1. IBM Cloudのコンソールで、Node-REDと、Cloudantから自動作成されたDb2 Warehouse on Cloudを接続します。

この手順を行うと、Node-REDを再ステージするよう促されますので、OKします。


  • 2. Node-REDで、下記のfunctionノードを作ります。

ノードの内容


// ノードIDを設定 (複数のノードがある場合ここを固有のIDにする)
var node_id = "abc";


// キー項目にするために現在時刻を取得
var getCurrentTime = function () {
    var date = new Date();
    date.setHours(date.getHours() + 9);
    var d = date.getFullYear() + '-';
    d += ('0' + (date.getMonth() + 1)).slice(-2) + '-';
    d += ('0' + date.getDate()).slice(-2) + 'T';
    d += ('0' + date.getHours()).slice(-2) + ':';
    d += ('0' + date.getMinutes()).slice(-2) + ':';
    d += ('0' + date.getSeconds()).slice(-2) + '.';
    d += ('0' + date.getMilliseconds()).slice(-3) + 'Z';
    return d;
};

//さらにランダムなシードをmax〜minの範囲で取得
var max = 10000;
var min = max/10;
var random_val = Math.floor( Math.random() * (max + 1 - min) ) + min ;

var keyNames = [];
var varNames = [];
for( var a in msg) {
    if (a == "_msgid") continue;    // _msgidは加工しない
    keyNames = keyNames.concat(a.toUpperCase());
    varNames = varNames.concat(msg[a]);
    delete msg[a];  // 既存のenumerableプロパティは削除
}

// キー項目として先程の時刻情報+ランダムシードを入れる
msg.payload =  {
"_ID": getCurrentTime()+"+"+node_id+":"+random_val,
"_REV": 0,
} 

for(var b in keyNames){
  msg.payload[keyNames[b]] = varNames[b];
}


return msg;



- 3. dashDBノードを作成します。


プロパティで、Cloudantから書き出しを行っているDb2 Warehouse on Cloudを選択します。

  • 4. Cloudantに書き込みを行っているノードから、上記のノードの左にリンクをつなぎます。
  • 5. 上記のノードの右から、dashDBのノードにリンクをつなぎます。
  • 6. フローを「デプロイ」します。ここで稼働確認して下さい。
  • 7. 問題なければ、Cloudantのコンソールで、「Analytics」のdashDB連携機能を停止して下さい。

下記の「Action」で「■」を押すと止まります。

以上で完了です。

注意点

  • 上記のコードだと、既存のmsgに格納しているプロパティの内容が「 _msgid」以外すべてmsg.payloadに変換されます。 もし、そのままの形で保存したいプロパティがあれば、「 _msgid」同様に、スキップ(continue)するようにして下さい。
  • Db2 Warehouse on Cloudに存在しない列項目があったり、欠けている列項目があると、データベースInsertが失敗します。
    • 存在しない列項目については、いままではCloudantでRescanすれば復旧できましたが、今後はできなくなります。必要な列項目についてはあらかじめ追加しておいて下さい。
    • 欠けている列項目については、項目名: "" 等と記載して補ってやる必要があります。