简体   繁体   中英

Using jq to select a parent by searching child key/value pair

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. ie "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));

ps 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 ?'

这是一个使用索引的解决方案

.Subnets[] | select(.Tags | indices({Key:"Name", Value:"TheName"}) != [])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM