db2chartノードを使ってNode-REDでデータベースのデータをグラフ表示する方法

本記事では、以下のようなテーブルがデータベース上にあったとき、

|name|value|
|---|---|
|Jan|5|
|Feb|6|
|Mar|9|
|Apr|10|

1列目をラベル、2列目を値として以下のようなグラフを[Node-RED](https://nodered.org/ )&reg;で作る方法を紹介します。

![graph](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581362/2163f168-9a77-1bd8-f22a-5c0ba33db624.png)

# データの準備
今回、データベースとしてPostgreSQL&reg;を使いました。

以下のSQLを実行してデータを登録しておきます。
```sql
CREATE TABLE tbl1 (name text, value integer);
INSERT INTO tbl1 VALUES('Jan', 5);
INSERT INTO tbl1 VALUES('Feb', 6);
INSERT INTO tbl1 VALUES('Mar', 9);
INSERT INTO tbl1 VALUES('Apr', 10);
```

# Node-REDの準備
Node-REDのバージョンは3.1.8を使用しました。  
追加ノードとして、以下のノードをインストールしました（カッコ内はバージョン）。

* [node-red-dashboard](https://flows.nodered.org/node/node-red-dashboard) (3.6.5)  
    グラフを作成するためのノード
* [node-red-contrib-postgresql](https://flows.nodered.org/node/node-red-contrib-postgresql) (0.14.0)  
    データベース（PostgreSQL）にアクセスし、データを取得するためのノード
* [@pgspider/node-red-db2chart](https://flows.nodered.org/node/@pgspider/node-red-db2chart) (1.0.1)  
    データを整形するためのノード

右上のメニューから、「パレットの管理」→「ノードを追加」をクリックし、上記のノードをインストールできます。

![add_node](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581362/8aced346-8845-41e5-e3bd-6bb80b6eae5b.png)

# フローの作成
フローのサンプルは[本記事の末尾](#appendix)に記載しておきました。

処理を開始する「inject」ノードを起点に、以下のようにノードを配置します。

![flow](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581362/290be718-bce2-a645-b5d5-072691249801.png)

ここで重要なのが、db2chartノードを使ってpostgresqlノードの出力データのフォーマットを変換してやることです。

以下の図のように、postgresqlノードを直接chartノードに接続してしまうと、postgresqlノードの出力がchartノードが期待するフォーマットではないためエラーになってしまいます。
![error](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581362/718c3e76-1d2f-c9b2-212e-614df042b76a.png)

## postgresqlノードの設定

今回実行したSQLは「SELECT name, value FROM tbl1」です。1列目がデータラベル列、2列目が値列となります。  
グラフに必要な要素のみがクエリ結果として作成されるようにします（クエリ結果の中から一部のデータを使ってグラフ化することはできなく、クエリによってグラフ化の対象を設定する）。

![postgresql_config](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581362/aa91aa90-e612-1cf3-0262-8e3a86022f20.png)


## db2chartノードの設定

第一列をデータラベルとして扱いたいので、チェックボックスをチェックします。

![db2chart_config](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581362/70f0feb6-a88a-6145-e3b1-297313e05149.png)

## chartノードの設定

デフォルト設定でグラフグループを作成します。
3つのグラフノードを配置しましたが、それぞれグラフの種類を「折れ線グラフ」「棒グラフ」「円グラフ」に設定します。

![graph_config](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581362/20ce9f83-d9f5-aae2-cb93-5b2e59d3bacc.png)

以上で設定は完了です。  

# フローの実行とダッシュボードの確認

それでは実行してダッシュボードを見てみましょう。

デプロイしたあと、injectノードの左のボタンを押してフローを実行します。

ダッシュボードを見るには、右上のメニューから「dashboard」をクリックする、あるいはhttp://{Node-REDのIP}:{ポート}/ui をブラウザで開きます。

すると、本記事の冒頭に掲載したグラフが表示できているはずです。

# おわりに
Node-REDでデータベースのデータをグラフ表示する方法を説明しました。  
db2chartノードを使うと、node-red-contrib-postgresqlノードで取得したデータをchartノード向けに簡単に整形してくれます。  
今回はデータベースとしてPostgreSQLを使用しましたが、node-red-contrib-postgresqlノードを使ってアクセスできるデータ統合エンジン[PGSpider](https://github.com/pgspider/pgspider)&trade;のデータも同様にグラフ表示できます。  
さらに、MySQL&reg;（node-red-node-mysql）やSQL Server&reg;（node-red-contrib-mssql-plus）など他のデータベースのノードも同じデータフォーマットなので、db2chartノードを使って同じことが実現できます。

# Appendix

<details>
<summary>フロー</summary>

```json
[
    {
        "id": "f91463b3db934a59",
        "type": "tab",
        "label": "フロー 1",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "7c5de0fd46857d50",
        "type": "inject",
        "z": "f91463b3db934a59",
        "name": "inject",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "[{\"series\":[\"A\",\"B\",\"C\"],\"data\":[[{\"x\":1504029632890,\"y\":5},{\"x\":1504029636001,\"y\":4},{\"x\":1504029638656,\"y\":2}],[{\"x\":1504029633514,\"y\":6},{\"x\":1504029636622,\"y\":7},{\"x\":1504029639539,\"y\":6}],[{\"x\":1504029634400,\"y\":7},{\"x\":1504029637959,\"y\":7},{\"x\":1504029640317,\"y\":7}]],\"labels\":[\"\"]}]",
        "payloadType": "json",
        "x": 170,
        "y": 260,
        "wires": [
            [
                "e3160f9dc65dbc20"
            ]
        ]
    },
    {
        "id": "e3160f9dc65dbc20",
        "type": "postgresql",
        "z": "f91463b3db934a59",
        "name": "",
        "query": "SELECT name, value FROM tbl1;",
        "postgreSQLConfig": "911f6b69e491e0b6",
        "split": false,
        "rowsPerMsg": 1,
        "outputs": 1,
        "x": 330,
        "y": 260,
        "wires": [
            [
                "3bac80c0a83d6879"
            ]
        ]
    },
    {
        "id": "6b059773c3a90604",
        "type": "ui_chart",
        "z": "f91463b3db934a59",
        "name": "",
        "group": "8553ddf46345bbc0",
        "order": 0,
        "width": 0,
        "height": 0,
        "label": "chart",
        "chartType": "bar",
        "legend": "false",
        "xformat": "auto",
        "interpolate": "linear",
        "nodata": "",
        "dot": true,
        "ymin": "",
        "ymax": "",
        "removeOlder": 1,
        "removeOlderPoints": "",
        "removeOlderUnit": "604800",
        "cutout": 0,
        "useOneColor": false,
        "useUTC": false,
        "colors": [
            "#1f77b4",
            "#aec7e8",
            "#ff7f0e",
            "#2ca02c",
            "#98df8a",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "outputs": 1,
        "useDifferentColor": false,
        "className": "",
        "x": 690,
        "y": 260,
        "wires": [
            []
        ]
    },
    {
        "id": "3bac80c0a83d6879",
        "type": "db2chart",
        "z": "f91463b3db934a59",
        "name": "",
        "firstcol": true,
        "x": 500,
        "y": 260,
        "wires": [
            [
                "6b059773c3a90604",
                "8f61b8bbabc31ad0",
                "465ccdc9553eee12"
            ]
        ]
    },
    {
        "id": "8f61b8bbabc31ad0",
        "type": "ui_chart",
        "z": "f91463b3db934a59",
        "name": "",
        "group": "8553ddf46345bbc0",
        "order": 0,
        "width": 0,
        "height": 0,
        "label": "chart",
        "chartType": "pie",
        "legend": "false",
        "xformat": "auto",
        "interpolate": "linear",
        "nodata": "",
        "dot": true,
        "ymin": "",
        "ymax": "",
        "removeOlder": 1,
        "removeOlderPoints": "",
        "removeOlderUnit": "604800",
        "cutout": 0,
        "useOneColor": false,
        "useUTC": false,
        "colors": [
            "#1f77b4",
            "#aec7e8",
            "#ff7f0e",
            "#2ca02c",
            "#98df8a",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "outputs": 1,
        "useDifferentColor": false,
        "className": "",
        "x": 690,
        "y": 320,
        "wires": [
            []
        ]
    },
    {
        "id": "465ccdc9553eee12",
        "type": "ui_chart",
        "z": "f91463b3db934a59",
        "name": "",
        "group": "8553ddf46345bbc0",
        "order": 0,
        "width": 0,
        "height": 0,
        "label": "chart",
        "chartType": "line",
        "legend": "false",
        "xformat": "auto",
        "interpolate": "linear",
        "nodata": "",
        "dot": true,
        "ymin": "",
        "ymax": "",
        "removeOlder": 1,
        "removeOlderPoints": "",
        "removeOlderUnit": "604800",
        "cutout": 0,
        "useOneColor": false,
        "useUTC": false,
        "colors": [
            "#1f77b4",
            "#aec7e8",
            "#ff7f0e",
            "#2ca02c",
            "#98df8a",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "outputs": 1,
        "useDifferentColor": false,
        "className": "",
        "x": 690,
        "y": 200,
        "wires": [
            []
        ]
    },
    {
        "id": "911f6b69e491e0b6",
        "type": "postgreSQLConfig",
        "name": "",
        "host": "localhost",
        "hostFieldType": "str",
        "port": "5432",
        "portFieldType": "num",
        "database": "postgres",
        "databaseFieldType": "str",
        "ssl": "false",
        "sslFieldType": "bool",
        "applicationName": "",
        "applicationNameType": "str",
        "max": "10",
        "maxFieldType": "num",
        "idle": "1000",
        "idleFieldType": "num",
        "connectionTimeout": "10000",
        "connectionTimeoutFieldType": "num",
        "user": "postgres",
        "userFieldType": "str",
        "password": "postgres",
        "passwordFieldType": "str"
    },
    {
        "id": "8553ddf46345bbc0",
        "type": "ui_group",
        "name": "デフォルト",
        "tab": "64a5876eef82c7b5",
        "order": 1,
        "disp": true,
        "width": "6",
        "collapse": false,
        "className": ""
    },
    {
        "id": "64a5876eef82c7b5",
        "type": "ui_tab",
        "name": "ホーム",
        "icon": "dashboard",
        "disabled": false,
        "hidden": false
    }
]
```
</details>

# 参考文献
* Node-RED: https://nodered.org/  
* @pgspider/node-red-db2chart: https://flows.nodered.org/node/@pgspider/node-red-db2chart  
* node-red-dashboard: https://flows.nodered.org/node/node-red-dashboard  
* node-red-contrib-postgresql: https://flows.nodered.org/node/node-red-contrib-postgresql
* PGSpider: https://github.com/pgspider/pgspider

---  
PGSpiderは(株)東芝の登録商標です。  
社名・商品名・サービス名などは、それぞれ各社が商標として使用している場合があります。​