Node-RED Design Patterns

When programming object oriented code there are many design patterns that you can reuse to solve commonly occurring problems. Some of these patterns might include the singleton, Mediator or Factory patterns. When using RedConnect and Node-RED there is a number of patterns that can be reused. The use of these design patterns in your projects has a number of advantages:

– Makes it easier to understand a flow
– Helps your team standardize a series of processes
– Increases efficiency

Here are 8 patterns that you can use in your own apps. All the flows are available to copy and paste at the bottom of this page.


1. Store & Search

Store & Search is a simple pattern to perform the storage and retrieval of data from a data source. In the example below we are using a CouchDB database to store and then retrieve the data.

Store pattern, is used to store the input payload into a database. In this example, there is a function node that selects the data to be stored.
Search pattern, is a pattern for searching the data stored using the Store pattern.


2. UI & API pattern

These flows work together to demonstrate the UI & API patterns. When navigating to the GET /input endpoint the user is presented with a form. When the form is submitted it calls the GET /output method. During the output flow the request is sent to the GET /api and the results are formatted and returned to the user.

UI pattern, is useful when you need user input to trigger a flow or you need to display data in HTML format to the use. Although, it is possible to create an entire website this way it would become unmanageable.
API pattern, allows you to configure RedConnect as a REST API server. You can create GET, POST, PUT and DELETE request endpoints to trigger a flow. As demonstrated above this can become very powerful when combined with the UI pattern.


3. Timeout pattern

This flow extends the output flow shown above to add a timeout feature. After 5 seconds if the /api endpoint has not responded then a timeout message is sent in the response.

Timeout pattern, often when calling API’s or database in a remote location the data does not respond instantly. A request to a flow could potentially wait indefinitely whilst gathering the data it needs. The timeout pattern can be used to add a number of seconds before failing gracefully.


4. While pattern

The while pattern is used as a drop in replacement for the traditional while pattern found in computer science.

While pattern, allows you to repeat a node ‘x’ number of times. Once the loop is complete the finished loop flow is started. This is a useful pattern when you need to repeat a loop a “known” number of times. We will show later on how this flow can be combined with the Separator pattern to loop a dynamic number of times.


5. Sequence pattern

The flow below shows how you can hold on to a value and use it later in the flow. In this case we are adding two numbers together. The first number is defined and added to the tmp property. We later add another number and combine the two numbers, displaying the result.

Sequence pattern, demonstrates how you can add new properties to the msg object that is passed along the flow. By design all nodes can overwrite the payload property. By assigning new properties to the msg object you can use these values in the latter stages of the flow. A good practical example of this is that the http request node adds a property called res to the msg object which is used by the http response node at the end of the flow. One thing to be cautious of is that any node can overwrite your custom property. Therefore it’s important to make sure the key name you use is unique enough so that you don’t lose data.


6. Aggregator pattern

This flow allows you to run two or more parallel operations and then combine the results. Here we take two functions that pass a single number each in the payload. Once both operations are complete the numbers are added together and the result is returned.

Aggregator pattern is useful for combining asynchronous operations. A practical example of this would be when you need to combine the responses from two or more API requests into a single response. This pattern has an advantage over the sequence pattern as both requests happen simultaneously, reducing delay.


7. Separator pattern

This pattern is used when you need to send two or more outputs from a node. In this flow the output of the function node returns an array or msg objects that are then passed to the output.

Separator pattern is the inverse of the aggregator pattern instead of combining two or more outputs, the separator pattern splits the output into multiple messages. It sometimes can be useful to combine the aggregator pattern and separator pattern when you need to send dynamic data to the parallel functions of the aggregator pattern. This is commonly referred to as MapReduce and it’s this pattern we will look at next.


8. MapReduce pattern

This pattern is created by combining the Aggregator and Separator patterns. In this example we are counting the words in the sentence. We require 2 outputs those words that start from a-m and those from n-z. We start by passing in a sentence into the Map node, where the words for that sentence are counted and added to an array. The Reduce node then combines all 3 arrays, creating a new array of the combined totals from all 3 sentences.

