24 votos

Alternativas a ogr2ogr para cargar grandes archivos GeoJson en PostGIS

Tengo un archivo GeoJson de 7 GB que me gustaría cargar en una base de datos PostGIS. He intentado usar ogr2ogr pero falla porque el archivo es demasiado grande para que ogr2ogr lo cargue en memoria y luego lo procese.

¿Existen otras alternativas para cargar este fichero geojson en PostGIS?

El error ogr2ogr que obtengo es:

ERROR 2: CPLMalloc(): Sin memoria asignando -611145182 bytes. Esta aplicación aplicación ha pedido al Runtime que la termine de un modo inusual. inusual. Por favor, contacte con el equipo de soporte de la aplicación para más información.

19voto

Celso Puntos 66

Desgraciadamente, JSON es, al igual que XML, muy poco adecuado para el procesamiento en flujo, por lo que casi todas las implementaciones requieren que todo el conjunto de datos se cargue en memoria. Aunque esto está bien para conjuntos pequeños, en tu caso no hay otra opción que dividir el conjunto de datos en trozos más pequeños y manejables.

Mejorando la solución de Pablo, he aquí una que no requiere abrir y cargar el archivo en un editor y dividirlo a mano, sino que intenta automatizar todo el proceso en la medida de lo posible.

Copie el archivo json en un host Unix (linux, osx) o instale las herramientas cygwin en Windows. A continuación, abra un intérprete de comandos y utilice vim para eliminar la primera y la última fila del archivo:

$ vim places.json

tipo dd para eliminar la primera línea y, a continuación SHIFT-G para desplazar el final del archivo, escriba dd de nuevo para eliminar la última línea. Ahora escriba :wq para guardar los cambios. Esto debería llevar sólo un par de minutos como máximo.

Ahora aprovecharemos toda la potencia de unix para dividir el archivo en trozos más manejables. En el shell escribe:

$ split -l 10000 places.json places-chunks-

Ve a tomar una cerveza. Esto dividirá el archivo en muchos archivos más pequeños, cada uno con 10000 líneas. Puede aumentar el número de líneas, siempre que lo mantenga lo suficientemente pequeño como para que ogr2gr puede gestionarlo.

Ahora vamos a pegar la cabeza y la cola a cada uno de los archivos:

$ echo '{"type":"FeatureCollection","features":[' > head
$ echo ']}' > tail
$ for f in places-chunks-* ; do cat head $f tail > $f.json && rm -f $f ; done

Ve a coger un snak. Los dos primeros comandos simplemente crean un archivo de encabezado y pie de página con el contenido correcto (sólo por conveniencia en realidad), mientras que el último añadirá encabezado y pie de página a cada uno de los trozos que dividimos anteriormente y eliminará el trozo sin encabezado/pie de página (para ahorrar espacio).

En este punto, es de esperar que pueda procesar los muchos lugares-chunks-*.json archivos con ogr2ogr:

$ for f in places-chunks-*.json ; do ogr2ogr -your-options-here $f ; done

10voto

Pablo Puntos 6414

La muestra que has enviado muestra que puede ser posible dividir manualmente el archivo usando un editor como notepad++

1)Crea una cabecera para cada trozo:

{"type":"FeatureCollection","features":[

2)Después de la cabecera colocar muchas características:

{"geometry": {"type": "Point", "coordinates": [-103.422819, 20.686477]}, "type": "Feature", "id": "SG_3TspYXmaZcMIB8GxzXcayF_20.686477_-103.422819@1308163237", "properties": {"website": "http://www.buongiorno.com", "city": "M\u00e9xico D.F. ", "name": "Buongiorno", "tags": ["mobile", "vas", "community", "social-networking", "connected-devices", "android", "tablets", "smartphones"], "country": "MX", "classifiers": [{"category": "Professional", "type": "Services", "subcategory": "Computer Services"}], "href": "http://api.simplegeo.com/1.0/features/SG_3TspYXmaZcMIB8GxzXcayF_20.686477_-103.422819@1308163237.json", "address": "Le\u00f3n Tolstoi #18 PH Col. Anzures", "owner": "simplegeo", "postcode": "11590"}},

3) Termina el trozo con:

]}

EDITAR - Aquí está el código python que dividirá el archivo en trozos de tamaño definido (en número de características):

import sys

class JsonFile(object):
    def __init__(self,file):
        self.file = open(file, 'r') 
    def split(self,csize):
        header=self.file.readline()
        number=0
        while True:
            output=open("chunk %s.geojson" %(number),'w')
            output.write(header)
            number+=1
            feature=self.file.readline()
            if feature==']}':
                break
            else:
                for i in range(csize):
                    output.write(feature)
                    feature=self.file.readline()
                    if feature==']}':
                        output.write("]}")
                        output.close()
                        sys.exit("Done!")
                output.write("]}")
                output.close()

if __name__=="__main__":
    myfile = JsonFile('places_mx.geojson')
    myfile.split(2000) #size of the chunks.

2voto

harpo Puntos 17399

Debería ser sencillo escribir un lector y escritor perezoso en Python que convirtiera tu archivo geojson al formato shapefile, mucho más pequeño, o directamente a SQL sin hacerlo todo en memoria. Una vez convertidos, las herramientas nativas de PostGIS pueden importar grandes conjuntos de datos. El soporte geojson en OGR es relativamente nuevo y no hay ninguna bandera para el manejo de archivos de gran tamaño.

Si de alguna manera puedes compartir una parte manejable de tu archivo podría ayudarte.

2voto

AlexMcCollister Puntos 31

Esto ha mejorado en GDAL 2.3.0 https://trac.osgeo.org/gdal/wiki/Release/2.3.0-News ahora es mucho más eficiente en memoria en la lectura de grandes archivos GeoJSON.

1voto

Es posible cargar sus datos con FME Desktop. Es muy fácil.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X