2010-01-07 9 views
9

मेरे पास लाखों पंक्तियों के साथ एक पोस्टग्रेज़ डेटाबेस है जिसमें इसका नाम जिओम नामक एक कॉलम है जिसमें संपत्ति की सीमा होती है।पोस्टगिस - मैं डालने से पहले ज्यामिति प्रकार की जांच कैसे करूं

एक पायथन स्क्रिप्ट का उपयोग करके मैं इस तालिका से जानकारी निकाल रहा हूं और इसे एक नई तालिका में दोबारा डालने वाला हूं।

जब मैं निम्नलिखित के साथ बाहर नई तालिका में सम्मिलित स्क्रिप्ट कीड़े:

Traceback (most recent call last): 
    File "build_parcels.py", line 258, in <module> 
    main() 
    File "build_parcels.py", line 166, in main 
    update_cursor.executemany("insert into parcels (par_id, street_add, title_no, proprietors, au_name, ua_name, geom) VALUES (%s, %s, %s, %s, %s, %s, %s)", inserts) 
psycopg2.IntegrityError: new row for relation "parcels" violates check constraint "enforce_geotype_geom" 

नई तालिका है एक जांच बाधा enforce_geotype_geom = ((geometrytype (geom) = 'बहुभुज' :: पाठ) या (geom IS NULL)) जबकि पुरानी तालिका नहीं है, इसलिए पुरानी तालिका में dud डेटा या गैर बहुभुज (शायद multipolygon डेटा?) अनुमान लगा रहा हूँ। मैं नया डेटा बहुभुज के रूप में रखना चाहता हूं इसलिए कुछ और नहीं डालना चाहता हूं।

प्रारंभ में मैंने मानक पायथन त्रुटि के साथ क्वेरी को लपेटने की कोशिश की, उम्मीद है कि डूड जियो पंक्तियां असफल हो जाएंगी लेकिन स्क्रिप्ट चलती रहेगी, लेकिन स्क्रिप्ट को अंत में प्रतिबद्ध करने के लिए लिखा गया है, प्रत्येक पंक्ति नहीं, इसलिए यह काम नहीं करता है ।

मुझे लगता है कि मुझे क्या करना है पुरानी तालिका भू-पंक्तियों के माध्यम से पुनरावृत्ति करना है और जांचें कि वे किस प्रकार की ज्यामिति हैं, इसलिए मैं यह स्थापित कर सकता हूं कि मैं इसे रखना चाहता हूं या नहीं, इससे पहले कि मैं नई टेबल में डालूं

इस बारे में जाने का सबसे अच्छा तरीका क्या है?

उत्तर

7

PostGIS एसक्यूएल का यह आश्चर्यजनक उपयोगी बिट की मदद करनी चाहिए आप यह पता लगा ... यहाँ कई ज्यामिति प्रकार परीक्षण कर रहे हैं:

-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
-- 
-- $Id: cleanGeometry.sql 2008-04-24 10:30Z Dr. Horst Duester $ 
-- 
-- cleanGeometry - remove self- and ring-selfintersections from 
--     input Polygon geometries 
-- http://www.sogis.ch 
-- Copyright 2008 SO!GIS Koordination, Kanton Solothurn, Switzerland 
-- Version 1.0 
-- contact: horst dot duester at bd dot so dot ch 
-- 
-- This is free software; you can redistribute and/or modify it under 
-- the terms of the GNU General Public Licence. See the COPYING file. 
-- This software is without any warrenty and you use it at your own risk 
-- 
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


CREATE OR REPLACE FUNCTION cleanGeometry(geometry) 
    RETURNS geometry AS 
$BODY$DECLARE 
    inGeom ALIAS for $1; 
    outGeom geometry; 
    tmpLinestring geometry; 

Begin 

    outGeom := NULL; 

-- Clean Process for Polygon 
    IF (GeometryType(inGeom) = 'POLYGON' OR GeometryType(inGeom) = 'MULTIPOLYGON') THEN 

-- Only process if geometry is not valid, 
-- otherwise put out without change 
    if not isValid(inGeom) THEN 

-- create nodes at all self-intersecting lines by union the polygon boundaries 
-- with the startingpoint of the boundary. 
     tmpLinestring := st_union(st_multi(st_boundary(inGeom)),st_pointn(boundary(inGeom),1)); 
     outGeom = buildarea(tmpLinestring);  
     IF (GeometryType(inGeom) = 'MULTIPOLYGON') THEN  
     RETURN st_multi(outGeom); 
     ELSE 
     RETURN outGeom; 
     END IF; 
    else  
     RETURN inGeom; 
    END IF; 


