Как я могу отфильтровать записи, которые НЕ содержат пару ключ-значение во вложенном массиве

Допустим, у меня есть следующий вывод JSON:

{
 "Stacks": [
        {
            "StackName": "hello-world",
            "Tags": [
                {
                    "Key": "environment",
                    "Value": "sandbox"
                },
                {
                    "Key": "Joe Shmo",
                    "Value": "Dev"
                }
            ]
        },
        {
            "StackName": "hello-man",
            "Tags": [
                {
                    "Key": "environment",
                    "Value": "live"
                },
                {
                    "Key": "Tandy",
                    "Value": "Dev"
                }
            ]
        }
    ]
}

Как мне написать запрос jq, чтобы получить все StackName для стеков, которые НЕ имеют значение Tags "Key": "Joe Shmo"? Таким образом, результат вернет просто hello-man.


person Mike    schedule 11.01.2019    source источник


Ответы (2)


Используя contains, например:

jq -r '.Stacks[]|select(.Tags|contains([{"Key": "Joe Shmo"}])|not).StackName'

Примечание: -r удаляет кавычки из вывода, иначе jq напечатает "hello-man" (в двойных кавычках)

person hek2mgl    schedule 11.01.2019

.Stacks[]
| select( any(.Tags[]; .Key == "Joe Shmo" ) | not)
| .StackName

Это эффективно проверяет равенство (any имеет семантику короткого замыкания), тогда как contains будет проверять включение.

person peak    schedule 11.01.2019
comment
Я проверяю, содержит ли .Tags объект с точным ключом Joe Shmo. По крайней мере, я думаю, что мой код делает это - person hek2mgl; 11.01.2019
comment
мой Бог! Теперь я понимаю, что вы имеете в виду. Серьезно, это может быть неправильно понято. Тем более, что в мануале об этом не сказано. Если бы я был автором, я бы поставил красную рамку в руководстве: ОСТОРОЖНО: эта функция не работает - person hek2mgl; 11.01.2019
comment
PS: неф. SO не позволяет удалить принятый ответ. - person hek2mgl; 11.01.2019