Here the Map node is performing the Separator pattern and Reduce is performing the Aggregator pattern. Although the MapReduce pattern is generally quite complex in traditional programming, visually it is much easier to understand and implement. MapReduce is normally used in the real world for data analysis when you need to produce analytics for a stream of input data.

Source code

To use these patterns in your RedConnect app or in Node-RED, copy the below json to your clipboard. Then open your RedConnect app, go to the menu in the upper right corner and choose Import-> Clipboard. Then paste the source code.

Store & Search pattern

[{"id":"7d1d2d42.82e2d4","type":"cloudant","z":"940f1bba.6bf0e8","host":"redant.cloudant.com","name":""},{"id":"cdd8116a.3227f","type":"comment","z":"940f1bba.6bf0e8","name":"Store pattern","info":"","x":227,"y":162.82151126861572,"wires":[]},{"id":"a3fcf0fd.5c031","type":"function","z":"940f1bba.6bf0e8","name":"Select the data to be stored","func":"msg.payload = {DATA: new Date(msg.payload).toString()};\nreturn msg;","outputs":1,"noerr":0,"x":440.7500305175781,"y":208.821533203125,"wires":[["bf441e57.40bbe"]]},{"id":"bb3bcee0.44c43","type":"inject","z":"940f1bba.6bf0e8","name":"Search term","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":239.50003814697266,"y":351.0715284347534,"wires":[["35d1c37a.ca2e3c"]]},{"id":"bedef5d9.412108","type":"inject","z":"940f1bba.6bf0e8","name":"Input data","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":241.7500343322754,"y":208.82152843475342,"wires":[["a3fcf0fd.5c031"]]},{"id":"7566e1a.f8a992","type":"debug","z":"940f1bba.6bf0e8","name":"Search results output","active":true,"console":"false","complete":"payload","x":642.5000610351562,"y":351.071533203125,"wires":[]},{"id":"eb94fbd4.146b08","type":"comment","z":"940f1bba.6bf0e8","name":"Search pattern","info":"","x":232.00003051757812,"y":302.82151889801025,"wires":[]},{"id":"35d1c37a.ca2e3c","type":"cloudant in","z":"940f1bba.6bf0e8","service":"_ext_","cloudant":"7d1d2d42.82e2d4","name":"Database","database":"test","search":"_id_","design":"","index":"","x":422,"y":351,"wires":[["7566e1a.f8a992"]]},{"id":"bf441e57.40bbe","type":"cloudant in","z":"940f1bba.6bf0e8","service":"_ext_","cloudant":"7d1d2d42.82e2d4","name":"Database ","database":"test","search":"_id_","design":"","index":"","x":648,"y":209,"wires":[["e9a37b37.165c88"]]},{"id":"e9a37b37.165c88","type":"debug","z":"940f1bba.6bf0e8","name":"Inserted document","active":true,"console":"false","complete":"payload","x":835,"y":209,"wires":[]}]

UI & API pattern

