Truy vấn SQL để có một tính năng Geojson hoàn chỉnh từ PostGIS?


35

Tôi muốn có một tính năng Geojson với các thuộc tính từ PostGIS. Tôi đã tìm thấy một ví dụ để có một bộ sưu tập tính năng nhưng tôi không thể làm cho nó hoạt động chỉ cho một tính năng.

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;

cho đến nay tôi đã cố gắng sửa đổi truy vấn bộ sưu tập tính năng của ví dụ. nhưng đầu ra không hợp lệ.


Tôi đã phải làm một bằng chứng về khái niệm cho một ứng dụng khác để kết hợp repo này, một phần sử dụng các câu trả lời từ đây. Hy vọng sẽ giúp bắt đầu với công cụ này - tìm nó ở đây: pg-us-c điều tra-poc
zak

Câu trả lời:


59

Điều này có thể được thực hiện đơn giản hơn một chút với json_build_objectPostgreQuery 9.4+, cho phép bạn xây dựng JSON bằng cách cung cấp các đối số khóa / giá trị xen kẽ. Ví dụ:

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;

Mọi thứ thậm chí còn tốt hơn trong PostgreQuery 9.5+, trong đó một số toán tử mới được thêm vào cho jsonbkiểu dữ liệu ( tài liệu ). Điều này giúp bạn dễ dàng thiết lập một đối tượng "thuộc tính" chứa mọi thứ trừ id và hình học .

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;

Bạn muốn tạo một FeatureCollection? Chỉ cần gói tất cả lại với 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
Chỉ riêng chức năng này đã khiến tôi phải vật lộn để nâng cấp từ 9.3.5 lên 9.5.3 sáng nay. Giá như nó đơn giản như regexp_replace(current_setting('server_version'),'(\d)\.(\d)\.(\d)','\1.\3.\2')...
GT.

1
OK - tất cả được nâng cấp ngay bây giờ (mặc dù không thể có 9.5.3 để chạy dưới dạng dịch vụ Windoze). Dù sao đi nữa ... một điều nhỏ về ví dụ được đưa ra - thứ hai json_build_objectcó dấu hai chấm thay vì dấu phẩy.
GT.

không hoạt động với tôi trên pg v9.6
Pak

2
Để cho hoàn chỉnh, có thể các đỉnh hình học không theo đúng thứ tự cho Geojson nghiêm ngặt (quy tắc thuận tay phải), để khắc phục điều đó, chúng ta có thể sắp xếp lại các đỉnh trong geom bằng ST_ForcePolygonCCW - postgis.net/docs/manual-dev/ ST_ForcePolygonCCW.html
chrismarx

1
@chrismarx đây là một điểm tốt và đặt ra vấn đề liệu có ST_AsGeoJSONnên sửa đổi chức năng của PostGIS để tự điều chỉnh hướng hay không.
dbaston

21

Câu trả lời này có thể được sử dụng với phiên bản PostgreSQL trước 9,4. Sử dụng câu trả lời của dbaston cho PostgreQuery 9.4+

Truy vấn như sau: (trong đó 'GEOM'là trường hình học, idtrường cần bao gồm trong các thuộc tính json, shapefile_featuretên bảng và 489445là id của tính năng mong muốn)

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;

đầu ra:

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

vì bạn đã chuyển câu hỏi này từ phần chính câu hỏi của mình sang câu trả lời, điều này có nghĩa là truy vấn này và kết quả hiện đang hoạt động chính xác? Chạy nó thông qua GeoJSONLint , nó vẫn không xuất hiện để đưa ra đầu ra hợp lệ.
RyanDalton

1
Tuyệt vời, điều đó có ý nghĩa. Tôi đoán tôi chỉ không nhìn kỹ đủ. Vui lòng đánh dấu câu này là "Được chấp nhận" một khi GIS.SE cho phép nó đóng câu hỏi. Cảm ơn!
RyanDalton

1
Không chỉ GeoJSONLint không chấp nhận dấu ngoặc đơn. JSON cũng không chính thức nhận ra các trích dẫn đơn lẻ. Nếu bất kỳ trình phân tích cú pháp nào nhận ra chúng, đó là một phần mở rộng không chuẩn và có lẽ tốt nhất nên tránh.
jpmc26

@BelowtheRadar Đó là một dict, không phải JSON. Chúng là những thứ rất khác nhau. JSON là một chuỗi. Luôn luôn. Đây là định dạng văn bản, theo cùng một cách XML chỉ là định dạng văn bản. A dictlà một đối tượng trong bộ nhớ.
jpmc26

5

Chỉ cần sửa một chút cho câu trả lời của dbaston (Tôi sẽ bình luận nhưng tôi không có điểm) Bạn cần phải đưa ra kết quả đầu ra của ST_AsGeoJSON là json (điều này ::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;

Nếu không, thành viên hình học sẽ là một chuỗi. Điều đó không hợp lệ GeoJSON


4

Câu trả lời của @ dbaston đã được sửa đổi gần đây bởi @John Powell hay còn gọi là Barça và nó tạo ra Geojsons không hợp lệ ở phía tôi. Khi được sửa đổi, tập hợp trên các tính năng trả về mỗi tính năng được lồng bên trong một đối tượng json, không hợp lệ.

Tôi không có tiếng để bình luận trực tiếp về câu trả lời, nhưng jsonb_agg cuối cùng phải nằm trên cột "tính năng" chứ không phải về truy vấn "tính năng". Tổng hợp trên tên cột (hoặc "features.feature" nếu bạn thấy nó gọn gàng hơn) đặt mọi phần tử thẳng vào mảng "tính năng" sau tập hợp, đó là cách phù hợp.

Vì vậy, những điều sau đây, khá giống với câu trả lời của @ dbaston vì nó đã tồn tại cho đến vài tuần trước (cộng với sự điều chỉnh của @Jonh Powell đối với việc đặt tên truy vấn phụ) không hoạt động:

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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.