Simplify function node

Hi,

I have the following function node that I'm trying to simplify, instead of listing all array items is there a way to make it loop them?

The number of array items may not always be the same.

msg.payload = {
    "@type": "MessageCard",
    "@context": "https://schema.org/extensions",
    "themeColor": "0078D7",
    "title": "A Record change",
    "summary": "Card \"A Record change\"",
    "sections": [
        {
            "facts": [
                { "name": "Warning", "value": msg.topicstatus },
                { "name": "A record", "value": msg.domain },
                { "name": "Added IP", "value": msg.payload[0] },
                { "name": "Added IP", "value": msg.payload[1] },
                { "name": "Added IP", "value": msg.payload[2] },
                { "name": "Added IP", "value": msg.payload[3] },
                { "name": "Added IP", "value": msg.payload[4] },
                { "name": "Added IP", "value": msg.payload[5] },
                { "name": "Added IP", "value": msg.payload[6] },
                { "name": "Added IP", "value": msg.payload[7] },
                { "name": "Added IP", "value": msg.payload[8] },
                { "name": "Added IP", "value": msg.payload[9] },
                { "name": "Added IP", "value": msg.payload[10] },
                { "name": "Added IP", "value": msg.payload[11] },
                { "name": "Added IP", "value": msg.payload[12] },
                { "name": "Added IP", "value": msg.payload[13] }],
        }
    ]
}
return msg;

Of course, that is just simple JavaScript. If you aren't familiar, you may wish to quickly run through a simple JavaScript course.

As msg.payload is clearly an array, you can loop through arrays in several ways but this is the one I tend to use most:

msg.payload.forEach( element => {
   // do stuff here, element contains each of the payload elements msg.payload[x]
}

Something like this (untested):

const newpayload = {
    "@type": "MessageCard",
    "@context": "https://schema.org/extensions",
    "themeColor": "0078D7",
    "title": "A Record change",
    "summary": "Card \"A Record change\"",
    "sections": [
        {
            "facts": [
                { "name": "Warning", "value": msg.topicstatus },
                { "name": "A record", "value": msg.domain },
            ]
        }
    ]
}

msg.payload.forEach( element => {
    newpayload.sections.facts.push(  { "name": "Added IP", "value": element} )
}

return { topic: msg.topic, payload: newpayload }

Note - this was in reply to someone who hijacked the thread and subsequently deleted her posts. It's not relevant to the original poster's enquiry

I cannot make sense of your example msg.payload, the use of single and double quotes looks wrong.

However, at least in MySQL, you can have a statement like this

INSERT INTO fruits (id, name, price) VALUES (17, "Peach", 4.5)
ON DUPLICATE KEY UPDATE name = "Peach", price = 4.5;

A function node uses javascript, yes.

In your first post you said that you wanted to insert new data into a database or update existing records.
Now you say that you want to display new data on a web page.

I expect it is possible to do both of these things in a single function node. But if I were doing it I would break the task down between nodes appropriate to each step.

Perhaps it would make things clearer if you post your flow as it currently is, including some real data. Use the "preformatted text" option to post your code.

Sorry, no.
But I (and others) am happy to help in the forum.

no worries.
well the diagram and the query is a prototype for the project so unfortunately, cannot share it. but thanks for your time though. :slight_smile:

Hi,

Thanks for your example. I had to edit it slightly as there was single bit of code that needed adding above the return line at the bottom.

msg.payload.forEach( element => {
    newpayload.sections.facts.push(  { "name": "Added IP", "value": element} )
    }
)
return { topic: msg.topic, payload: newpayload }

When I now run this I get the following error back.

TypeError: Cannot read property 'push' of undefined

My full config

const newpayload = {
    "@type": "MessageCard",
    "@context": "https://schema.org/extensions",
    "themeColor": "0078D7",
    "title": "A Record change",
    "summary": "Card \"A Record change\"",
    "sections": [
        {
            "facts": [
                { "name": "Warning", "value": msg.topicstatus },
                { "name": "A record", "value": msg.domain },
            ]
        }
    ]
}

msg.payload.forEach( element => {
    newpayload.sections.facts.push(  { "name": "Added IP", "value": element} )
    }
)
return { topic: msg.topic, payload: newpayload }

You can also use a JSONata expression in a change node -- which avoids needing to know how many elements are in the payload array:

{
    "@type": "MessageCard",
    "@context": "https://schema.org/extensions",
    "themeColor": "0078D7",
    "title": "A Record change",
    "summary": "Card \"A Record change\"",
    "sections": [
        {
            "facts": [
                { "name": "Warning", "value": msg.topicstatus },
                { "name": "A record", "value": msg.domain },
                payload.{ "name": "Added IP", "value": $ }
            ]
        }
    ]
}

Just make sure to select the J: expression value (not JSON ;*) -- you can even copy some real data from your debug nodes into the Test expression area, and see how the output will look before deploying your flow, like so:

Many people prefer to use plain Javascript code, but I like to use JSONata for restructuring data, like in this use case... so I'm including an example in case you had never tried to use expressions before.

Thankyou for your detailed explanation and example, I've certainly learnt from that.

That is now working.