node-redjsonata

Search for an element in a global context messages array in node-red


Context

I defined in the context of my node-red instance a global context variable "devices" with each element defined by the {device_id, agent_id} element pair that it obtains from the values in the received message payload. Here is an example of a message and the global var:

msg.payload: {"agent_id":"agent01","device_id":"device01"}
devices: [{"agent_id":"agent01","device_id":"device01"},{"agent_id":"agent02","device_id":"device01"},{"agent_id":"agent01","device_id":"device03"}]

I would like to make it so that after receiving the message, the flow via the change and switch nodes (NO function node) would look to see if the device_id - agent_id pair is already present in the global variable, and if it is not present to add it to the array.

My attempt

I tried to define the value of a boolean format element in the "msg.exists" attribute message via a change node with the JSONata expression:

$exists($globalContext('devices')[agent_id = $.payload.agent_id and device_id = $.payload.device_id])

and then via a switch node I route the stream according to the value of msg.exist: if true I add no element, if false I add it.

The problem

However, the value of msg.exist is always equal to false, even when I supply it with values that are present in the global variable.

Could you provide a solution to my problem?

enter image description here


Solution

  • I belive the issue is in the filter. Try adding another $ to get the agent_id from the root object, like so:

    $exists($globalContext('devices')[agent_id = $$.payload.agent_id and device_id = $$.payload.device_id])
    

    If that doesn't work, try changing $globalContext('devices') to $.globalContext.devices.

    Also, if your json input is:

    {
      "payload": {
        "agent_id": "agent01",
        "device_id": "device01"
      },
      "globalContext": {
        "devices": [
          {
            "agent_id": "agent01",
            "device_id": "device01"
          },
          {
            "agent_id": "agent01",
            "device_id": "device02"
          },
          {
            "agent_id": "agent01",
            "device_id": "device03"
          }
        ]
      }
    }
    

    And your expression is:

    $.globalContext.devices[agent_id = $$.payload.agent_id and device_id = $$.payload.device_id]
    

    or this

    (
      $payloadAgentId := $.payload.agent_id;
      $payloadDeviceId := $.payload.device_id;
      $.globalContext.devices[agent_id = $payloadAgentId and device_id = $payloadDeviceId]
    )
    

    The result will be truthy:

    {
      "agent_id": "agent01",
      "device_id": "device01"
    }