------------------------------------------------------------------------------ 
-- Clean Process for LINESTRINGS, self-intersecting parts of linestrings 
-- will be divided into multiparts of the mentioned linestring 
------------------------------------------------------------------------------ 
    ELSIF (GeometryType(inGeom) = 'LINESTRING') THEN 

-- create nodes at all self-intersecting lines by union the linestrings 
-- with the startingpoint of the linestring. 
    outGeom := st_union(st_multi(inGeom),st_pointn(inGeom,1)); 
    RETURN outGeom; 
    ELSIF (GeometryType(inGeom) = 'MULTILINESTRING') THEN 
    outGeom := multi(st_union(st_multi(inGeom),st_pointn(inGeom,1))); 
    RETURN outGeom; 
    ELSIF (GeometryType(inGeom) = '<NULL>' OR GeometryType(inGeom) = 'GEOMETRYCOLLECTION') THEN 
    RETURN NULL; 
    ELSE 
    RAISE NOTICE 'The input type % is not supported %',GeometryType(inGeom),st_summary(inGeom); 
    RETURN inGeom; 
    END IF;  
End;$BODY$ 
    LANGUAGE 'plpgsql' VOLATILE; 
+0

से ऊपर के उत्तर के समान, धन्यवाद एक हाइब्रिड पायथन/पोस्टग्रेस उत्तर के लिए बस गया होगा, लेकिन यह पोस्टग्रेस के अंदर सभी को करने में सक्षम होने के लिए आश्चर्यजनक है। आपके उत्तर के लिए धन्यवाद – ADAM

2

विकल्प 1 प्रत्येक डालने से पहले एक सेवपॉइंट बनाना है और INSERT विफल होने पर उस सुरक्षित बिंदु पर वापस रोल करना है।

विकल्प 2 चेक बाधा अभिव्यक्ति को मूल क्वेरी पर WHERE स्थिति के रूप में संलग्न करना है जो डेटा को बिल्कुल चुनने से बचने के लिए उत्पादित करता है।

सबसे अच्छा जवाब टेबल के आकार, दोषपूर्ण पंक्तियों की सापेक्ष संख्या, और कितनी तेज़ और अक्सर इसे चलाने के लिए माना जाता है, पर निर्भर करता है।

+0

जवाब के लिए धन्यवाद। मुझे विकल्प 2 पसंद है लेकिन मुझे अभी भी डालने वाले अन्य डेटा की आवश्यकता है, भले ही भौम सम्मिलित न हो। क्या आप जानते हैं कि मैं सिर्फ एक चुनिंदा कथन कैसे कर सकता हूं जो प्रत्येक पंक्ति के लिए जियोम प्रकार को प्रिंट करता है? – ADAM

+0

और डेटाबेस को स्पष्ट करने के लिए लगभग 5 मिलियन पंक्तियां हैं और डेटा को पुन: उत्पन्न करने के लिए प्रति माह केवल 1 बार चलाया जाता है और तेज़ होने की आवश्यकता नहीं होती है।मुझे अभी तक दोषपूर्ण पंक्तियों की संख्या नहीं पता है – ADAM

+1

आप मूल क्वेरी (विकल्प 2 के अनुसार) जैसे SELECT par_id, street_add, title_no, proprietors, au_name, ua_name, CASE WHEN ((ज्यामिति टाइप (geom) = 'पॉलीगॉन' :: पाठ) या (geom IS NULL)) फिर geome ELSE शून्य अंत पुराने geROM से geom के रूप में; भौगोलिक मानों के लिए शून्य को प्रतिस्थापित करने के लिए जो "फिट" नहीं है। –

0

मुझे लगता है कि आप ST_CollectionExtract उपयोग कर सकते हैं - यह देखते हुए एक (बहु) ज्यामिति , एक (बहु) ज्यामिति देता है जिसमें निर्दिष्ट प्रकार के तत्व शामिल होते हैं।

मैं ST_Intersection के परिणामों को सम्मिलित करते समय इसका उपयोग करता हूं, ST_Dump किसी भी बहु-बहुभुज को अलग करता है, व्यक्तिगत ज्यामिति में संग्रह करता है। तब ST_CollectionExtract (theGeom, 3) कुछ भी छोड़ देता है, लेकिन बहुभुज:

ST_CollectionExtract((st_dump(ST_Intersection(data.polygon, grid.polygon))).geom,)::geometry(polygon, 4326)

3 ऊपर दूसरा पैरामीटर हो सकता है: 1 == POINT, 2 == LINESTRING, 3 == POLYGON

संबंधित मुद्दे