PostGIS Geometri Sorgusu yalnızca belirli değerler için “Hata: Karışık SRID geometrilerinde çalışma” döndürür


17

Her iki SRID 4326 ile tanımlanan iki geometri sütun ile PostGIS tablo var. Aşağıdaki INSERTdeyimi kullanarak (nerede lngve latdeğerleri programlı olarak geçirilir) tabloya sorunsuz ekleyebilirsiniz :

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
)

Ama aldığım noktanın değerine bağlı olarak ST_Intersects kullanarak bir kavşak için sorgu yaptığımda ERROR: Operation on mixed SRID geometries.

Örneğin, bu sorgu çalışır:

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

Ve bu hatalar:

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

Unutmayın, bunlar boylam değeri dışında özdeş sorgulardır. Farklı değerlerle denemeler yaptım, ancak çalışan ve çalışmayan sorgular arasında net bir geçiş noktası belirlemedim.

Sanırım temelde bir şeyi yanlış anlıyorum. Şu an için, çözülmüş / düzeltilmiş / sorguyu kullanmak için yeniden biçimlendirerek ST_GeomFromTextve açıkça SRID belirterek sorun etrafında çalıştım :

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

Ama dürüstçe, farkın ne olduğunu gerçekten anlamıyorum ya da bu gerçekten "çözüm" ise.

Benim sorum: Neden sadece belirli değerler için bir hata alıyorum ve bu sorguyu biçimlendirmek için uygun yol nedir?

İşte referans için benim tablo tanımı:

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)
);

Ayrıca geometry_columns SRID sadece bir tür olduğunu doğruladı:

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

Yardım / tavsiye takdir. Teşekkür ederim! (Not: Bu soruyu da gördüm , ancak zaten tabloya eklerken geometri SRID'lerimi açıkça tanımladığım için, olan şey bu değil gibi görünüyor.)

Yanıtlar:


24

SRID'siz bir geometri belirttiğinizde, aslında 0(veya -1<2 sürümü için):

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

Yani bu geometriyi SRID = 4326 olan başka bir geometriyle kullandığınızda, karıştırıyor 0ve 4326. Uzamsal referanslar gerçekten farklıysa, bu genellikle yararlı bir hatadır. Sizin durumunuzda, SRID'ler aynıdır, ancak SRID'yi sorgu noktasına kodlamadınız. Bu nedenle, sorgunuzu düzeltmek için her zaman sorgu noktanız için aynı SRID'yi belirtin ve bunlar artık karıştırılmayacaktır.

Bir yan not olarak, tip burada gösterildiği gibi, 4326 varsayılan SRID (WGS 84) sahiptir:geography

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

Bu nedenle, geographytürler yerine türler kullanırsanız geometry, SRID'nin belirtilmesi gerekmez (Mars veya başka bir alternatif elipsoid için farklı bir SRID istemiyorsanız).


Bir sorgunun neden bir hatası olduğu ve diğerinin neden olmadığı konusunda, ST_Intersectsönce &&hızlı ve SRID'leri umursamayan bir sınırlayıcı kutu araması yapar. Sınırlayıcı kutular kesişmezse karma SRID hata iletileri yükseltilmez. Ancak kesişirlerse, ikinci filtre _ST_Intersectsdaha hassastır ve iki SRID'yi eşleştiğinden emin olmak için kontrol eder ve karıştırıldıklarında bir hata oluşturur. Örneğin:

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 
);

kesişen sınırlayıcı kutusu yoktur ve baypas eder _ST_Intersects. Ancak POINT(-122.334172173172 47.602634395263560), sınırlayıcı kutular üst üste geldiğinden hatayı yükseltir (geometriler aslında kesişmese bile).

Ancak, aynı geometriler ve farklı filtrelerle:

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 
);

sınırlayıcı kutular dikkate alınmadığından, karışık bir SRID hatası atar.


vay, teşekkür ederim. mantıklı. SRID=4326ifadesinin geri kalanı için SRID'yi ayarlamanın doğru yolunu (yukarıda yaptığınız gibi) önek olarak kullanmak? ( ST_GeomFromTextsadece SRID belirtmek için başka bilmiyordum çünkü kullanmak yerine ...?) sorgular için varsayılan bir SRID ayarlamak için bir yolu var mı? her seferinde açıkça ayarlamak için oldukça ayrıntılı görünüyor. Tekrar teşekkürler!
jessykate

1
Cevabımı geographyher zaman 4326 olan türleri kullanmayı önermek için güncelledim. Ayrıca, SRID'yi belirtmenin birkaç yolu vardır .
Mike T

0

Point(Double, Double)Yardımcı olabilecek birkaç gözlem: Birincisi, bir PostGIS veri türüne zorladığınız yerel bir PostgreSQL işlevidir. ST_MakePoint(double x, double y)uygun geometri oluşturacaktır. Ayrıca, sorunuzda ikinci argümana boylam olarak atıfta bulunuyorsunuz. Uygun düzen x, ybuna karşılık gelir Longitude, Latitude. Bu durumun tersine çevrilmesi, herhangi bir istisna atmadan beklenmedik sonuçlar döndürebilir.

Bunların hiçbiri ilk örneğinizin neden bazen değil de bazen çalıştığını açıklamıyor, ancak umarım bu iyi sorgular oluşturmanıza yardımcı olur.

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.