[{"id":"8477e60d.7b8818","type":"comment","z":"2aa88aac.d55776","name":"UI pattern","info":"","x":229,"y":93,"wires":[]},{"id":"80def98e.7f2108","type":"http in","z":"2aa88aac.d55776","name":"","url":"/output","method":"get","swaggerDoc":"","x":235.27773666381836,"y":221.1944227218628,"wires":[["37d5bd03.c82a42"]]},{"id":"37d5bd03.c82a42","type":"function","z":"2aa88aac.d55776","name":"Create API request URL","func":"msg.url = msg.req.host + \"/api?q=\" + encodeURI(msg.payload.q);\nreturn msg;","outputs":1,"noerr":0,"x":419.8491516113281,"y":221.2895965576172,"wires":[["5efac301.a1053c"]]},{"id":"5efac301.a1053c","type":"http request","z":"2aa88aac.d55776","name":"Call API","method":"GET","ret":"obj","url":"","x":588.1349601745605,"y":220.62292575836182,"wires":[["c11d748.f3ee288"]]},{"id":"3ac8f608.c5370a","type":"http response","z":"2aa88aac.d55776","name":"HTTP Response","x":712.373046875,"y":318.7181091308594,"wires":[]},{"id":"c11d748.f3ee288","type":"change","z":"2aa88aac.d55776","name":"Delete headers","rules":[{"t":"delete","p":"headers"}],"action":"","property":"","from":"","to":"","reg":false,"x":379.5626525878906,"y":318.7657470703125,"wires":[["e57a5751.1a85a8"]]},{"id":"e57a5751.1a85a8","type":"template","z":"2aa88aac.d55776","name":"Format HTML","field":"payload","format":"html","template":"\nResponse from the API: {{payload}}\n","x":545.2777442932129,"y":318.86103534698486,"wires":[["3ac8f608.c5370a"]]},{"id":"f9bdd9aa.064228","type":"http response","z":"2aa88aac.d55776","name":"HTTP Response","x":631.5160827636719,"y":137.99990844726562,"wires":[]},{"id":"3c5717fb.c3a8e8","type":"http in","z":"2aa88aac.d55776","name":"","url":"/input","method":"get","swaggerDoc":"","x":232.1825828552246,"y":138.99992179870605,"wires":[["fc1780bc.03e88"]]},{"id":"fc1780bc.03e88","type":"template","z":"2aa88aac.d55776","name":"Input form HTML","field":"payload","format":"html","template":"<HTML><BODY><FORM method='GET' action='output'>Search: <INPUT type='text' name='q'><INPUT type='submit'></FORM></BODY></HTML>","x":421.8492736816406,"y":138.66655731201172,"wires":[["f9bdd9aa.064228"]]},{"id":"ac7b9aa3.538468","type":"http in","z":"2aa88aac.d55776","name":"","url":"/api","method":"get","swaggerDoc":"","x":227.63874053955078,"y":461.5278043746948,"wires":[["3a537b3e.c5ac84"]]},{"id":"4346579.fbcb9a8","type":"http response","z":"2aa88aac.d55776","name":"HTTP応答","x":657.5277786254883,"y":461.2420463562012,"wires":[]},{"id":"35cc05dc.ca33fa","type":"comment","z":"2aa88aac.d55776","name":"API pattern","info":"","x":235.0000343322754,"y":414.4166865348816,"wires":[]},{"id":"e6d0607a.192fa","type":"comment","z":"2aa88aac.d55776","name":"↓ A query is sent to the API pattern below","info":"","x":689.2500419616699,"y":180.16671752929688,"wires":[]},{"id":"62689784.9d9768","type":"comment","z":"2aa88aac.d55776","name":"↓ Returns a HTML form","info":"","x":438.0000305175781,"y":92.83335876464844,"wires":[]},{"id":"6b3258ab.94cda8","type":"comment","z":"2aa88aac.d55776","name":"↓ Form submission above triggers this flow","info":"","x":332.2500343322754,"y":180.50003051757812,"wires":[]},{"id":"f06dd82a.0f9228","type":"comment","z":"2aa88aac.d55776","name":"↑ Logic to get data for query","info":"","x":458.4723205566406,"y":503.51983642578125,"wires":[]},{"id":"3a537b3e.c5ac84","type":"template","z":"2aa88aac.d55776","name":"Format Response","field":"payload","format":"handlebars","template":"You searched for: {{payload.q}}","x":429.31341552734375,"y":461.46429443359375,"wires":[["4346579.fbcb9a8"]]}]

Timeout pattern

