jq map_values 在非常大的文件上
Posted
技术标签:
【中文标题】jq map_values 在非常大的文件上【英文标题】:jq map_values on very large file 【发布时间】:2019-05-03 15:58:52 【问题描述】:我正在使用 jq 在一个非常大的 JSON 文件 (500MB+) 中查找模式,该文件具有以下平面对象结构:
"prop1": "large string",
"prop2": "another large string",
"prop3": "yet another large string",
...
以下查询运行良好,返回结果不到 15 秒:
jq 'map(select(contains("PATTERN")==true))' largefile.json > res.json
但这会返回一个包含模式的字符串数组,所以我丢失了属性名称。 当我尝试使用 map_values 时,我也可以获取属性名称,如:
jq 'map_values(select(contains("PATTERN")==true))' largefile.json > res.json
查询需要很长时间。
是否有类似 map 的等价查询,它还可以为我提供键:值对?
【问题讨论】:
你能和pastebin分享那个json的一部分(如果不是私有的话)吗? 对不起,文件是私有的,但是,是的,非常容易重新创建,只需将随机字符串值按顺序添加到道具中。 顺便说一下,map_values(select(...))
的行为因 jq 的一个版本而异。
【参考方案1】:
由于您的 JSON 文件对于 jq
读取来说不是太大,因此一个简单有效的解决方案(以使用 jq 将文件读入内存为模)是使用 keys_unsorted/0
和 test/1
:
keys_unsorted[] as $k
| select(.[$k] | test("another"))
| [$k, .[$k]]
(使用map_values
会不必要地低效,除非您完全了解其复杂性,否则使用contains
可能不是一个好主意。)
如果您要求输出是单个对象,您可以调整上述内容,或者(以输出对象所需的内存为代价):
. as $in
| reduce keys_unsorted[] as $k (;
if ($in[$k] | test("another"))
then .[$k] = $in[$k]
else . end)
非常大的文件
对于太大而无法正常读入 jq 的文件,您可以使用 jq 的流式解析器,即使用 --stream
命令行选项。不幸的是,这说起来容易做起来难,但一个简单的方法是使用 atomize
定义例如在jq --stream filter on multiple values of same key
【讨论】:
您在此处提供的 keys_unsorted 示例因此不会产生正确的 JSON 对象。文件的顶部和底部缺少大括号。 您的问题要求key:value
对。也许你应该澄清你的要求,例如按照minimal reproducible example。同时,也许您可以弄清楚如何调整 jq 程序以实现您想要的,例如从($k): .[$k]
开始【参考方案2】:
只需使用with_entries/1
,它就可以根据键和/或值有效地过滤掉对象的属性。
with_entries(select(.value | contains("PATTERN")))
【讨论】:
这绝对可以按我的意愿工作,快速并将对象键留在我想要的位置。谢谢你,@杰夫以上是关于jq map_values 在非常大的文件上的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在 nginx 上使用 django 上传一个非常大的文件?