【问题标题】:jq map_values on very large filejq map_values 在非常大的文件上
【发布时间】: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 的一个版本而异。

标签: json select jq keyvaluepair


【解决方案1】:

由于您的 JSON 文件对于 jq 读取来说不是太大,因此一个简单有效的解决方案(以使用 jq 将文件读入内存为模)是使用 keys_unsorted/0test/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")))

【讨论】:

  • 这绝对可以按我的意愿工作,快速并将对象键留在我想要的位置。谢谢你,@杰夫
猜你喜欢
  • 2012-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 2013-05-07
  • 1970-01-01
  • 1970-01-01
  • 2010-12-14
相关资源
最近更新 更多