Alternatywy dla ogr2ogr dla ładowania dużych plików GeoJson do PostGIS

24

Mam plik GeoJson o pojemności 7 GB, który chciałbym załadować do bazy danych PostGIS. Próbowałem użyć ogr2ogr, ale to się nie udaje, ponieważ plik jest zbyt duży, aby ogr2ogr mógł załadować do pamięci, a następnie przetworzyć.

Czy istnieją inne alternatywy dla ładowania tego pliku geojson do PostGIS?

Występuje błąd ogr2ogr:

BŁĄD 2: CPLMalloc (): Za mało pamięci przydziela -611145182 bajtów. Ta aplikacja poprosiła środowisko wykonawcze o zakończenie go w nietypowy sposób. Skontaktuj się z zespołem pomocy technicznej aplikacji, aby uzyskać więcej informacji.

RyanDalton
źródło
1
Czy próbowałeś opcji „-gt”? Domyślnie grupuje 200 funkcji na transakcję.
Pablo
Nie wiedziałem o opcji -gt i nie próbowałem jej wcześniej. Właśnie próbowałem uruchomić ponownie przy użyciu opcji -gt i niestety napotkałem ten sam błąd. Próbowałem także użyć opcji -WHERE, aby ograniczyć liczbę opcji do przeszukiwania, ale to również nie pomogło.
RyanDalton
GDAL / OGR poprawił odczyt dużych plików GeoJSON w 2.3.0, co znacznie zmniejsza obciążenie pamięci.
AndrewHarvey

Odpowiedzi:

10

Wysłany przykład pokazuje, że możliwe jest ręczne podzielenie pliku za pomocą edytora, takiego jak notepad ++

1) Dla każdego fragmentu utwórz nagłówek:

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

2) Po nagłówku umieść wiele funkcji:

{"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) Zakończ część z:

]}

EDYCJA - Oto kod Pythona, który podzieli plik na części o zdefiniowanym rozmiarze (pod względem liczby funkcji):

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
źródło
19

Niestety JSON, podobnie jak XML, źle nadaje się do przetwarzania strumieniowego, więc prawie wszystkie implementacje wymagają załadowania całego zestawu danych do pamięci. Chociaż w twoim przypadku jest to w porządku dla małych zestawów, nie ma innej opcji niż rozbicie zestawu danych na mniejsze, łatwe do zarządzania fragmenty.

Ulepszając rozwiązanie Pablo, oto takie, które nie wymaga faktycznego otwierania i wczytywania pliku do edytora i dzielenia go ręcznie, ale próbuje zautomatyzować w jak największym stopniu cały proces.

Skopiuj plik json na hosta uniksowego (linux, osx) lub zainstaluj narzędzia cygwin w systemie Windows. Następnie otwórz powłokę i użyj vima, aby usunąć pierwszy i ostatni wiersz z pliku:

$ vim places.json

wpisz dd, aby usunąć pierwszy wiersz, a następnie SHIFT-G, aby przenieść koniec pliku, wpisz dd ponownie, aby usunąć ostatni wiersz. Teraz wpisz : wq, aby zapisać zmiany. Powinno to zająć najwyżej kilka minut.

Teraz wykorzystamy czystą moc unixa, aby podzielić plik na łatwiejsze do zarządzania części. W typie powłoki:

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

Idź napij się piwa. Spowoduje to podzielenie pliku na wiele mniejszych plików, każdy zawierający 10000 linii. Możesz zwiększyć liczbę linii, o ile utrzymujesz ją na tyle małą, aby ogr2gr mógł nią zarządzać.

Teraz przykleimy głowę i ogon do każdego z plików:

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

Idź złap węża. Pierwsze dwa polecenia po prostu tworzą plik nagłówka i stopki z poprawną zawartością (tak naprawdę dla wygody), a ostatnie dodają nagłówek i stopkę do każdej z części, które podzieliliśmy powyżej i usuwają fragment bez nagłówka / stopki (aby zaoszczędzić miejsce ).

W tym momencie możesz, mam nadzieję, przetworzyć wiele miejsc-fragmentów - plików * .json za pomocą ogr2ogr:

$ for f in places-chunks-*.json ; do ogr2ogr -your-options-here $f ; done
unicoletti
źródło
1
Czy za pomocą tej metody nie musielibyśmy się upewnić, że „fragmenty” plików zostały podzielone na końcu bloku funkcji? Ponieważ już wstępnie przetworzyłem dane w Pythonie, aby dodać informacje o nagłówku i stopce, powinienem móc dodać licznik, aby porcji danych. Potem spróbuję. Dzieki za sugestie.
RyanDalton
Przykładowe dane, które podałeś, miały jedną cechę w wierszu, dlatego wybrałem split -l . Jeśli tak nie jest w przypadku rzeczywistych danych, obawiam się, że to nie zadziała.
unicoletti
Tak, oczywiście masz rację, gdzie każda funkcja jest w osobnej linii. Nie myślałem o tym przez całą drogę.
RyanDalton
Aby usunąć linie bez otwierania pliku. Usuń pierwszą linię: sed -i "1d" places.json Usuń pierwsze 4 linie: sed -i "1,4d" places.json Usuń ostatnie 4 linie: head -n -4 places.json > places2.json
egofer
2

Możliwe jest ładowanie danych za pomocą FME Desktop. To jest bardzo łatwe.


źródło
Czy przetworzy taki bardzo duży plik?
RyanDalton
Na przykład podziel plik na wiele plików przed transformacją. hjsplit.org I zaimportuj pliki wiadomości do FME Desktop w celu zaimportowania do PostGIS.
1
prawdopodobnie, a jeśli tak nie jest, możesz krzyknąć na wsparcie :)
simplexio
2

Powinno być proste napisanie leniwego czytnika i pisarza w Pythonie, który przekonwertowałby twój plik geojson na znacznie mniejszy format pliku shapefile lub bezpośrednio na SQL bez robienia wszystkiego w pamięci. Po konwersji natywne narzędzia PostGIS mogą importować duże zestawy danych. Obsługa geojson w OGR jest stosunkowo nowa i nie ma żadnych flag do obsługi dużych plików.

Jeśli możesz w jakiś sposób udostępnić zarządzalny fragment pliku, mógłbym ci pomóc.

GeospatialPython.com
źródło