JMESpath表达式按属性过滤对象并返回具有此属性集的对象名称列表

时间:2018-05-09 09:06:55

标签: ansible jmespath json-query

是否可以编写JMESPath表达式以返回设置了特定子属性值的对象名列表?在下面的示例中,我想获得 fileexists.stat.exists 设置为true的所有主机名列表。

我的目标是使用Ansible hostvars结构来获取存在特定文件的所有主机的列表。

{
"hostvars": {
    "oclab1n01.example.org": {
        "fileexists": {
            "changed": false, 
            "failed": false, 
            "stat": {
                "exists": false
            }
        }
    }, 
    "oclab1n02.example.org": {
        "fileexists": {
            "changed": false, 
            "failed": false, 
            "stat": {
                "exists": true
            }
        }
    }, 
    "oclab1n03.example.org": {
        "fileexists": {
            "changed": false, 
            "failed": false, 
            "stat": {
                "exists": true
            }
        }
    }
} }

在这个例子中,我想获得以下输出

["oclab1n02.example.org", "oclab1n03.example.org"]

1 个答案:

答案 0 :(得分:0)

简短回答(TL; DR)

是的,这是有可能的,但是它非常麻烦,因为对于这种通用查询,源数据集被标准化程度很差

上下文

  • jmespath查询语言
  • 查询深度嵌套对象的对象属性

问题

  • 如何使用过滤器表达式构造jmespath查询
  • 目标是过滤具有任意嵌套的对象属性的对象

解决方案

  • 这可以通过jmespath完成,但操作麻烦
  • 一个有问题的问题:这种jmespath查询的源数据集标准化较差
  • 为了构造jmespath查询,我们必须假设在创建查询之前预先知道所有主对象键
  • 在此特定示例中,我们必须先知道只有三个主机名,然后才能构造jmespath查询 ...如果希望灵活地指定,这不是一个好方法任意数量的主机名

示例

以下(太大)的jmespath查询...

  [
    {
      "hostname": `oclab1n01.example.org`
      ,"fileexists_stat_exists":  @.hostvars."oclab1n01.example.org".fileexists.stat.exists
    }
    ,{
      "hostname": `oclab1n02.example.org`
      ,"fileexists_stat_exists":  @.hostvars."oclab1n02.example.org".fileexists.stat.exists
    }
    ,{
      "hostname": `oclab1n03.example.org`
      ,"fileexists_stat_exists":  @.hostvars."oclab1n02.example.org".fileexists.stat.exists
    }
  ]|[? @.fileexists_stat_exists == `true`]|[*].hostname

返回以下期望结果

  [
    "oclab1n02.example.org",
    "oclab1n03.example.org"
  ]

陷阱

  • 这种用例的一个主要陷阱是对这种查询的源数据集进行了规范化
  • 更扁平的数据结构将更易于查询
  • 因此,如果可能的话,一种更好的方法是对源数据集进行扁平化,然后对它运行jmespath查询

具有不同原始数据集的替代示例

如果原始数据被组织为一个对象列表,而不是对象中的一组嵌套对象,则无需事先了解 即可更轻松地搜索,排序和过滤列表涉及多少个主机名条目。

{"hostvars": [
    {"hostname":"oclab1n01.example.org"
      ,"fileexists":        true
      ,"filechanged":       false
      ,"filefailed":        false
      ,"filestat_exists":   false
      ,"we_can_even_still_deeply_nest":{"however":
           {"im_only_doing":"it here","to":"prove a point"}
         }
     }
    ,{"hostname":"oclab1n02.example.org"
      ,"fileexists":        true
      ,"filechanged":       false
      ,"filefailed":        false
      ,"filestat_exists":   true
     }
    ,{"hostname":"oclab1n03.example.org"
      ,"fileexists":        true
      ,"filechanged":       false
      ,"filefailed":        false
      ,"filestat_exists":   true
     }
  ]
}

上面的重新规范化数据集现在可以轻松查询

hostvars|[? @.filestat_exists == `true`]|[*].hostname