SQL查询是否具有PostGIS的完整geojson功能?


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-普查POC
ZAK

Answers:


59

使用json_build_objectPostgreSQL 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+中,情况变得更好了,在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
好的-现在已全部升级(尽管无法获得9.5.3作为Windoze服务运行)。无论如何...关于给定示例的一件事-第二个json_build_object问题是冒号而不是逗号。
GT。

在pg v9.6上对我不起作用

2
为了完整起见,对于严格的geojson(右手规则)来说,几何顶点可能没有正确的顺序,为纠正这一点,我们可以使用ST_ForcePolygonCCW重新排列geom中的顶点-postgis.net/docs/manual-dev/ ST_ForcePolygonCCW.html
chrismarx

1
@chrismarx这是一个好点,并提出了是否ST_AsGeoJSON应修改PostGIS 函数以自行纠正方向的问题。
dbaston

21

此答案可用于9.4之前的PostgreSQL版本。将dbaston的答案用于PostgreSQL 9.4+

查询如下:(其中'GEOM'的geometry字段,id要包含在json属性中的字段,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运行它,似乎仍然没有提供有效的输出。
RyanDalton 2014年

1
太好了,这很有意义。我想我看起来不够仔细。一旦GIS.SE允许它结束问题,请随时将其标记为“已接受”。谢谢!
RyanDalton 2014年

1
不接受单引号的不仅是GeoJSONLint。JSON也不正式识别单引号。如果有任何解析器识别出它们,则这是一个非标准扩展,最好避免。
jpmc26

@BelowtheRadar这是dict,而不是JSON。他们是完全不同的东西。JSON是一个字符串。总是。它是一种文本格式,就像XML只是一种文本格式一样。A dict是内存中对象。
jpmc26 2013年

5

只是对dbaston的答案做了些微修正(我会发表评论,但我没有要点)您需要将ST_AsGeoJSON的输出转换为json(thingie ::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的答案最近已由@John Powell akaBarça 修改,并且在我这一端产生了无效的geojson。修改后,要素聚合将返回嵌套在json对象中的每个要素,这是无效的。

我没有直接在答案上发表评论的声誉,但是最终的jsonb_agg应该在“功能”列上而不是在“功能”子查询上。聚集列名(如果发现更整洁,则聚集在“ 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;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.