Пакетная обработка большого JSON файла с помощью jq - PullRequest
2 голосов
/ 09 января 2020

У меня есть большой JSON файл, который представляет собой массив многих объектов, которые я хочу передать в API, который принимает массовые загрузки данных. Я узнал, что могу использовать потоковый режим jq, чтобы избежать загрузки всего файла в память:

jq --stream -nc 'fromstream(1|truncate_stream(inputs))' < data.json | curl ...

Я хотел бы пакетировать это, поэтому я делаю запрос в пакетах, скажем, для 100 объекты одновременно.

Ответы [ 3 ]

2 голосов
/ 09 января 2020

Вы можете использовать GNU параллельно:

< data.json jq --stream -nc '
    fromstream(1|truncate_stream(inputs))' |
  parallel --pipe -N100 curl ...

Или, в более общем смысле:

< data.json jq --stream -nc '
    fromstream( inputs|(.[0] |= .[1:]) | select(. != [[]]) )' |
  parallel --pipe -N100 curl ...
1 голос
/ 10 января 2020

Если ваши входные данные являются массивом, тогда все пути будут начинаться с цифры (индекса в массиве). Вы можете эффективно разбивать этот массив на страницы, фильтруя по индексам.

$ jq --stream -n --argjson skip 0 --argjson top 100 '
[fromstream(1|truncate_stream(
    inputs | . as [[$index]] | select($index >= $skip and $index < $skip + $top)
))]
' data.json | curl ...

Просто установите аргумент пропуска на соответствующее смещение.

Я создал пример на игровой площадке, чтобы вы могли поиграть с этим. jqplay

1 голос
/ 09 января 2020

Я придумал это, используя встроенный mapfile из Bash 4:

while mapfile -n 100 LINES && ((${#LINES[@]})); do
    echo "Uploading ${#LINES[@]} records..."
    echo "${LINES[@]}" | curl --silent ... --data-binary @- >/dev/null
done < <(jq --stream -cn 'fromstream(1|truncate_stream(inputs))' < data.json)
...