Создать таблицу Redshift с новым типом геометрии через psycopg2 - PullRequest
1 голос
/ 01 февраля 2020

После того, как Redshift объявил о поддержке типов геометрии и пространственных функций, я хотел бы создать таблицу с полигонами для всех стран. Я не могу сделать INSERT и был бы признателен за помощь.

Вот что я попробовал:

Я скачал geo json и распаковал (https://datahub.io/core/geo-countries)

Затем для успешного создания таблицы использовался следующий фрагмент python (я использовал тип GEOMETRY, не уверен, что смогу оптимизировать и использовать подтип POLYGON):

import psycopg2

conn = psycopg2.connect(...connection params)
cur = conn.cursor()
cur.execute("CREATE TABLE engagement.geospatial_countries (id INTEGER PRIMARY KEY, name VARCHAR(25), code VARCHAR(10), polygon GEOMETRY);")

Следующий скрипт успешно читает geo json, каждая запись в "странах", содержащая функцию Polygon Geo Json:

f = open("geospatial-data/countries.geojson", "r")
countries_file_contents = f.read()
countries_geojson = json.loads(countries_file_contents)
countries = countries_geojson["features"]

Для тех, кто не знаком с Geo Json, это просто набор JSON данных, которые описывают геопространственные формы. Вот выдержка из данных:

{ "type": "FeatureCollection", "features": [{ "type": "Feature", "properties": { "ADMIN": "Aruba", "ISO_A3": "ABW" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -69.996937628999916, 12.577582098000036 ], [ -69.936390753999945, 12.531724351000051 ], [ -69.924672003999945, 12.519232489000046 ], [ -69.915760870999918, 12.497015692000076 ], [ -69.880197719999842, 12.453558661000045 ], [ -69.876820441999939, 12.427394924000097 ], [ -69.888091600999928, 12.417669989000046 ], [ -69.908802863999938, 12.417792059000107 ], [ -69.930531378999888, 12.425970770000035 ], [ -69.945139126999919, 12.44037506700009 ], [ -69.924672003999945, 12.44037506700009 ], [ -69.924672003999945, 12.447211005000014 ], [ -69.958566860999923, 12.463202216000099 ], [ -70.027658657999922, 12.522935289000088 ], [ -70.048085089999887, 12.531154690000079 ], [ -70.058094855999883, 12.537176825000088 ], [ -70.062408006999874, 12.546820380000057 ], [ -70.060373501999948, 12.556952216000113 ], [ -70.051096157999893, 12.574042059000064 ], [ -70.048736131999931, 12.583726304000024 ], [ -70.052642381999931, 12.600002346000053 ], [ -70.059641079999921, 12.614243882000054 ], [ -70.061105923999975, 12.625392971000068 ], [ -70.048736131999931, 12.632147528000104 ], [ -70.00715084499987, 12.5855166690001 ], [ -69.996937628999916, 12.577582098000036 ] ] ] } }, ... more countries }]}

Прежде чем я вставлю все страны, я сначала просто хочу попытаться создать его для отдельной страны:

country = countries[0]
geometry_to_insert = (
    country["properties"]["ADMIN"],
    country["properties"]["ISO_A3"],
    Json.dumps(country["geometry"]) # Have also tried psycopg2.extras.Json(country["geometry"]), as well as just using the dict
)

Следующая ошибка:

cur.execute(
  "INSERT INTO engagement.geospatial_countries (name, code, polygon) VALUES %s",
  geometry_to_insert
)

Со следующей ошибкой: TypeError: не все аргументы преобразованы во время форматирования строки

Я также пытался

cur.execute(
  "INSERT INTO engagement.geospatial_countries (name, code, polygon) VALUES (%s, %s, %s)",
  geometry_to_insert
)

Но это дает следующую ошибку: psycopg2.errors.InternalError_: исключение ввода-вывода компаса: обнаружены неправильные шестнадцатеричные символы

Как вставить многоугольник в красное смещение, используя новые типы геометрии?

Ответы [ 3 ]

1 голос
/ 02 февраля 2020

Геометрия postgres / redshift не является Geo JSON, вам нужно использовать JSON тип столбца:

...
cur.execute("CREATE TABLE engagement.geospatial_countries (id INTEGER PRIMARY KEY, name VARCHAR(25), code VARCHAR(10), polygon JSON)")
country = countries[0]
geometry_to_insert = (
    country["properties"]["ADMIN"],
    country["properties"]["ISO_A3"],
    Json.dumps(country["geometry"])
)
cur.execute(
      "INSERT INTO engagement.geospatial_countries (name, code, polygon) VALUES (%s, %s, %s)", geometry_to_insert
)
1 голос
/ 03 февраля 2020

Здесь я приведу шаги, которые работали для его вставки в БД.

Во-первых, небольшая поправка при создании таблицы для геометрий, использующая IDENTITY для автоматического увеличения ID:

conn = psycopg2.connect(...connection params)
cur = conn.cursor()
cur.execute("CREATE TABLE engagement.geospatial_countries (id INTEGER IDENTITY(0,1) PRIMARY KEY, name VARCHAR(25), code VARCHAR(10), polygon GEOMETRY);")

На геометрию. Чтобы вставить значение, используйте значение WKT:

import geojson
from shapely.geometry import shape
...
# exact same steps as in question to read file, then
country = countries[0]
geom = shape(country["geometry"])
geometry_to_insert = (
    country["properties"]["ADMIN"],
    country["properties"]["ISO_A3"],
    geom.wkt
)

Затем введите следующую команду для вставки значения:

cur.execute(
  "INSERT INTO engagement.geospatial_countries (name, code, polygon) VALUES (%s, %s, ST_GeomFromText(%s))",
  geometry_to_insert
)

Ответы от @Maurice Meyer и @piro привели меня к этому ответить.

1 голос
/ 01 февраля 2020

Это должно работать:

cur.execute(
  "INSERT INTO engagement.geospatial_countries (name, code, polygon) VALUES (%s, %s, %s)",
  geometry_to_insert
)

, пожалуйста, прочитайте в документации , как передать параметры в запрос и, если вы хотите вставить несколько объектов одновременно, execute_values() функция .

...