Alternativen zu ogr2ogr zum Laden großer GeoJson-Dateien in PostGIS

24

Ich habe eine 7 GB GeoJson-Datei, die ich in eine PostGIS-Datenbank laden möchte. Ich habe versucht, ogr2ogr zu verwenden, aber es schlägt fehl, weil die Datei zu groß ist, damit ogr2ogr in den Speicher geladen und dann verarbeitet werden kann.

Gibt es andere Alternativen zum Laden dieser Geojson-Datei in PostGIS?

Der Ogr2ogr-Fehler, den ich erhalte, ist:

FEHLER 2: CPLMalloc (): Nicht genügend Speicher für die Zuweisung von -611145182 Byte. Diese Anwendung hat die Runtime aufgefordert, sie auf ungewöhnliche Weise zu beenden. Bitte wenden Sie sich an das Support-Team der Anwendung, um weitere Informationen zu erhalten.

RyanDalton
quelle
1
Haben Sie die Option "-gt" ausprobiert? Standardmäßig werden 200 Features pro Transaktion gruppiert.
Pablo
Die Option -gt war mir nicht bekannt und ich hatte sie zuvor noch nicht ausprobiert. Ich habe gerade versucht, es mit der Option -gt erneut auszuführen, und leider ist derselbe Fehler aufgetreten. Ich habe auch versucht, die Option -WHERE zu verwenden, um die Anzahl der durchsuchbaren Optionen zu begrenzen, aber das schien auch nicht zu helfen.
RyanDalton
GDAL / OGR hat das Lesen großer GeoJSON-Dateien in 2.3.0 verbessert, wodurch sich der Speicheraufwand erheblich verringert.
AndrewHarvey

Antworten:

10

Das von Ihnen gesendete Beispiel zeigt, dass es möglicherweise möglich ist, die Datei mit einem Editor wie notepad ++ manuell zu teilen

1) Erstellen Sie für jeden Block einen Header:

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

2) Nach dem Header werden viele Features eingefügt:

{"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) Beenden Sie den Block mit:

]}

BEARBEITEN - Hier ist Python-Code, der die Datei in Stücke definierter Größe (in Anzahl der Features) aufteilt:

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
quelle
19

Leider ist JSON, ähnlich wie XML, für die Stream-Verarbeitung schlecht geeignet, sodass bei fast allen Implementierungen das gesamte Dataset in den Arbeitsspeicher geladen werden muss. Dies ist zwar für kleine Mengen in Ihrem Fall in Ordnung, es gibt jedoch keine andere Möglichkeit, als den Datensatz in kleinere, handhabbare Teile aufzuteilen.

In der folgenden Lösung von Pablo müssen Sie die Datei nicht unbedingt öffnen und in einen Editor laden und von Hand teilen, sondern versuchen, den gesamten Prozess so weit wie möglich zu automatisieren.

Kopieren Sie die JSON-Datei auf einen Unix-Host (Linux, OSX) oder installieren Sie die Cygwin-Tools unter Windows. Öffnen Sie dann eine Shell und entfernen Sie mit vim die erste und letzte Zeile aus der Datei:

$ vim places.json

Geben Sie dd ein , um die erste Zeile zu entfernen, und drücken Sie UMSCHALT-G , um das Ende der Datei zu verschieben. Geben Sie dd erneut ein, um die letzte Zeile zu entfernen. Geben Sie nun Folgendes ein: wq , um die Änderungen zu speichern. Dies sollte höchstens ein paar Minuten dauern.

Jetzt werden wir die Leistungsfähigkeit von Unix nutzen, um die Datei in handlichere Teile aufzuteilen. In der Shell-Typ:

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

Geh ein Bier holen. Dadurch wird die Datei in viele kleinere Dateien mit jeweils 10000 Zeilen aufgeteilt. Sie können die Anzahl der Zeilen erhöhen, solange Sie sie klein genug halten, damit ogr2gr sie verwalten kann.

Jetzt werden wir Kopf und Schwanz an jede der Dateien kleben:

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

Geh und schnapp dir eine Schlange. Die ersten beiden Befehle erstellen einfach eine Kopf- und Fußzeilendatei mit dem richtigen Inhalt (nur aus praktischen Gründen), während der letzte Befehl jedem der oben aufgeteilten Blöcke Kopf- und Fußzeilen hinzufügt und den Block ohne Kopf- und Fußzeilen entfernt (um Platz zu sparen) ).

Zu diesem Zeitpunkt können Sie hoffentlich die vielen Places-Chunks - * .json-Dateien mit ogr2ogr verarbeiten:

$ for f in places-chunks-*.json ; do ogr2ogr -your-options-here $f ; done
unicoletti
quelle
1
Müssten wir bei dieser Methode nicht sicherstellen, dass die Datei "Chunks" am Ende eines Feature-Blocks aufgeteilt wurden? Da ich die Daten in Python bereits vorverarbeitet habe, um die Kopf- und Fußzeileninformationen hinzuzufügen, sollte es mir möglich sein, einen Zähler hinzuzufügen, um die Daten zu teilen. Ich werde das als nächstes versuchen. Danke für den Vorschlag.
RyanDalton
Die Beispieldaten, die Sie angegeben haben, hatten ein Feature pro Zeile. Deshalb habe ich split -l gewählt . Wenn dies bei tatsächlichen Daten nicht der Fall ist, wird es leider nicht funktionieren.
unicoletti
Ja, natürlich haben Sie Recht, wenn sich jedes Merkmal in einer separaten Zeile befindet. Ich habe das nicht durchgedacht.
RyanDalton
Um die Zeilen zu entfernen, ohne die Datei zu öffnen. Entfernen Sie die erste Zeile: sed -i "1d" places.json Entfernen Sie die ersten 4 Zeilen: sed -i "1,4d" places.json Entfernen Sie die letzten 4 Zeilen: head -n -4 places.json > places2.json
egofer
2

Es ist möglich, Ihre Daten mit FME Desktop zu laden. Es ist sehr leicht.


quelle
Wird eine extrem große Datei wie diese verarbeitet?
RyanDalton
Teilen Sie die Datei beispielsweise vor der Umwandlung in mehrere Dateien auf. hjsplit.org Und importieren Sie die Nachrichtendateien in FME Desktop für den Import nach PostGIS.
1
wahrscheinlich, und wenn es dosent können Sie schreien zu unterstützen :)
simplexio
2

Es sollte einfach sein, in Python einen faulen Leser und Schreiber zu schreiben, der Ihre Geojson-Datei in das viel kleinere Shapefile-Format oder direkt in SQL konvertiert, ohne alles im Speicher zu tun. Nach der Konvertierung können die nativen PostGIS-Tools große Datenmengen importieren. Die Geojson-Unterstützung in OGR ist relativ neu und es gibt keine Flags für den Umgang mit großen Dateien.

Wenn Sie irgendwie einen überschaubaren Teil Ihrer Datei teilen können, könnte ich Ihnen helfen.

GeospatialPython.com
quelle