[{"id":"63a6c88e.9c5938","type":"comment","z":"95ceac5b.6a315","name":"Timeout pattern","info":"","x":184,"y":110,"wires":[]},{"id":"70e64796.8f19b8","type":"comment","z":"95ceac5b.6a315","name":"When the search completes within 5 seconds, it displays the search results on the browser","info":"","x":412.5,"y":157.99998474121094,"wires":[]},{"id":"823e2da8.7dc1d","type":"comment","z":"95ceac5b.6a315","name":" ↑ If the search takes longer than 5 seconds, it displays a \"timed out\" message on the browser","info":"","x":524,"y":400.8333740234375,"wires":[]},{"id":"5590633d.aa6f9c","type":"delay","z":"95ceac5b.6a315","name":"Wait 5 Seconds","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":288.3214111328125,"y":360.84130859375,"wires":[["331d7201.cce28e"]]},{"id":"331d7201.cce28e","type":"template","z":"95ceac5b.6a315","name":"Time-out display HTML","field":"payload","format":"html","template":"\nIt Timed Out.\n","x":494.3214111328125,"y":360.84130859375,"wires":[["cec18476.313e78"]]},{"id":"fc008a64.03ff78","type":"http in","z":"95ceac5b.6a315","name":"","url":"/output","method":"get","swaggerDoc":"","x":171,"y":203,"wires":[["560f4353.a9f0bc","5590633d.aa6f9c"]]},{"id":"560f4353.a9f0bc","type":"function","z":"95ceac5b.6a315","name":"Create API request URL","func":"msg.url = msg.req.host + \"/unknown?q=\" + encodeURI(msg.payload.q);\nreturn msg;","outputs":1,"noerr":0,"x":355.57141494750977,"y":203.0951738357544,"wires":[["59c69b1c.a63964"]]},{"id":"59c69b1c.a63964","type":"http request","z":"95ceac5b.6a315","name":"Call API","method":"GET","ret":"obj","url":"","x":523.8572235107422,"y":202.42850303649902,"wires":[["b5a00be5.4a5ff8"]]},{"id":"cec18476.313e78","type":"http response","z":"95ceac5b.6a315","name":"HTTP Response","x":694.0953063964844,"y":316.5236511230469,"wires":[]},{"id":"b5a00be5.4a5ff8","type":"change","z":"95ceac5b.6a315","name":"Delete headers","rules":[{"t":"delete","p":"headers"}],"action":"","property":"","from":"","to":"","reg":false,"x":361.284912109375,"y":316.5712890625,"wires":[["3a1fba6.fc5e046"]]},{"id":"3a1fba6.fc5e046","type":"template","z":"95ceac5b.6a315","name":"Format HTML","field":"payload","format":"html","template":"\nResponse from the API: {{payload}}\n","x":527.0000038146973,"y":316.66657733917236,"wires":[["cec18476.313e78"]]}]

While pattern

[{"id":"f7537637.08ac88","type":"template","z":"c7269dcb.38d96","name":"i=0","field":"i","format":"handlebars","template":"0","x":277,"y":266.4443883895874,"wires":[["2e73c592.d18c3a"]]},{"id":"2e73c592.d18c3a","type":"switch","z":"c7269dcb.38d96","name":"i<4","property":"i","rules":[{"t":"lt","v":"4"},{"t":"else"}],"checkall":"true","outputs":2,"x":415,"y":266.4443883895874,"wires":[["8fc4ffb5.703b"],["3f1e738b.c0e18c"]]},{"id":"ab756b91.548a98","type":"function","z":"c7269dcb.38d96","name":"i++","func":"msg.i++;\n\nreturn msg;","outputs":1,"noerr":0,"x":521,"y":171.4443883895874,"wires":[["2e73c592.d18c3a"]]},{"id":"b70d1dec.48f2e","type":"debug","z":"c7269dcb.38d96","name":"End","active":true,"console":"false","complete":"payload","x":789,"y":316.44439697265625,"wires":[]},{"id":"64c1427a.9b3ebc","type":"debug","z":"c7269dcb.38d96","name":"Output \"i\"","active":true,"console":"false","complete":"payload","x":795.3999633789062,"y":266.5110321044922,"wires":[]},{"id":"434af4eb.bcb50c","type":"inject","z":"c7269dcb.38d96","name":"Start","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":158.89581298828125,"y":266.3333044052124,"wires":[["f7537637.08ac88"]]},{"id":"4184c9e2.be7b38","type":"comment","z":"c7269dcb.38d96","name":"while pattern","info":"","x":150.16665649414062,"y":171,"wires":[]},{"id":"513b77da.aec488","type":"comment","z":"c7269dcb.38d96","name":"↓ Outputs 4 times","info":"","x":818.9999389648438,"y":225.6110076904297,"wires":[]},{"id":"1b603a4c.e49fc6","type":"comment","z":"c7269dcb.38d96","name":"loop while i < 4 is true ↑","info":"","x":368.6666564941406,"y":307.11102294921875,"wires":[]},{"id":"1999ecc8.e66613","type":"comment","z":"c7269dcb.38d96","name":"Start the incremented value at 0 ↓","info":"","x":214.16665649414062,"y":224.611083984375,"wires":[]},{"id":"dd46beea.22b94","type":"comment","z":"c7269dcb.38d96","name":"← increments the value \"i\"","info":"","x":718.5,"y":170.7777557373047,"wires":[]},{"id":"3f1e738b.c0e18c","type":"template","z":"c7269dcb.38d96","name":"Loop Finished","field":"payload","format":"handlebars","template":"Loop Finished","x":570.2380752563477,"y":317.3134059906006,"wires":[["b70d1dec.48f2e"]]},{"id":"8fc4ffb5.703b","type":"template","z":"c7269dcb.38d96","name":"Output current \"i\" value","field":"payload","format":"handlebars","template":"{{i}}","x":597.9999694824219,"y":266.4443817138672,"wires":[["64c1427a.9b3ebc","ab756b91.548a98"]]}]

