使用 jq 分区 JSON 数据,然后发送 Rest 查询

Partition JSON data using jq and then send Rest query

我有一个如下所示的 json 文件

[
    {
        "field": {
            "empID": "sapid",
            "location": "India",            
        }
    },
    {
        "field": {
            "empID": "sapid",
            "location": "India",            
        }
    },
    {
        "field": {
            "empID": "sapid",
            "location": "India",            
        }
    }
    {
        "field": {
            "empID": "sapid",
            "location": "India",            
        }
    },
    {
        "field": {
            "empID": "sapid",
            "location": "India",            
        }
    }
        {
        "field": {
            "empID": "sapid",
            "location": "India",            
        }
    }
    .... upto 1 million
]

我必须使用这个 json 作为休息请求的输入例如

curl <REST Server URL with temp.json as input> "Content-Type: application/json" -d @temp.json

我的服务器不会一次接受 100 万个 json 对象。 我正在寻找一种方法,我必须从主 json 中提取前 500 个对象并将其发送到一个剩余查询中,然后在第二个剩余查询中发送下一个 500 个对象,依此类推。

你能建议我如何通过 jq 实现这个吗?

假设你有这种格式,拆分可以通过解包数组并将所需数量的对象保存到单独的文件中来完成,例如:

<input.json jq -c '.[]' | split -l500

它用前 500 个对象创建 xaa,用接下来的 500 个对象创建 xab,等等。如果要将对象重新打包到数组中,请使用 -s 选项到 jq,例如:jq -s . xaa.

您还没有共享您正在使用的系统的任何硬件信息 运行。至少你需要做一些多处理来让它更快而不是 运行ning (1000000/500) curl 请求。

一种方法是使用 GNU xargs,它有 built-in 到 运行 个给定进程的并行实例,使用 -P 标志和数字使用 L 标志随时读取的输入行数。

首先,您可以执行类似下面的操作,指示 curl 一次在 500 行上 运行 并并行调用 20 个这样的调用。因此,在给定的滴答声中,将处理大约 (500 *20) 行输入。您可以根据您在主机端和服务器端的硬件功能调整数字。

xargs -L 500 -P 20 curl -X POST -H "Content-Type: application/json"  http://sample-url -d @- < <(jq -c 'range(0;length;500) as $i | .[$i: $i+500]' json)

修改了 jq 过滤器以将 JSON 有效负载打包为对象数组(来源 )。早期版本 jq -c '.[]' json 可能无法工作,因为一次传递的单个行块不代表有效的 JSON.

注意:由于性能限制,未进行测试。

space 和时间效率之间存在内在的权衡。下面重点介绍后者。

假设每次调用 curl 都必须发送一个 JSON 数组,一个 time-efficient 解决方案可以按照以下几行构造:

< array.json jq -c '
  def batch($n): length as $l | range(0;length;$n) as $i | .[$i: $i+n];
  batch(500)
' | while read -r json
do
    echo "$json" | curl -X POST -H "Content-Type: application/json" -d -@ ....
done

此处....表示附加适当的curl参数。

GNU 并行

您可能还想考虑使用 GNU ,例如:

< array.json jq -c '
  def batch($n):
    length as $l
    | range(0;length;$n) as $i
    | .[$i: $i+n];
  batch(500)
' | parallel --pipe -N1 curl -X POST -H "Content-Type: application/json"  -d @- ....

如果你想从 shell 执行此操作,你可以使用 jq 拆分你的 JSON 并将其传递给 xargs 以调用 curl 对于返回的每个对象。

jq -c '.[]' temp.json | xargs -I {} curl <REST Server URL with temp.json as input> "Content-Type: application/json" -d '{}'

这将为每个对象发送 一个 curl 请求。但是,如果您例如想要在 单个 curl 请求中发送前 500 个对象,可以在 jq 过滤器中指定一个子数组。要发送所有 JSON 对象,您将需要以某种方式重复该命令,因为 afaik jq 没有 built-in 将输入拆分为对象块的方法。

jq -c '.[0:500]' temp.json | xargs -I {} curl <REST Server URL with temp.json as input> "Content-Type: application/json" -d '{}'
jq -c '.[500:1000]' temp.json | xargs -I {} curl <REST Server URL with temp.json as input> "Content-Type: application/json" -d '{}'
jq -c '.[1000:1500]' temp.json | xargs -I {} curl <REST Server URL with temp.json as input> "Content-Type: application/json" -d '{}'
[...]