如何使用jq从一个非常大的整体JSON文档的开始附近经济地提取一个小的JSON片段?



所讨论的JSON文件相当大(约1.5GB),但在开始附近的已知位置(.meta.view.approvals)有一些元数据。

如何使用jq或gojq来提取该位置的对象而无需加载将整个文件放入内存,而不必等待整个文件的处理停止在提取出感兴趣的项目之后?

寻找泛型方法,但我感兴趣的特定文件是行。Json在https://data.montgomerycountymd.gov/api/views/4mse-ku6q/rows.json我的副本在2023年1月12日被检索;文件大小为1459382170字节,.meta.view的值为。文件中的createdAt为1403103517

命令行选项jq、gojq和jm也很有趣,只要它们在内存和CPU使用方面都是经济的。

将jq(或gojq)的流解析器与first/1结合使用,如下所示。

这减少了执行时间和内存需求,例如,与使用非流解析器相比:从50秒到几微秒,从4,112MB RAM (mrss)到3MB。

指出:

  • jq和gojq不会产生相同的结果,因为gojq不尊重对象内键的顺序。
  • 下面显示的性能统计数据是针对行的。Q.

以下是在3GHz机器上显示命令调用和关键性能统计数据的记录摘录。

+ /usr/bin/time -lp gojq -n --stream 'first(fromstream(3|truncate_stream(inputs| select(.[0][0:3] == ["meta","view", "approvals"]) )))' rows.json
user 0.00
sys 0.00
3702784  maximum resident set size
1531904  peak memory footprint
+ /usr/bin/time -lp jq -n --stream 'first(fromstream(3|truncate_stream(inputs| select(.[0][0:3] == ["meta","view", "approvals"]) )))' rows.json
user 0.00
sys 0.00
1990656  maximum resident set size
1114112  peak memory footprint
/usr/bin/time -lp jq .meta.view.approvals rows.json
user 39.90
sys 11.82
4112465920  maximum resident set size
6080188416  peak memory footprint
/usr/bin/time -lp gojq -n --stream '
fromstream(3|truncate_stream(inputs | select(.[0][0:3] == ["meta","view", "approvals"]) ))' rows.json
user 495.30
sys 273.72
7858896896  maximum resident set size
38385831936  peak memory footprint
下面的jm命令产生的结果基本相同:
/usr/bin/time -lp jm --pointer /meta/view/approvals rows.json
user 0.05
sys 0.07
13594624  maximum resident set size
7548928  peak memory footprint

另一种选择是使用first_run/2定义如下:

# Emit the first run of the items in the stream for which the condition is truthy
def first_run(stream; condition):
label $out
| foreach stream as $x (null;
($x|condition) as $y
| if $y
then [$x]
elif . then break $out
else .
end;
if . then .[0] else empty end);

最新更新