Вопрос или проблема
Как мне заставить 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
Это в основном тройной цикл, где…
- Внешний цикл перебирает элементы
.cluster.collections
, устанавливая$collection
и$config
в ключ коллекции и атрибут.configName
коллекции соответственно. - Второй цикл перебирает элементы фрагмента коллекции, устанавливая
$shard
в ключ фрагмента. - Внутренний цикл затем перебирает реплики фрагмента, создавая массив с необходимой информацией, т.е. именем набора данных, именем конфигурации, именем фрагмента, конкатенированным с именем реплики, и, наконец, ядром и именем узла реплики.
Массивы, созданные внутренним циклом, передаются через @csv
, чтобы быть преобразованными в записи CSV. Если вы хотите использовать запятую и пробел в качестве разделителя для выводимых полей, замените @csv
на join(", ")
.
Смотрите также:
- Документация для
to_entries
.
Ответ или решение
Для извлечения данных из сложных вложенных объектов 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
Объяснение скрипта
-
.cluster.collections | to_entries[]
: Мы берем коллекции, преобразуем их в массив пар ключ-значение и проходим по нему. Переменные$collection
и$config
содержат имя коллекции и имя конфигурации, соответственно. -
.value.shards | to_entries[]
: На этом этапе мы проходим по всем шардов каждой коллекции. -
.value.replicas | to_entries[]
: На этом шаге мы проходим по всем репликам каждого шардов. -
[$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-файлом, добавляя дополнительные коллекции или изменяя структуру, если это необходимо.