-
-
Notifications
You must be signed in to change notification settings - Fork 23
Search Keyword: name
The [name()]
search keyword will yield the name of the present Hash (map/dict) key or the index of the present Array (sequence/list) element. This cannot be inverted. This is especially useful for returning the name of matched Hash children, particularly when paired with the [parent([STEPS])
search keyword for complex data structures and queries.
[name()]
accepts no parameters. It operates only against the present data node.
To illustrate what this search keyword does, consider the following sample data, named name-examples.yaml:
---
hash:
with:
children: having
properties: and
enabled: [M,W,F]
values:
in: a
complex: structure
enabled: [T,R]
anywhere:
in: any
compatible: data
enabled: [S,U]
searchable:
using: simple
yaml: paths
enabled: [S,M,W,F]
array:
- with
- several
- elements
A query like the following doesn't yield any more information than you already knew:
$ yaml-get --query='/hash/with/children[name()]' name-examples.yaml
children
The query author already knew the name of the target node, children. So, this doesn't really yield anything new.
But what if you need the names of Hash keys that you don't know in advance? Consider for example: Which of the hash
entities in the sample data are enabled on Wednesday (W
)? Try this:
$ yaml-get --query='/hash/**[enabled=W][parent(2)][name()]' name-examples.yaml
with
searchable
You can visually confirm that the with
and searchable
entities are in fact enabled on Wednesday. Let's break that query and its result down to understand how it works.
First, we know that need to match child entities of the hash
data structure, so we set the query to start at the hash
key of the document root: /hash
. Alone, that yields the entire contents of the hash
Hash:
$ yaml-get --query='/hash' name-examples.yaml
{"with": {"children": "having", "properties": "and", "enabled": ["M", "W", "F"]}, "values": {"in": "a", "complex": "structure", "enabled": ["T", "R"]}, "anywhere": {"in": "any", "compatible": "data", "enabled": ["S", "U"]}, "searchable": {"using": "simple", "yaml": "paths", "enabled": ["S", "M", "W", "F"]}}
Then, we cheat a little bit by employing a deep traversal on an assumption about the particular structure of this data: **
.
$ yaml-get --query='/hash/**' name-examples.yaml
having
and
M
W
F
a
structure
T
R
any
data
S
U
simple
paths
S
M
W
F
That's way too much data! Since we're only interested in enabled
conditions, filter the query to yield only that data:
$ yaml-get --query='/hash/**/enabled' name-examples.yaml
["M", "W", "F"]
["T", "R"]
["S", "U"]
["S", "M", "W", "F"]
That's a lot more manageable, but still needs to be filtered to only entities that are enabled on Wednesday. So, filter the traversal results further using a search expression that says, "match only when there is an enabled
key having exactly a W
value:
$ yaml-get --query='/hash/**[enabled=W]' name-examples.yaml
W
W
We can see now that there are exactly two entities that are enabled on Wednesday, but which ones are they? Step up one level to investigate:
yaml-get --query='/hash/**[enabled=W][parent()]' name-examples.yaml
["M", "W", "F"]
["S", "M", "W", "F"]
Well, that is the entire enabled
data for each entity which is enabled on Wednesday, but still not high enough in the data hierarchy to tell us which entities have matched, by name. Step up another parent level:
yaml-get --query='/hash/**[enabled=W][parent(2)]' name-examples.yaml
{"children": "having", "properties": "and", "enabled": ["M", "W", "F"]}
{"using": "simple", "yaml": "paths", "enabled": ["S", "M", "W", "F"]}
That finally looks like the entirety of the entities we are interested in, but we still need their names. Tell the YAML Path to yield only the names of the present, matched entities:
yaml-get --query='/hash/**[enabled=W][parent(2)][name()]' name-examples.yaml
with
searchable
And we have our answer!
Perhaps less interesting, the [name()]
search keyword can also yield the element index at which an Array (sequence/list) match exists. This isn't especially useful when you already know the index of any particular element, as with:
$ yaml-get --query='/array[1]' name-examples.yaml
several
$ yaml-get --query='/array[1][name()]' name-examples.yaml
1
Remember that YAML Path uses zero-based indexing, so element 1
is the second element in the Array. Further, we clearly already knew that "element at index 1 is indeed at index 1". But what if we don't already know the index and we need to know? Imagine a scenario where we somehow needed to know at exactly which element index(es) our sample Array held values containing the letter e
. We'd answer that using:
$ yaml-get --query='/array/*e*[name()]' name-examples.yaml
1
2
For fun, what if we needed the index of elements containing both an e
and an m
? Try this:
yaml-get --query='(/array/*e*)*m*[name()]' name-examples.yaml
2
This scary-looking YAML Path is actually really simple. It Collects into a list all elements in the sample Array which contain a letter e
. It then filters that list to match only the results which also contain a letter m
. It then finally returns only the index of the matches within the sample Array. Easy!