【问题标题】:how to use json_query filter to extract all items equals to a value如何使用 json_query 过滤器提取所有项目等于一个值
【发布时间】:2021-01-26 14:43:06
【问题描述】:

这是我的 json 输出:

{
"kind": [
    {
        "inventory": "",
        "inventory_sources": "",
        "job_templates": "",
        "workflow_job_templates": "104"
    },
    {
        "inventory": "",
        "inventory_sources": "",
        "job_templates": "114",
        "workflow_job_templates": ""
    },
    {
        "inventory": "24",
        "inventory_sources": "",
        "job_templates": "",
        "workflow_job_templates": ""
    },
    {
        "inventory": "",
        "inventory_sources": "108",
        "job_templates": "",
        "workflow_job_templates": ""
    }
]

}

我想显示所有包含特定值的项目名称。 例如,我想显示包含“104”的项目名称是“workflow_job_templates”

我测试了一些语法但没有成功:

    - debug: 
      msg: "104 is {{kind|json_query(query)}}"
      vars:
        query: "[?*==`104`].workflow_job_templates"

我知道这是一种错误的做法,但有人可以告诉我他会如何为自己做吗?

【问题讨论】:

    标签: ansible json-query


    【解决方案1】:

    (更新)

    下面的任务

        - debug:
            msg: "{{ item }} {{ kind|
                                map('dict2items')|
                                map('json_query', query)|
                                flatten }}"
          loop: [104, 114, 108, 24]
          vars:
            query: "[?to_string(value) == to_string('{{ item }}')].key"
    

    给予

      msg: 104 ['workflow_job_templates']
      msg: 114 ['job_templates']
      msg: 108 ['inventory_sources']
      msg: 24 ['inventory']
    

    (记录在案。蛮力方法)

    创建一个唯一的键列表

        - set_fact:
            my_keys: "{{ my_keys|default([]) + item.keys()|list }}"
          loop: "{{ kind }}"
        - set_fact:
            my_keys: "{{ my_keys|unique }}"
    

    给予

      my_keys:
      - inventory
      - inventory_sources
      - job_templates
      - workflow_job_templates
    

    创建一个包含所有值的字典

        - set_fact:
            my_dict: "{{ my_dict|default({})|combine({item: values}) }}"
          loop: "{{ my_keys }}"
          vars:
            query: "[].{{ item }}"
            values: "{{ kind|json_query(query) }}"
    

    给予

      my_dict:
        inventory:
        - ''
        - ''
        - '24'
        - ''
        inventory_sources:
        - ''
        - ''
        - ''
        - '108'
        job_templates:
        - ''
        - '114'
        - ''
        - ''
        workflow_job_templates:
        - '104'
        - ''
        - ''
        - ''
    

    然后搜索字典。例如

        - debug:
            msg: "{{ item }} {{ my_dict|dict2items|json_query(query) }}"
          loop: [104, 114, 108, 24]
          vars:
            query: "[?value[?contains(@, '{{ item }}')]].key"
    

    给予

      msg: 104 ['workflow_job_templates']
      msg: 114 ['job_templates']
      msg: 108 ['inventory_sources']
      msg: 24 ['inventory']
    

    【讨论】:

    • 你能分享一个关于 json_query 语法的教程链接吗,我已经搜索了一段时间关于“包含”或其他语义词但没有成功
    【解决方案2】:

    json_query 可能是您解决方案等式的一部分,但这里实际上不需要。

    下面这段代码的解释:

    • dict2items 过滤器应用于列表的每个元素。这会将每个映射转换为{key: "key", value: "value"} 对的列表
    • 展平给定的列表,以便我们将所有这些元素放在一个顶层
    • 仅选择值为“104”的元素
    • 提取列表中每个元素的key 属性
    • 使该列表独一无二并对其进行排序。
        - name: Display all element having a value of 104
          debug:
            msg: "{{ kind | map('dict2items') | flatten | selectattr('value', '==', '104') | map(attribute='key') | unique | sort }}"
    

    请注意,如果相同的键名与不同的值但其中一个是 '104,则此解决方案将为您提供结果。根据您的上述数据,结果是:

    TASK [Display all element having a value of 104] ***************************************************************************************************************************************************************************************
    ok: [localhost] => {
        "msg": [
            "workflow_job_templates"
        ]
    }
    

    【讨论】:

      【解决方案3】:

      如果你真的只想使用 json_query()

      ---
      - name: PLAYBOOK Filtering
        hosts: localhost # run locally
        
        tasks:
        - name: Create json
          set_fact:
            kind: '{{ lookup("file", "kind.json") }}'
      
        - name: check the var was created properly
          debug:
            var: kind 
      
        - name: output the element that matches 104
          debug: 
            msg: "{{ kind | json_query(\"kind[?workflow_job_templates=='104'].workflow_job_templates\") }}"
      
        - name: 
          set_fact: 
            output: "{{ kind | json_query(\"kind[?workflow_job_templates=='104'].workflow_job_templates\") }}"
      
      

      输出

      TASK [output the element that matches 104] *************************************************************************************************************
      ok: [localhost] => {
          "msg": [
              "104"
          ]
      }
      

      【讨论】:

      • 这个解决方案没有达到预期的效果,它应该返回元素名称而不是值。
      【解决方案4】:

      selectattr 与 json_query 的正确替代方法是:

          - debug:
              msg: "{{ kind | map('dict2items') | flatten | json_query(query)}}"
            vars:
              - query: "[?value == `\"104\"`].key"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-23
        • 2021-11-19
        • 2021-11-23
        • 2022-01-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多