📦 Node-RED Batchノード ガイド

このガイドでは、Node-REDのBatchノードについて、初心者の方でも理解できるように詳しく説明します。

📚 1. Batchノードとは?

🤔 「Batch」って何?

Batchノードは、連続するメッセージをグループ化して新しいメッセージシーケンスを作成するノードです。 日常生活で例えると、工場のベルトコンベアで製品を箱詰めする作業のようなものです。

📦 工場の箱詰めラインに例えると:

📦 基本的な動作

Function
(送信)
→→→ Batch →→→ Join Debug

Batchノードは、連続するメッセージを受け取り、指定した条件でグループ化したメッセージシーケンスを出力します。 出力されるのはmsg.partsを持つメッセージシーケンスなので、Joinノードと組み合わせて配列にまとめることができます。

入力(30個のメッセージ)
0 → 1 → 2 → 3 → 4 → 5 → 6 → ... → 29
↓ Batch(5個ずつ) ↓
出力(6つのグループ)
[0,1,2,3,4] → [5,6,7,8,9] → ... → [25,26,27,28,29]

⚙️ 2. Batchノードの3つのモード

数量 数量ベースモード

指定した数のメッセージをグループ化

N個ずつまとめて シーケンス作成 オーバーラップ可能

時間 時間ベースモード

指定時間内のメッセージをグループ化

N秒間に届いた メッセージを1グループに

連結 連結モード

複数のシーケンスを結合

トピック別の シーケンスを順番に連結

📋 設定項目一覧

設定項目 説明 使用モード
モード 数量/時間/連結から選択 全モード共通
メッセージ数 1グループにまとめるメッセージ数 数量ベース
オーバーラップ 隣接グループ間で共有するメッセージ数 数量ベース
msg.partsを用いたbatch操作を許可 受信メッセージのmsg.partsを考慮する 数量ベース
間隔(秒) グループ化する時間間隔 時間ベース
メッセージを受信しない場合、空のメッセージを送信 メッセージがない場合も空シーケンスを出力 時間ベース
トピック 連結するシーケンスのトピック順序 連結モード

🎯 オーバーラップの動作

数量ベースモードでは、グループ間でメッセージを共有(オーバーラップ)できます。

オーバーラップなし(overlap=0):

0 1 2 3 4 | 5 6 7 8 9 | 10...

オーバーラップあり(overlap=1):

0 1 2 3 4 5 6 7 8 9...
グループ1: [0,1,2,3,4] → グループ2: [4,5,6,7,8] → グループ3: [8,9,10,11,12]...

📌 オーバーラップの活用例:

🎯 3. 実用的な使用パターン

📥 サンプルフローのインポート方法:

  1. 下のサンプルフローJSONをコピー
  2. Node-REDエディタで メニュー → 読み込み を選択
  3. JSONをペーストして「読み込み」をクリック

このサンプルフローには、以下で説明する全パターンの実例が含まれています。

📋 サンプルフロー(クリックで展開)

参照元:NodeREDエディター内サンプルフロー

