# Set payload to first occurence of certain key/value in array

**URL:** <https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857>\
**Category:** General\
**Created:** [23 March 2023 09:09 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857 "2023-03-23T09:09:52Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![network\_potato](https://avatars.discourse-cdn.com/v4/letter/n/59ef9b/32.png) [@network\_potato](https://discourse.nodered.org/u/network_potato)\
**Post date:** [23 March 2023 09:09 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/1 "2023-03-23T09:09:52Z")

</div>

Flow:

```auto
[
    {
        "id": "1c81edcb527606e1",
        "type": "inject",
        "z": "1151076dd0552f2d",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "[{\"status\":\"DELIVERED\",\"dateIso\":\"2023-03-03T10:26:00+01:00\"},{\"status\":\"HANDED_IN\",\"dateIso\":\"2023-02-24T14:10:50+01:00\"},{\"status\":\"DELIVERED\",\"dateIso\":\"2023-01-26T12:42:50+01:00\"},{\"status\":\"IN_TRANSIT\",\"dateIso\":\"2023-01-23T19:28:08+01:00\"},{\"status\":\"PRE_NOTIFIED\",\"dateIso\":\"2023-01-19T09:01:08+01:00\"}]",
        "payloadType": "json",
        "x": 1010,
        "y": 1260,
        "wires": [
            [
                "6660c65d96d28d5c"
            ]
        ]
    },
    {
        "id": "6660c65d96d28d5c",
        "type": "debug",
        "z": "1151076dd0552f2d",
        "name": "debug 28",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1140,
        "y": 1260,
        "wires": []
    }
]

```

This array has 5 items where 0 is the newest and 4 is the oldest.

As you can see, both item 0 and 2 has a status of `DELIVERED`.

I want to do two things:

1. First I want to look for any occurence of `DELIVERED` in the array. If the array contains a status of `DELIVERED` in any of the items, the message shall pass through a switch node.
2. Then, I want to set the payload to the array item with the oldest occurence of `DELIVERED`. So in this case, the payload should be set to `{"status":"DELIVERED","dateIso":"2023-01-26T12:42:50+01:00"}` because item 2 is the oldest where `DELIVERED` appears.

How would I go on about this? This is just an example array - the array may have 10 items where every other item has `DELIVERED`, for example.

Thanks!

---

<div class="post-metadata">

**Author:** ![zenofmud](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/zenofmud/32/316_2.png) [@zenofmud](https://discourse.nodered.org/u/zenofmud)\
**Post date:** [23 March 2023 09:25 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/2 "2023-03-23T09:25:34Z")

</div>

Though I'm sure you could use a JSONata expression to do this, I'd use a function node.

1. get the length of the array,
2. set a variable 'oldest\_date' to 0
3. use a 'For loop' to loop thru each of the items and search the status for delivered.
4. If found, compare the data of that occurrence to the 'oldest\_date'
5. if older, store that date.
6. when you exit the loop, you will have the oldest data to do with what you want.

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [23 March 2023 09:38 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/3 "2023-03-23T09:38:17Z")

</div>

I know its not low-code - but all can be done in 1 function node.

```auto
/* Filter to DELIVERED */
const FilterToDelivered = msg.payload.filter((ArrayEntry) => ArrayEntry.status === 'DELIVERED');

/* Only continue if we have DELIVERED */
if (FilterToDelivered.length > 0){
    
    /* Get Min Timestamp of DELIVERED */
    const MinTimeStamp = Math.min(...FilterToDelivered.map((ArrayEntry) => Date.parse(ArrayEntry.dateIso)))

    /* Now set payload to oldest - using the min Timestamp we got above */
    msg.payload = FilterToDelivered.find((ArrayEntry) => Date.parse(ArrayEntry.dateIso) === MinTimeStamp)

    return msg
}

```

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/2/9/2934cbb11b7abca4379cde11f134cc979e530588.png)

---

<div class="post-metadata">

**Author:** ![network\_potato](https://avatars.discourse-cdn.com/v4/letter/n/59ef9b/32.png) [@network\_potato](https://discourse.nodered.org/u/network_potato)\
**Post date:** [23 March 2023 10:11 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/5 "2023-03-23T10:11:11Z")

</div>

Hmm, when implementing this into my flow I get some issues.

The actual path to the object with the array is:

```auto
msg.payload.consignmentSet[0].packageSet[0].eventSet

```

So I changed the code to this:

```auto
const FilterToDelivered = msg.payload.consignmentSet[0].packageSet[0].eventSet.status.filter((ArrayEntry) => ArrayEntry.status === 'DELIVERED');

```

But then I get the following error:

```auto
TypeError: Cannot read properties of undefined (reading 'filter')

```

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [23 March 2023 10:14 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/6 "2023-03-23T10:14:58Z")

</div>

```auto
const FilterToDelivered = msg.payload.consignmentSet[0].packageSet[0].eventSet.status.filter((ArrayEntry) => ArrayEntry.status === 'DELIVERED');

```

Should be

```auto
const FilterToDelivered = msg.payload.consignmentSet[0].packageSet[0].eventSet.filter((ArrayEntry) => ArrayEntry.status === 'DELIVERED');

```

You were trying to call `filter` on a property, not the array its self

`filter` should be applied on an array object, and you provide a delegate to do the filtering:  
In our case the item in the array (I called it `ArrayEntry`) its `status` property is `DELIVERED`

---

<div class="post-metadata">

**Author:** ![network\_potato](https://avatars.discourse-cdn.com/v4/letter/n/59ef9b/32.png) [@network\_potato](https://discourse.nodered.org/u/network_potato)\
**Post date:** [23 March 2023 10:28 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/7 "2023-03-23T10:28:27Z")

</div>

Thanks!

Any way to give the function node 2 outputs, where the message is sent to output 1 if `DELIVERED` exists, and output 2 if it does not? Like a switch node.

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [23 March 2023 10:31 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/8 "2023-03-23T10:31:42Z")

</div>

Set the function node properties to have 2 outputs (setup tab)  
Then...

```auto
/* Filter to DELIVERED */
const FilterToDelivered = msg.payload.consignmentSet[0].packageSet[0].eventSet.filter((ArrayEntry) => ArrayEntry.status === 'DELIVERED');

/* Only continue if we have DELIVERED */
if (FilterToDelivered.length > 0){
    
    /* Get Min Timestamp of DELIVERED */
    const MinTimeStamp = Math.min(...FilterToDelivered.map((ArrayEntry) => Date.parse(ArrayEntry.dateIso)))

    /* Now set payload to oldest - using the min Timestamp we got above */
    msg.payload = FilterToDelivered.find((ArrayEntry) => Date.parse(ArrayEntry.dateIso) === MinTimeStamp)

    return [msg, undefined] /* Top output */
} else {
    return [undefined, msg] /* Bottom output */
}

```

Anymore, you probably want to start using the built in nodes 😅

---

<div class="post-metadata">

**Author:** ![network\_potato](https://avatars.discourse-cdn.com/v4/letter/n/59ef9b/32.png) [@network\_potato](https://discourse.nodered.org/u/network_potato)\
**Post date:** [23 March 2023 10:42 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/9 "2023-03-23T10:42:03Z")

</div>

Thank you so much for the help, I have achieved what I want now 🙂

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [23 March 2023 11:08 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/10 "2023-03-23T11:08:59Z")

</div>

Is it always the last 'delivered' entry in the array that you want? If so there is a simpler solution using `findLast()`

---

<div class="post-metadata">

**Author:** ![network\_potato](https://avatars.discourse-cdn.com/v4/letter/n/59ef9b/32.png) [@network\_potato](https://discourse.nodered.org/u/network_potato)\
**Post date:** [23 March 2023 11:11 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/11 "2023-03-23T11:11:11Z")

</div>

I always want the first one, not the last one.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [23 March 2023 11:18 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/12 "2023-03-23T11:18:34Z")

</div>

In that case one can use `find()`  
Something like (untested)

```auto
msg.payload = msg.payload.consignmentSet[0].packageSet[0].eventSet.find(
  (ArrayEntry) => ArrayEntry.status === 'DELIVERED'
);
if (typeof msg.payload !="undefined") {
  return msg
}

```

**[Edit]** Fixed some typos above

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [23 March 2023 12:01 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/13 "2023-03-23T12:01:16Z")

</div>

To extend on the simpler approach by @Colin and to retain the ability to output to a 2nd pin if non are delivered.

```auto
const FirstDelivered = msg.payload.consignmentSet[0].packageSet[0].eventSet.find((ArrayEntry) => ArrayEntry.status === 'DELIVERED');
if (FirstDelivered !== undefined){
    return [{payload:FirstDelivered}, undefined] /* Top output */
} else {
    return [undefined, msg] /* Bottom output */
}

```

I cant remember if Javascript arrays are **guaranteed order** - I'm sure they are.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [23 March 2023 12:24 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/14 "2023-03-23T12:24:56Z")

</div>

I think I would marginally prefer that to be

```auto
const FirstDelivered = msg.payload.consignmentSet[0].packageSet[0].eventSet.find((ArrayEntry) => ArrayEntry.status === 'DELIVERED');
if (FirstDelivered !== undefined){
    msg.payload = FirstDelivered
    return [msg, undefined] /* Top output */
} else {
    return [undefined, msg] /* Bottom output */
}

```

or even

```auto
const FirstDelivered = msg.payload.consignmentSet[0].packageSet[0].eventSet.find((ArrayEntry) => ArrayEntry.status === 'DELIVERED');
let answer = []
if (FirstDelivered !== undefined){
    msg.payload = FirstDelivered
    answer = [msg, undefined] /* Top output */
} else {
    answer = [undefined, msg] /* Bottom output */
}
return answer

```

I prefer just to have one return at the end. Too many times over many years I have seen code added to a function at the end, forgetting that there has already been a return made earlier in the function, so I have a rule that I never do that, even in a simple case like this.

---

<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:** [6 April 2023 12:25 UTC](https://discourse.nodered.org/t/set-payload-to-first-occurence-of-certain-key-value-in-array/76857/15 "2023-04-06T12:25:46Z")

</div>

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