{ “title”: “Перепишите этот заголовок в формате JSON с использованием jq для вложенных объектов JSON” }

Вопрос или проблема

Как мне заставить jq принимать json, как этот:

{
  "responseHeader":{
    "status":0,
    "QTime":1
  },
  "cluster":{
    "collections":{
      "collection1-stored":{
        "pullReplicas":"0",
        "configName":"collection1-stored-conf1",
        "replicationFactor":1,
        "router":{
          "name":"compositeId"
        },
        "nrtReplicas":1,
        "tlogReplicas":"0",
        "shards":{
          "shard1":{
            "range":"80000000-7fffffff",
            "state":"active",
            "replicas":{
              "core_node2":{
                "core":"collection1-stored_shard1_replica_n1",
                "node_name":"servername1:8983_solr",
                "type":"NRT",
                "state":"active",
                "leader":"true",
                "force_set_state":"false",
                "base_url":"http://servername1:8983/solr"
              }
            },
            "health":"GREEN"
          }
        },
        "health":"GREEN",
        "znodeVersion":3,
        "creationTimeMillis":1727780823546
      },
      "collection2-multi":{
        "pullReplicas":"0",
        "configName":"collection2-multi-conf2",
        "replicationFactor":2,
        "router":{
          "name":"compositeId"
        },
        "nrtReplicas":2,
        "tlogReplicas":"0",
        "shards":{
          "shard1":{
            "range":"80000000-7fffffff",
            "state":"active",
            "replicas":{
              "core_node3":{
                "core":"collection2-multi_shard1_replica_n1",
                "node_name":"servername1:8983_solr",
                "type":"NRT",
                "state":"active",
                "leader":"true",
                "force_set_state":"false",
                "base_url":"http://servername1:8983/solr"
              },
              "core_node4":{
                "core":"collection2-multi_shard1_replica_n2",
                "node_name":"servername2:8983_solr",
                "type":"NRT",
                "state":"active",
                "force_set_state":"false",
                "base_url":"http://servername2:8983/solr"
              }
            },
            "health":"GREEN"
          }
        },
        "health":"GREEN",
        "znodeVersion":5,
        "creationTimeMillis":1727780813821,
        "aliases":["collection2-multi-query","collection2-multi-upd"]
      },
      "collection4-multi-multi1":{
        "pullReplicas":"0",
        "configName":"collection4-multi-multi-conf4",
        "replicationFactor":2,
        "router":{
          "name":"compositeId"
        },
        "nrtReplicas":2,
        "tlogReplicas":"0",
        "shards":{
          "shard1":{
            "range":"80000000-ffffffff",
            "state":"active",
            "replicas":{
              "core_node5":{
                "core":"collection4-multi-multi1_shard1_replica_n2",
                "node_name":"servername1:8983_solr",
                "type":"NRT",
                "state":"active",
                "force_set_state":"false",
                "base_url":"http://servername1:8983/solr"
              },
              "core_node8":{
                "core":"collection4-multi-multi1_shard1_replica_n6",
                "node_name":"servername2:8983_solr",
                "type":"NRT",
                "state":"active",
                "leader":"true",
                "force_set_state":"false",
                "base_url":"http://servername2:8983/solr"
              }
            },
            "health":"GREEN"
          },
          "shard2":{
            "range":"0-7fffffff",
            "state":"active",
            "replicas":{
              "core_node3":{
                "core":"collection4-multi-multi1_shard2_replica_n1",
                "node_name":"servername1:8983_solr",
                "type":"NRT",
                "state":"active",
                "leader":"true",
                "force_set_state":"false",
                "base_url":"http://servername1:8983/solr"
              },
              "core_node7":{
                "core":"collection4-multi-multi1_shard2_replica_n4",
                "node_name":"servername2:8983_solr",
                "type":"NRT",
                "state":"active",
                "force_set_state":"false",
                "base_url":"http://servername2:8983/solr"
              }
            },
            "health":"GREEN"
          }
        },
        "health":"GREEN",
        "znodeVersion":7,
        "creationTimeMillis":1727780770838,
        "aliases":["collection4-multi-multi"]
      },
      "collection3-multi":{
        "pullReplicas":"0",
        "configName":"collection3-multi-conf3",
        "replicationFactor":2,
        "router":{
          "name":"compositeId"
        },
        "nrtReplicas":2,
        "tlogReplicas":"0",
        "shards":{
          "shard1":{
            "range":"80000000-7fffffff",
            "state":"active",
            "replicas":{
              "core_node7":{
                "core":"collection3-multi_shard1_replica_n1",
                "node_name":"servername2:8983_solr",
                "type":"NRT",
                "state":"active",
                "force_set_state":"false",
                "base_url":"http://servername2:8983/solr"
              },
              "core_node5":{
                "core":"collection3-multi_shard1_replica_n2",
                "node_name":"servername1:8983_solr",
                "type":"NRT",
                "state":"active",
                "leader":"true",
                "force_set_state":"false",
                "base_url":"http://servername1:8983/solr"
              }
            },
            "health":"GREEN"
          }
        },
        "health":"GREEN",
        "znodeVersion":6,
        "creationTimeMillis":1727780768553,
        "aliases":["collection3-multi-index","collection3-multi-query"]
      }
    }
  }
}

