PostGISの完全なgeojson機能を持つSQLクエリ?


35

PostGISのプロパティでgeojson機能を取得したいと思います。機能のコレクションを持つを見つけましが、機能だけで機能させることはできません。

SELECT row_to_json(fc)
 FROM ( SELECT 'FeatureCollection' As type, array_to_json(array_agg(f)) As features
 FROM (SELECT 'Feature' As type
    , ST_AsGeoJSON(lg.geog)::json As geometry
    , row_to_json(lp) As properties
   FROM locations As lg 
         INNER JOIN (SELECT loc_id, loc_name FROM locations) As lp 
       ON lg.loc_id = lp.loc_id  ) As f )  As fc;

これまで、例の機能コレクションクエリを変更しようとしました。しかし、出力は無効です。


別のアプリの概念実証を行う必要があったので、ここからの回答を一部使用するこのレポを作成しました。うまくいけば、このようなことを始めるのに役立ちます-ここで見つけてください:pg-us-census-poc
zak

回答:


59

これはjson_build_object、PostgreSQL 9.4+でもう少し簡単に行うことができます。これにより、キーと値の引数を交互に指定してJSONを構築できます。例えば:

SELECT json_build_object(
    'type',       'Feature',
    'id',         gid,
    'geometry',   ST_AsGeoJSON(geom)::json,
    'properties', json_build_object(
        'feat_type', feat_type,
        'feat_area', ST_Area(geom)::geography
     )
 )
 FROM input_table;

PostgreSQL 9.5以降では、jsonbデータ型にいくつかの新しい演算子が追加されています(docs)。これにより、idとgeometry以外のすべてを含む「プロパティ」オブジェクトを簡単に設定できます。

SELECT jsonb_build_object(
    'type',       'Feature',
    'id',         gid,
    'geometry',   ST_AsGeoJSON(geom)::jsonb,
    'properties', to_jsonb(row) - 'gid' - 'geom'
) FROM (SELECT * FROM input_table) row;

FeatureCollectionを作成したいですか?すべてをまとめてjsonb_aggください:

SELECT jsonb_build_object(
    'type',     'FeatureCollection',
    'features', jsonb_agg(features.feature)
)
FROM (
  SELECT jsonb_build_object(
    'type',       'Feature',
    'id',         gid,
    'geometry',   ST_AsGeoJSON(geom)::jsonb,
    'properties', to_jsonb(inputs) - 'gid' - 'geom'
  ) AS feature
  FROM (SELECT * FROM input_table) inputs) features;

1
この機能だけで、今朝9.3.5から9.5.3にアップグレードしようと急いでいます。唯一の場合は、のように、単純なようだったregexp_replace(current_setting('server_version'),'(\d)\.(\d)\.(\d)','\1.\3.\2')...
GT。

1
OK-すべてアップグレードされました(ただし、9.5.3をWindozeサービスとして実行することはできません)。とにかく...与えられた例についての1つの小さなことjson_build_object-2 番目はコンマの代わりにコロンを持っています。
GT。

PGのv9.6に私のために動作しません

2
完全を期すために、ジオメトリの頂点は厳密なgeojson(右利きのルール)の正しい順序ではない可能性が高いため、それを修正するために、ST_ForcePolygonCCWでgeomの頂点を並べ替えることができます-postgis.net/docs/manual-dev/ ST_ForcePolygonCCW.html
chrismarx

1
@chrismarxこれは良い点であり、PostGISのST_AsGeoJSON機能を修正して向きを修正する必要があるかどうかの問題を提起します。
-dbaston

21

この回答は、9.4より前のPostgreSQLバージョンで使用できます。PostgreSQL 9.4+にはdbastonの回答を使用します

クエリは次のとおりです('GEOM'geometryフィールド、idjsonプロパティに含めるフィールドshapefile_feature、テーブル名、および必要な489445機能のidです)。

SELECT row_to_json(f) As feature \
     FROM (SELECT 'Feature' As type \
     , ST_AsGeoJSON('GEOM')::json As geometry \
     , row_to_json((SELECT l FROM (SELECT id AS feat_id) As l)) As properties \
     FROM shapefile_feature As l WHERE l.id = 489445) As f;

出力:

{
   "geometry":{
      "type":"MultiPolygon",
      "coordinates":[
         [
            [
               [
                  -309443.24253826,
                  388111.579584133
               ],
               [
                  -134666.391073443,
                  239616.414560895
               ],
               [
                  -308616.222736376,
                  238788.813082666
               ],
               [
                  -309443.24253826,
                  388111.579584133
               ]
            ]
         ]
      ]
   },
   "type":"Feature",
   "properties":{
      "feat_id":489445
   }
}

これを質問の本文から回答に移動したので、これはこのクエリと結果が正しく機能することを意味しますか?これをGeoJSONLintで実行する、まだ有効な出力が得られないようです。
ライアンダルトン14

1
それは理にかなっています。私はちょうど十分によく見ていないと思います。GIS.SEが問題を解決できるようになったら、これを「Accepted」としてマークしてください。ありがとう!
ライアンダルトン

1
単一引用符を受け入れないのはGeoJSONLintだけではありません。JSONは正式に一重引用符も認識しません。パーサーがそれらを認識する場合、それは非標準の拡張機能であり、おそらく回避するのが最善です。
jpmc26

@BelowtheRadarこれはdictJSONではなく、です。それらは非常に異なるものです。JSONは文字列です。常に。XMLは単なるテキスト形式であるのと同じように、テキスト形式です。A dictはメモリ内オブジェクトです。
jpmc26

5

dbastonの答えを少し修正するだけです(コメントしますが、ポイントはありません)。ST_AsGeoJSONの出力をjson(::json事物)としてキャストする必要があります。

SELECT json_build_object(
  'type',       'Feature',
  'id',         gid,
  'geometry',   ST_AsGeoJSON(geom)::json,
  'properties', json_build_object(
    'feat_type', feat_type,
    'feat_area', ST_Area(geom)::geography
  )
)
FROM input_table;

それ以外の場合、ジオメトリメンバは文字列になります。それは有効なGeoJSONではありません


4

@dbastonの答えは最近Barçaとしても知られる@John Powellによって最近修正され、私の側で無効なジオソンを生成します。変更されたように、機能の集約はjsonオブジェクト内にネストされた各機能を返しますが、これは無効です。

答えに直接コメントする評判はありませんが、最終的なjsonb_aggは「features」サブクエリではなく「feature」列にある必要があります。列名(または、より適切な場合は「features.feature」)で集計すると、集計後に「features」配列にすべての要素が配置されます。これが正しい方法です。

そのため、数週間前までの@dbastonの回答(およびサブクエリの命名に対する@Jonh Powellの修正)に非常によく似た以下が機能します。

SELECT jsonb_build_object(
  'type',     'FeatureCollection',
  'features', jsonb_agg(feature)
)
FROM (
  SELECT jsonb_build_object(
    'type',       'Feature',
    'id',         gid,
    'geometry',   ST_AsGeoJSON(geom)::jsonb,
    'properties', to_jsonb(inputs) - 'gid' - 'geom'
  ) AS feature
  FROM (
    SELECT * FROM input_table
  ) inputs
) features;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.