Sequence pattern

[{"id":"d7939db8.286c6","type":"comment","z":"6f95f26a.906a0c","name":"Sequence pattern","info":"","x":175,"y":103.16662788391113,"wires":[]},{"id":"f1dcb937.0e2348","type":"function","z":"6f95f26a.906a0c","name":"payload=451","func":"msg.payload = 451;\n\nreturn msg;","outputs":1,"noerr":0,"x":414.66666412353516,"y":147.50000190734863,"wires":[["aa735bc7.558ca8"]]},{"id":"4fd64087.b029c","type":"function","z":"6f95f26a.906a0c","name":"msg.tmp + msg.payload","func":"msg.payload = msg.tmp + msg.payload;\n\nreturn msg;","outputs":1,"noerr":0,"x":609.6666641235352,"y":230.50000190734863,"wires":[["581b04d0.a7e4fc"]]},{"id":"147ecfda.eb813","type":"function","z":"6f95f26a.906a0c","name":"payload=326","func":"msg.payload = 326;\n\nreturn msg;","outputs":1,"noerr":0,"x":414.66666412353516,"y":230.50000190734863,"wires":[["4fd64087.b029c"]]},{"id":"581b04d0.a7e4fc","type":"debug","z":"6f95f26a.906a0c","name":"Result = 777","active":true,"console":"false","complete":"payload","x":794.6666641235352,"y":230.50000190734863,"wires":[]},{"id":"433d6e90.bcc29","type":"inject","z":"6f95f26a.906a0c","name":"Calculate the sum of two values","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":199.66665649414062,"y":147.5,"wires":[["f1dcb937.0e2348"]]},{"id":"aa735bc7.558ca8","type":"function","z":"6f95f26a.906a0c","name":"tmp=payload","func":"msg.tmp = msg.payload;\n\nreturn msg;","outputs":1,"noerr":0,"x":573.6666641235352,"y":147.50000190734863,"wires":[["147ecfda.eb813"]]},{"id":"c1e9d2fd.3e163","type":"comment","z":"6f95f26a.906a0c","name":"↓ Save the payload in tmp","info":"","x":612.1666259765625,"y":103,"wires":[]},{"id":"37020d8a.c8fdf2","type":"comment","z":"6f95f26a.906a0c","name":"↓ Set 1st value","info":"","x":420.1666564941406,"y":102.83331298828125,"wires":[]},{"id":"6435a49f.9bca5c","type":"comment","z":"6f95f26a.906a0c","name":"↑ Set 2nd value","info":"","x":413.6666488647461,"y":274.16657161712646,"wires":[]},{"id":"9be8fcda.6417","type":"comment","z":"6f95f26a.906a0c","name":"↑ Perform the calculation","info":"","x":613.1666259765625,"y":273.16668701171875,"wires":[]}]

Aggregator pattern

