Can I increment a (possibly null) context variable in a change node?

I am trying to count the number of each node type in flows.json. Not difficult using a function but I would like to do it without writing javascript code.

So read the file and split the resulting array gives me one message per node with the node type in msg.payload.type

How can I use a change node to increment a flow counter eg flow.messagecounts["function"] += 1 ?

I have tried this but I think because flow.messagecounts[msg.payload.type] is initially undefined, the increment never works?

[{"id":"e14a6f161d1bebd0","type":"inject","z":"db04fd79f3a93d19","g":"8b1229d76a3c7516","name":"go","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":110,"y":600,"wires":[["ac2c02ad65697585"]]},{"id":"c932017ee7d0618e","type":"file in","z":"db04fd79f3a93d19","g":"8b1229d76a3c7516","name":"flows.json","filename":".node-red/flows.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":500,"y":600,"wires":[["d9dd00679dbd79dc"]]},{"id":"d9dd00679dbd79dc","type":"json","z":"db04fd79f3a93d19","g":"8b1229d76a3c7516","name":"","property":"payload","action":"","pretty":false,"x":630,"y":600,"wires":[["232a1f4fb159234b"]]},{"id":"232a1f4fb159234b","type":"split","z":"db04fd79f3a93d19","g":"8b1229d76a3c7516","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":750,"y":600,"wires":[["18620a135bbb3d51"]]},{"id":"ac2c02ad65697585","type":"change","z":"db04fd79f3a93d19","g":"8b1229d76a3c7516","name":"delete flow.messagecounts","rules":[{"t":"delete","p":"messagecounts","pt":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":300,"y":600,"wires":[["c932017ee7d0618e"]]},{"id":"18620a135bbb3d51","type":"change","z":"db04fd79f3a93d19","g":"8b1229d76a3c7516","name":"","rules":[{"t":"set","p":"increment","pt":"msg","to":"messagecounts[msg.payload.type]","tot":"flow"},{"t":"set","p":"increment","pt":"msg","to":"increment + 1","tot":"jsonata"},{"t":"set","p":"messagecounts[msg.payload.type]","pt":"flow","to":"increment","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":680,"y":660,"wires":[[]]}]

You could use a Switch to test for undefined, and a change node to set it to zero if so. Then increment it in the next node.

I expect someone will come up with a one-liner JSONata expression to count them.

You can use the $sum() trick

$sum([$$.increment]) + 1

I thought it might be possible to do the whole thing in JSONata, feeding in the flows file and ending up with the total node count for each type.

Yes I am sure it is, and save it all to context

That's a good thought! It's a json file so I am sure that would be possible.

But what I am actually doing is revising my personal recipe for embedding awk in a template node. The Node-red version is for comparison.
I only thought of flows.json because it's there and has records spanning multiple lines.
A magical sentence of jsonata will only reinforce the idea that awk is last century technology!

I'm having trouble with @Colin's switch node suggestion. something odd is going on. More investigation needed.

JSONata will indeed have trouble incrementing an undefined value... but you can protect your expression by using this ternary:

increment ? increment + 1 : 1

I know you don't want to write "function" code, but just for reference you can easily group/count the entire flow using this JSONata expression:

payload { type: $count($) }

I think this flow does the same thing, but using the localhost:1880/admin/flows url to get the flow JSON (instead of trying to locate, read, and parse the flows.json file).

[{"id":"e14a6f161d1bebd0","type":"inject","z":"3729ccee2b11666e","name":"go","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":110,"y":100,"wires":[["95d9639c08ce944b"]]},{"id":"30d599f146373c72","type":"change","z":"3729ccee2b11666e","name":"flow: messagecounts","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload { type: $count($) }","tot":"jsonata"},{"t":"set","p":"messagecounts","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":100,"wires":[["7e3ed51935ab040b"]]},{"id":"7e3ed51935ab040b","type":"debug","z":"3729ccee2b11666e","name":"type: count","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":670,"y":100,"wires":[]},{"id":"95d9639c08ce944b","type":"http request","z":"3729ccee2b11666e","name":"GET /admin/flows","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://localhost:1880/admin/flows","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":270,"y":100,"wires":[["30d599f146373c72"]]}]

Since the entire flows.json is processed into a summary object, I just replace the whole flow variable.

That's the answer!
So using that I have

[{"id":"112a69ed01730f17","type":"inject","z":"3378d78bb37c052e","name":"go","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":90,"y":60,"wires":[["d51cde875f4b5a0a"]]},{"id":"b23439ad43e95d6e","type":"file in","z":"3378d78bb37c052e","name":"flows.json","filename":".node-red/flows.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":480,"y":60,"wires":[["69782fbbccdc6b91"]]},{"id":"69782fbbccdc6b91","type":"json","z":"3378d78bb37c052e","name":"","property":"payload","action":"","pretty":false,"x":610,"y":60,"wires":[["cb63f29ecd2aaa90"]]},{"id":"cb63f29ecd2aaa90","type":"split","z":"3378d78bb37c052e","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":730,"y":60,"wires":[["ba5835d2d3c68141"]]},{"id":"d51cde875f4b5a0a","type":"change","z":"3378d78bb37c052e","name":"delete flow.messagecounts","rules":[{"t":"set","p":"messagecounts","pt":"flow","to":"{\"ui_spacer\": 2}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":280,"y":60,"wires":[["b23439ad43e95d6e"]]},{"id":"ba5835d2d3c68141","type":"change","z":"3378d78bb37c052e","name":"Count each node type","rules":[{"t":"set","p":"increment","pt":"msg","to":"messagecounts[msg.payload.type]","tot":"flow"},{"t":"set","p":"increment","pt":"msg","to":"increment ? increment + 1 : 1","tot":"jsonata"},{"t":"set","p":"messagecounts[msg.payload.type]","pt":"flow","to":"increment","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":140,"y":120,"wires":[["9893a5a9708d4e00"]]},{"id":"9893a5a9708d4e00","type":"switch","z":"3378d78bb37c052e","name":"Last msg part?","property":"parts.count","propertyType":"msg","rules":[{"t":"eq","v":"parts.index + 1","vt":"jsonata"}],"checkall":"true","repair":false,"outputs":1,"x":340,"y":120,"wires":[["6c23c7047b383eb2"]]},{"id":"b121e56aabb8829a","type":"debug","z":"3378d78bb37c052e","name":"debug 482","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":750,"y":120,"wires":[]},{"id":"6c23c7047b383eb2","type":"change","z":"3378d78bb37c052e","name":"Final counts to payload","rules":[{"t":"set","p":"payload","pt":"msg","to":"messagecounts","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":120,"wires":[["b121e56aabb8829a"]]}]

None of the other approaches worked for me, sorry guys :thinking:
I appreciate the suggestions though.

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