【问题标题】:Batch processing of a large JSON file with jq使用 jq 批量处理大型 JSON 文件
【发布时间】:2020-04-26 12:46:54
【问题描述】:

我有一个大型 JSON 文件,它是一个包含许多对象的数组,我想将它们提交给接受批量数据上传的 API。我了解到我可以使用 jq 的流模式来避免将整个文件加载到内存中:

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

我想批量处理这个,所以我要批量请求,例如,一次 100 个对象。

【问题讨论】:

  • 不要忘记 -n 命令行选项!!!
  • 我看到了那个建议,但我不清楚为什么。 “根本不读取任何输入!相反,过滤器使用 null 作为输入运行一次。这在将 jq 用作简单计算器或从头构造 JSON 数据时很有用。”没有它似乎也可以工作,我也不想将 jq 用作简单的计算器。如果它很重要,为什么 --stream 不暗示它?
  • 是的,这可能有点令人困惑,但是如果您省略 -n ,那么您将丢失一个 JSON 实体。比较 echo 1 | jq -n --stream inputs 和没有 -n 选项的相同事物。

标签: bash jq


【解决方案1】:

您可以使用 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 ...

【讨论】:

    【解决方案2】:

    我是使用 Bash 4 中的 mapfile 内置的:

    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)
    

    【讨论】:

    • 警告:如果没有-n 选项,这个 jq 调用实际上会跳过 data.json 中的第一个 JSON 实体
    【解决方案3】:

    如果您的输入是一个数组,那么路径都将以数字开头(数组的索引)。您可以通过按索引过滤来有效地对该数组进行分页。

    $ 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-14
      • 2019-08-31
      • 2022-11-24
      • 2017-06-01
      相关资源
      最近更新 更多