使用 json_query 过滤嵌套列表中的元素
Filtering elements in nested list with json_query
我想根据键的存在从嵌套列表中过滤掉条目。给定以下字典:
hostvars:
host1:
backups:
- src: somesource
target: sometarget
- src: anothersource
host2:
backups:
- src: somesource for host2
target: fancy target
host3:
backups:
- src: yet another src
- src: and another one
当 target
键不存在时,我想过滤掉 backups
列表中的所有元素。
我最接近的是:
- set_fact:
data: "{{ hostvars | dict2items | json_query(query) }}"
vars:
query: "[?value.backups[?target]]"
这导致
hostvars:
host1:
backups:
- src: somesource
target: sometarget
- src: anothersource
host2:
backups:
- src: somesource for host2
target: fancy target
所以我已经成功过滤掉 host3
,它在备份列表中没有包含 target
键的元素。
但是,我还想从 host1
的 backups
列表中删除第二个元素(也不包含 target
键)。
非常感谢任何指点。
例如
- set_fact:
data: "{{ hostvars|
dict2items|
json_query(_query)|
selectattr('value')|
items2dict }}"
vars:
_query: '[].{key: key, value: value.backups[?target]}'
run_once: true
给予
data:
host1:
- src: somesource
target: sometarget
host2:
- src: somesource for host2
target: fancy target
下一个选项是添加默认属性 target: None
(如果缺少),例如
- set_fact:
backups: "{{ [{'target': None}]|product(backups)|map('combine') }}"
- debug:
var: backups
给予
TASK [debug] ****************************************************
ok: [host1] =>
backups:
- src: somesource
target: sometarget
- src: anothersource
target: null
ok: [host2] =>
backups:
- src: somesource for host2
target: fancy target
ok: [host3] =>
backups:
- src: yet another src
target: null
- src: and another one
target: null
然后,select 'not null' 目标
- set_fact:
data: "{{ hostvars|
json_query('*.backups')|
map('selectattr', 'target')|
flatten }}"
run_once: true
- debug:
var: data
run_once: true
给予
TASK [debug] ****************************************************
ok: [host1] =>
data:
- src: somesource
target: sometarget
- src: somesource for host2
target: fancy target
要识别主机,请将此属性也添加到列表中,例如
- set_fact:
backups: "{{ [{'target': None, 'host': inventory_hostname}]|
product(backups)|map('combine') }}"
给出结果
TASK [debug] ****************************************************
ok: [host1] =>
data:
- host: host1
src: somesource
target: sometarget
- host: host2
src: somesource for host2
target: fancy target
以纯 JMESPath 方式,您可以重新创建 value
属性 对实际值进行 merge
过滤 backups
属性查询:
[].{
key: key,
value: merge(value, {backups: value.backups[?target]})
} | [?value.backups]
因此,鉴于任务:
- debug:
var: hostvars | dict2items | json_query(query) | items2dict
vars:
query: >-
[].{
key: key,
value: merge(value, {backups: value.backups[?target]})
} | [?value.backups]
这产生:
hostvars | dict2items | json_query(query) | items2dict:
host1:
backups:
- src: somesource
target: sometarget
host2:
backups:
- src: somesource for host2
target: fancy target
我想根据键的存在从嵌套列表中过滤掉条目。给定以下字典:
hostvars:
host1:
backups:
- src: somesource
target: sometarget
- src: anothersource
host2:
backups:
- src: somesource for host2
target: fancy target
host3:
backups:
- src: yet another src
- src: and another one
当 target
键不存在时,我想过滤掉 backups
列表中的所有元素。
我最接近的是:
- set_fact:
data: "{{ hostvars | dict2items | json_query(query) }}"
vars:
query: "[?value.backups[?target]]"
这导致
hostvars:
host1:
backups:
- src: somesource
target: sometarget
- src: anothersource
host2:
backups:
- src: somesource for host2
target: fancy target
所以我已经成功过滤掉 host3
,它在备份列表中没有包含 target
键的元素。
但是,我还想从 host1
的 backups
列表中删除第二个元素(也不包含 target
键)。
非常感谢任何指点。
例如
- set_fact:
data: "{{ hostvars|
dict2items|
json_query(_query)|
selectattr('value')|
items2dict }}"
vars:
_query: '[].{key: key, value: value.backups[?target]}'
run_once: true
给予
data:
host1:
- src: somesource
target: sometarget
host2:
- src: somesource for host2
target: fancy target
下一个选项是添加默认属性 target: None
(如果缺少),例如
- set_fact:
backups: "{{ [{'target': None}]|product(backups)|map('combine') }}"
- debug:
var: backups
给予
TASK [debug] ****************************************************
ok: [host1] =>
backups:
- src: somesource
target: sometarget
- src: anothersource
target: null
ok: [host2] =>
backups:
- src: somesource for host2
target: fancy target
ok: [host3] =>
backups:
- src: yet another src
target: null
- src: and another one
target: null
然后,select 'not null' 目标
- set_fact:
data: "{{ hostvars|
json_query('*.backups')|
map('selectattr', 'target')|
flatten }}"
run_once: true
- debug:
var: data
run_once: true
给予
TASK [debug] ****************************************************
ok: [host1] =>
data:
- src: somesource
target: sometarget
- src: somesource for host2
target: fancy target
要识别主机,请将此属性也添加到列表中,例如
- set_fact:
backups: "{{ [{'target': None, 'host': inventory_hostname}]|
product(backups)|map('combine') }}"
给出结果
TASK [debug] ****************************************************
ok: [host1] =>
data:
- host: host1
src: somesource
target: sometarget
- host: host2
src: somesource for host2
target: fancy target
以纯 JMESPath 方式,您可以重新创建 value
属性 对实际值进行 merge
过滤 backups
属性查询:
[].{
key: key,
value: merge(value, {backups: value.backups[?target]})
} | [?value.backups]
因此,鉴于任务:
- debug:
var: hostvars | dict2items | json_query(query) | items2dict
vars:
query: >-
[].{
key: key,
value: merge(value, {backups: value.backups[?target]})
} | [?value.backups]
这产生:
hostvars | dict2items | json_query(query) | items2dict:
host1:
backups:
- src: somesource
target: sometarget
host2:
backups:
- src: somesource for host2
target: fancy target