通过搜索子 key/value 对,使用 jq 到 select 父

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

使用 jq,如果父对象包含满足两个过滤器要求的子对象,我如何 select 父对象?

在这个例子中,我想 select 所有具有子标签的子网元素,键 "Name" 和值 "TheName"。我的示例有两个子网。第一个在错误的键中有 "TheName"。第二个子网有我正在寻找的 name/value 对。即 "Key": "Name", "Value": "TheName"

以下 select 是一个子网,其中一个标签具有指定值,但标签对中没有。它 returns 两个子网而不是仅第二个子网。

jq '.Subnets[] | select(.Tags[].Value=="TheName")' output

如何使用 jq 仅 select 具有我要查找的 name/value 对的子网?

{
    "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"
                }
            ]
        }
    ]
}

所需的输出将是:

{
    "VpcId": "vpc-12345678",
    "SubnetId": "subnet-1234567b",
    "Tags": [
        {
            "Key": "IgnoreThis",
            "Value": "ignore"
        },
        {
            "Key": "Name",
            "Value": "TheName"
        }
    ]
}

假设您的 jq 有 any/2,一个简单有效的解决方案是:

.Subnets[]
| select( any (.Tags[]; .Key == "Name" and .Value == "TheName") )

这样就产生了你想要的输出,这里就不再赘述了。

如果您的 jq 没有 any/2,我建议升级,但如果这样做不方便或不是一个选项,您可以使用此 def:

def any(f;g): reduce f as $i (false; . or ($i|g));

p.s。 any(str; cond) 可以读作:'Is there any element, e, in the stream, str, such that e|cond has a value other than null or false?'

这是一个使用 indices

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