и генерировать такой вывод:

collection1-stored, collection1-stored-conf1, shard1:core_node2, collection1-stored_shard1_replica_n1, servername1:8983_solr
collection2-multi, collection2-multi-conf2, shard1:core_node3, collection2-multi_shard1_replica_n1, servername1:8983_solr
collection2-multi, collection2-multi-conf2, shard1:core_node4, collection2-multi_shard1_replica_n2, servername2:8983_solr
collection4-multi-multi1, collection4-multi-multi-conf4, shard1:core_node5, collection4-multi-multi1_shard1_replica_n2, servername1:8983_solr
collection4-multi-multi1, collection4-multi-multi-conf4, shard1:core_node8, collection4-multi-multi1_shard1_replica_n6, servername2:8983_solr
collection4-multi-multi1, collection4-multi-multi-conf4, shard2:core_node3, collection4-multi-multi1_shard2_replica_n1, servername1:8983_solr
collection4-multi-multi1, collection4-multi-multi-conf4, shard2:core_node7, collection4-multi-multi1_shard2_replica_n4, servername2:8983_solr
collection3-multi, collection3-multi-conf3, shard1:core_node7, collection3-multi_shard1_replica_n1, servername2:8983_solr
collection3-multi, collection3-multi-conf3, shard1:core_node5, collection3-multi_shard1_replica_n2, servername1:8983_solr

используя форматировщик jq.

В общем, мне нужно получить для каждого набора данных имя и для каждого его фрагмента и для каждой его реплики строку, содержащую имя набора данных, значение configName, имя ядра, значение ядра и значение node_name.

Я смог дойти только до первого уровня фильтрации, как:

jq ".cluster.collections"

Спасибо

Предполагая, что вы хотите CSV-вывод:

$ jq -r -f script file
"collection1-stored","collection1-stored-conf1","shard1:core_node2","collection1-stored_shard1_replica_n1","servername1:8983_solr"
"collection2-multi","collection2-multi-conf2","shard1:core_node3","collection2-multi_shard1_replica_n1","servername1:8983_solr"
"collection2-multi","collection2-multi-conf2","shard1:core_node4","collection2-multi_shard1_replica_n2","servername2:8983_solr"
"collection4-multi-multi1","collection4-multi-multi-conf4","shard1:core_node5","collection4-multi-multi1_shard1_replica_n2","servername1:8983_solr"
"collection4-multi-multi1","collection4-multi-multi-conf4","shard1:core_node8","collection4-multi-multi1_shard1_replica_n6","servername2:8983_solr"
"collection4-multi-multi1","collection4-multi-multi-conf4","shard2:core_node3","collection4-multi-multi1_shard2_replica_n1","servername1:8983_solr"
"collection4-multi-multi1","collection4-multi-multi-conf4","shard2:core_node7","collection4-multi-multi1_shard2_replica_n4","servername2:8983_solr"
"collection3-multi","collection3-multi-conf3","shard1:core_node7","collection3-multi_shard1_replica_n1","servername2:8983_solr"
"collection3-multi","collection3-multi-conf3","shard1:core_node5","collection3-multi_shard1_replica_n2","servername1:8983_solr"

… где script есть

