#json #performance #jq
Вопрос:
Я ищу некоторую помощь, чтобы увеличить свой jq-foo, и мне не помешало бы небольшое руководство. У меня есть несколько заданий etl, которые я пишу с помощью JQ, и я хочу посмотреть, есть ли способ сделать запуски более эффективными с точки зрения загрузки процессора и / или скорости.
Вот образец полезной нагрузки:
{ "timestamp": 1636601959, "uniqueId": "Foo", "value": 10 }, { "timestamp": 1636601859, "uniqueId": "Bar", "value": 13 }
и я хочу сделать что-то вроде (псевдокода):
if [ (epoch 15 minutes ago) -le timestamp ]; then name=uniqueId; value_total=value(total); uniqueId_count=(uniqueId(count_total)) fi
Прямо сейчас я делаю что-то вроде (псевдокода):
for jq[timestamps] in $(json); do if [ (epoch 15 minutes ago) -le timestamp ]; then name=uniqueId; value_total=(value_total value); uniqueId_count=(uniqueId_count 1). fi done
Есть ли способ упростить это без использования цикла for для перебора каждого объекта, вызывая jq 'select() ...'
его снова и снова?
Комментарии:
1. Должно
.uniqueId_count
ли поле в выводе суммироваться по всему входу или увеличиваться от элемента к элементу?2. Это число будет равняться общему количеству раз, когда UniqueID появляется в документе json. Поэтому мне в основном нужно получить общее количество groupby(уникальных идентификаторов), которые приходятся на последние 15 минут. Значения также будут суммированы аналогичным образом. Поэтому, если » foo » появляется в разных временных метках, но все в течение 15 минут назад, мне нужно общее значение(10 n n и т. Д.)
3. Но в вашем псевдокоде проверка
timestamp -le (epoch 15 minutes ago)
обнаружит эти элементы старше 15 минут, а не «в течение последних 15 минут».4. Ах, совершенно верно, я объяснил это неправильно… это должно быть в течение 15 минут… фактический код выглядит так
if [ "${minutes_ago}" -le "${time}" ]; then
, гдеminutes_ago
эпоха 15 минут назад иtime
является отметкой времени json5. Обновил свой ответ, чтобы отразить все изменения (я надеюсь).
Ответ №1:
Если вы либо избавитесь от запятых между объектами, либо заключите весь ввод в квадратные скобки массива (чтобы получить правильный JSON), то вы можете сделать (используйте -s
опцию для {}{}{}
стиля или отбросьте ее для [{],{},{}]
стиля):
jq -s --argjson delta $((15*60)) --argjson addvalue 10 ' (now - $delta) as $pivot | map(select(.timestamp gt;= $pivot)) | group_by(.uniqueId) | map({ name: first.uniqueId, value_total: map(.value) | (add $addvalue), uniqueId_count: length }) '
Комментарии:
1. Это потрясающе, спасибо за это! Я собираюсь попробовать и посмотреть, повезет ли мне… было бы здорово не
for
зацикливаться на каждом объекте2. Кроме того, я отредактировал свою операцию, значение=10 на самом деле должно было быть value_total=значение(всего)