# Change msg.topic via function

**URL:** <https://discourse.nodered.org/t/change-msg-topic-via-function/24086>\
**Category:** General\
**Created:** [2 April 2020 10:28 UTC](https://discourse.nodered.org/t/change-msg-topic-via-function/24086 "2020-04-02T10:28:44Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![agoralive](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/agoralive/32/14407_2.png) [@agoralive](https://discourse.nodered.org/u/agoralive)\
**Post date:** [2 April 2020 10:28 UTC](https://discourse.nodered.org/t/change-msg-topic-via-function/24086/1 "2020-04-02T10:28:44Z")

</div>

So 🙂

Always found this to be a nice way to start asking questions.

I have an mqtt topic with a message where I wan't to keep the message but change the topic into 8 different topics.

I have an incomming mqtt:

topic = first/second/third/fourth/0  
message = HelloWorld

Put together for simplicity:  
first/second/third/fourth/0-\>HelloWorld

How do I "convert" this into 8 messages, which only changes the last number in the string topic, but keeps the message

Like this:

first/second/third/fourth/1-\>HelloWorld  
first/second/third/fourth/2-\>HelloWorld  
first/second/third/fourth/3-\>HelloWorld  
first/second/third/fourth/4-\>HelloWorld  
first/second/third/fourth/5-\>HelloWorld  
first/second/third/fourth/6-\>HelloWorld  
first/second/third/fourth/7-\>HelloWorld  
first/second/third/fourth/8-\>HelloWorld

Topics are not the same length everytime, so it need's to be something where the last character in the topic is changed there can be no counting (unless this can be done from the back)

---

<div class="post-metadata">

**Author:** ![JGKK](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jgkk/32/18515_2.png) [@JGKK](https://discourse.nodered.org/u/JGKK)\
**Post date:** [2 April 2020 10:45 UTC](https://discourse.nodered.org/t/change-msg-topic-via-function/24086/2 "2020-04-02T10:45:28Z")

</div>

Hello,  
If you want to do this in a function node you will have to look at two concepts.  
First is iterating over something for a specified number of times. You can use the for loop for this:

> **[for](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for)**
>
> The for statement creates a loop that consists of three optional expressions, enclosed in parentheses and separated by semicolons, followed by a statement (usually a block statement) to be executed in the loop.

  
You can do this to do something eight times.  
Secondly you want to do some string manipulation. You can have a look at regex for this. Javascript has some build in regex functions. Have a look at:  

> **[String.prototype.replace()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace)**
>
> The replace() method returns a new string with some or all matches of a pattern replaced by a replacement.

  
and:  
[https://www.rexegg.com/](https://www.rexegg.com/)  
and  

> **[Online regex tester and debugger: PHP, PCRE, Python, Golang and JavaScript](https://regex101.com/)**
>
> Regex101 allows you to create, debug, test and have your expressions explained for PHP, PCRE, Python, Golang and JavaScript. The website also features a community where you can share useful expressions.

  
Here you can learn about and test regular expressions. You will have to look at anchors, quantifiers and tokens.  
A combination of those two. Eg a replace with a regex inside a for loop that looks for the numbers at the end of the string.  
you will also have to have a look at the node.send() function to send things from the function node while in the loop:  
[https://nodered.org/docs/user-guide/writing-functions](https://nodered.org/docs/user-guide/writing-functions)  
If you have more questions or need help figuring it out just ask.  
stay healthy and have fun, Johannes

---

<div class="post-metadata">

**Author:** ![agoralive](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/agoralive/32/14407_2.png) [@agoralive](https://discourse.nodered.org/u/agoralive)\
**Post date:** [2 April 2020 13:05 UTC](https://discourse.nodered.org/t/change-msg-topic-via-function/24086/3 "2020-04-02T13:05:56Z")

</div>

Hmm, here I was hoping for a simple solution... Well

I came up with this:

```auto
original = msg.topic
var first = original.slice(0, original.length-1);
msg.topic = first + 1;
node.send (msg);

second = first
var second = second.slice(0, second.length-0);
msg.topic = second + 2;
node.send (msg);

third = second
var third = third.slice(0, third.length-0);
msg.topic = third + 3;
node.send (msg);

fourth = third
var fourth = fourth.slice(0, fourth.length-0);
msg.topic = fourth + 4;
node.send (msg);

fifth = fourth
var fifth = fifth.slice(0, fifth.length-0);
msg.topic = fifth + 5;
node.send (msg);

sixt = fifth
var sixt = sixt.slice(0, sixt.length-0);
msg.topic = sixt + 6;
node.send (msg);

seventh = sixt
var seventh = seventh.slice(0, seventh.length-0);
msg.topic = seventh + 7;
node.send (msg);

eight = seventh
var eight = eight.slice(0, eight.length-0);
msg.topic = eight + 8;

return msg

```

Now I will have to test to see if this actually does what I hope it will....

---

<div class="post-metadata">

**Author:** ![JGKK](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jgkk/32/18515_2.png) [@JGKK](https://discourse.nodered.org/u/JGKK)\
**Post date:** [2 April 2020 13:23 UTC](https://discourse.nodered.org/t/change-msg-topic-via-function/24086/4 "2020-04-02T13:23:29Z")

</div>

Have a look at this:

```auto
let newtopic = msg.topic;
for(i=0;i<8;i++){
    newtopic = newtopic.replace(/[0-9]*$/g, "")+(i+1);
    node.send({payload:msg.payload,topic:newtopic});
}
node.done();
return;

```

This is what I described above utilizing the methods i linked.  
We use a for loop to do something eight times

```auto
for(i=0;i<8;i++)

```

we than use the regex replace to replace numbers at the back of the topic string with nothing hence the `""` and use the counter var `i` of the for loop to add a new number to the string (we have to add 1 as the counter starts at 0)

```auto
newtopic = newtopic.replace(/[0-9]*$/g, "")+(i+1);

```

have a look here for what this specific regular expression does [https://regex101.com/r/nA7x1m/2](https://regex101.com/r/nA7x1m/2)  
Now we use the asynchronus `node.send()` to send the result of each loop.

```auto
node.send({payload:msg.payload,topic:newtopic});

```

after the loop we use the `node.done()` to tell the runtime that the function node is finished and return it without sending a further message.  
I hope this makes sense.  
Johannes

---

<div class="post-metadata">

**Author:** ![cymplecy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/cymplecy/32/2773_2.png) [@cymplecy](https://discourse.nodered.org/u/cymplecy)\
**Post date:** [2 April 2020 13:26 UTC](https://discourse.nodered.org/t/change-msg-topic-via-function/24086/5 "2020-04-02T13:26:56Z")

</div>

If you just want to do this specific case then switch followed by eight parallel change nodes to change the topic

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/e/9ed75776915f9e9bffd83c19749652bf50ab773c.jpeg)

---

<div class="post-metadata">

**Author:** ![agoralive](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/agoralive/32/14407_2.png) [@agoralive](https://discourse.nodered.org/u/agoralive)\
**Post date:** [2 April 2020 13:31 UTC](https://discourse.nodered.org/t/change-msg-topic-via-function/24086/6 "2020-04-02T13:31:11Z")

</div>

Hi

That works too, BUT: I have NO idea or do I understand how that worked.....

With \<8 and 0-9

Could I change these into \<20 and 0-21 if I wanted ot execute more topics?

---

<div class="post-metadata">

**Author:** ![agoralive](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/agoralive/32/14407_2.png) [@agoralive](https://discourse.nodered.org/u/agoralive)\
**Post date:** [2 April 2020 13:33 UTC](https://discourse.nodered.org/t/change-msg-topic-via-function/24086/7 "2020-04-02T13:33:26Z")

</div>

@cymplecy This was what I did before, but required that I knew which topics were incomming.... I wanted a solution where I could handle all incomming topics (ofcause in specific topic levels)

---

<div class="post-metadata">

**Author:** ![agoralive](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/agoralive/32/14407_2.png) [@agoralive](https://discourse.nodered.org/u/agoralive)\
**Post date:** [2 April 2020 13:37 UTC](https://discourse.nodered.org/t/change-msg-topic-via-function/24086/8 "2020-04-02T13:37:08Z")

</div>

> [@agoralive](#):
>
> Hi
> 
> That works too, BUT: I have NO idea or do I understand how that worked.....
> 
> With \<8 and 0-9
> 
> Could I change these into \<20 and 0-21 if I wanted ot execute more topics?

Tried but that did not work 🙂

Problem occured when there was 2 number which needed to be deleted, and this was not math.......

---

<div class="post-metadata">

**Author:** ![JGKK](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jgkk/32/18515_2.png) [@JGKK](https://discourse.nodered.org/u/JGKK)\
**Post date:** [2 April 2020 13:50 UTC](https://discourse.nodered.org/t/change-msg-topic-via-function/24086/9 "2020-04-02T13:50:03Z")

</div>

Its all explained in the links I posted. The [0-9] is part of the regular expression and just means only look for numbers. The only thing you need to change is the i\<8 in the for loop.  
So I ll explain what the things in the for loop definition do and what the regex does:

```auto
for(i=0;i<8;i++)

```

`i` is our counter var we give it a starting value, in this case 0 `i=0`  
we want the loop to run eight times so this is what the second part does:  
`i<8` the loop will run as long as i is smaller than 8.  
the third part defines something we do to i on every loop, in this case `i++`  
++ is an increment operator [https://codeburst.io/javascript-increment-and-decrement-8c223858d5ed](https://codeburst.io/javascript-increment-and-decrement-8c223858d5ed)  
so it counts up i by one on every loop, so its the same as writing `i+=1` or `i=i+1`  
So i will be 0 than 1 than 2 than 3... but it will never reach eight as the loop will break as soon as it is \>=8 because the second part wont be true anymore.

```auto
/[0-9]*$/g

```

is a regular expression which can be used to make rules to find stuff in strings. They are something that is used in allmost all programming languages.  
This one has three main parts  
`[0-9]` means were only looking for number characters in the string  
`*` means dont stop after you find the first number because their might be more  
`$` anchors the search to the back of the string  
So the regex will find any number characters at the back of a string.  
[https://regex101.com/r/nA7x1m/2](https://regex101.com/r/nA7x1m/2) click on the link and play around with it, its great to understand this and this site is very good at showing you whats going on.

I hope this explains some of it. Those methods are great to have in your toolkit.  
Best regards Johannes

---

<div class="post-metadata">

**Author:** ![JGKK](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jgkk/32/18515_2.png) [@JGKK](https://discourse.nodered.org/u/JGKK)\
**Post date:** [2 April 2020 13:52 UTC](https://discourse.nodered.org/t/change-msg-topic-via-function/24086/10 "2020-04-02T13:52:48Z")

</div>

```auto
[{"id":"e998f937.a449e8","type":"function","z":"f954564f.03e718","name":"","func":"let newtopic = msg.topic;\nfor(i=0;i<20;i++){\n newtopic = newtopic.replace(/[0-9]*$/g, \"\")+(i+1);\n node.send({payload:msg.payload,topic:newtopic});\n}\nnode.done();\nreturn;","outputs":1,"noerr":0,"x":470,"y":3620,"wires":[["1b24bd31.7fe503"]]},{"id":"ffe0d075.aa1f1","type":"inject","z":"f954564f.03e718","name":"","topic":"test/thisisatest/6089","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":320,"y":3620,"wires":[["e998f937.a449e8"]]},{"id":"1b24bd31.7fe503","type":"debug","z":"f954564f.03e718","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":630,"y":3620,"wires":[]}]

```

Have a look at this, the topic has 4 numbers at the end and the loop repeats 20 times

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [16 April 2020 13:52 UTC](https://discourse.nodered.org/t/change-msg-topic-via-function/24086/11 "2020-04-16T13:52:50Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
