Alternative a ogr2ogr per il caricamento di file GeoJson di grandi dimensioni su PostGIS


24

Ho un file GeoJson da 7 GB che vorrei caricare in un database PostGIS. Ho provato a usare ogr2ogr ma non riesce perché il file è troppo grande per essere caricato in memoria e poi processato da ogr2ogr.

Esistono altre alternative per caricare questo file geojson in PostGIS?

L'errore ogr2ogr che ottengo è:

ERRORE 2: CPLMalloc (): memoria esaurita allocando -611145182 byte. Questa applicazione ha richiesto a Runtime di terminarlo in modo insolito. Per ulteriori informazioni, contattare il team di supporto dell'applicazione.


1
Hai provato l'opzione "-gt"? Per impostazione predefinita, raggruppa 200 funzionalità per transazione.
Pablo,

Non ero a conoscenza dell'opzione -gt e non l'avevo mai provato prima. Ho appena tentato di ripetere la corsa usando l'opzione -gt, e purtroppo ho riscontrato lo stesso errore. Ho anche tentato di utilizzare l'opzione -WHERE per limitare il numero di opzioni ricercabili, ma non mi è sembrato utile neanche questo.
Ryan Dalton,

GDAL / OGR ha migliorato la lettura di file GeoJSON di grandi dimensioni in 2.3.0, riducendo notevolmente il sovraccarico di memoria.
AndrewHarvey,

Risposte:


10

L'esempio che hai inviato mostra che potrebbe essere possibile dividere manualmente il file usando un editor come notepad ++

1) Per ogni pezzo creare un'intestazione:

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

2) Dopo l'intestazione posizionare molte funzionalità:

{"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 il pezzo con:

]}

MODIFICA - Ecco il codice Python che divide il file in pezzi di dimensioni definite (in numero di funzioni):

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.

19

Sfortunatamente, JSON è molto simile a XML, non è adatto per l'elaborazione di flussi, quindi quasi tutte le implementazioni richiedono che l'intero set di dati venga caricato in memoria. Mentre questo è ok per piccoli insiemi nel tuo caso, non c'è altra opzione che suddividere il set di dati in blocchi più piccoli e gestibili.

Migliorando la soluzione di Pablo, eccone uno che non richiede di aprire e caricare il file in un editor e dividerlo manualmente, ma cerca di automatizzare il più possibile l'intero processo.

Copia il file json su un host Unix (linux, osx) o installa gli strumenti cygwin su Windows. Quindi apri una shell e usa vim per rimuovere la prima e l'ultima riga dal file:

$ vim places.json

digitare dd per rimuovere la prima riga, quindi MAIUSC-G per spostare la fine del file, digitare nuovamente dd per rimuovere l'ultima riga. Ora digita : wq per salvare le modifiche. Questo dovrebbe richiedere solo un paio di minuti al massimo.

Ora sfrutteremo la pura potenza di unix per dividere il file in blocchi più gestibili. Nel tipo di shell:

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

Vai a prendere una birra. Questo dividerà il file in molti file più piccoli, ognuno contenente 10000 righe. È possibile aumentare il numero di righe, purché lo si mantenga abbastanza piccolo da consentire a ogr2gr di gestirlo.

Ora atteniamo testa e coda a ciascuno dei file:

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

Vai a prendere uno snak. I primi due comandi creano semplicemente un file di intestazione e piè di pagina con il contenuto corretto (solo per praticità in realtà), mentre l'ultimo aggiungerà intestazione e piè di pagina a ciascuno dei blocchi che abbiamo diviso sopra e rimuoverà il pezzo di intestazione / footerless (per risparmiare spazio ).

A questo punto si spera di poter elaborare i molti file di luoghi-blocchi - *. Json con ogr2ogr:

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

1
Con questo metodo, non dovremmo assicurarci che i "blocchi" di file siano stati divisi alla fine di un blocco funzionale? Dato che ho già pre-elaborato i dati in Python per aggiungere le informazioni di intestazione e piè di pagina, dovrei essere in grado di aggiungere un contatore per bloccare i dati. Lo proverò dopo. Grazie per il suggerimento
Ryan Dalton,

I dati di esempio che hai fornito avevano una funzione per riga, ecco perché sono andato con split -l . Se questo non è il caso dei dati effettivi, temo che non funzionerà.
unicoletti,

Sì, certo che hai ragione, dove ogni funzione si trova su una linea separata. Non lo pensavo fino in fondo.
Ryan Dalton,

Per rimuovere le righe senza aprire il file. Rimuovere la prima riga: sed -i "1d" places.json rimuovere le prime 4 righe: sed -i "1,4d" places.json rimuovere le ultime 4 righe: head -n -4 places.json > places2.json
egofer

2

È possibile caricare i tuoi dati con FME Desktop. È molto facile.


Elaborerà un file estremamente grande come questo?
Ryan Dalton,

Ad esempio, suddividere il file in molti file prima della trasformazione. hjsplit.org E importare i file delle notizie in FME Desktop per l'importazione in PostGIS.

1
probabilmente, e se dosante puoi urlare per supportare :)
simplexio

2

Dovrebbe essere semplice scrivere un lettore e uno scrittore pigro in Python che converti il ​​tuo file geojson in un formato molto più piccolo o direttamente in SQL senza fare tutto in memoria. Una volta convertiti, gli strumenti PostGIS nativi possono importare set di dati di grandi dimensioni. Il supporto geojson in OGR è relativamente nuovo e non ci sono flag per la gestione di file di grandi dimensioni.

Se riesci in qualche modo a condividere una parte gestibile del tuo file, potrei aiutarti.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.