Using jq, how do I select a parent object if it contains a child object that meets two filter requirements?
In this example I want to select all Subnets elements that have a child tag with key "Name" and value "TheName". My example has two subnets. The first has "TheName" in the wrong key. The second subnet has the name/value pair I am looking for. i.e. "Key": "Name", "Value": "TheName"
The following selects a subnet with the specified value in one of the tags but not the pair. It returns both subnets instead of only the second subnet.
jq '.Subnets[] | select(.Tags[].Value=="TheName")' output
How do I use jq to select only the subnets that have the name/value pair I am looking for?
{
"Subnets": [
{
"VpcId": "vpc-12345678",
"SubnetId": "subnet-1234567a",
"Tags": [
{
"Key": "IgnoreThis",
"Value": "TheName"
},
{
"Key": "Name",
"Value": "NotTheName"
}
]
},
{
"VpcId": "vpc-12345678",
"SubnetId": "subnet-1234567b",
"Tags": [
{
"Key": "IgnoreThis",
"Value": "ignore"
},
{
"Key": "Name",
"Value": "TheName"
}
]
}
]
}
The desired output would be:
{
"VpcId": "vpc-12345678",
"SubnetId": "subnet-1234567b",
"Tags": [
{
"Key": "IgnoreThis",
"Value": "ignore"
},
{
"Key": "Name",
"Value": "TheName"
}
]
}
Assuming your jq has any/2
, a simple and efficient solution would be:
.Subnets[]
| select( any (.Tags[]; .Key == "Name" and .Value == "TheName") )
This produces the output you want, so I won't repeat it here.
If your jq does not have any/2
, I'd suggest upgrading, but if that's inconvenient or not an option, you could use this def:
def any(f;g): reduce f as $i (false; . or ($i|g));
p.s. any(str; cond)
can be read as: 'Is there any element, e, in the stream, str, such that e|cond
has a value other than null
or false
?'
Here is a solution which uses indices
.Subnets[] | select(.Tags | indices({Key:"Name", Value:"TheName"}) != [])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With