question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot join multiple msg properties using the (core) join node

See original GitHub issue

Cannot join multiple msg properties using the (core) join node

The “reduce sequence” mode in Join node assigns value only to msg.payload; i.e.

  • To use split node only a single msg property is required to split the node, which is more often than not the payload itself. Other properties of the msg are copied into all new msgs. This is fine and not an issue
  • To join multiple parts (lets call them child msgs) of an original msg (lets call them parent msg), the join node “joins” the payload or any other property when ‘manual’ node is selected. The issue arises when child msgs contain more than one property to be “joined”. I was of the view that it can be done using the ‘reduce sequence’ mode, however I realized that the ‘reduce sequence’ mode assigns the final value to msg.payload (Probably this line in the code base: https://github.com/node-red/node-red/blob/0ecd9673b84435f645bb45984e5237b0c3572017/packages/node_modules/%40node-red/nodes/core/sequence/17-split.js#L284). Thus, in the current state of affairs, we cannot “join” multiple properties while using the join node.

What are the steps to reproduce?

Run the following flow: image

[{"id":"c73b49fa.c381f8","type":"split","z":"9e357fb1.f5191","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":500,"y":360,"wires":[["5acc1cd3.5a7f44","4adb9cc4.001254"]]},{"id":"4adb9cc4.001254","type":"change","z":"9e357fb1.f5191","name":"","rules":[{"t":"set","p":"amount","pt":"msg","to":"$millis()","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":360,"wires":[["d68d9cfc.7da0c","2f39cffd.c6088"]]},{"id":"66557073.501e4","type":"inject","z":"9e357fb1.f5191","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[\"a\", \"b\"]","payloadType":"json","x":300,"y":360,"wires":[["c73b49fa.c381f8","8be41a7b.a805b8"]]},{"id":"2f39cffd.c6088","type":"join","z":"9e357fb1.f5191","name":"","mode":"reduce","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"($step1 := \t   $ ~> | $ | {\t       \"payload\": $append($A.payload, payload),\t       \"amount\": $A.amount + amount\t}, [\"parts\"]|\t)\t","reduceInit":"{\"payload\":[], \"amount\": 0}","reduceInitType":"json","reduceFixup":"$A","x":890,"y":360,"wires":[["37cf4fcd.80ee6"]]},{"id":"37cf4fcd.80ee6","type":"debug","z":"9e357fb1.f5191","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":975,"y":420,"wires":[],"l":false}]

What happens?

The output of the above flow (using debug node) is

// msg obj = 
{
  "payload": {
    "payload": [
      "a",
      "b"
    ],
    "_msgid": "5156fb62.3b85f4",
    "amount": 3207579255663
  },
  "_msgid": "46f5a6bd.8fec08"
}

the issue is that our JSONata is assigned to msg.payload instead of the msg

What do you expect to happen?

// msg obj = 
{
  
    "payload": [
      "a",
      "b"
    ],
    "_msgid": "5156fb62.3b85f4",
    "amount": 3207579255663
}

Please tell us about your environment:

  • Node-RED version: 1.1.0
  • Node.js version: 14.2.0
  • npm version: N/A
  • Platform/OS: N/A
  • Browser: N/A

Some background (just one of the use cases we have)

We build HTTP based microservices using NR, so everything is invoked using HTTP in node. Then some logic runs e.g. fetching all files from a remote server. Each file then needs to be transformed and while transforming, we would add some metadata to the msg object (like number of rows processed, status, time-taken etc.) At the end of processing these file, we would join the msgs that correspond to the one HTTP request and then serve the data and combined metadata using the HTTP response node

Edit 1: Current workaround to solve the issue

the flow.json posted under “What are the steps to reproduce?” above does not work with multiple split and join nodes combination. Use the below flow instead

  1. Use split as is
  2. Use join node along with function node (one can use change node in place of function) So, the flow becomes: image
[{"id":"f4ade963.7b67f8","type":"inject","z":"9e357fb1.f5191","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[[1, 2], [11, 22]]","payloadType":"json","x":140,"y":380,"wires":[["c73b49fa.c381f8"]]},{"id":"c73b49fa.c381f8","type":"split","z":"9e357fb1.f5191","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":330,"y":380,"wires":[["4adb9cc4.001254"]]},{"id":"4adb9cc4.001254","type":"change","z":"9e357fb1.f5191","name":"","rules":[{"t":"set","p":"amount","pt":"msg","to":"$millis()","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":380,"wires":[["cab7d96d.889cc8"]]},{"id":"37cf4fcd.80ee6","type":"debug","z":"9e357fb1.f5191","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1095,"y":440,"wires":[],"l":false},{"id":"15f5893b.171567","type":"function","z":"9e357fb1.f5191","name":"","func":"return{\n    ...msg.payload\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","x":960,"y":440,"wires":[["37cf4fcd.80ee6"]]},{"id":"cab7d96d.889cc8","type":"split","z":"9e357fb1.f5191","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":670,"y":380,"wires":[["312a19ba.79df56"]]},{"id":"f157d987.f3d308","type":"debug","z":"9e357fb1.f5191","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1095,"y":380,"wires":[],"l":false},{"id":"31f2b275.8b12fe","type":"function","z":"9e357fb1.f5191","name":"","func":"return{\n    ...msg.payload\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","x":940,"y":380,"wires":[["f157d987.f3d308","66bd6404.12c62c"]]},{"id":"66bd6404.12c62c","type":"join","z":"9e357fb1.f5191","name":"","mode":"reduce","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"(\t$isFinalPart := $not($exists($.parts.parts));\t$step1 := \t   $ ~> | $ | {\t       \"payload\": $append($A.payload, ( $type(payload) = \"array\" ? [[payload]] : payload ) ),\t       \"amount\": $A.amount + amount,\t       \"parts\": $.parts.parts\t}, $isFinalPart ? \"parts\" : \"\" |;\t)\t","reduceInit":"{\"payload\":[], \"amount\": 0}","reduceInitType":"json","reduceFixup":"$A","x":830,"y":440,"wires":[["15f5893b.171567"]]},{"id":"312a19ba.79df56","type":"join","z":"9e357fb1.f5191","name":"","mode":"reduce","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"(\t$isFinalPart := $not($exists($.parts.parts));\t$step1 := \t   $ ~> | $ | {\t       \"payload\": $append($A.payload, ( $type(payload) = \"array\" ? [[payload]] : payload ) ),\t       \"amount\": $A.amount + amount,\t       \"parts\": $.parts.parts\t}, $isFinalPart ? \"parts\" : \"\" |;\t)\t","reduceInit":"{\"payload\":[], \"amount\": 0}","reduceInitType":"json","reduceFixup":"$A","x":810,"y":380,"wires":[["31f2b275.8b12fe"]]}]

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:11 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
mannharleencommented, Oct 27, 2020

or should it be more like the debug node and be image

(with payload as the default) so you could assign it to other properties also ?

I like this. Will attempt a PR. Hope its ok to get some guidance from you both before I make any changes.

1reaction
dceejaycommented, Oct 27, 2020

or should it be more like the debug node and be image

(with payload as the default) so you could assign it to other properties also ?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Problem with join node - General - Node-RED Forum
I would like to combine some payloads but allways receive this error: "Message missing key property 'msg.topic' - cannot add to object" I...
Read more >
Understanding and Using The Node-Red Message Object
The Msg Object is a standard JavaScript object and has several existing properties or parts depending on where it originated. You can see...
Read more >
Merging Flows - Node-RED Essentials - YouTube
This video will show you two of the common patterns for merging flows together. One using the Join node, and one using the...
Read more >
Implementing two inputs in Node-RED - Stack Overflow
For your original question, you are looking for a way to merge 2 payloads from different sensors into a single object. The core...
Read more >
Transform data | Grafana documentation
Use this transformation to combine the results from multiple queries (combining on a passed join field or the first time column) into one...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found