Function - Insert additional keys from matching keys in array of objects

Hey all, I'm struggling with JS & looping through an array of objects, matching a key in each object and inserting associated values into another separate object.

I have this array of objects:

const cameraData = [
    { entity_name:"camera.1", lat: 31.2345, lon: -81.2345 },
    { entity_name:"camera.2", lat: 32.2345, lon: -81.2345 },
    { entity_name:"camera.3", lat: 33.2345, lon: -81.2345 },
    { entity_name:"camera.4", lat: 34.2345, lon: -81.2345 },
    { entity_name:"camera.5", lat: 35.2345, lon: -81.2345 },
    { entity_name:"camera.6", lat: 36.2345, lon: -81.2345 }
 ];

and I'm trying to match the first key "entity_name" to an incoming msg.payload single object from another function that emits a series of objects as they are queried earlier in the flow. The object looks like this:

{
  "attributes": 0,
  "context": 0,
  "last_changed": "2023-03-26T13:04:26.517Z",
  "last_updated": "2023-03-26T14:44:23.734Z",
  "timeSinceChangedMs": 6252438,
  "name": "Camera 1 - Front",
  "entity_name": "camera.1",
  "photoUrl": "http://0.0.0.0:8123/api/camera_proxy/camera.garden_shed_high?token=abc123"
}

I would like to append the keys "lat" and "lon" to each matching object, so it would look like this:

{
  "attributes": 0,
  "context": 0,
  "last_changed": "2023-03-26T13:04:26.517Z",
  "last_updated": "2023-03-26T14:44:23.734Z",
  "timeSinceChangedMs": 6252438,
  "name": "Camera 1 - Front",
  "entity_name": "camera.1",
  "photoUrl": "http://0.0.0.0:8123/api/camera_proxy/camera.garden_shed_high?token=abc123"
  "lat": "31.2345",
  "lon": "-81.2345"
}

Can anyone assist me please? Thanks!

Hi @mgottholsen

If I understand your requirement:

You can use the find method for an array, and use the found array item, to extract the values you need, and then add them to the incoming payload.

const cameraData = [
    { entity_name:"camera.1", lat: 31.2345, lon: -81.2345 },
    { entity_name:"camera.2", lat: 32.2345, lon: -81.2345 },
    { entity_name:"camera.3", lat: 33.2345, lon: -81.2345 },
    { entity_name:"camera.4", lat: 34.2345, lon: -81.2345 },
    { entity_name:"camera.5", lat: 35.2345, lon: -81.2345 },
    { entity_name:"camera.6", lat: 36.2345, lon: -81.2345 }
 ]

const matchedCamera = cameraData.find((Camera) => Camera.entity_name === msg.payload.entity_name)

if(matchedCamera !== undefined){
  msg.payload.lat = matchedCamera.lat
  msg.payload.lon = matchedCamera.lon
}

return msg;
1 Like

That was exactly it, thank you! Definitely more simple than what I was trying to do.

If that is your own array, I would structure it as a lookup object.
e.g.

{
    "camera.1":{"lat":31.2345,"lon":-81.2345},
    "camera.2":{"lat":32.2345,"lon":-81.2345},
    "camera.3":{"lat":33.2345,"lon":-81.2345},
    "camera.4":{"lat":34.2345,"lon":-81.2345},
    "camera.5":{"lat":35.2345,"lon":-81.2345},
    "camera.6":{"lat":36.2345,"lon":-81.2345}
}

That way you could do a simple lookup. You can add a if(msg.payload.lat) to return or not also.

const lookup = {
    "camera.1":{"lat":31.2345,"lon":-81.2345},
    "camera.2":{"lat":32.2345,"lon":-81.2345},
    "camera.3":{"lat":33.2345,"lon":-81.2345},
    "camera.4":{"lat":34.2345,"lon":-81.2345},
    "camera.5":{"lat":35.2345,"lon":-81.2345},
    "camera.6":{"lat":36.2345,"lon":-81.2345}
}

Object.assign(msg.payload, lookup[msg.payload.entity_name])
return msg;

Or You could also do it in a change node
e.g.

[{"id":"68cb0bbef3e3b379","type":"inject","z":"65617ffeb779f51c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{   \"attributes\": 0,   \"context\": 0,   \"last_changed\": \"2023-03-26T13:04:26.517Z\",   \"last_updated\": \"2023-03-26T14:44:23.734Z\",   \"timeSinceChangedMs\": 6252438,   \"name\": \"Camera 1 - Front\",   \"entity_name\": \"camera.1\",   \"photoUrl\": \"http://0.0.0.0:8123/api/camera_proxy/camera.garden_shed_high?token=abc123\" }","payloadType":"json","x":130,"y":4180,"wires":[["f1d77eb605782d62","bc9516c595e48c9d"]]},{"id":"f1d77eb605782d62","type":"function","z":"65617ffeb779f51c","name":"function 21","func":"const lookup = {\n    \"camera.1\":{\"lat\":31.2345,\"lon\":-81.2345},\n    \"camera.2\":{\"lat\":32.2345,\"lon\":-81.2345},\n    \"camera.3\":{\"lat\":33.2345,\"lon\":-81.2345},\n    \"camera.4\":{\"lat\":34.2345,\"lon\":-81.2345},\n    \"camera.5\":{\"lat\":35.2345,\"lon\":-81.2345},\n    \"camera.6\":{\"lat\":36.2345,\"lon\":-81.2345}\n}\n\nObject.assign(msg.payload, lookup[msg.payload.entity_name])\nif(msg.payload.lat) return msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":310,"y":4180,"wires":[["165ab9717d3ff499"]]},{"id":"bc9516c595e48c9d","type":"change","z":"65617ffeb779f51c","name":"","rules":[{"t":"set","p":"lookup","pt":"msg","to":"{\"camera.1\":{\"lat\":31.2345,\"lon\":-81.2345},\"camera.2\":{\"lat\":32.2345,\"lon\":-81.2345},\"camera.3\":{\"lat\":33.2345,\"lon\":-81.2345},\"camera.4\":{\"lat\":34.2345,\"lon\":-81.2345},\"camera.5\":{\"lat\":35.2345,\"lon\":-81.2345},\"camera.6\":{\"lat\":36.2345,\"lon\":-81.2345}}","tot":"json"},{"t":"set","p":"payload.lat","pt":"msg","to":"lookup[msg.payload.entity_name].lat","tot":"msg"},{"t":"set","p":"payload.lon","pt":"msg","to":"lookup[msg.payload.entity_name].lon","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":4240,"wires":[["d778b812bb579cea"]]},{"id":"165ab9717d3ff499","type":"debug","z":"65617ffeb779f51c","name":"debug 253","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":490,"y":4180,"wires":[]},{"id":"d778b812bb579cea","type":"debug","z":"65617ffeb779f51c","name":"debug 252","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":510,"y":4240,"wires":[]}]

1 Like

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