Alternatives à ogr2ogr pour le chargement de fichiers GeoJson volumineux dans PostGIS

24

J'ai un fichier GeoJson de 7 Go que je voudrais charger dans une base de données PostGIS. J'ai essayé d'utiliser ogr2ogr mais il échoue parce que le fichier est trop gros pour que ogr2ogr se charge en mémoire, puis traite.

Existe-t-il d'autres alternatives pour charger ce fichier geojson dans PostGIS?

L'erreur ogr2ogr que j'obtiens est:

ERREUR 2: CPLMalloc (): Mémoire insuffisante allouant -611145182 octets. Cette application a demandé au Runtime de la terminer de manière inhabituelle. Veuillez contacter l'équipe d'assistance de l'application pour plus d'informations.

RyanDalton
la source
1
Avez-vous essayé l'option "-gt"? Par défaut, il regroupe 200 fonctionnalités par transaction.
Pablo
Je n'étais pas au courant de l'option -gt et je ne l'avais pas essayé auparavant. J'ai juste tenté une nouvelle exécution en utilisant l'option -gt, cependant, et j'ai malheureusement rencontré la même erreur. J'ai également tenté d'utiliser l'option -WHERE pour limiter le nombre d'options consultables, mais cela ne m'a pas aidé non plus.
RyanDalton
GDAL / OGR a amélioré la lecture des gros fichiers GeoJSON dans 2.3.0, ce qui réduit considérablement la surcharge de la mémoire.
AndrewHarvey

Réponses:

10

L'exemple que vous avez envoyé montre qu'il peut être possible de fractionner manuellement le fichier à l'aide d'un éditeur comme notepad ++

1) Pour chaque morceau, créez un en-tête:

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

2) Après l'en-tête, placez de nombreuses fonctionnalités:

{"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/[email protected]", "address": "Le\u00f3n Tolstoi #18 PH Col. Anzures", "owner": "simplegeo", "postcode": "11590"}},

3) Terminez le morceau avec:

]}

EDIT - Voici le code python qui divisera le fichier en morceaux de taille définie (en nombre de fonctionnalités):

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.
Pablo
la source
19

Malheureusement, JSON est, tout comme XML, mal adapté au traitement de flux, donc presque toutes les implémentations nécessitent que l'ensemble de données soit chargé en mémoire. Bien que cela soit acceptable pour les petits ensembles dans votre cas, il n'y a pas d'autre option que de diviser l'ensemble de données en morceaux plus petits et gérables.

En améliorant la solution de Pablo, en voici une qui ne vous oblige pas à ouvrir et à charger le fichier dans un éditeur et à le diviser à la main, mais essaie d'automatiser autant que possible l'ensemble du processus.

Copiez le fichier json sur un hôte Unix (linux, osx) ou installez les outils cygwin sous Windows. Ouvrez ensuite un shell et utilisez vim pour supprimer la première et la dernière ligne du fichier:

$ vim places.json

tapez dd pour supprimer la première ligne, puis MAJ-G pour déplacer la fin du fichier, tapez à nouveau dd pour supprimer la dernière ligne. Tapez maintenant : wq pour enregistrer les modifications. Cela ne devrait prendre que quelques minutes au maximum.

Nous allons maintenant exploiter la puissance d'Unix pour diviser le fichier en morceaux plus faciles à gérer. Dans le type de shell:

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

Allez prendre une bière. Cela divisera le fichier en de nombreux fichiers plus petits, chacun contenant 10000 lignes. Vous pouvez augmenter le nombre de lignes, tant que vous le gardez suffisamment petit pour que ogr2gr puisse le gérer.

Maintenant, nous allons coller tête et queue à chacun des fichiers:

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

Allez prendre un snak. Les deux premières commandes créent simplement un fichier d'en-tête et de pied de page avec le contenu correct (juste pour plus de commodité), tandis que la dernière ajoutera un en-tête et un pied de page à chacun des morceaux que nous séparons ci-dessus et supprimera le morceau sans en-tête / pied de page (pour économiser de l'espace ).

À ce stade, nous espérons pouvoir traiter les nombreux fichiers place-chunks - *. Json avec ogr2ogr:

$ for f in places-chunks-*.json ; do ogr2ogr -your-options-here $f ; done
unicoletti
la source
1
Avec cette méthode, ne serait-il pas nécessaire de s'assurer que les "morceaux" de fichiers étaient divisés à la fin d'un bloc de fonctionnalités? Comme j'ai déjà prétraité les données en Python pour ajouter les informations d'en-tête et de pied de page, je devrais pouvoir ajouter un compteur pour fragmenter les données. Je vais essayer ça ensuite. Merci pour la suggestion.
RyanDalton
Les données d'exemple que vous avez fournies avaient une fonctionnalité par ligne, c'est pourquoi j'ai choisi split -l . Si ce n'est pas le cas avec les données réelles, je crains que cela ne fonctionne pas.
unicoletti
Oui, bien sûr, vous avez raison, chaque fonctionnalité se trouvant sur une ligne distincte. Je ne pensais pas à ça tout au long.
RyanDalton
Pour supprimer les lignes sans ouvrir le fichier. Supprimer la première ligne: sed -i "1d" places.json Supprimer les 4 premières lignes: sed -i "1,4d" places.json Supprimer les 4 dernières lignes: head -n -4 places.json > places2.json
egofer
2

Il est possible de charger vos données avec FME Desktop. C'est très facile.


la source
Traitera-t-il un fichier extrêmement volumineux comme celui-ci?
RyanDalton
Par exemple, divisez le fichier en plusieurs fichiers avant la transformation. hjsplit.org Et importez les fichiers de nouvelles dans FME Desktop pour les importer dans PostGIS.
1
probablement, et si c'est le cas, vous pouvez crier pour soutenir :)
simplexio
2

Il devrait être simple d'écrire un lecteur et un écrivain paresseux en Python qui convertirait votre fichier geojson au format de fichier de formes beaucoup plus petit ou directement en SQL sans tout faire en mémoire. Une fois convertis, les outils natifs de PostGIS peuvent importer de grands ensembles de données. La prise en charge de geojson dans OGR est relativement nouvelle et il n'y a aucun indicateur pour gérer les fichiers volumineux.

Si vous pouvez en quelque sorte partager une partie gérable de votre fichier, je pourrais vous aider.

GeospatialPython.com
la source