jq多条件查询失效求助:跨层级字段筛选无法缩小结果范围
问题描述
尝试用jq执行跨层级多条件查询,单条件筛选SchedulerNodeName能得到预期结果,但添加Configs.PXType的筛选条件后,无法缩小结果范围,所有Configs下的ID仍被返回。
单条件查询(正常工作)
筛选指定SchedulerNodeName的节点:
$ NODE="host-inf-4"; cat pxctl-cd-list-short.json | jq -c '.[] | select (.SchedulerNodeName == '"${NODE}"')'
返回包含该节点所有Configs的JSON结构,符合预期。
提取该节点下所有Configs的ID:
$ NODE="host-inf-4"; cat pxctl-cd-list-short.json | jq -c '.[] | select (.SchedulerNodeName == '"${NODE}"').Configs[].ID'
返回两个ID:
"[datastore--21] adsadaiuhwiorgwipo/_00ca/hipeghwerwjks.vmdk" "[datastore-21] ukisvljrosoowpg/_00mb/jjgowhohgiyfiaaawjo.vmdk"
多条件查询失效情况
尝试添加PXType筛选条件(比如筛选kvdb或data),以下两种写法均无法缩小结果范围,仍返回全部两个ID:
$ NODE="host-inf-4"; cat pxctl-cd-list-short.json | jq -c '.[] | select (.SchedulerNodeName == '"${NODE}"') | select ( .Configs[].PXType == "kvdb").Configs[].ID'
$ NODE="host-inf-4"; cat pxctl-cd-list-short.json | jq -c '.[] | select (.SchedulerNodeName == '"${NODE}"' and .Configs[].PXType == "data" ).Configs[].ID'
对应的JSON结构:
{ "1dfasdavsdfsvhoho028": { "Configs": { "[datastore-21] adsadaiuhwiorgwipo/_00ca/hipeghwerwjks.vmdk": { "Type": "zeroedthick", "Size": 32, "ID": "[datastore--21] adsadaiuhwiorgwipo/_00ca/hipeghwerwjks.vmdk", "PoolID": "", "Path": "/dev/sdc", "Iops": 0, "Vpus": 0, "PXType": "kvdb", "State": "Pending Add", "labels": { "datastore": "vsanDatastore" }, "AttachOptions": { "ext": ".vmdk" }, "Provisioner": "", "EncryptionKeyInfo": "" }, "[datastore-21] ukisvljrosoowpg/_00mb/jjgowhohgiyfiaaawjo.vmdk": { "Type": "lazyzeroedthick", "Size": 150, "ID": "[datastore-21] ukisvljrosoowpg/_00mb/jjgowhohgiyfiaaawjo.vmdk", "PoolID": "a471iidfisaj8i8124asdadsoif8ie82", "Path": "/dev/sdb", "Iops": 0, "Vpus": 0, "PXType": "data", "State": "In Use", "labels": { "datastore": "vsanDatastore" }, "AttachOptions": { "ext": ".vmdk" }, "Provisioner": "", "EncryptionKeyInfo": "" } }, "NodeID": "16a-8243r20-8fihqwc8-adew-2343ase", "ReservedInstanceID": "", "SchedulerNodeName": "host-inf-4", "NodeIndex": 12, "CreateTimestamp": "2024-11-22T00:27:38.432162311Z", "InstanceID": "42sdada08ihjpb3fe-6b-4873-0ya7-be80079acasca", "Zone": "default", "State": "In Use", "labels": { "px/metadata-node": "true" } }, "asdada-42764533fff2": { "Configs": null, "NodeID": "1", "ReservedInstanceID": "", "SchedulerNodeName": "host-wkr-19", "NodeIndex": 19, "CreateTimestamp": "0001-01-01T00:00:00Z", "InstanceID": "asda0098q921", "Zone": "default", "State": "In Use", "labels": { "px/metadata-node": "false" } } }
原因分析
写法错误在于将对象迭代(.Configs[])放在了select内部,导致:
- 当执行
.Configs[].PXType == "kvdb"时,jq会遍历节点下所有Configs对象,只要其中一个满足条件,整个select就返回true,保留整个节点。 - 后续提取
.Configs[].ID时,自然会返回该节点下所有Configs的ID,而非筛选后的结果。
简单说:你是先筛选节点(只要节点内存在符合PXType的Configs就保留),再提取该节点所有Configs的ID,而非直接筛选Configs对象。
解决方案
正确逻辑是:先筛选出目标节点,再遍历该节点的Configs对象,对每个Configs单独做筛选,最后提取符合条件的ID。
写法1:分步筛选
$ NODE="host-inf-4"; cat pxctl-cd-list-short.json | jq -c '.[] | select(.SchedulerNodeName == '"${NODE}"') | .Configs[] | select(.PXType == "kvdb") | .ID'
逻辑拆解:
.[]:遍历顶层所有节点select(.SchedulerNodeName == ...):筛选出目标节点.Configs[]:遍历该节点下所有Configs对象select(.PXType == ...):筛选出符合PXType的Configs.ID:提取该Configs的ID
写法2:用to_entries处理Configs
如果需要先在节点层面过滤Configs,再提取ID,可将Configs的键值对转为数组处理:
$ NODE="host-inf-4"; cat pxctl-cd-list-short.json | jq -c '.[] | select(.SchedulerNodeName == '"${NODE}"') | .Configs | to_entries[] | select(.value.PXType == "data") | .value.ID'
测试结果
执行第一种写法筛选kvdb时,返回:
"[datastore--21] adsadaiuhwiorgwipo/_00ca/hipeghwerwjks.vmdk"
筛选data时,返回:
"[datastore-21] ukisvljrosoowpg/_00mb/jjgowhohgiyfiaaawjo.vmdk"
符合预期。
内容的提问来源于stack exchange,提问作者Burvil
相关产品推荐
相关产品推荐

