Node-RED: Lecture 6 – Example 6.2 Counting words in a string using a function Node

Next, let’s write a more complex function node that receives some text in a message payload, then outputs multiple messages containing all individual words and the number of times each word was used.

Listing 6.3 Word count function

  1. var outputMsgs = [];
  2. var wordMap = {};
  3. var sentence = msg.payload.replace(/[.,-\/#!$%\^&\*;:{}=\-_`~()]/g,””);
  4. sentence = sentence.replace(/\s{2,}/g,” “);
  5. var words = sentence.split(” “);
  6. for (var i = 0; i < words.length; i++) {
  7.   var lowerCaseWord = words[i].toLowerCase();
  8.   if (!wordMap[lowerCaseWord]) {
  9.     wordMap[lowerCaseWord] = 1;
  10.   } else {
  11.     wordMap[lowerCaseWord] = wordMap[lowerCaseWord] + 1;
  12.   }
  13. }
  14. for (var prop in wordMap) {
  15.   if( wordMap.hasOwnProperty( prop ) ) {
  16.     outputMsgs.push({payload:{word:prop,count:wordMap[prop]}});
  17.   }
  18. }
  19. return [outputMsgs];

In Listing 6.3, the list of output messages and an object to hold the word counts (Lines 1 and 2) is declared. In lines 4 and 5 the payload is ‘cleaned’, removing punctuation and extra spaces using regular expressions. Regular expressions are a very useful tool for text processing; you can learn more about regular expressions by looking at the Mozilla Developers pages for JavaScript (here).  Line 7 splits the text into multiple words, then iterates through the words, creating a mapping of the lowercase version of each word to word count called wordMap in Lines 8-15.  Lines 16 to 18 split the wordMap into multiple messages in the outputMsgs array[1].   Finally, in line 21, an array of this array of messages is returned, sending them all to the first output port one at a time[2].

Let’s wire this up and see it run with some example text.  First, create a function node, and copy in the code above. Call it word count. Then add an inject node and add the following text:

Figure 6.7 Inject node to test word count function node.

Add a debug node and wire up the flow as follows:

Figure 6.8 Test flow for word count function node.

When you click on the inject node, you should see the list of word counts in the debug pane:

Figure 6.9 Debug output from word count function node.

BACK to start of lecture             NEXT Example


[1] The check for hasOwnProperty() in line 17 is good practice when iterating through the properties of an object using the JavaScript in operator. It ensures you’re getting only properties you’ve added yourselve and none that you’ve (unexpectedly) inherited from the Object base class.

[2] Note that if you returned outputMsgs directly, the function node would attempt to send each message to a different output.

Author: Rodger Lea

Currently CEO of Internet of Things startup, Sense Tecnic, Dr. Lea has over 25 years experience spanning academic, large corporations and startups. For the last 10 years, he has started or helped start 4 new companies while managing an active research program (University of British Columbia, Canada and Lancaster University, UK) into distributed and ubiquitous computing, the IoT and Smart Cities.