How can I iterate recursivly throgh msg.payload to find a specific key/Value

I have a nested array that I'm trying to find a specific key/value in.
Path: payload[0][11].mac
Value: 10:2b:41:11:c8:b6

To find the value I'm iterating using forEach:

msg.payload.forEach(function (key,value) {
    if (value == '10:2b:41:11:c8:b6') {
        node.warn("Found!")
    }
});

However, the forEach function only seems to return the first level? How can I iterate throgh all the levels to find the key/value? The path [0][11] will change.

Thanks,
Tom

If it is always a 2 level array then a simple for loop followed by a filter will do it...

const findMac = msg.topic
const data = msg.payload
const foundEntries = []
for (let index = 0; index < data.length; index++) {
    const element = data[index]
    foundEntries.push(... element.filter(e => e.mac === findMac))
}
msg.payload = foundEntries
return msg

Demo Flow...

[{"id":"945d1ab3b1d5ed07","type":"inject","z":"57d91feb40155fe2","name":"find mac 10:2b:41:11:c8:b6","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"10:2b:41:11:c8:b6","x":1630,"y":140,"wires":[["6e34f7eef0b64fdc"]]},{"id":"692493a1c2cf9554","type":"function","z":"57d91feb40155fe2","name":"find mac` in `payload[x][y]`","func":"const findMac = msg.topic\nconst data = msg.payload\nconst foundEntries = []\nfor (let index = 0; index < data.length; index++) {\n    const element = data[index]\n    foundEntries.push(... element.filter(e => e.mac === findMac))\n}\nmsg.payload = foundEntries\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1660,"y":200,"wires":[["d65ea97a17dc8060"]]},{"id":"d65ea97a17dc8060","type":"debug","z":"57d91feb40155fe2","name":"debug 8","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1880,"y":200,"wires":[]},{"id":"6e34f7eef0b64fdc","type":"change","z":"57d91feb40155fe2","name":"generate fake data[x][y]","rules":[{"t":"set","p":"payload","pt":"msg","to":"[[{\"mac\":\"10:2b:40:11:c8:10\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:40:11:c8:11\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:40:11:c8:12\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:40:11:c8:13\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:40:11:c8:a3\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:40:11:c8:a4\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:40:11:c8:b5\",\"ip\":\"aaa.bbb.ccc.ddd\"}],[{\"mac\":\"10:2b:41:11:c8:10\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:11\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:12\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:13\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:a3\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:a7\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:b7\",\"ip\":\"aaa.bbb.ccc.ddd\"}],[{\"mac\":\"10:2b:42:11:c8:10\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:42:11:c8:11\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:42:11:c8:12\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:b6\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:42:11:c8:a3\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:42:11:c8:a4\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:42:11:c8:b5\",\"ip\":\"aaa.bbb.ccc.ddd\"}],[{\"mac\":\"10:2b:44:11:c8:10\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:44:11:c8:11\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:44:11:c8:12\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:44:11:c8:13\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:44:11:c8:a3\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:44:11:c8:a4\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:44:11:c8:b5\",\"ip\":\"aaa.bbb.ccc.ddd\"}]]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":1890,"y":140,"wires":[["692493a1c2cf9554"]]},{"id":"a95eb283c4d740ea","type":"inject","z":"57d91feb40155fe2","name":"find mac 10:2b:44:11:c8:13","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"10:2b:44:11:c8:13","x":1630,"y":100,"wires":[["6e34f7eef0b64fdc"]]},{"id":"9b07bc6546ba2b41","type":"inject","z":"57d91feb40155fe2","name":"find mac id:0n:ot:ex:is:t!","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"id:0n:ot:ex:is:t!","x":1620,"y":60,"wires":[["6e34f7eef0b64fdc"]]}]

EDIT

This is likely very simple with a change node and JSONata - I just dont do JSONata

Ok, so here is the JSONata (to satisfy my mind)...

$filter(payload.**, function($v, $i, $a) { $v.mac = topic })

Demo Flow...

[{"id":"945d1ab3b1d5ed07","type":"inject","z":"57d91feb40155fe2","name":"find mac 10:2b:41:11:c8:b6","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"10:2b:41:11:c8:b6","x":1630,"y":140,"wires":[["6e34f7eef0b64fdc"]]},{"id":"692493a1c2cf9554","type":"function","z":"57d91feb40155fe2","name":"find mac` in `payload[x][y]`","func":"const findMac = msg.topic\nconst data = msg.payload\nconst foundEntries = []\nfor (let index = 0; index < data.length; index++) {\n    const element = data[index]\n    foundEntries.push(... element.filter(e => e.mac === findMac))\n}\nmsg.payload = foundEntries\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1660,"y":200,"wires":[["d65ea97a17dc8060"]]},{"id":"d65ea97a17dc8060","type":"debug","z":"57d91feb40155fe2","name":"debug 8","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1880,"y":200,"wires":[]},{"id":"6e34f7eef0b64fdc","type":"change","z":"57d91feb40155fe2","name":"generate fake data[x][y]","rules":[{"t":"set","p":"payload","pt":"msg","to":"[[{\"mac\":\"10:2b:40:11:c8:10\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:40:11:c8:11\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:40:11:c8:12\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:40:11:c8:13\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:40:11:c8:a3\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:40:11:c8:a4\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:40:11:c8:b5\",\"ip\":\"aaa.bbb.ccc.ddd\"}],[{\"mac\":\"10:2b:41:11:c8:10\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:11\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:12\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:13\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:a3\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:a7\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:b7\",\"ip\":\"aaa.bbb.ccc.ddd\"}],[{\"mac\":\"10:2b:42:11:c8:10\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:42:11:c8:11\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:42:11:c8:12\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:41:11:c8:b6\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:42:11:c8:a3\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:42:11:c8:a4\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:42:11:c8:b5\",\"ip\":\"aaa.bbb.ccc.ddd\"}],[{\"mac\":\"10:2b:44:11:c8:10\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:44:11:c8:11\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:44:11:c8:12\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:44:11:c8:13\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:44:11:c8:a3\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:44:11:c8:a4\",\"ip\":\"aaa.bbb.ccc.ddd\"},{\"mac\":\"10:2b:44:11:c8:b5\",\"ip\":\"aaa.bbb.ccc.ddd\"}]]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":1890,"y":140,"wires":[["692493a1c2cf9554","958bcf257db6d1b8"]]},{"id":"a95eb283c4d740ea","type":"inject","z":"57d91feb40155fe2","name":"find mac 10:2b:44:11:c8:13","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"10:2b:44:11:c8:13","x":1630,"y":100,"wires":[["6e34f7eef0b64fdc"]]},{"id":"9b07bc6546ba2b41","type":"inject","z":"57d91feb40155fe2","name":"find mac id:0n:ot:ex:is:t!","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"id:0n:ot:ex:is:t!","x":1620,"y":60,"wires":[["6e34f7eef0b64fdc"]]},{"id":"958bcf257db6d1b8","type":"change","z":"57d91feb40155fe2","name":"find mac JSONata","rules":[{"t":"set","p":"payload","pt":"msg","to":"$filter(payload.**, function($v, $i, $a) { $v.mac = topic })","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1640,"y":260,"wires":[["0a28d2ea0ed57687"]]},{"id":"0a28d2ea0ed57687","type":"debug","z":"57d91feb40155fe2","name":"debug 9","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1880,"y":260,"wires":[]}]

Just to note the JSONata $filter function is not required,
this should work
[$$.payload.**[$.mac = $$.topic]]

1 Like

At least I tried JSONata :wink: :rofl:

3 Likes

I see, i'm still recovering from the shock!

3 Likes

Just goes to show why any sensible person would use a function node. :wink:

2 Likes

Thanks guys, a lot of good suggestions that pointed me the right way. I ended doing it like this, which is useful for whatever key in whatever depth :slight_smile:

function recurse(data) {

    data.forEach(function (element){
        if(Array.isArray(element)) {
            recurse(element);
        } else {
            if (element.hasOwnProperty('mac')) {
                    node.warn(element['mac']);
            }
        }
    });
}


recurse(msg.payload);

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