PostGIS'ten tam bir geojson özelliğine sahip olmak için SQL sorgusu?


35

PostGIS'in özelliklerine sahip bir geojson özelliği almak istiyorum. Bir özellik koleksiyonuna sahip bir örnek buldum , ancak sadece bir özellik için çalışmasını sağlayamıyorum.

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;

Şimdiye kadar, örneğin özellik toplama sorgusunu değiştirmeye çalıştım. ancak çıktı geçerli değil.


Başka bir uygulama için konseptin bir kanıtını yapmak zorunda kaldım, bu yüzden bu cevabı bir araya getirip kısmen yanıtları kullandım. Umarım bu şeylerle başlamanıza yardımcı olur - burada bulun: pg-us-census-poc
zak

Yanıtlar:


59

Bu, json_build_objectalternatif anahtar / değer argümanları sağlayarak bir JSON oluşturmanıza izin veren PostgreSQL 9.4+ ile biraz daha kolay bir şekilde yapılabilir . Örneğin:

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;

Şeyler daha iyi bazı yeni operatörler için eklenen PostgreSQL 9.5+, içeri jsonbveri türü ( docs ). Bu , id ve geometri dışında her şeyi içeren bir "özellikler" nesnesi oluşturmayı kolaylaştırır .

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 yapmak ister misiniz? Hepsini şununla sarın 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
Yalnız bu işlevsellik beni bu sabah 9.3.5'ten 9.5.3'e yükseltmek için çabalıyor. Keşke o kadar basit olsaydı regexp_replace(current_setting('server_version'),'(\d)\.(\d)\.(\d)','\1.\3.\2')...
GT.

1
Tamam - hepsi şimdi yükseltildi (ancak bir Windoze servisi olarak çalıştırılması için 9.5.3 alınamıyor). Her neyse ... verilen örnekle ilgili küçük bir şey - ikincisinde json_build_objectvirgül yerine virgül var.
GT.

benim için pg v9.6 üzerinde çalışmıyor
Pak

2
Bütünlük için, geometri köşelerinin kesin geojson (doğru verilen kural) için doğru sırada olmaması muhtemeldir, bunu düzeltmek için, geomdeki köşeleri ST_ForcePolygonCCW - postgis.net/docs/manual-dev/
chrismarx

1
@ chrismarx bu iyi bir nokta ve ST_AsGeoJSONyönelimi tek başına düzeltmek için PostGIS işlevinin değiştirilip değiştirilmemesi gerektiği konusunu gündeme getiriyor .
dbaston

21

Bu cevap PostgreSQL'in 9.4'ten önceki sürümlerinde kullanılabilir. PostgreSQL 9.4+ için dbaston'ın cevabını kullanın

Sorgu şu şekildedir: ( 'GEOM'geometri alanı, idjson özelliklerine eklenecek alan shapefile_feature, tablo adı ve 489445istenen özelliğin kimliği)

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;

çıktı:

{
   "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
   }
}

Bunu sorunuzun gövdesinden cevaba taşıdığınız için, bu sorgu şu anda doğru sonuç veriyor mu? GeoJSONLint aracılığıyla bu çalıştıran , hala geçerli çıktı veriyor gibi görünmüyor.
RyanDalton

1
Harika, bu mantıklı. Sanırım yeterince yakından bakmadım. GIS.SE soruyu kapatmasına izin verdiğinde bunu "Kabul Edildi" olarak işaretlemekten çekinmeyin. Teşekkürler!
RyanDalton

1
Tek tırnak kabul etmeyen sadece GeoJSONLint değil. JSON , tek tek tırnak işaretleri de resmen tanımıyor. Herhangi bir ayrıştırıcı bunları tanırsa, standart olmayan bir uzantıdır ve muhtemelen en iyi şekilde kaçınılması gerekir.
jpmc26

@BelowtheRadar Bu bir dictJSON değil. Onlar çok farklı şeyler. JSON bir dizedir. Her zaman. Bu bir metin formatıdır, aynı şekilde XML sadece bir metin formatıdır. A dict, bellekteki bir nesnedir.
jpmc26

5

Dbaston'ın cevabına ufak bir düzeltme (yorum yapmalıyım ama puanım yok) ST_AsGeoJSON'un çıktısını json olarak yazmanız gerekiyor ::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;

Aksi takdirde, geometri üyesi bir dize olacak. Bu geçerli bir GeoJSON değil


4

@ dbaston'ın cevabı son zamanlarda @John Powell aka Barça tarafından değiştirildi ve benim tarafımda geçersiz geojsons üretti. Değiştirildiği gibi, özelliklerin toplanması, geçersiz bir json nesnesinin içine yerleştirilmiş olan her özelliği döndürür.

Doğrudan cevaba yorum yapma itibarı yok, ancak son jsonb_agg "özellikler" sütununda olmalı ve "özellikler" alt sorgusunda olmamalıdır. Sütun adında toplama (veya onu daha temiz bulursanız "features.feature"), her öğeyi toplamadan sonraki "doğru" sıraya koyar.

Bu nedenle, @ dbaston'ın cevabına oldukça benzeyen aşağıdaki birkaç hafta öncesine kadar (artı @Jonh Powell'ın alt sorgulamada düzeltmesi) işe yarıyor:

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;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.