Menyimpan GeoJSON FeatureCollection ke PostgreSQL dengan PostGIS?

21

Saya baru mengenal GeoJSON. Saya memiliki koleksi fitur GeoJSON seperti yang ditunjukkan dan ingin menyimpannya di tabel postgres (testtable). Tabel postgres saya memiliki id seri dan kolom geometri.

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [
                    2565453.1826721914,
                    -3835048.659760314
                ]
            }
        },
        {
            "type": "Feature",
            "geometry": {
                "type": "LineString",
                "coordinates": [
                    [
                        2727584.7219710173,
                        -3713449.1942418693
                    ],
                    [
                        2732476.691781269,
                        -3992291.473426192
                    ]
                ]
            }
        },
        {
            "type": "Feature",
            "geometry": {
                "type": "Polygon",
                "coordinates": [
                    [
                        [
                            2442627.9025405287,
                            -3705499.954308534
                        ],
                        [
                            2425506.008204649,
                            -3886502.837287831
                        ],
                        [
                            2425506.008204649,
                            -3886502.837287831
                        ],
                        [
                            2555143.2081763083,
                            -3910962.686339088
                        ],
                        [
                            2442627.9025405287,
                            -3705499.954308534
                        ]
                    ]
                ]
            }
        }
    ]
}

Saya ingin memasukkan data GeoJSON ke dalam tabel testtable.

Bagaimana saya melakukannya?

Saya menggunakan postgres versi 9.3.5 dengan postgis versi 2.1.3


Saya telah diarahkan ke pertanyaan sebelumnya yang menjawab bagaimana cara menyimpan fitur tunggal misalnya titik atau poligon. Pertanyaan saya menanyakan bagaimana cara menyimpan banyak fitur dalam file GeoJSON. Dengan beberapa fitur yang saya maksud adalah campuran dari titik, garis dan tipe fitur poligon dalam satu file.

Jay
sumber
kemungkinan duplikat dari Bagaimana cara memasukkan poligon GeoJSON ke dalam tabel PostGIS?
Ricardo Oliveira
Hai Ricardo, saya telah melihat pertanyaan itu tetapi tidak menjawab masalah saya. Saya ingin menyimpan daftar fitur, bukan hanya tipe fitur tunggal. Silakan lihat koleksi fitur GeoJSON saya di pertanyaan saya.
Jay
@Jay Jadi sekarang pertanyaan Anda adalah "Bagaimana cara memecah koleksi geojson menjadi fitur tunggal atau Anda perlu menambahkan lebih banyak informasi (mungkin menyimpan informasi bahwa geometri itu termasuk dalam semacam koleksi?)
Jakub Kania
1
Terima kasih @John atas tanggapan Anda. Karena saya baru mengenal GIS dan GeoJSON, saya ingin beberapa petunjuk tentang masalah saya. Latar belakang pertanyaan: Seorang pengguna menggambar fitur-fitur pada peta dan saya menangkap kumpulan fitur yang digambar. Saya ingin menyimpan koleksi ini dalam DB dengan id unik. Kemudian, data yang disimpan dapat diambil untuk id yang disediakan. Testable di postgres memiliki 2 kolom. kolom gid yang merupakan tipe serial, untuk menampung id, dan kolom geom yang bertipe geometri.
Jay
1
@ Jay Ya, Anda dapat menyimpan JSON tapi itu tidak akan menjadi geometri sehingga Anda tidak akan dapat mencari tetangga terdekat dengan mudah dll.
Jakub Kania

Jawaban:

26

Dengan asumsi Anda memiliki setidaknya PostgreSQL versi 9.3, Anda dapat menggunakan beberapa fungsi dan operator JSON untuk mengekstrak bagian relevan dari spesifikasi GeoJSON yang diperlukan oleh ST_GeomFromGeoJSON untuk membuat geometri.

Coba yang berikut, di mana Anda dapat mengganti JSON di bagian atas:

WITH data AS (SELECT '{ "type": "FeatureCollection",
    "features": [
      { "type": "Feature",
        "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
        "properties": {"prop0": "value0"}
        },
      { "type": "Feature",
        "geometry": {
          "type": "LineString",
          "coordinates": [
            [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]
            ]
          },
        "properties": {
          "prop0": "value0",
          "prop1": 0.0
          }
        },
      { "type": "Feature",
         "geometry": {
           "type": "Polygon",
           "coordinates": [
             [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
               [100.0, 1.0], [100.0, 0.0] ]
             ]
         },
         "properties": {
           "prop0": "value0",
           "prop1": {"this": "that"}
           }
         }
       ]
     }'::json AS fc)

SELECT
  row_number() OVER () AS gid,
  ST_AsText(ST_GeomFromGeoJSON(feat->>'geometry')) AS geom,
  feat->'properties' AS properties
FROM (
  SELECT json_array_elements(fc->'features') AS feat
  FROM data
) AS f;

Menemukan tiga geometri. The geomkolom memiliki objek geometri, dan gidadalah nomor fitur. The ST_AsTextFungsi menunjukkan yang WKT setara dengan masing-masing geometri. Saya juga menyertakan propertiesatribut atau yang dapat didefinisikan untuk setiap geometri, seperti yang ditunjukkan dalam spesifikasi.

 gid |                   geom                   |              properties
-----+------------------------------------------+--------------------------------------
   1 | POINT(102 0.5)                           | {"prop0": "value0"}
   2 | LINESTRING(102 0,103 1,104 0,105 1)      | {                                   +
     |                                          |           "prop0": "value0",        +
     |                                          |           "prop1": 0.0              +
     |                                          |           }
   3 | POLYGON((100 0,101 0,101 1,100 1,100 0)) | {                                   +
     |                                          |            "prop0": "value0",       +
     |                                          |            "prop1": {"this": "that"}+
     |                                          |            }
(3 rows)

Anda harus menetapkan SRID untuk geometri, menggunakan ST_SetSRID.

Atau jika Anda hanya membutuhkan satu GEOMETRI heterogen, Anda dapat membuatnya kompak seperti ini:

SELECT ST_AsText(ST_Collect(ST_GeomFromGeoJSON(feat->>'geometry')))
FROM (
  SELECT json_array_elements('{ ... put JSON here ... }'::json->'features') AS feat
) AS f;

GEOMETRYCOLLECTION(POINT(2565453.18267219 -3835048.65976031),LINESTRING(2727584.72197102 -3713449.19424187,2732476.69178127 -3992291.47342619),POLYGON((2442627.90254053 -3705499.95430853,2425506.00820465 -3886502.83728783,2555143.20817631 -3910962.68633909,2442627.90254053 -3705499.95430853)))

Lihat juga Membuat Koleksi Fitur GeoJSON dengan fungsi JSON dan PostGIS dari Postgres OnLine Journal, yang melakukan sebaliknya.

Mike T
sumber