# Search and return a value from within a flow variable?

**URL:** <https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461>\
**Category:** General\
**Created:** [23 April 2019 11:56 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461 "2019-04-23T11:56:11Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![swiftnesses](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@swiftnesses](https://discourse.nodered.org/u/swiftnesses)\
**Post date:** [23 April 2019 11:56 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/1 "2019-04-23T11:56:11Z")

</div>

Hello,

I've stored a number of values in a flow variable, example:

```auto
{
	"data": {
		"item_1": "value_1",
		"item_2": "value_2"
	}
}

```

From within the function node I'd like to search for a value and return the associated key, example:

A search for "value\_1" would return "item\_1"

Is this possible?

---

<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:** [23 April 2019 12:34 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/2 "2019-04-23T12:34:26Z")

</div>

> [@swiftnesses](#):
>
> Is this possible?

yes.

Literally thousands of posts on the internet - e.g...  
[https://www.google.com/search?q=js+search+object+for+value](https://www.google.com/search?q=js+search+object+for+value)

Here is an [example i knocked up](https://repl.it/@StephenMcLaughl/FindInObj)

---

<div class="post-metadata">

**Author:** ![swiftnesses](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@swiftnesses](https://discourse.nodered.org/u/swiftnesses)\
**Post date:** [23 April 2019 13:33 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/3 "2019-04-23T13:33:26Z")

</div>

Hi Steve,

I think my example was pretty terrible. Here is the data I'm trying to search:

 ![19](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/2X/f/f5a50b38a56243a6a798a72791205bf1e1b6b4db.png)

I want to return for example, "this\_week" via "BTC-USD-190426" which I have as part of a payload.

i.e. A search for "BTC-USD-190426" will return "this\_week"

---

<div class="post-metadata">

**Author:** ![swiftnesses](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@swiftnesses](https://discourse.nodered.org/u/swiftnesses)\
**Post date:** [23 April 2019 14:15 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/4 "2019-04-23T14:15:47Z")

</div>

I've tried pretty much every example I can find over the last few hours, with no luck ☹

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [23 April 2019 14:27 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/5 "2019-04-23T14:27:55Z")

</div>

If you set `msg.target` to the value you want to search for (`BTC-USD-190426`), then you can use a Change node to evaluate the following JSONata Expression:

```auto
$keys(payload.*.$sift(function($v, $k) {$v = $$.target}))

```

This assumes the object you've shown the screenshot of lives under `msg.payload`.

---

<div class="post-metadata">

**Author:** ![swiftnesses](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@swiftnesses](https://discourse.nodered.org/u/swiftnesses)\
**Post date:** [23 April 2019 15:34 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/6 "2019-04-23T15:34:44Z")

</div>

Hi,

How would I setup the change node, I'll give this a try, thank you 🙂

---

<div class="post-metadata">

**Author:** ![swiftnesses](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@swiftnesses](https://discourse.nodered.org/u/swiftnesses)\
**Post date:** [23 April 2019 16:01 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/7 "2019-04-23T16:01:04Z")

</div>

Urgh, 5 hours in, must have tried 100 possibilities to search through this data and return the right result. Close to giving up... ☹

---

<div class="post-metadata">

**Author:** ![swiftnesses](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@swiftnesses](https://discourse.nodered.org/u/swiftnesses)\
**Post date:** [23 April 2019 16:06 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/8 "2019-04-23T16:06:10Z")

</div>

The JSON appears to be:

```auto
{
	"BTC": {
		"USD": {
			"this_week": "BTC-USD-190426",
			"next_week": "BTC-USD-190503",
			"quarter": "BTC-USD-190628"
		}
	},
	"LTC": {
		"USD": {
			"this_week": "LTC-USD-190426",
			"next_week": "LTC-USD-190503",
			"quarter": "LTC-USD-190628"
		}
	},
	"ETH": {
		"USD": {
			"this_week": "ETH-USD-190426",
			"next_week": "ETH-USD-190503",
			"quarter": "ETH-USD-190628"
		}
	},
	"ETC": {
		"USD": {
			"this_week": "ETC-USD-190426",
			"next_week": "ETC-USD-190503",
			"quarter": "ETC-USD-190628"
		}
	},
	"XRP": {
		"USD": {
			"this_week": "XRP-USD-190426",
			"next_week": "XRP-USD-190503",
			"quarter": "XRP-USD-190628"
		}
	},
	"BCH": {
		"USD": {
			"this_week": "BCH-USD-190426",
			"next_week": "BCH-USD-190503",
			"quarter": "BCH-USD-190628"
		}
	},
	"BSV": {
		"USD": {
			"this_week": "BSV-USD-190426",
			"next_week": "BSV-USD-190503",
			"quarter": "BSV-USD-190628"
		}
	},
	"EOS": {
		"USD": {
			"this_week": "EOS-USD-190426",
			"next_week": "EOS-USD-190503",
			"quarter": "EOS-USD-190628"
		}
	}
}

```

Basically, I need a compact method (ideally via a function node) to grab the key for a given value, i.e. "BTC-USD-190426", I tried to suggestion above with a change node but didn't have any luck, sadly.

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [23 April 2019 16:14 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/9 "2019-04-23T16:14:54Z")

</div>

> [@swiftnesses](#):
>
> I tried to suggestion above with a change node but didn't have any luck, sadly.

The JSON you've shared here is _different_ to the JSON you shared previously. So the JSONata expression I gave you won't work.

Here's an example flow that does work once the JSONata has been updated for your latest JSON format...

```auto
[{"id":"ba39e234.05ea2","type":"inject","z":"41b925f9.3c983c","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":220,"wires":[["eed0c1d6.1d737"]]},{"id":"eed0c1d6.1d737","type":"function","z":"41b925f9.3c983c","name":"","func":"msg.payload = {\n\t\"BTC\": {\n\t\t\"USD\": {\n\t\t\t\"this_week\": \"BTC-USD-190426\",\n\t\t\t\"next_week\": \"BTC-USD-190503\",\n\t\t\t\"quarter\": \"BTC-USD-190628\"\n\t\t}\n\t},\n\t\"LTC\": {\n\t\t\"USD\": {\n\t\t\t\"this_week\": \"LTC-USD-190426\",\n\t\t\t\"next_week\": \"LTC-USD-190503\",\n\t\t\t\"quarter\": \"LTC-USD-190628\"\n\t\t}\n\t},\n\t\"ETH\": {\n\t\t\"USD\": {\n\t\t\t\"this_week\": \"ETH-USD-190426\",\n\t\t\t\"next_week\": \"ETH-USD-190503\",\n\t\t\t\"quarter\": \"ETH-USD-190628\"\n\t\t}\n\t},\n\t\"ETC\": {\n\t\t\"USD\": {\n\t\t\t\"this_week\": \"ETC-USD-190426\",\n\t\t\t\"next_week\": \"ETC-USD-190503\",\n\t\t\t\"quarter\": \"ETC-USD-190628\"\n\t\t}\n\t},\n\t\"XRP\": {\n\t\t\"USD\": {\n\t\t\t\"this_week\": \"XRP-USD-190426\",\n\t\t\t\"next_week\": \"XRP-USD-190503\",\n\t\t\t\"quarter\": \"XRP-USD-190628\"\n\t\t}\n\t},\n\t\"BCH\": {\n\t\t\"USD\": {\n\t\t\t\"this_week\": \"BCH-USD-190426\",\n\t\t\t\"next_week\": \"BCH-USD-190503\",\n\t\t\t\"quarter\": \"BCH-USD-190628\"\n\t\t}\n\t},\n\t\"BSV\": {\n\t\t\"USD\": {\n\t\t\t\"this_week\": \"BSV-USD-190426\",\n\t\t\t\"next_week\": \"BSV-USD-190503\",\n\t\t\t\"quarter\": \"BSV-USD-190628\"\n\t\t}\n\t},\n\t\"EOS\": {\n\t\t\"USD\": {\n\t\t\t\"this_week\": \"EOS-USD-190426\",\n\t\t\t\"next_week\": \"EOS-USD-190503\",\n\t\t\t\"quarter\": \"EOS-USD-190628\"\n\t\t}\n\t}\n};\n\nmsg.target = \"EOS-USD-190426\"\nreturn msg;","outputs":1,"noerr":0,"x":230,"y":220,"wires":[["cfdb4b36.94a9e8"]]},{"id":"cfdb4b36.94a9e8","type":"change","z":"41b925f9.3c983c","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$keys(payload.*.*.$sift(function($v, $k) {$v = $$.target}))","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":220,"wires":[["3064c623.ae541a"]]},{"id":"3064c623.ae541a","type":"debug","z":"41b925f9.3c983c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":590,"y":220,"wires":[]}]

```

---

<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:** [23 April 2019 17:06 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/10 "2019-04-23T17:06:45Z")

</div>

@swiftnesses, you could have learned about recursion or JSONata in that 5hrs 🙂

@knolleary I must spend some time looking into JSONata - seems to be very powerful.

@swiftnesses  
In case you do want this as a function - or - you change the data structure (for a 4th time) then this function should work for all situations (unless you add arrays)

[See my recursive object search function in action here](https://repl.it/@StephenMcLaughl/RecursiveObjSearch)

---

<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:** [23 April 2019 17:12 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/11 "2019-04-23T17:12:43Z")

</div>

The code...

```auto
function deepSearchObject(theObject, theValue) {
    var result = null;
    for(var prop in theObject) {
        if(theObject[prop] == theValue) {
          return {prop:prop, path:prop}; 
        }        
        if(theObject[prop] instanceof Object) {
            result = deepSearchObject(theObject[prop], theValue);
            if(result){
              result.path = prop + "." + result.path
              return result;
            }
        }          
    }
    return result;
}
var result = deepSearchObject(data,"EOS-USD-190503");
console.log("EOS-USD-190503 is in property : ", result.prop);
console.log("EOS-USD-190503 full path = ", result.path);

```

notes...

- there WILL be bugs (it is barely tested)
- i don't handle arrays (will leave that to you)
- if `theObject` is not an object, it wont work
- searching for undefined or null is not supported
- searching for falsey values will likely give odd results (unless you change the comparitor to `===`)

---

<div class="post-metadata">

**Author:** ![swiftnesses](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@swiftnesses](https://discourse.nodered.org/u/swiftnesses)\
**Post date:** [24 April 2019 09:31 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/12 "2019-04-24T09:31:06Z")

</div>

Thank you everyone, used @knolleary's solution in the end and spend some time learning JSONata (which should come in handy!).

---

<div class="post-metadata">

**Author:** ![Holger-Will](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/holger-will/32/7302_2.png) [@Holger-Will](https://discourse.nodered.org/u/Holger-Will)\
**Post date:** [24 April 2019 10:08 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/13 "2019-04-24T10:08:13Z")

</div>

given that the value you have already contain parts of the search path (the "EOS-USD" part, you can simply do:

```auto
var flatSearch = (theObject, theValue)=>{
  var part = theValue.split("-")
  var result = null
  var interrestingPartOfObject = theObject[part[0]][part[1]]
  for(prop in interrestingPartOfObject){
    if(interrestingPartOfObject[prop] === theValue){
      return {prop: prop, path: `${part[0]}.${part[1]}.${prop}`}
    }
  }
}

```

var result = flatSearch(data,"EOS-USD-190503")

the solution Steve gave is more general, but for your case, this function will be much faster for large objects.

---

<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:** [24 April 2019 10:26 UTC](https://discourse.nodered.org/t/search-and-return-a-value-from-within-a-flow-variable/10461/14 "2019-04-24T10:26:30Z")

</div>

I did consider short-cutting as you have here `theObject[part[0]][part[1]]` however the spec of the data changed 3 times so thought a generic solution may be advisable.

In fact, as the last part seems to be a date (`190503`) we could probably have provided a simpler (non scanning) logical solution - but we have to assume the provided data may change.
