แทรกจุดลงใน PostGIS โดยใช้ Python


คำตอบ:


21

ก่อนอื่นให้ติดตั้งแพ็คเกจpsycopg2ซึ่งเป็นอินเตอร์เฟส Pythonic สำหรับ PostgreSQL

จากนั้นใช้ST_MakePoint:

>>> import psycopg2
>>> conn = psycopg2.connect(dbname=..., port=..., user=...,
                            password=..., host=...)
>>> cur = conn.cursor()
>>> x, y, z, = 32, 34, 0
>>> cur.execute("SELECT ST_SetSRID(ST_MakePoint(%s, %s, %s),4326);", (x, y, z))
>>> cur.fetchall()
[('01010000A0E6100000000000000000404000000000000041400000000000000000',)]

ST_AsText สามารถใช้ในการตรวจสอบค่า:

>>> cur.execute("SELECT ST_AsText(ST_SetSRID(ST_MakePoint(%s, %s, %s),4326));", (x, y, z))
>>> cur.fetchall()
[('POINT Z (32 34 0)',)]

หมายเหตุ

  • โปรดจำไว้ว่า(lat, lon)เป็นไม่ได้(y, x)(x, y)
  • มักจะใช้พารามิเตอร์มากกว่า manipulations สตริงเพื่อป้องกันการฉีด SQL ในตัวอย่างนี้เราทำการอัด(x, y, z)ไว้ที่ท้ายเพื่อให้psycopg2สามารถจัดการกับการเปลี่ยนตัวได้

20

สำหรับรูปทรงเรขาคณิตที่ซับซ้อนมากขึ้นเช่นรูปทรง LineString และรูปหลายเหลี่ยมคุณสามารถจัดการกับรูปทรงเหล่านี้ได้ด้วย Shapely จากนั้นส่งผ่านรูปแบบ psycopg2 เป็น WKB ที่เข้ารหัสด้วย hex โปรดทราบว่าต้องใช้ Shapely 1.3 หรือใหม่กว่าเพื่อจัดการกับการส่งออกรูปทรงเรขาคณิต 3 มิติด้วยwkb_hexคุณสมบัติ

import psycopg2
from shapely.geometry import LineString
from shapely import wkb

conn = psycopg2.connect('...')
curs = conn.cursor()

# Make a Shapely geometry
ls = LineString([(2.2, 4.4, 10.2), (3.3, 5.5, 8.4)])
ls.wkt  # LINESTRING Z (2.2 4.4 10.2, 3.3 5.5 8.4)
ls.wkb_hex  # 0102000080020000009A999999999901409A999999999911406666666666662440666666...

# Send it to PostGIS
curs.execute('CREATE TEMP TABLE my_lines(geom geometry, name text)')
curs.execute(
    'INSERT INTO my_lines(geom, name)'
    'VALUES (ST_SetSRID(%(geom)s::geometry, %(srid)s), %(name)s)',
    {'geom': ls.wkb_hex, 'srid': 4326, 'name': 'First Line'})

conn.commit()  # save data

# Fetch the data from PostGIS, reading hex-encoded WKB into a Shapely geometry
curs.execute('SELECT name, geom FROM my_lines')
for name, geom_wkb in curs:
    geom = wkb.loads(geom_wkb, hex=True)
    print('{0}: {1}'.format(name, geom.wkt))
# First Line: LINESTRING Z (2.2 4.4 10.2, 3.3 5.5 8.4)

หมายเหตุเพิ่มเติมว่าสามารถทำได้คล้ายกันโดยการส่ง WKT ของรูปทรงเรขาคณิต แต่เนื่องจากมันถูกแปลงเป็นข้อความจึงสูญเสียและอาจลดความแม่นยำของอังสตรอม การถ่ายโอนรูปทรงเรขาคณิตเป็น WKB ที่เข้ารหัสด้วยเลขฐานสิบหกนั้นไม่มีความสูญเสียและรักษาความแม่นยำที่แน่นอนของแต่ละพิกัด


ยอดเยี่ยมขอบคุณ! ฉันสงสัยว่ามีความแตกต่างด้านประสิทธิภาพระหว่างสองแนวทางนี้หรือไม่
Adam Matan

มีจุดสร้างข้อได้เปรียบด้านประสิทธิภาพ 10% ST_MakePointซึ่งเหมาะสำหรับรูปทรงจุด อย่างไรก็ตามการสร้างรูปทรงเรขาคณิตที่ซับซ้อนมากขึ้นโดยทั่วไปจะง่ายขึ้นด้วย Shapely
Mike T
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.