在一个大的JSON文件(50GB)上使用jq

4

我想在一个50GB的文件上使用jq。不用说,机器的内存无法处理它。它已经耗尽了内存。

我尝试了几个选项,包括--stream,但都没有帮助。有人能告诉我我做错了什么吗?以及如何解决它

jq -cn --stream 'fromstream(1|truncate_stream(inputs))' file.json |   jq -cr .data[] >> out.json

该文件包含如下数据:

{"data":[{"id":"id1","value":"value1"},{"id":"id2","value":"value2"},{"id":"id3","value":"value3"}...]}

我想读取数据字段中数组的每个值,并将其逐行放入另一个文件中,例如下面这样。
{"id":"id1","value":"value1"}
{"id":"id2","value":"value2"}
{"id":"id3","value":"value3"}

现在命令运行时内存不足并被终止。


5
一旦调用 fromstream,您就要求 jq 从流中读取数据并在内存中创建一个数据结构。使用 --stream 是没有用的,除非在调用 fromstream 之前将流过滤为更易处理的内容(如果您真的需要这样做)。至于如何解决这个问题的建议... 如果您详细描述一下您要解决的实际问题,会更有帮助。 - hobbs
1
如何解决问题?您的错误消息/异常行为/内容示例/所需输出示例是什么? - Alexey Larionov
你的目标是从原始数据的顶层对象中提取data键吗?那里找到的值是否足够小,可以适应RAM?还是你想做其他事情? - hobbs
“我想在一个50GB的文件上使用jq” - 这不是错误的工具吗?为什么非要用jq?我通常认为,任何以“想使用X来解决问题Y”陈述的问题都是本末倒置。很少有情况下已经明确了要使用哪种工具。 - Christian Fritz
1
我会看一下“大数据”工具。虽然我没有跟上它们的发展,但也许可以看看Hadoop或Apache Spark。考虑到数据是一个数组,你可能也可以直接使用MongoDB。查看mongoimport命令以将文件加载到Mongo中。一旦加载完成,其他所有操作都将变得微不足道。 - Christian Fritz
显示剩余2条评论
3个回答

1

就你的例子而言,下面的代码足以满足要求:

jq -cn --stream 'fromstream( inputs|(.[0] |= .[2:]) | select(. != [[]]) )'

如果你只想要.itemized的数据数组,请将上面的inputs替换为:

inputs|select(first|first=="data")

记录一下,你也可以以完全相同的方式使用 gojq(jq 的 Go 实现)。


0
假设您的大文件包含许多JSON对象,您可以逐个处理它们并提取字段.data[]
这样,内存消耗仅受输入中最大JSON的大小限制,而不是所有JSON输入大小之和的限制。
或者,您的问题是单个JSON对象太大,内存不足?
echo '
{ "key":"A1", "property":"A2", "data":[1,2,3] }{"key":"B1","property":"B2","data":[4,5,6]}
{ 
   "key":"C1", 
   "property":"C2", 
   "data":[7,8,9] 
}' | jq -cr '.data[]'

结果

1
2
3
4
5
6
7
8
9

0
还有什么其他工具可以完成这项工作?
我写的“JSON Machine”命令行包装器jm非常易于使用,通常比jq的流解析器更经济实惠。在当前情况下,要列出.data,您可以编写以下内容:
jm —-pointer '/data'

或者同样地,在相同的代码库中使用基于Python的脚本:

jm.py -i data.item file.json

假设只有一个顶级键,则在这种特殊情况下的另一种选择是:

jstream -d 2 <  file.json

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接