[ { "id": "batch_sample_tab", "type": "tab", "label": "Batch Sample", "disabled": false, "info": "", "env": [] }, { "id": "batch_count_inject", "type": "inject", "z": "batch_sample_tab", "name": "実行", "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 110, "y": 100, "wires": [["batch_count_func"]] }, { "id": "batch_count_func", "type": "function", "z": "batch_sample_tab", "name": "send: 0-29", "func": "for(var x = 0; x < 30; x++) {\n node.send({payload: x});\n}", "outputs": 1, "x": 250, "y": 100, "wires": [["batch_count_node"]] }, { "id": "batch_count_node", "type": "batch", "z": "batch_sample_tab", "name": "5個ずつ", "mode": "count", "count": 5, "overlap": 0, "interval": 10, "allowEmptySequence": false, "honourParts": false, "topics": [], "x": 400, "y": 100, "wires": [["batch_count_join"]] }, { "id": "batch_count_join", "type": "join", "z": "batch_sample_tab", "name": "配列化", "mode": "auto", "build": "array", "property": "payload", "propertyType": "msg", "key": "topic", "joiner": "\\n", "joinerType": "str", "accumulate": false, "timeout": "", "count": "", "x": 550, "y": 100, "wires": [["batch_count_debug"]] }, { "id": "batch_count_debug", "type": "debug", "z": "batch_sample_tab", "name": "結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 690, "y": 100, "wires": [] }, { "id": "batch_overlap_inject", "type": "inject", "z": "batch_sample_tab", "name": "実行", "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 110, "y": 200, "wires": [["batch_overlap_func"]] }, { "id": "batch_overlap_func", "type": "function", "z": "batch_sample_tab", "name": "send: 0-14", "func": "for(var x = 0; x < 15; x++) {\n node.send({payload: x});\n}", "outputs": 1, "x": 250, "y": 200, "wires": [["batch_overlap_node"]] }, { "id": "batch_overlap_node", "type": "batch", "z": "batch_sample_tab", "name": "5個(overlap=2)", "mode": "count", "count": 5, "overlap": 2, "interval": 10, "allowEmptySequence": false, "honourParts": false, "topics": [], "x": 420, "y": 200, "wires": [["batch_overlap_join"]] }, { "id": "batch_overlap_join", "type": "join", "z": "batch_sample_tab", "name": "配列化", "mode": "auto", "build": "array", "property": "payload", "propertyType": "msg", "key": "topic", "joiner": "\\n", "joinerType": "str", "accumulate": false, "timeout": "", "count": "", "x": 570, "y": 200, "wires": [["batch_overlap_debug"]] }, { "id": "batch_overlap_debug", "type": "debug", "z": "batch_sample_tab", "name": "結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 710, "y": 200, "wires": [] }, { "id": "batch_interval_inject", "type": "inject", "z": "batch_sample_tab", "name": "実行", "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 110, "y": 320, "wires": [["batch_interval_func"]] }, { "id": "batch_interval_func", "type": "function", "z": "batch_sample_tab", "name": "send: 0-9", "func": "for(var x = 0; x < 10; x++) {\n node.send({payload: x});\n}", "outputs": 1, "x": 250, "y": 320, "wires": [["batch_interval_delay"]] }, { "id": "batch_interval_delay", "type": "delay", "z": "batch_sample_tab", "name": "1msg/sec", "pauseType": "rate", "timeout": "1", "timeoutUnits": "seconds", "rate": "1", "nbRateUnits": "1", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": false, "x": 400, "y": 320, "wires": [["batch_interval_node"]] }, { "id": "batch_interval_node", "type": "batch", "z": "batch_sample_tab", "name": "3秒間隔", "mode": "interval", "count": 10, "overlap": 0, "interval": 3, "allowEmptySequence": false, "honourParts": false, "topics": [], "x": 540, "y": 320, "wires": [["batch_interval_join"]] }, { "id": "batch_interval_join", "type": "join", "z": "batch_sample_tab", "name": "配列化", "mode": "auto", "build": "array", "property": "payload", "propertyType": "msg", "key": "topic", "joiner": "\\n", "joinerType": "str", "accumulate": false, "timeout": "", "count": "", "x": 670, "y": 320, "wires": [["batch_interval_debug"]] }, { "id": "batch_interval_debug", "type": "debug", "z": "batch_sample_tab", "name": "結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 810, "y": 320, "wires": [] } ]

パターン1: 数量ベースのグループ化

用途: 連続メッセージを指定数ずつグループ化

Inject Function
(0-29送信)
→→→ Batch
(count=5)
→→→ Join Debug

📌 動作の流れ:

  1. Functionノードで0〜29の30メッセージを連続送信
  2. Batchノードが5メッセージずつグループ化
  3. 6つのメッセージシーケンスを出力(各5メッセージ)
  4. JoinノードでそれぞれをJSON配列に変換

設定例:

モード: 数量ベース メッセージ数: 5 オーバーラップ: 0 入力: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... , 29 (30メッセージ) 出力: [0,1,2,3,4], [5,6,7,8,9], ... , [25,26,27,28,29] (6グループ)

パターン2: オーバーラップ付きグループ化

用途: 隣接グループでメッセージを共有(移動平均など)

Inject Function
(0-29送信)
→→→ Batch
(count=5, overlap=1)
→→→ Join Debug

📌 オーバーラップの効果:

設定例:

モード: 数量ベース メッセージ数: 5 オーバーラップ: 1 入力: 0, 1, 2, ..., 29 (30メッセージ) 出力: グループ1: [0,1,2,3,4] グループ2: [4,5,6,7,8] ← 4が共有 グループ3: [8,9,10,11,12] ← 8が共有 ...

パターン3: 時間ベースのグループ化

用途: 一定時間内に届いたメッセージをまとめる

Inject Function Delay
(1msg/sec)
→→→ Batch
(5秒間隔)
→→→ Join Debug

📌 時間ベースのポイント:

設定例:

モード: 時間ベース 間隔: 5秒 空シーケンスを許可: OFF 入力: 1秒間隔で 0, 1, 2, 3, ... , 29 出力: 5秒ごとに [0,1,2,3,4] → [5,6,7,8,9] → ...

📌 応用パターン(連結モード):

連結モードは、異なるトピックのシーケンスを順番に結合する高度な機能です。サンプルフローには含まれていませんが、以下のような用途で活用できます:

🏋️ 4. 実践演習

演習1: 基本的なグループ化初級

📝 課題:

1〜12の数値を3つずつグループ化してください。

🎯 要求仕様:

📊 期待される動作:

✅ 成功の条件:

💡 ヒント

Functionノードの設定:

  • コード例:
    for(var i = 1; i <= 12; i++) {
    node.send({payload: i});
    }

Batchノードの設定:

  • モード: 数量ベース
  • メッセージ数: 3
  • オーバーラップ: 0

Joinノードの設定:

  • モード: 自動
✅ 解答例フロー
[ { "id": "ex1_inject", "type": "inject", "name": "実行", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 110, "y": 100, "wires": [["ex1_function"]] }, { "id": "ex1_function", "type": "function", "name": "1-12送信", "func": "for(var i = 1; i <= 12; i++) {\n node.send({payload: i});\n}", "outputs": 1, "x": 260, "y": 100, "wires": [["ex1_batch"]] }, { "id": "ex1_batch", "type": "batch", "name": "3個ずつ", "mode": "count", "count": 3, "overlap": 0, "interval": 10, "allowEmptySequence": false, "honourParts": false, "topics": [], "x": 400, "y": 100, "wires": [["ex1_join"]] }, { "id": "ex1_join", "type": "join", "name": "配列化", "mode": "auto", "build": "array", "property": "payload", "propertyType": "msg", "key": "topic", "joiner": "\\n", "joinerType": "str", "accumulate": false, "timeout": "", "count": "", "x": 550, "y": 100, "wires": [["ex1_debug"]] }, { "id": "ex1_debug", "type": "debug", "name": "結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 690, "y": 100, "wires": [] } ]

演習2: 移動ウィンドウの実装中級

📝 課題:

オーバーラップを使って3要素の移動ウィンドウを作成してください。

🎯 要求仕様:

📊 期待される動作:

✅ 成功の条件:

💡 ヒント

Functionノードの設定:

  • 1〜6の6メッセージを送信

Batchノードの設定:

  • モード: 数量ベース
  • メッセージ数: 3
  • オーバーラップ: 2(3-1=2で1要素ずつスライド)
✅ 解答例フロー
[ { "id": "ex2_inject", "type": "inject", "name": "実行", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 110, "y": 100, "wires": [["ex2_function"]] }, { "id": "ex2_function", "type": "function", "name": "1-6送信", "func": "for(var i = 1; i <= 6; i++) {\n node.send({payload: i});\n}", "outputs": 1, "x": 260, "y": 100, "wires": [["ex2_batch"]] }, { "id": "ex2_batch", "type": "batch", "name": "3個(overlap=2)", "mode": "count", "count": 3, "overlap": 2, "interval": 10, "allowEmptySequence": false, "honourParts": false, "topics": [], "x": 420, "y": 100, "wires": [["ex2_join"]] }, { "id": "ex2_join", "type": "join", "name": "配列化", "mode": "auto", "build": "array", "property": "payload", "propertyType": "msg", "key": "topic", "joiner": "\\n", "joinerType": "str", "accumulate": false, "timeout": "", "count": "", "x": 570, "y": 100, "wires": [["ex2_debug"]] }, { "id": "ex2_debug", "type": "debug", "name": "結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 710, "y": 100, "wires": [] } ]

演習3: 時間ベースの集約中級

📝 課題:

2秒ごとにメッセージをまとめてください。

🎯 要求仕様:

📊 期待される動作:

✅ 成功の条件:

💡 ヒント

Functionノードの設定:

  • 0〜9の10メッセージを送信

Delayノードの設定:

  • レート制限モード
  • 2メッセージ/秒(0.5秒間隔)

Batchノードの設定:

  • モード: 時間ベース
  • 間隔: 2秒
✅ 解答例フロー
[ { "id": "ex3_inject", "type": "inject", "name": "実行", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 90, "y": 100, "wires": [["ex3_function"]] }, { "id": "ex3_function", "type": "function", "name": "0-9送信", "func": "for(var i = 0; i < 10; i++) {\n node.send({payload: i});\n}", "outputs": 1, "x": 220, "y": 100, "wires": [["ex3_delay"]] }, { "id": "ex3_delay", "type": "delay", "name": "2msg/sec", "pauseType": "rate", "timeout": "1", "timeoutUnits": "seconds", "rate": "2", "nbRateUnits": "1", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": false, "x": 360, "y": 100, "wires": [["ex3_batch"]] }, { "id": "ex3_batch", "type": "batch", "name": "2秒間隔", "mode": "interval", "count": 10, "overlap": 0, "interval": 2, "allowEmptySequence": false, "honourParts": false, "topics": [], "x": 500, "y": 100, "wires": [["ex3_join"]] }, { "id": "ex3_join", "type": "join", "name": "配列化", "mode": "auto", "build": "array", "property": "payload", "propertyType": "msg", "key": "topic", "joiner": "\\n", "joinerType": "str", "accumulate": false, "timeout": "", "count": "", "x": 630, "y": 100, "wires": [["ex3_debug"]] }, { "id": "ex3_debug", "type": "debug", "name": "結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 770, "y": 100, "wires": [] } ]

演習4: センサーデータの移動平均上級

📝 課題:

センサー値の3点移動平均を計算してください。

🎯 要求仕様:

📊 期待される動作:

✅ 成功の条件:

💡 ヒント

Templateノードの設定:

  • 形式: JSON
  • テンプレート: [10, 20, 30, 40, 50]

Splitノードの設定:

  • 配列を個別メッセージに分割

Batchノードの設定:

  • モード: 数量ベース
  • メッセージ数: 3
  • オーバーラップ: 2

Joinノードの設定:

  • モード: 自動(配列に結合)

Functionノード(平均計算)の設定:

  • 配列の平均を計算してmsg.payloadに設定
  • コード例: msg.payload = msg.payload.reduce((a,b)=>a+b) / msg.payload.length;
✅ 解答例フロー
[ { "id": "ex4_inject", "type": "inject", "name": "実行", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 90, "y": 100, "wires": [["ex4_template"]] }, { "id": "ex4_template", "type": "template", "name": "センサー値", "field": "payload", "fieldType": "msg", "format": "json", "syntax": "plain", "template": "[10, 20, 30, 40, 50]", "output": "json", "x": 220, "y": 100, "wires": [["ex4_split"]] }, { "id": "ex4_split", "type": "split", "name": "分割", "splt": "\\n", "spltType": "str", "arraySplt": 1, "arraySpltType": "len", "stream": false, "addname": "", "property": "payload", "x": 350, "y": 100, "wires": [["ex4_batch"]] }, { "id": "ex4_batch", "type": "batch", "name": "3点ウィンドウ", "mode": "count", "count": 3, "overlap": 2, "interval": 10, "allowEmptySequence": false, "honourParts": false, "topics": [], "x": 480, "y": 100, "wires": [["ex4_join"]] }, { "id": "ex4_join", "type": "join", "name": "配列化", "mode": "auto", "build": "array", "property": "payload", "propertyType": "msg", "key": "topic", "joiner": "\\n", "joinerType": "str", "accumulate": false, "timeout": "", "count": "", "x": 610, "y": 100, "wires": [["ex4_avg"]] }, { "id": "ex4_avg", "type": "function", "name": "平均計算", "func": "msg.payload = msg.payload.reduce((a,b) => a+b) / msg.payload.length;\nreturn msg;", "outputs": 1, "x": 740, "y": 100, "wires": [["ex4_debug"]] }, { "id": "ex4_debug", "type": "debug", "name": "結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 870, "y": 100, "wires": [] } ]

🎓 5. まとめ

Batchノードの重要ポイント

⚠️ よくある間違い

📚 次のステップ

Batchノードをマスターしたら、以下のノードも学んでみましょう:

🔧 6. トラブルシューティング

よくある問題と解決方法

問題 原因 解決方法
グループが出力されない メッセージ数が足りない count数以上のメッセージを送信するか、時間モードを使用
配列にならない Joinノードがない Batchの後にJoinノードを追加
オーバーラップが想定と違う オーバーラップ値の理解ミス overlap = count - 移動幅 で計算
連結モードが動かない msg.topicが未設定 Changeノードでtopicを設定
時間モードで空グループ 空シーケンスを許可がON 必要に応じて設定を変更
グループサイズが不均一 時間モード使用中 数量モードに変更するか、想定内として対応

💡 7. 実務での活用例

ケース1: センサーデータの移動平均

温度センサーから1秒ごとにデータ受信 ↓ Batch(count=5, overlap=4) ↓ 5点移動平均ウィンドウ ↓ Join → Function(平均計算) ↓ ノイズを除去した温度値

ケース2: ログの定期バッチ処理

アプリケーションログが随時到着 ↓ Batch(interval=60秒) ↓ 1分間のログをまとめる ↓ Join → データベースに一括保存

ケース3: APIレート制限対策

大量のAPIリクエスト ↓ Batch(count=10) ↓ 10件ずつまとめる ↓ バルクAPIで一括送信 ↓ API呼び出し回数を1/10に削減

ケース4: IoTデバイスからのデータ集約

複数センサーからのデータ(異なるtopic) ↓ Batch(concat mode: temp, humidity, pressure) ↓ センサー種別ごとに順序付けて結合 ↓ 統合レポート生成

🔗 8. 追加リソース


このガイドが役に立ちましたら、実際のプロジェクトで練習してみてください!
Batchノードはデータ集約・移動平均計算の強力なツールです。

参照元:NodeREDエディター内サンプルフロー

🏠