JQ добавить поле в массив в цикле и вернуть весь JSON - PullRequest
0 голосов
/ 15 мая 2018

Я хочу добавить поле в массив aggregations.domains.buckets ниже json, используя jq, и вернуть полный json с новыми полями?Я хочу добавить {"cost": 122.45}, где стоимость динамически вычисляется для каждого ключа.

{
   "aggregations":{
      "domains":{
         "doc_count_error_upper_bound":0,
         "sum_other_doc_count":0,
         "buckets":[
            {
               "key":"other",
               "doc_count":8679,
               "environments":{
                  "value":49
               }
            },
            {
               "key":"CREATIVESandPREVIEWS",
               "doc_count":1235,
               "environments":{
                  "value":21
               }
            },
            {
               "key":"Integration",
               "doc_count":65,
               "environments":{
                  "value":1
               }
            },
            {
               "key":"devops",
               "doc_count":1,
               "environments":{
                  "value":1
               }
            }
         ]
      }
   }
}

Вот мой скрипт:

#!/bin/bash
curl -u xx:xx -H 'Content-Type: application/json' -XPOST 'http://172.21.4.55:9200/log_index-dev-gcecomputeinstances-*/_search?size=0' -o instancesdomainagg.json --data @instancesdomainaggquery.json

var=0
for domain in $(cat instancesdomainagg.json | jq '.aggregations.domains.buckets[].key' | sed -e 's/^"//' -e 's/"$//' | sed -e 's/\(.*\)/\L\1/'); do
curl --trace-ascii curl.trace -u xx:xx -H 'Content-Type: application/json' -XPOST 'http://172.21.4.55:9200/log_index-dev-gcebillingbq-*/_search?size=0' -o bqdomainagg.json --data-binary '{"query":{"bool":{"must":{"term":{"environment_domain.keyword":"'"$domain"'"}},"filter":{"range":{"usage_end_time.value":{"from":"now-1d","to":"now"}}}}},"aggs":{"cost":{"sum":{"field":"cost"}}}}'
val="$(cat bqdomainagg.json | jq '.aggregations.cost.value')"
jq '.aggregations.domains.buckets['"$var"'] |= .+ {"cost": "'"$val"'"}' instancesdomainagg.json > output.json
var=$((var+1))
done

Но он возвращает JSON только споследнее поле добавлено.Как динамически обновить JSON?

Заранее спасибо.

1 Ответ

0 голосов
/ 15 мая 2018

Если стоимость является функцией входного JSON, подход, который вы бы использовали, был бы похож на следующий фильтр, который просто добавляет {"cost": null}:

.aggregations.domains.buckets |= map( . + {cost} )

Если стоимость зависит от key в соответствии с каким-либо другим критерием, то, вероятно, было бы лучше создать словарь JSON, отображающий ключи к стоимости, а затем передать этот словарь в jq и объединить результаты, используя Техника проиллюстрирована на:

Объединение JSON по общим парам ключ-значение

Решение с использованием vals.txt

program.jq:

.aggregations.domains.buckets |=
  reduce range(0; $costs|length) as $i (.;
      .[$i] += {cost: $costs[$i]} )

Если вы хотите, чтобы стоимость была числовой, вы должны написать:

{cost: $costs[$i]|tonumber } )

Вызов:

jq -f program.jq --argfile costs <(jq -Rs '
  split("\n")|map(select(length>0))' vals.txt) input.json

Выход:

{
  "aggregations": {
    "domains": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "other",
          "doc_count": 8679,
          "environments": {
            "value": 49
          },
          "cost": "1280.7631275949711"
        },
        {
          "key": "CREATIVESandPREVIEWS",
          "doc_count": 1235,
          "environments": {
            "value": 21
          },
          "cost": "2210.8813614145324"
        },
        {
          "key": "Integration",
          "doc_count": 65,
          "environments": {
            "value": 1
          },
          "cost": "3143.5814890583424"
        },
        {
          "key": "devops",
          "doc_count": 1,
          "environments": {
            "value": 1
          },
          "cost": "836.4116237582436"
        },
        {
          "cost": "1280.7631275949711"
        }
      ]
    }
  }
}
...