我正在尝试加载一个大的3 GB JSON文件。目前,使用JQ实用程序,我可以在近40分钟内加载整个文件。现在,我想知道如何在JQ中使用并行/多线程方法,以便在更短的时间内完成该过程。我正在使用v1.5
使用的命令:
{
"results": [
{
"_id": "0000001",
"body": {
"party": {
"related-parties": {},
"general-info": {
"last-update-ts": "2011-02-14T08:21:51.000-05:00",
"full-name": "Ibercaja Gestion SGIIC SAPensiones Nuevas Oportunidades",
"status": "ACTIVE",
"last-update-user": "TS42922",
"create-date": "2011-02-14T08:21:51.000-05:00",
"classifications": {
"classification": [
{
"code": "PENS"
}
]
}
},
"xrefs": {
"xref": [
{
"type": "LOCCU1",
"id": "X00893X"
},
{
"type": "ID",
"id": "1012227139"
}
]
}
}
}
},
{
"_id": "000002",
"body": {
"party": {
"related-parties": {},
"general-info": {
"last-update-ts": "2015-05-21T15:10:45.174-04:00",
"full-name": "Innova Capital Sp zoo",
"status": "ACTIVE",
"last-update-user": "jw74592",
"create-date": "1994-08-31T00:00:00.000-04:00",
"classifications": {
"classification": [
{
"code": "CORP"
}
]
}
},
"xrefs": {
"xref": [
{
"type": "ULTDUN",
"id": "144349875"
},
{
"type": "AVID",
"id": "6098743"
},
{
"type": "LOCCU1",
"id": "1001210218"
},
{
"type": "ID",
"id": "1001210218"
},
{
"type": "BLMBRG",
"id": "10009050"
},
{
"type": "REG_CO",
"id": "0000068508"
},
{
"type": "SMCI",
"id": "13159"
}
]
}
}
}
}
]
}
我的数据:
from bs4 import BeautifulSoup
import urllib,sys
reload(sys)
sys.setdefaultencoding("utf-8")
r = urllib.urlopen('https://twitter.com/ndtv').read()
soup = BeautifulSoup(r)
有人可以帮助我在v1.5中使用哪个命令来实现并行/多线程。
答案 0 :(得分:2)
以下是一种流式处理方法,假设您的3GB数据文件位于data.json
,以下过滤器位于filter1.jq
中:
select(length==2)
| . as [$p, $v]
| {r:$p[1]}
| if $p[2:6] == ["body","party","general-info","full-name"] then .name = $v
elif $p[2:6] == ["body","party","xrefs","xref"] and $p[7] == "id" then .id = $v
else empty
end
使用
运行jq时$ jq -M -c --stream -f filter1.jq data.json
jq将生成一个结果流,您需要的细节最少
{"r":0,"name":"Ibercaja Gestion SGIIC SAPensiones Nuevas Oportunidades"}
{"r":0,"id":"X00893X"}
{"r":0,"id":"1012227139"}
{"r":1,"name":"Innova Capital Sp zoo"}
{"r":1,"id":"144349875"}
{"r":1,"id":"6098743"}
{"r":1,"id":"1001210218"}
{"r":1,"id":"1001210218"}
{"r":1,"id":"10009050"}
{"r":1,"id":"0000068508"}
{"r":1,"id":"13159"}
您可以使用第二个filter2.jq
:
foreach .[] as $i (
{c: null, r:null, id:null, name:null}
; .c = $i
| if .r != .c.r then .id=null | .name=null | .r=.c.r else . end # control break
| .id = if .c.id == null then .id else .c.id end
| .name = if .c.name == null then .name else .c.name end
; [.id, .name]
| if contains([null]) then empty else . end
| join("~")
)
在使用
运行时消耗第一个过滤器的输出$ jq -M -c --stream -f filter1.jq data.json | jq -M -s -r -f filter2.jq
并制作
X00893X~Ibercaja Gestion SGIIC SAPensiones Nuevas Oportunidades
1012227139~Ibercaja Gestion SGIIC SAPensiones Nuevas Oportunidades
144349875~Innova Capital Sp zoo
6098743~Innova Capital Sp zoo
1001210218~Innova Capital Sp zoo
1001210218~Innova Capital Sp zoo
10009050~Innova Capital Sp zoo
0000068508~Innova Capital Sp zoo
13159~Innova Capital Sp zoo
只需使用两个 jq 进程即可。如果需要更多并行性,可以使用记录号(r)来对数据进行分区并并行处理分区。例如,如果将中间输出保存到temp.json
文件
$ jq -M -c --stream -f filter1.jq data.json > temp.json
然后您可以与
等过滤器并行处理temp.json
$ jq -M 'select(0==.r%3)' temp.json | jq -M -s -r -f filter2.jq > result0.out &
$ jq -M 'select(1==.r%3)' temp.json | jq -M -s -r -f filter2.jq > result1.out &
$ jq -M 'select(2==.r%3)' temp.json | jq -M -s -r -f filter2.jq > result2.out &
并在必要时将分区连接到最后的单个结果中。此示例使用3个分区,但如果需要更多并行性,则可以轻松地将此方法扩展到任意数量的分区。
GNU parallel也是不错的选择。如JQ Cookbook中所述,jq-hopkok's parallelism folder有一些很好的例子
答案 1 :(得分:0)
对于此大小的文件,您需要将文件流式传输并一次处理一个项目。首先寻找''结果':['然后使用一个名为'readItem'的函数,使用堆栈来匹配大括号,直到你的左大括号关闭,将每个字符附加到缓冲区,然后在关闭大括号后反序列化项目找到。
我推荐使用node.js + lodash作为实现语言。