Truy vấn Hình học PostGIS trả về Lỗi Lỗi: Hoạt động trên hình học SRID hỗn hợp Chỉ dành cho một số giá trị nhất định


17

Tôi có bảng PostGIS với hai cột hình học, cả hai được xác định bằng SRID 4326. Tôi có thể chèn vào bảng mà không gặp vấn đề gì, sử dụng INSERTcâu lệnh sau (trong đó lnglatlà các giá trị được truyền theo chương trình):

INSERT INTO pad_meta (
    uuid, created, updated, name, origin, radius, area, expiry, creator
) VALUES (
    $1, now(), now(), $2, ST_GeomFromText('POINT(lng, lat)', 4326), $3, 
    ST_Buffer(ST_GeomFromText('POINT(lng, lat)', 4326), $4), $5, $6
)

Nhưng khi tôi truy vấn một giao lộ bằng ST_Intersects, tùy thuộc vào giá trị của điểm tôi nhận được ERROR: Operation on mixed SRID geometries.

Ví dụ: truy vấn này hoạt động:

SELECT * FROM pad_meta where ST_Intersects(
    'POINT(-122.334172173172 46.602634395263560)'::geometry, area::geometry 
) ORDER BY created DESC;

Và lỗi này là:

SELECT * FROM pad_meta where ST_Intersects(
    'POINT(-122.334172173172 47.602634395263560)'::geometry, area::geometry 
) ORDER BY created DESC;

Lưu ý, chúng là các truy vấn giống hệt nhau ngoại trừ giá trị của kinh độ. Tôi đã thử nghiệm với các giá trị khác nhau, nhưng không xác định được điểm chuyển tiếp rõ ràng giữa các truy vấn hoạt động và không.

Tôi nghĩ rằng về cơ bản tôi đang hiểu nhầm một cái gì đó. Hiện tại, tôi đã giải quyết / sửa chữa / khắc phục sự cố bằng cách định dạng lại truy vấn để sử dụng ST_GeomFromTextvà chỉ định rõ ràng SRID:

SELECT * FROM pad_meta where ST_Intersects(
    ST_GeomFromText('POINT(-122.334172173172 47.602634395263560)', 4326), area
) ORDER BY created DESC;

Nhưng tôi thực sự không hiểu sự khác biệt là gì, hoặc nếu đây thực sự là "giải pháp".

Câu hỏi của tôi là: Tại sao tôi chỉ nhận được một lỗi cho các giá trị cụ thể và cách thích hợp để định dạng truy vấn này là gì?

Dưới đây là định nghĩa bảng của tôi để tham khảo:

CREATE TABLE IF NOT EXISTS pad_meta (
  uuid CHAR(32),
  created TIMESTAMP,
  updated TIMESTAMP,
  name VARCHAR(128),
  origin GEOMETRY(Point, 4326),
  radius INTEGER,
  area GEOMETRY(Polygon, 4326),
  expiry TIMESTAMP,
  creator CHAR(32),
  PRIMARY KEY (uuid)
);

Tôi cũng đã xác minh rằng chỉ có một loại SRID trong hình học_columns:

SELECT f_table_name, f_geometry_column, srid FROM geometry_columns;
f_table_name | f_geometry_column | srid
--------------+-------------------+------
 pad_meta     | origin            | 4326
 pad_meta     | area              | 4326

Trợ giúp / tư vấn đánh giá cao. Cảm ơn bạn! (Lưu ý: Tôi cũng đã thấy câu hỏi này , nhưng vì tôi đã xác định rõ ràng các SRID hình học của mình khi chèn vào bảng, có vẻ như đó không phải là điều đang xảy ra.)

Câu trả lời:


24

Khi bạn chỉ định hình học không có SRID, nó thực sự 0(hoặc -1cho phiên bản <2):

SELECT ST_SRID('POINT(-122.334172173172 46.602634395263560)'::geometry);
 st_srid
---------
       0

