JMESpath 表达式按属性过滤对象并返回设置了此属性的对象名称列表 [英] JMESpath expression to filter object by property and return list of object names having this property set

查看:25
本文介绍了JMESpath 表达式按属性过滤对象并返回设置了此属性的对象名称列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

<代码>{主机变量":{oclab1n01.example.org":{文件已存在": {改变":假,失败":错误,统计":{存在":假}}},oclab1n02.example.org":{文件已存在": {改变":假,失败":错误,统计":{存在":真实}}},oclab1n03.example.org":{文件已存在": {改变":假,失败":错误,统计":{存在":真实}}}} }

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

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

解决方案

Short answer (TL;DR)

是的,这是可能的,但它非常麻烦,因为至少在使用 JMESpath 方面,源数据集对于这种通用查询标准化很差.>

上下文

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

问题

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

解决方案

  • 这个可以用jmespath来完成,但是操作起来会繁琐
  • 一个有问题的问题:对于这种 jmespath 查询,源数据集标准化不佳
  • 为了构建 jmespath 查询,我们必须假设所有主对象键在创建查询之前都是已知的
  • 在这个特定的例子中,我们必须在构建 jmespath 查询之前知道只有三个主机名 ...如果我们想要灵活地指定,这不是一个有利的情况任意数量的主机名

示例

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

<预><代码> [{主机名":`oclab1n01.example.org`,fileexists_stat_exists":@.hostvars.oclab1n01.example.org".fileexists.stat.exists},{主机名":`oclab1n02.example.org`,fileexists_stat_exists":@.hostvars.oclab1n02.example.org".fileexists.stat.exists},{主机名":`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":[{主机名":oclab1n01.example.org",文件存在":真,文件已更改":false,文件失败":假,filestat_exists":假,we_can_even_still_deeply_nest":{但是":{im_only_doing":它在这里",to":证明一个点"}}},{主机名":oclab1n02.example.org",文件存在":真,文件已更改":false,文件失败":假,filestat_exists":真},{主机名":oclab1n03.example.org",文件存在":真,文件已更改":false,文件失败":假,filestat_exists":真}]}

现在可以轻松查询上述重新归一化数据集

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

Is it possible to write JMESPath expression to return a list of object names where a specific subproperty value is set? In the example below I'd like to get a list of all hostsnames where fileexists.stat.exists is set to true.

My goal is to use Ansible hostvars structure to get a list of all hosts where a specific file is present.

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

In this example I'd like to get the following output

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

解决方案

Short answer (TL;DR)

Yes, this is possible, but it is extremely cumbersome, because, at least in terms of working with JMESpath, the source dataset is poorly normalized for this kind of general-purpose query.

Context

  • jmespath query language
  • querying object properties for deeply nested objects

Problem

  • How to construct a jmespath query with filter expressions
  • The goal is to filter on objects with arbitrarily nested object properties

Solution

  • This can be done with jmespath, but the operation will be cumbersome
  • One problematic issue: the source dataset is poorly normalized for this kind of jmespath query
  • In order to construct the jmespath query, we have to assume all the primary object keys are known in advance of creating the query
  • In this specific example, we have to know that there are three and only three hostnames in advance of constructing the jmespath query ... this is not a favorable circumstance if we want the flexibility to specify any arbitrary number of hostnames

Example

The following (way-too-huge) jmespath query ...

  [
    {
      "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

returns the following desired result

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

Pitfalls

  • One major pitfall with this use-case is the source dataset is poorly normalized for this kind of query
  • A more flattened data structure would be easier to query
  • Consequently, if possible, a better approach would be to flatten the source dataset before running jmespath queries against it

Alternate example with a different original dataset

If the original data were organized as a list of objects, instead of a set of nested objects within objects, it would be easier to search, sort and filter the list without having to know in advance how many hostname entries are involved.

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

The above re-normalized dataset can now be easily queried

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

这篇关于JMESpath 表达式按属性过滤对象并返回设置了此属性的对象名称列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