how to use json_query filter to extract all items equals to a value

Here is my json output:

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

I'd like to display all items name that contain a specific value. For example, for a search value of 104 I want to get the key name workflow_job_templates

I tested some syntaxes without any success:

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

I know it is wrong but can someone tell me how he'd do for himself?

Upvotes: 2

Views: 2879

Answers (3)

Zeitounator
Zeitounator

Reputation: 44595

json_query could be part of the equation for your solution but is really not needed here.

Explanation of the below piece of code:

  • Apply the dict2items filter to each element of your list. This transforms each mapping to a list of {key: "key", value: "value"} pairs
  • Flatten the given list so we get all those elements to a single top level
  • Select elements having a value of '104' only
  • Extract the key attribute of each element in a list
  • Make that list unique and sort it.
    - name: Display all element having a value of 104
      debug:
        msg: "{{ kind | map('dict2items') | flatten
          | selectattr('value', '==', '104')
          | map(attribute='key') | unique | sort }}"

Please note that this solution will give you a result if the same key name has different values but one of them is `104. With your above data the result is:

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

Upvotes: 3

The correct alternative of selectattr with json_query is:

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

Upvotes: 0

Vladimir Botka
Vladimir Botka

Reputation: 67959

(Update)

The task below

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

gives

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

(For the record. Brute-force approach)

Create a unique list of the keys

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

gives

  my_keys:
  - inventory
  - inventory_sources
  - job_templates
  - workflow_job_templates

Create a dictionary with all values

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

gives

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

Then search the dictionary. For example

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

gives

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

Upvotes: 2

Related Questions