# Saving a single value to context

**URL:** <https://discourse.nodered.org/t/saving-a-single-value-to-context/46670>\
**Category:** General\
**Created:** [3 June 2021 20:59 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670 "2021-06-03T20:59:17Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [3 June 2021 20:59 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/1 "2021-06-03T20:59:17Z")

</div>

I'm saving a JSON object to file context similar to;

```auto
{
  "192-168-1-10": [
    {
      "last_on": 1622751269764
    },
    {
      "last_off": 1622751272068
    }
  ],
  "192-16-1-13": [
    {
      "last_on": 1622751772269
    },
    {
      "last_off": 1622751774284
    }
  ]
}

```

The data is constructed as; `"192-168-1-10` which represents the IP address of a connected device, and `last_on` & `last_off` are self explanatory timestamps.  
Presently, when any of the status's change within each of the array's, I need to reconstruct the whole array, and then write it to context.  
`global.set(mystore.192-16-1-13, newarray);`  
The size of the arrays are likely to increase as new features are added, and ideally I would like to just update one value directly, leaving the other values in the respective array unchanged.  
Is there a way to write a revised timestamp directly to one of the values, without writing the whole array?

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [3 June 2021 21:19 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/2 "2021-06-03T21:19:22Z")

</div>

Must your data be in that format (in particular the array with objects)? If you use object properties you can simply update the value.

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [3 June 2021 21:28 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/3 "2021-06-03T21:28:14Z")

</div>

Using my data above, can you give an example of what structure you recommend pls.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [3 June 2021 21:28 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/4 "2021-06-03T21:28:39Z")

</div>

Sure. Ginnie a couple of mins.

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [3 June 2021 21:34 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/5 "2021-06-03T21:34:20Z")

</div>

> [@Paul-Reed](#):
>
> global.set(mystore.192-16-1-13, newarray);

`global.set("mystore.192-16-1-13[0].last_on", 16227512720888);`  
should work, But as Steve said would be best with objects.

something like this, will allow you to add mre properties as and when.

```auto
{
    "192-168-1-10": {
        "last_on": {
            "time": 1622751269764
        },
        "last_off": {
            "time": 1622751272068
        }
    },
    "192-16-1-13": {
        "last_on": {
            "time": 1622751772269
        },
        "last_off": {
            "time": 1622751774284
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [3 June 2021 21:41 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/6 "2021-06-03T21:41:02Z")

</div>

```auto
{
  "192.168.1.10": {
      "last_on": 1622751269764,
      "last_off": 1622751272068
    },
    "192.16.1.13": {
      "last_on": 1622751772269,
      "last_off": 1622751774284
    }
}

```

Working demo updating the values of the objects properties...

```auto
[{"id":"4d40b13c.c8309","type":"function","z":"1bd2b382.4dd4f4","name":"setup demo data","func":"msg.payload = {\n \"192.168.1.10\": {\n \"last_on\": 1622751269764,\n \"last_off\": 1622751272068\n },\n \"192.16.1.13\": {\n \"last_on\": 1622751772269,\n \"last_off\": 1622751774284\n }\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":648,"y":256,"wires":[["2263910a.99b7ae"]]},{"id":"d96e022b.81642","type":"inject","z":"1bd2b382.4dd4f4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":412,"y":256,"wires":[["4d40b13c.c8309"]]},{"id":"2263910a.99b7ae","type":"change","z":"1bd2b382.4dd4f4","name":"","rules":[{"t":"set","p":"deviceMonitor","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":882,"y":256,"wires":[[]]},{"id":"22b4dbc7.70a144","type":"inject","z":"1bd2b382.4dd4f4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"192.168.1.10","payload":"on","payloadType":"str","x":432,"y":304,"wires":[["b241fd6f.3bc79"]]},{"id":"b241fd6f.3bc79","type":"function","z":"1bd2b382.4dd4f4","name":"update value","func":"\nvar deviceMonitor = flow.get(\"deviceMonitor\") || {};\nvar device = deviceMonitor[msg.topic];\nif(!device) {\n deviceMonitor[msg.topic] = {\n last_on: null,\n last_off: null,\n }\n device = deviceMonitor[msg.topic]\n}\nswitch(msg.payload) {\n case \"on\": \n device.last_on = Date.now();\n break;\n case \"off\": \n device.last_off = Date.now();\n break;\n}\n\n//update flow context.\n//NOTE: This only sets the reference (doesnt re-create the object\n// and is infact not even needed. E.g. if you comment the \n// next line out, everything still works!\nflow.set(\"deviceMonitor\", deviceMonitor);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":646,"y":304,"wires":[[]]},{"id":"a9d4c512.088868","type":"inject","z":"1bd2b382.4dd4f4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"192.168.1.10","payload":"off","payloadType":"str","x":432,"y":352,"wires":[["b241fd6f.3bc79"]]},{"id":"aa35fac0.f475f8","type":"inject","z":"1bd2b382.4dd4f4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"192.168.1.11","payload":"on","payloadType":"str","x":432,"y":400,"wires":[["b241fd6f.3bc79"]]},{"id":"7f4af8f9.d842e8","type":"inject","z":"1bd2b382.4dd4f4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"192.168.1.11","payload":"off","payloadType":"str","x":432,"y":448,"wires":[["b241fd6f.3bc79"]]},{"id":"fbc0bb0c.1c9d98","type":"inject","z":"1bd2b382.4dd4f4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"192.168.1.99","payload":"on","payloadType":"str","x":432,"y":496,"wires":[["b241fd6f.3bc79"]]},{"id":"c176579b.3d9bd8","type":"inject","z":"1bd2b382.4dd4f4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"192.168.1.99","payload":"off","payloadType":"str","x":432,"y":544,"wires":[["b241fd6f.3bc79"]]}]

```

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [3 June 2021 21:59 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/7 "2021-06-03T21:59:09Z")

</div>

> [@E1cid](#):
>
> `global.set("mystore.192-16-1-13[0].last_on", 16227512720888);`  
> should work

Thanks, but I tried that earlier, but it just crashes node-RED.

> [@Steve-Mcl](#):
>
> Working demo updating the values of the objects properties...

That's a really helpful example, thanks Steve.  
That will improve my code by a mile, as currently, I have to retrieve the values from context first, only to have to reconstruct the array with one changed value, and then write the whole lot back again.  
Also, I won't have to replace the dots in the IP for dashes, and it will also cut down on the lines of code!!  
👍

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [3 June 2021 22:17 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/8 "2021-06-03T22:17:05Z")

</div>

> [@Paul-Reed](#):
>
> Thanks, but I tried that earlier, but it just crashes node-RED.

Works for me on node-red 1.2.9

> [@Paul-Reed](#):
>
> The size of the arrays are likely to increase as new features are added,

~~How would you add to the last\_on if it is not an object or an array?~~  
Never mind I was thinking you wanted to store more values under last\_on, etc

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [3 June 2021 22:35 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/9 "2021-06-03T22:35:03Z")

</div>

> [@E1cid](#):
>
> Works for me on node-red 1.2.9

I'm using v1.3.5  
It was intuitive to format it that way, but I tried it twice and it failed for me.  
Regardless, I think I need to change the structure, and get rid of the arrays.  
Thanks.

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [3 June 2021 22:47 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/10 "2021-06-03T22:47:32Z")

</div>

I blame Julian (@TotallyInformation ) it's all his fault 😉😉😉

> [@Calculate the time of operation between ON and OFF given Boolean](https://discourse.nodered.org/t/calculate-the-time-of-operation-between-on-and-off-given-boolean/46494/4):
>
> Bit late to the conversation but I store last\_on and last\_off as part of any IoT switch, this is also sent to MQTT. When the state changes, I record the on\_duration and off\_duration: The calculations are done by a single function node that enriches the known\_devices data both in the global variable and MQTT. The updated and updated\_by properties are ones that I now use as standard all over the place since my flows have got a bit complex. grinning It means that it is much quicker t…

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [3 June 2021 23:01 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/11 "2021-06-03T23:01:39Z")

</div>

I am that virus! 🧙

Actually, I think we had a discussion previously on the forum about retrieving/saving context variables and the decision then is that you might was well get/set the whole object. Because JavaScript passes by reference it may actually be more efficient (at least for memory and file based variables). It is certainly easier to get your head around than messing with a string reference - well it is for my little brain anyway.

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [4 June 2021 09:09 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/12 "2021-06-04T09:09:41Z")

</div>

How does this work???  
Even with the `flow.set` command commented out (as per the comment), the `device.last_on` & `device.last_off` context values still get updated... despite there not being a command to do so!!  
A wild guess is that it's due to javascript pass-by-reference, but I'm probably wrong 😬

```auto
var deviceMonitor = flow.get("deviceMonitor") || {};
var device = deviceMonitor[msg.topic];
if(!device) {
    deviceMonitor[msg.topic] = {
        last_on: null,
        last_off: null,
    }
    device = deviceMonitor[msg.topic]
}
switch(msg.payload) {
    case "on": 
        device.last_on = Date.now();
        break;
    case "off": 
        device.last_off = Date.now();
        break;
}
//update flow context.
//NOTE: This only sets the reference (doesnt re-create the object
// and is infact not even needed. E.g. if you comment the 
// next line out, everything still works!
//flow.set("deviceMonitor", deviceMonitor);
return msg;

```

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [4 June 2021 09:13 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/13 "2021-06-04T09:13:15Z")

</div>

> [@Paul-Reed](#):
>
> A wild guess is that it's due to javascript pass-by-reference, but I'm probably wrong

No, you are correct(ish) 😉

The objects retrieved by these 2 lines...

```auto
var deviceMonitor = flow.get("deviceMonitor") || {};
var device = deviceMonitor[msg.topic];

```

are getting a reference to the stored object. (deviceMonitor is an object & device is a sub property object)

When you update the values of the property, you are modifying the actual object (by reference).

The reason to include `flow.set("deviceMonitor", deviceMonitor);` is to make things play nice when you have an alternative storage (e.g. file backed context)

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [4 June 2021 14:19 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/14 "2021-06-04T14:19:25Z")

</div>

If you were to use file-based storage, I think you would get a slightly different result 🙂

While JavaScripts pass by reference is super efficient, it is also a pain from time-to-time. And doubly confusing since core data types (string, number, etc) are treated differently to complex objects.

Let's face it, JavaScript is a mess! Oh for those good old days of COBOL 🤣 and [APL](https://en.wikipedia.org/wiki/APL_syntax_and_symbols) 😱

Here is a typical section of "help" regarding APL: "The reduce and scan operators expect a dyadic function on their left, forming a monadic composite function applied to the vector on its right." 🧙

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [18 June 2021 14:20 UTC](https://discourse.nodered.org/t/saving-a-single-value-to-context/46670/15 "2021-06-18T14:20:06Z")

</div>

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