【问题标题】:jq: filter result by value (contains) is very slowjq:按值(包含)过滤结果非常慢
【发布时间】:2021-06-24 20:10:21
【问题描述】:

我正在尝试使用 jq 过滤大量 JSON 文件并提取属于特定域的每个对象的 id,以及该域中的完整 URL。以下是数据示例:

{
    "items": [
        {
            "completeness": 5,
            "dcLanguageLangAware": {
                "def": [
                    "de"
                ]
            },
            "edmIsShownBy": [
                "https://gallica.example/image/2IC6BQAEGWUEG4OP7AYBDGIGYAX62KZ6H366KXP2IKVAF4LKY37Q/presentation_images/5591be60-01fc-11e6-8e10-fa163e091926/node-3/image/SBB/Berliner_Börsenzeitung/1920/02/27/F_065_098_0/F_SBB_00007_19200227_065_098_0_001/full/full/0/default.jpg"
            ],
            "id": "/9200355/BibliographicResource_3000117730632",
            "type": "TEXT",
            "ugc": [
                false
            ]
        }
    ]
}

这里有更大的示例:https://www.dropbox.com/s/0s0zjtxe01mecjc/AoQhRn%2B56KDm5AJJPwEvOTIwMDUyMC9hcmtfXzEyMTQ4X2JwdDZrMTAyNzY2Nw%3D%3D.json?dl=0

我可以使用以下命令提取包含字符串“gallica”的 id 和 URL:

jq '[ .items[] | select(.edmIsShownBy[] | contains ("gallica")) |  {id: .id, link: .edmIsShownBy[] }]'

但是,我有超过 28000 个 JSON 文件要处理,并且需要大量时间(大约每分钟 1 个文件)。我正在使用带有命令的 bash 处理文件:

find . -name "*.json" -exec cat '{}' ';' | jq '[ .items[] | select(.edmIsShownBy[] | contains ("gallica")) |  {id: .id, link: .edmIsShownBy[] }]' 

我想知道速度慢是否是由于给 jq 的指令造成的,如果是这种情况,是否有更快的方法来过滤包含在所选值中的字符串?有什么想法吗?

【问题讨论】:

  • find . -name '*.json' -exec cat {} + | jq '[.items[] | select(.edmIsShownBy[0] | index("gallica")) | {id, link: .edmIsShownBy[0]}]' 会快一点
  • 查询中出现两次edmIsShownBy[] 的事实表明您的查询可能与您的意图或期望不符。请详细说明要求。
  • pastebin样本只有60KB,看起来比较小,jq处理速度很快(我的电脑0.035秒)1分钟的文件有多大?
  • pastebin 有一些长度限制。我现在编辑并添加了指向 Dropbox 中一个文件的链接。文件不大(大约 450kb),但确实很慢,这就是为什么我认为我做错了什么
  • 记录下来,Dropbox 样本约为 463KB,查询一次大约需要 0.05 秒(u+s,包括启动时间)。

标签: json substring jq


【解决方案1】:

最好不要一次尝试cat 所有文件;实际上,最好完全避免使用cat

例如,假设 program.jq 包含您决定选择的任何 jq 程序(并且在此处使用 contains 没有任何问题),您可以尝试:

find . -name "*.json" -exec jq -f program.jq '{}' +

使用非标准的 + 代替 ';'最小化必须调用 jq 的次数,尽管调用 jq 的开销实际上非常小。如果您的 find 不支持 + 并且您希望避免对每个文件调用一次 jq,那么请考虑使用 或带有 —-xargs 选项的 GNU parallel

如果您知道感兴趣的 JSON 文件在密码中,您还可以通过指定 -maxdepth 1 来加速 find

【讨论】:

  • 这解决了这个问题。不是 jq 而是 cat 让一切都变慢了。如果没有 cat(并且使用 maxdepth 1),处理 >28000 个 json 文件需要 10 分钟。非常感谢!我认为这是由于我对 jq 缺乏经验,但最终我只是找错了地方
猜你喜欢
  • 1970-01-01
  • 2014-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-02
  • 1970-01-01
相关资源
最近更新 更多