[{"id":"ead20d58.152df","type":"comment","z":"8941b246.76be5","name":"Aggregator pattern","info":"","x":168,"y":127,"wires":[]},{"id":"77fe5da9.8801a4","type":"function","z":"8941b246.76be5","name":"payload=451","func":"msg.payload = 451;\n\nreturn msg;","outputs":1,"noerr":0,"x":451.83329010009766,"y":210.50011253356934,"wires":[["43be81d8.bc418"]]},{"id":"43be81d8.bc418","type":"function","z":"8941b246.76be5","name":"Calculate Sum","func":"// Reduce the number of inputs\ncontext.global.n--;\n\n// Store the data in msg.payload for all operations as they complete\ncontext.global.data[context.global.n] = msg.payload;\n\n// When all operations are complete calculate the sum and return\nif (context.global.n === 0)\n{   // Calculate the total value\n    var sum = 0;\n    for (var i = 0; i < context.global.data.length; i++)\n    {\n        sum += context.global.data[i];\n    }\n    msg.payload = sum;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":646.8333435058594,"y":233.50013542175293,"wires":[["a465abf3.5b9a58"]]},{"id":"30a7f66d.cf580a","type":"function","z":"8941b246.76be5","name":"payload=326","func":"msg.payload = 326;\n\nreturn msg;","outputs":1,"noerr":0,"x":450.83331298828125,"y":258.50012493133545,"wires":[["43be81d8.bc418"]]},{"id":"a465abf3.5b9a58","type":"debug","z":"8941b246.76be5","name":"Returns 777","active":true,"console":"false","complete":"payload","x":828.8333206176758,"y":233.50012302398682,"wires":[]},{"id":"4ec8c1ad.b1374","type":"function","z":"8941b246.76be5","name":"Combine 2 Functions","func":"context.global.n = 2;\ncontext.global.data = new Array(2);\n\nreturn msg;","outputs":1,"noerr":0,"x":247.83331298828125,"y":235.5001220703125,"wires":[["77fe5da9.8801a4","30a7f66d.cf580a"]]},{"id":"b72a20f4.48d5e","type":"comment","z":"8941b246.76be5","name":"↓ 1st value","info":"","x":450.5798034667969,"y":172.07418823242188,"wires":[]},{"id":"45b83155.ba47d","type":"inject","z":"8941b246.76be5","name":"Calculate the sum of 2 numbers","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":207.8893585205078,"y":171.19322204589844,"wires":[["4ec8c1ad.b1374"]]},{"id":"77741e74.888be","type":"comment","z":"8941b246.76be5","name":"↑ 2nd value","info":"","x":449.4131546020508,"y":299.07410049438477,"wires":[]},{"id":"1f06d968.e0f927","type":"comment","z":"8941b246.76be5","name":"Define how many parallel operations ↑","info":"","x":197.34170532226562,"y":278.62158203125,"wires":[]},{"id":"1971bcd5.e68e43","type":"comment","z":"8941b246.76be5","name":"↑ Once all parallel operations complete, calculate sum","info":"","x":733.9132080078125,"y":275.907470703125,"wires":[]}]

Separator pattern

[{"id":"50e15885.af1ea8","type":"inject","z":"dd17be00.22e84","name":"Start","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":243,"y":225,"wires":[["838189bb.7c7e78"]]},{"id":"838189bb.7c7e78","type":"function","z":"dd17be00.22e84","name":"1st output 451, 2nd output 326","func":"msg.payload = 451;\nvar msg2 = {};\nmsg2.payload = 326;\n\nreturn [msg, msg2];","outputs":"2","noerr":0,"x":437,"y":225,"wires":[["ddaedfa2.22512"],["f8f12723.070ed8"]]},{"id":"ddaedfa2.22512","type":"debug","z":"dd17be00.22e84","name":"Returns 451","active":true,"console":"false","complete":"payload","x":650,"y":198,"wires":[]},{"id":"f8f12723.070ed8","type":"debug","z":"dd17be00.22e84","name":"Returns 326","active":true,"console":"false","complete":"payload","x":648,"y":251,"wires":[]},{"id":"1a8a3b82.e575c4","type":"comment","z":"dd17be00.22e84","name":"Separator pattern","info":"","x":245.33334350585938,"y":180.49991416931152,"wires":[]},{"id":"67c99e66.98366","type":"comment","z":"dd17be00.22e84","name":"↑ 1 input and 2 outputs","info":"","x":411.91314697265625,"y":269.4258117675781,"wires":[]}]