Vì vậy, khi bạn sử dụng hình học này với một hình khác với SRID = 4326, nó được trộn 04326. Đây thường là một lỗi hữu ích, nếu các tham chiếu không gian thực sự khác nhau. Với trường hợp của bạn, các SRID giống nhau, nhưng bạn đã không mã hóa SRID đến điểm truy vấn. Vì vậy, để khắc phục truy vấn của bạn luôn chỉ định cùng SRID cho điểm truy vấn của bạn và chúng sẽ không còn bị trộn lẫn nữa.

Là một mặt lưu ý, các geographyloại có SRID mặc định của 4326 (WGS 84), như ở đây:

SELECT ST_SRID('POINT(-122.334172173172 46.602634395263560)'::geography::geometry);
 st_srid
---------
    4326

Vì vậy, nếu bạn sử dụng geographycác loại thay vì các geometryloại, SRID không cần phải được chỉ định (trừ khi bạn muốn có một SRID khác cho một ellipsoid thay thế cho Sao Hỏa hoặc bất cứ điều gì).


Về lý do tại sao một truy vấn có lỗi, còn truy vấn kia thì không, ST_Intersectsđầu tiên thực hiện &&tìm kiếm hộp giới hạn, nhanh và không quan tâm đến SRID. Không có thông báo lỗi SRID hỗn hợp sẽ được nêu ra nếu các hộp giới hạn không giao nhau. Nhưng nếu chúng giao nhau, bộ lọc thứ hai _ST_Intersectschính xác hơn và kiểm tra hai SRID để đảm bảo chúng khớp nhau và gây ra lỗi nếu chúng bị trộn lẫn. Ví dụ:

WITH pad_meta AS (
    SELECT 'SRID=4326;POLYGON((-124 50, -124 47, -121 50, -124 50))'::geometry AS area)

SELECT * FROM pad_meta where ST_Intersects(
    'POINT(-122.334172173172 46.602634395263560)'::geometry, area::geometry 
);

không có bất kỳ hộp giới hạn giao nhau, và bỏ qua _ST_Intersects. Nhưng POINT(-122.334172173172 47.602634395263560)sẽ gây ra lỗi vì các hộp giới hạn thực hiện chồng lấp (mặc dù hình học không thực sự giao nhau).

Tuy nhiên, với cùng một hình học và bộ lọc khác nhau:

WITH pad_meta AS (
    SELECT 'SRID=4326;POLYGON((-124 50, -124 47, -121 50, -124 50))'::geometry AS area)

SELECT * FROM pad_meta where _ST_Intersects(
    'POINT(-122.334172173172 46.602634395263560)'::geometry, area::geometry 
);

ném một lỗi SRID hỗn hợp, vì các hộp giới hạn không được xem xét.


ồ, cảm ơn bạn. Điều đó có ý nghĩa. tiền tố một truy vấn với SRID=4326(như bạn đã làm ở trên) là cách đúng để đặt SRID cho phần còn lại của câu lệnh? (trái ngược với việc sử dụng ST_GeomFromTextđơn giản vì tôi không biết cách nào khác để chỉ định SRID ...?) có cách nào để đặt SRID mặc định cho các truy vấn không? có vẻ khá dài dòng để đặt nó rõ ràng mỗi lần. một lần nữa cám ơn!
jessykate

1
Tôi đã cập nhật câu trả lời của mình để đề xuất sử dụng geographycác loại, luôn là 4326. Ngoài ra, có một số cách để chỉ định SRID.
Mike T

0

Một vài quan sát có thể giúp ích: Một, Point(Double, Double)là một hàm PostgreQuery riêng mà bạn đang ép buộc với kiểu dữ liệu PostGIS. ST_MakePoint(double x, double y)sẽ tạo hình học thích hợp. Ngoài ra, trong câu hỏi của bạn, bạn dường như đề cập đến đối số thứ hai là kinh độ. Thứ tự thích hợp là x, y, tương ứng với Longitude, Latitude. Bắt những người đảo ngược có thể trả lại kết quả bất ngờ mà không đưa ra bất kỳ ngoại lệ.

Không ai trong số này thực sự giải thích lý do tại sao ví dụ đầu tiên của bạn đôi khi hoạt động chứ không phải những người khác, nhưng hy vọng điều này sẽ giúp bạn tạo ra các truy vấn tốt.

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.