ipfabric.*.links[? bfd == `yes`].nodes.h01.interface[]
Based on your sample data structure above, I "think" this is what you were hoping for:
ipfabric.lab.links[?bfd == `yes`].nodes.h01.interface
Since I do most of my testing in Ansible, one note I will add is that yes
translates to True
, so I had to wrap the yes
in single quotes to stop it from processing as a boolean value. If you are using the same, you can change it to this to search for the Boolean True
instead of the string yes
:
ipfabric.lab.links[?bfd == `true`].nodes.h01.interface
Re-reading what you wrote, I think I am gathering the picture. lab
also has other similar environments that need to be searched for thus needs to be wildcard'ed if I am understanding right...trying this:
ipfabric.*[].links[?bfd == `true`].nodes.h01.interface | []
The thing about using the dictionary wildcard ipfabric.*
converts the what you would expect to be dict results, actually converts it to a list. You can tell by doing this:
ipfabric.*
You will notice the top results is a list now, instead of a dictionary. To get past this conversion I simply flatten the list result from the asterisk and keep going. At the end you will notice that there is a list within a list, because of the flattening...so I pipe to another flatten and thus I think is the end goal you were hoping?
true
) and I also get an empty list. So somehow it doesn't return anything after the filtering. I cut down from the end to see if I miss something.
true
- but the same does not work for yes
It seems like you found your issue but I had already typed this out, and it is a helpful gem for new users and testing so I sent it anyways:
For JMESPath testing, I always start at the beginning and make my way down the rabbit hole, so to speak.
Start by commenting out the | json_query(jmespath_query)
Then if that works, uncomment it and start cutting down the jmespath_query filter one step at a time...like so:
ipfabric.
ipfabric.*
ipfabric.*[]
ipfabric.*[].links
ipfabric.*[].links[?bfd == `true`]
ipfabric.*[].links[?bfd == `true`].nodes
ipfabric.*[].links[?bfd == `true`].nodes.h01
ipfabric.*[].links[?bfd == `true`].nodes.h01.interface
ipfabric.*[].links[?bfd == `true`].nodes.h01.interface | []
If you don't see results from the first comment, then you know the variable network
is not the right one you should use in yours...look at where your data is coming from and change accordingly. If its in the jmespath filter, you will see it break (empty results) eventually and know where your query needs to be updated.
Your original query was accurate in my opinion...I think the only problem you had was due to ipfabric.*.links
as that would never yield results because the asterisk converts the dict to a list of matching dicts... so we had to deal with that by adding the flattener right after the asterisk:
ipfabric.*[].links
The rest was on par I believe (minus of course Ansible's fun yes/no to boolean good times). :)
ipfabric.* | [].links[?bfd].nodes.h01.interface | []
@jwalzer -
Be sure to use this little nugget with JMESPath and Ansible if you ever attempt to use functions in JMESPath with Ansible such as map, ends_with, et...:
- name: JMESPath Testing
vars:
jmespath_query: >-
ipfabric.* | [].links[*].nodes.h01.interface | [] | [?ends_with(@,'1')]
debug:
var: network | json_query(jmespath_query)
By all accounts this should work but you find that you get a "type" error:In function ends_with(), invalid type for value: swp1, expected one of: ['string'], received: \"unknown
This is due to Ansible's data types not matching the JSON spec is what I believe is the root cause. To fix it simply add the to_json and from_json syntax before the json_query and profit.
- name: JMESPath Testing
vars:
jmespath_query: >-
ipfabric.* | [].links[*].nodes.h01.interface | [] | [?ends_with(@,'1')]
debug:
var: network | to_json | from_json | json_query(jmespath_query)
[{
"backup": "b3",
"time_ended": "2020-09-10T14:55:39.840000+00:00"
}, {
"backup": "b2",
"time_ended": "2020-08-25T15:40:48.740000+00:00"
}, {
"backup": "b1",
"time_ended": "2020-07-10T15:40:48.740000+00:00"
}]
@alonsocamaro - THe homepage for JMESPath can be used as an online evaluator if desired. Its a real-time test and you can manipulate the search and json structure that will be searched.
I have not ran into an issue where it has "failed" for me thus far unless there is an error in my syntax which is most likely the cause of your not updating. That is one area where it lacks is it doesn't let you know when the syntax has an error so its likely assumed to be a web-based error. If you have a specific scenario/filter feel free to type it here and if I am paying attention will attempt to help.
I asked this on stackoverflow as well, but thought I'd ask it here to try and get some traction.
AWS's list-secrets
has an odd way of listing version strings as keys:
{
"SecretList": [
{
"Name": "sandbox_config",
"Description": "sandbox config file",
"SecretVersionsToStages": {
"2895f1a4-bcae-46b2-9a45-4f06f490d8ed": [
"AWSCURRENT"
],
"336a5030-cd81-4626-a100-1aa68b70b5b1": [
"AWSPREVIOUS"
]
}
}
]
}
I'm trying to figure out a query that will let me pull out the versionkey where AWSCURRENT
is in the value array.
This seems like it's close:
SecretList[].{Version:SecretVersionsToStages.*[?@==`AWSCURRENT`]|[]|[0] }
But I'm clearly missing something, since that just spits back AWSCURRENT
to me.
If you could... would you want to be able to do something like this:
expect(
search([6.1, 4.2, 6.3], "_groupBy(@, as_lambda('Math.floor'))")
).toStrictEqual({
'4': [4.2],
'6': [6.1, 6.3],
});
or perhaps
expect(
search([1, 2], "_flatMap(@, as_lambda('x => [x, x]'))")
).toStrictEqual([1, 1, 2, 2]);
Thoughts?
_flatMap
, _groupBy
and 184 other (fully typed) functions have been built into JMESPath expressions in our https://www.npmjs.com/package/@metrichor/jmespath-plus library. Level-up your JMESPath expressions with the power of lodash functions. Check out https://github.com/nanoporetech/jmespath-plus/releases/tag/v0.3.0 for a complete list of supported lodash functions
{
"subject": [
"Fwd: Please complete your assigned training"
],
"labelIds": [
"UNREAD",
"CATEGORY_PERSONAL",
"Label_6568222846829069483",
"INBOX"
]
}
{subject:payload.headers[?name=='Subject'].value,labelIds:labelIds}
{subject: payload.headers[?name=='Subject'].value, labelIds:map(&(!contains(['UNREAD', 'CATEGORY_PERSONAL', 'INBOX'], @) && [@]) || [] ,labelIds)[]}
OR {subject: payload.headers[?name=='Subject'].value, labelIds:labelIds[*][(!contains(['UNREAD', 'CATEGORY_PERSONAL', 'INBOX'], @) && @) ||[]][]}
Hi everyone, I have a question. Is it possible to use the result of a query to search again? For example, say we have the slightly modified example from jmespath.org
{
"locations": [
{"name": "Seattle", "state": "WA"},
{"name": "New York", "state": "NY"},
{"name": "Bellevue", "state": "WA"},
{"Seattle": "Olympia", "state": "WA"}
]
}
could this query
{value: @, key: keys(@)[?ends_with(@, 'Seattle')]} | @.value.[@.key]
return "Olympia"??