MapReduce pattern

[{"id":"2e071499.d1f8ec","type":"inject","z":"95ab7967.6a5488","name":"WordCount Start","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":186,"y":199.00004386901855,"wires":[["5ba772eb.a4588c"]]},{"id":"da2fc73d.25d038","type":"function","z":"95ab7967.6a5488","name":"Map","func":"var input = msg.payload.toLowerCase()\n                       .replace( /\\.$/, \"\")\n                       .split(/ |, /);\n// Map\nvar key_value = [];\nfor (var i=0; i<input.length; i++)\n{\n    var key = input[i];\n    if (key in key_value)\n    {\n        key_value[key]++;\n    } else {\n        key_value[key] = 1;\n    }\n}\n\n// Shuffle\nvar key1_value = [];\nvar key2_value = [];\nfor (var key in key_value)\n{\n    if ('a'<=key[0] && key[0]<='m')\n    {\n        key1_value.push([key, key_value[key]]);\n    } else {\n        key2_value.push([key, key_value[key]]);\n    }\n}\n\nmsg.payload = key1_value;\nvar msg2 = {};\nmsg2.payload = key2_value;\nreturn [msg, msg2];","outputs":"2","noerr":0,"x":486,"y":234,"wires":[["a6db13a3.5924f"],["d8efce74.27103"]]},{"id":"a6db13a3.5924f","type":"function","z":"95ab7967.6a5488","name":"Reduce","func":"context.global.n1--;\n\ncontext.global.data1[context.global.n1] = msg.payload;\n\nif (context.global.n1 === 0)\n{  \n    var tmp = [];\n    for (var i=0; i<context.global.data1.length; i++)\n    {\n        var input = context.global.data1[i];\n        for (var j=0; j<input.length; j++)\n        {\n            var key = input[j][0];\n            var value = input[j][1];\n            if (key in tmp)\n            {\n                tmp[key] += value;\n            } else {\n                tmp[key] = value;\n            }\n        }\n    }\n    \n    var output = [];\n    for (var key in tmp)\n    {\n        output.push([key, tmp[key]]);\n    }\n    msg.payload = output;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":694,"y":249,"wires":[["d0202e3f.2fdfd"]]},{"id":"d0202e3f.2fdfd","type":"debug","z":"95ab7967.6a5488","name":"Output","active":true,"console":"false","complete":"payload","x":834,"y":249,"wires":[]},{"id":"5ba772eb.a4588c","type":"function","z":"95ab7967.6a5488","name":"Map=3","func":"var map = 3;\n\ncontext.global.n1 = map;\ncontext.global.data1 = new Array(map);\n\ncontext.global.n2 = map;\ncontext.global.data2 = new Array(map);\n\nreturn msg;","outputs":1,"noerr":0,"x":173,"y":280,"wires":[["45046c79.bafb94","ffbf130e.0040f","1e9ff8b0.e16007"]]},{"id":"45046c79.bafb94","type":"template","z":"95ab7967.6a5488","name":"This is a pen.","field":"payload","format":"html","template":"This is a pen.","x":342,"y":234,"wires":[["da2fc73d.25d038"]]},{"id":"d8efce74.27103","type":"function","z":"95ab7967.6a5488","name":"Reduce","func":"context.global.n2--;\n\ncontext.global.data2[context.global.n2] = msg.payload;\n\nif (context.global.n2 === 0)\n{   \n    var tmp = [];\n    for (var i=0; i<context.global.data2.length; i++)\n    {\n        var input = context.global.data2[i];\n        for (var j=0; j<input.length; j++)\n        {\n            var key = input[j][0];\n            var value = input[j][1];\n            if (key in tmp)\n            {\n                tmp[key] += value;\n            } else {\n                tmp[key] = value;\n            }\n        }\n    }\n    \n    var output = [];\n    for (var key in tmp)\n    {\n        output.push([key, tmp[key]]);\n    }\n    msg.payload = output;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":696,"y":301,"wires":[["a3ae2ac4.5c51d8"]]},{"id":"a3ae2ac4.5c51d8","type":"debug","z":"95ab7967.6a5488","name":"Output","active":true,"console":"false","complete":"payload","x":835,"y":301,"wires":[]},{"id":"24723eda.db8dc2","type":"function","z":"95ab7967.6a5488","name":"Map","func":"var input = msg.payload.toLowerCase()\n                       .replace( /\\.$/, \"\")\n                       .split(/ |, /);\n// Map\nvar key_value = [];\nfor (var i=0; i<input.length; i++)\n{\n    var key = input[i];\n    if (key in key_value)\n    {\n        key_value[key]++;\n    } else {\n        key_value[key] = 1;\n    }\n}\n\n// Shuffle\nvar key1_value = [];\nvar key2_value = [];\nfor (var key in key_value)\n{\n    if ('a'<=key[0] && key[0]<='m')\n    {\n        key1_value.push([key, key_value[key]]);\n    } else {\n        key2_value.push([key, key_value[key]]);\n    }\n}\n\nmsg.payload = key1_value;\nvar msg2 = {};\nmsg2.payload = key2_value;\nreturn [msg, msg2];","outputs":"2","noerr":0,"x":487,"y":280,"wires":[["a6db13a3.5924f"],["d8efce74.27103"]]},{"id":"2047f8a.fdfb808","type":"function","z":"95ab7967.6a5488","name":"Map","func":"var input = msg.payload.toLowerCase()\n                       .replace( /\\.$/, \"\")\n                       .split(/ |, /);\n// Map\nvar key_value = [];\nfor (var i=0; i<input.length; i++)\n{\n    var key = input[i];\n    if (key in key_value)\n    {\n        key_value[key]++;\n    } else {\n        key_value[key] = 1;\n    }\n}\n\n// Shuffle\nvar key1_value = [];\nvar key2_value = [];\nfor (var key in key_value)\n{\n    if ('a'<=key[0] && key[0]<='m')\n    {\n        key1_value.push([key, key_value[key]]);\n    } else {\n        key2_value.push([key, key_value[key]]);\n    }\n}\n\nmsg.payload = key1_value;\nvar msg2 = {};\nmsg2.payload = key2_value;\nreturn [msg, msg2];","outputs":"2","noerr":0,"x":488,"y":326,"wires":[["a6db13a3.5924f"],["d8efce74.27103"]]},{"id":"ffbf130e.0040f","type":"template","z":"95ab7967.6a5488","name":"Give me a pen.","field":"payload","format":"html","template":"Give me a pen.","x":337,"y":280,"wires":[["24723eda.db8dc2"]]},{"id":"1e9ff8b0.e16007","type":"template","z":"95ab7967.6a5488","name":"This pen is small.","field":"payload","format":"html","template":"This pen is small.","x":330,"y":326,"wires":[["2047f8a.fdfb808"]]},{"id":"e8ae0aef.1751f8","type":"comment","z":"95ab7967.6a5488","name":"MapReduce pattern","info":"","x":173,"y":155,"wires":[]},{"id":"97307850.68cf88","type":"comment","z":"95ab7967.6a5488","name":"Set the map count ↑","info":"","x":133.91319274902344,"y":326.42590141296387,"wires":[]},{"id":"56a35efb.a95ca","type":"comment","z":"95ab7967.6a5488","name":"↓ input data to be processed","info":"","x":410.079833984375,"y":192.42582035064697,"wires":[]},{"id":"f5a268d1.0a5d98","type":"comment","z":"95ab7967.6a5488","name":"↑ seperates the words based on the first letter, a-m is sent to the top function, n-z is sent to the lower","info":"","x":743.4131469726562,"y":365.8516845703125,"wires":[]},{"id":"ef71c34d.108e4","type":"comment","z":"95ab7967.6a5488","name":"↓ reduce the arrays and count the total value","info":"","x":804.579833984375,"y":207.5184326171875,"wires":[]},{"id":"c21a5b5.f3de5a8","type":"comment","z":"95ab7967.6a5488","name":"After all inputs have returned,","info":"","x":755.5,"y":168.9166717529297,"wires":[]}]

This article was translated from this original article written in Japanese.