给出GEOJson文件如下: -
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"FEATCODE": 15014
},
"geometry": {
"type": "Polygon",
"coordinates": [
.....
我想最终得到以下结论: -
{
"type": "FeatureCollection",
"features": [
{
"tippecanoe : {"minzoom" : 13},
"type": "Feature",
"properties": {
"FEATCODE": 15014
},
"geometry": {
"type": "Polygon",
"coordinates": [
.....
即。我已将tippecanoe对象添加到数组功能
中的每个功能我可以使用以下方法: -
jq '.features[].tippecanoe.minzoom = 13' <GEOJSON FILE> > <OUTPUT FILE>
哪个适用于小文件。但处理一个414Mb的大文件似乎永远需要处理器最大化并且没有任何内容被写入OUTPUT FILE
进一步阅读jq似乎 - stream 命令行参数可能会有所帮助,但我对如何将其用于我的目的感到困惑。
我将非常感谢能够满足我的目的的示例命令行以及有关--stream正在做什么的解释。
答案 0 :(得分:2)
一次性jq-only方法可能需要比可用RAM更多的RAM。如果是这种情况,那么下面将显示一个简单的all-jq方法,以及基于使用jq和awk的更经济的方法。
除了将对象流重构为单个JSON文档之外,这两种方法是相同的。使用awk可以非常经济地完成这一步骤。
在这两种情况下,假定具有所需形式对象的大型JSON输入文件名为input.json。
jq -c '.features[]' input.json |
jq -c '.tippecanoe.minzoom = 13' |
jq -c -s '{type: "FeatureCollection", features: .}'
jq -c '.features[]' input.json |
jq -c '.tippecanoe.minzoom = 13' | awk '
BEGIN {print "{\"type\": \"FeatureCollection\", \"features\": ["; }
NR==1 { print; next }
{print ","; print}
END {print "] }";}'
为了进行比较,使用了.features []中包含10,000,000个对象的输入文件。它的大小约为1GB。
U + S:
jq-only: 15m 15s
jq-awk: 7m 40s
jq one-pass using map: 6m 53s
答案 1 :(得分:0)
另一种解决方案可能是:
jq '.features |= map_values(.tippecanoe.minzoom = 13)'
为了测试这个,我创建了一个样本JSON为
d = {'features': [{"type":"Feature", "properties":{"FEATCODE": 15014}} for i in range(0,N)]}
并将执行时间视为N
的函数。有趣的是,虽然map_values
方法似乎在N
中具有线性复杂性,但.features[].tippecanoe.minzoom = 13
表现出二次行为(已经为N = 50000,前一种方法在大约0.8秒内完成,而后者需要大约47秒)
或者,人们可以手动使用例如Python:
import json
import sys
data = {}
with open(sys.argv[1], 'r') as F:
data = json.load(F)
extra_item = {"minzoom" : 13}
for feature in data['features']:
feature["tippecanoe"] = extra_item
with open(sys.argv[2], 'w') as F:
F.write(json.dumps(data))
答案 2 :(得分:0)
在这种情况下,map
而不是map_values
要快得多(*):
.features |= map(.tippecanoe.minzoom = 13)
但是,使用这种方法仍然需要足够的RAM。
P.S。如果要使用jq生成大文件以进行计时,请考虑:
def N: 1000000;
def data:
{"features": [range(0;N) | {"type":"Feature", "properties": {"FEATCODE": 15014}}] };
(*)使用map
,20s表示100MB,近似线性。
答案 3 :(得分:0)
这里,基于GitHub上@nicowilliams的工作,是一个使用jq可用的流解析器的解决方案。该解决方案在内存方面非常经济,但如果输入很大,目前速度很慢。
该解决方案包含两部分:一个用于将更新注入到使用--stream命令行选项生成的流中的函数;以及以原始形式将流转换回JSON的功能。
jq -cnr --stream -f program.jq input.json
# inject the given object into the stream produced from "inputs" with the --stream option
def inject(object):
[object|tostream] as $object
| 2
| truncate_stream(inputs)
| if (.[0]|length == 1) and length == 1
then $object[]
else .
end ;
# Input: the object to be added
# Output: text
def output:
. as $object
| ( "[",
foreach fromstream( inject($object) ) as $o
(0;
if .==0 then 1 else 2 end;
if .==1 then $o else ",", $o end),
"]" ) ;
{}
| .tippecanoe.minzoom = 13
| output
def data(N):
{"features":
[range(0;2) | {"type":"Feature", "properties": {"FEATCODE": 15014}}] };
N = 2:
[
{"type":"Feature","properties":{"FEATCODE":15014},"tippecanoe":{"minzoom":13}}
,
{"type":"Feature","properties":{"FEATCODE":15014},"tippecanoe":{"minzoom":13}}
]