Alternativas ao ogr2ogr para carregar arquivos GeoJson grandes no PostGIS

24

Eu tenho um arquivo GeoJson de 7 GB que gostaria de carregar em um banco de dados PostGIS. Eu tentei usar ogr2ogr, mas ele falha porque o arquivo é muito grande para ogr2ogr carregar na memória e depois processar.

Existem outras alternativas para carregar esse arquivo geojson no PostGIS?

O erro ogr2ogr que recebo é:

ERRO 2: CPLMalloc (): falta de memória alocando -611145182 bytes. Este aplicativo solicitou que o tempo de execução o encerrasse de maneira incomum. Entre em contato com a equipe de suporte do aplicativo para obter mais informações.

RyanDalton
fonte
11
Você já tentou a opção "-gt"? Por padrão, agrupa 200 recursos por transação.
31411 Pablo
Eu não estava ciente da opção -gt e não a havia experimentado antes. Apenas tentei executar novamente usando a opção -gt e infelizmente encontrei o mesmo erro. Também tentei usar a opção -WHERE para limitar o número de opções pesquisáveis, mas isso também não pareceu ajudar.
RyanDalton
O GDAL / OGR melhorou a leitura de grandes arquivos GeoJSON na 2.3.0, o que reduz bastante a sobrecarga da memória.
AndrewHarvey

Respostas:

10

A amostra que você enviou mostra que pode ser possível dividir manualmente o arquivo usando um editor como o bloco de notas ++

1) Para cada pedaço, crie um cabeçalho:

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

2) Após o cabeçalho, coloque muitos recursos:

{"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) Finalize o pedaço com:

]}

EDIT - Aqui está o código python que dividirá o arquivo em partes de tamanho definido (em número de recursos):

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

Infelizmente, o JSON é muito parecido com o XML, pouco adequado para o processamento de fluxo, então quase todas as implementações exigem que todo o conjunto de dados seja carregado na memória. Embora isso seja bom para conjuntos pequenos no seu caso, não há outra opção além de dividir o conjunto de dados em blocos menores e gerenciáveis.

Melhorando a solução de Pablo, aqui está uma que não exige que você abra e carregue o arquivo em um editor e divida manualmente, mas tenta automatizar o máximo possível todo o processo.

Copie o arquivo json em um host Unix (linux, osx) ou instale as ferramentas cygwin no Windows. Em seguida, abra um shell e use o vim para remover a primeira e a última linha do arquivo:

$ vim places.json

digite dd para remover a primeira linha e, em seguida, SHIFT-G para mover o final do arquivo, digite dd novamente para remover a última linha. Agora digite : wq para salvar as alterações. Isso deve demorar apenas alguns minutos.

Agora vamos aproveitar o poder total do unix para dividir o arquivo em partes mais gerenciáveis. No tipo de shell:

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

Vá pegar uma cerveja. Isso dividirá o arquivo em muitos arquivos menores, cada um contendo 10000 linhas. Você pode aumentar o número de linhas, desde que o mantenha pequeno o suficiente para que o ogr2gr possa gerenciá-lo.

Agora vamos enfiar a cabeça e o rabo em cada um dos arquivos:

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

Vá pegar uma cobra. Os dois primeiros comandos simplesmente criam um arquivo de cabeçalho e rodapé com o conteúdo correto (apenas por conveniência), enquanto o último adiciona cabeçalho e rodapé a cada um dos blocos divididos acima e remove o bloco sem cabeçalho / rodapé (para economizar espaço) )

Neste ponto, esperamos que você possa processar os muitos arquivos places-chunks - *. Json com ogr2ogr:

$ for f in places-chunks-*.json ; do ogr2ogr -your-options-here $f ; done
unicoletti
fonte
11
Com esse método, não precisaríamos garantir que os "blocos" de arquivo fossem divididos no final de um bloco de recursos? Como eu já pré-processei os dados em Python para adicionar as informações de cabeçalho e rodapé, devo poder adicionar um contador para agrupar os dados. Vou dar uma chance a seguir. Obrigado pela sugestão.
RyanDalton
Os dados de exemplo que você forneceu tinham um recurso por linha, por isso fui com split -l . Se esse não é o caso dos dados reais, receio que não funcione.
Unicoletti 31/10/11
Sim, é claro que você está correto, onde cada recurso está em uma linha separada. Eu não estava pensando nisso por todo o caminho.
RyanDalton
Para remover as linhas sem abrir o arquivo. Remova a primeira linha: sed -i "1d" places.json Remova as 4 primeiras linhas: sed -i "1,4d" places.json Remova as 4 últimas linhas: head -n -4 places.json > places2.json
egofer 3/08/16
2

É possível carregar seus dados com o FME Desktop. É muito fácil.


fonte
Ele processará um arquivo extremamente grande como este?
RyanDalton
Por exemplo, divida o arquivo em vários arquivos antes da transformação. hjsplit.org E importe os arquivos de notícias no FME Desktop para a importação no PostGIS.
11
provavelmente, e se dosent você pode gritar para o apoio :)
simplexio
2

Deve ser fácil escrever um leitor e gravador preguiçoso em Python que converta seu arquivo geojson no formato shapefile muito menor ou diretamente no SQL sem fazer tudo na memória. Uma vez convertidas, as ferramentas nativas do PostGIS podem importar grandes conjuntos de dados. O suporte geojson no OGR é relativamente novo e não há sinalizadores para manipular arquivos grandes.

Se você puder compartilhar um pedaço gerenciável do seu arquivo, eu poderia ajudá-lo.

GeospatialPython.com
fonte