.cluster.collections | to_entries[] | [.key, .value.configName] as [$collection, $config] |
.value.shards        | to_entries[] | .key as $shard |
.value.replicas      | to_entries[] | [.key, .value.core, .value.node_name] as [$replica, $core, $node] |
[$collection, $config, $shard + ":" + $replica, $core, $node] | @csv

Это в основном тройной цикл, где…

  1. Внешний цикл перебирает элементы .cluster.collections, устанавливая $collection и $config в ключ коллекции и атрибут .configName коллекции соответственно.
  2. Второй цикл перебирает элементы фрагмента коллекции, устанавливая $shard в ключ фрагмента.
  3. Внутренний цикл затем перебирает реплики фрагмента, создавая массив с необходимой информацией, т.е. именем набора данных, именем конфигурации, именем фрагмента, конкатенированным с именем реплики, и, наконец, ядром и именем узла реплики.

Массивы, созданные внутренним циклом, передаются через @csv, чтобы быть преобразованными в записи CSV. Если вы хотите использовать запятую и пробел в качестве разделителя для выводимых полей, замените @csv на join(", ").

Смотрите также:

Ответ или решение

Для извлечения данных из сложных вложенных объектов JSON с помощью jq, можно использовать следующий подход. Ваша исходная структура JSON содержит коллекции, каждая из которых может иметь множество шардов, и каждый шард может иметь несколько реплик. Цель состоит в том, чтобы сгенерировать выходной CSV-файл, содержащий информацию о каждой коллекции, ее конфигурации, каждом шарде и всех его репликах.

Вот как можно это сделать:

Пример JSON

Предположим, у нас есть следующий JSON:

{
  "responseHeader": {
    "status": 0,
    "QTime": 1
  },
  "cluster": {
    "collections": {
      "collection1-stored": {
        "pullReplicas": "0",
        "configName": "collection1-stored-conf1",
        "replicationFactor": 1,
        "router": {
          "name": "compositeId"
        },
        "nrtReplicas": 1,
        "tlogReplicas": "0",
        "shards": {
          "shard1": {
            "range": "80000000-7fffffff",
            "state": "active",
            "replicas": {
              "core_node2": {
                "core": "collection1-stored_shard1_replica_n1",
                "node_name": "servername1:8983_solr",
                "type": "NRT",
                "state": "active",
                "leader": "true",
                "force_set_state": "false",
                "base_url": "http://servername1:8983/solr"
              }
            },
            "health": "GREEN"
          }
        },
        "health": "GREEN",
        "znodeVersion": 3,
        "creationTimeMillis": 1727780823546
      }
      // Другие коллекции опущены для краткости
    }
  }
}

Скрипт jq

Для преобразования данных и получения необходимого формата результата, используйте следующий скрипт jq:

jq -r '
.cluster.collections | to_entries[] | 
  [.key, .value.configName] as [$collection, $config] |
  .value.shards | to_entries[] |
  .value.replicas | to_entries[] |
  [$collection, $config, .key + ":" + .key, .value.core, .value.node_name] | @csv
' ваш_файл.json

Объяснение скрипта

  1. .cluster.collections | to_entries[]: Мы берем коллекции, преобразуем их в массив пар ключ-значение и проходим по нему. Переменные $collection и $config содержат имя коллекции и имя конфигурации, соответственно.

  2. .value.shards | to_entries[]: На этом этапе мы проходим по всем шардов каждой коллекции.

  3. .value.replicas | to_entries[]: На этом шаге мы проходим по всем репликам каждого шардов.

  4. [$collection, $config, .key + ":" + .key, .value.core, .value.node_name] | @csv: Собираем данные в массив, добавляя нужные поля. Затем используем @csv, чтобы преобразовать массив в строку формата CSV.

Вывод

Результирующий вывод будет в формате CSV, что соответствует вашему запросу. Он будет выглядеть приблизительно так:

"collection1-stored","collection1-stored-conf1","shard1:core_node2","collection1-stored_shard1_replica_n1","servername1:8983_solr"
...

Заключение

Этот скрипт позволяет эффективно обрабатывать вложенные JSON-структуры с использованием jq. Вы можете настроить его для работы с вашим конкретным JSON-файлом, добавляя дополнительные коллекции или изменяя структуру, если это необходимо.

Оцените материал
Добавить комментарий

Капча загружается...