Вызов функций PostGIS в Ruby - PullRequest
0 голосов
/ 11 июня 2019

Мне нужно выполнить функцию PostGIS st_intersection в предложении SQL SELECT в Ruby. На данный момент я делаю это как необработанный запрос SQL:

sql_query = "SELECT id, ST_ASEWKT(ST_INTERSECTION(geometry, ?)) FROM trips WHERE status='active';"
intersections = Trip.execute_sql(sql_query, self[:geometry].to_s)

Недостатком этого способа является то, что я получаю результат в виде текста, и мне нужно проанализировать объекты из строк. Намного приятнее было бы использовать интерфейс ActiveRecord для выполнения запросов. Однако я не смог найти никакого решения для запуска функций PostGIS (например, st_intersection) в ActiveRecord.

Более ранняя версия README адаптера activerecord-postgis-адаптера показала хороший пример использования gem squeel:

my_polygon = get_my_polygon    # Obtain the polygon as an RGeo geometry
MySpatialTable.where{st_intersects(lonlat, my_polygon)}.first

Поскольку это больше не является частью текущего README, мне интересно, не рекомендуется ли это или есть какие-нибудь лучшие альтернативы.

1 Ответ

2 голосов
/ 11 июня 2019

Здесь нужно решить две проблемы.

Первый использует функцию SQL в предложении .select. Обычно это довольно просто - вы просто используете AS, чтобы дать результату имя. Вот пример из ActiveRecord Rails Guide :

Order.select("date(created_at) as ordered_date, sum(price) as total_price").group("date(created_at)")

Полученные объекты Order будут иметь атрибуты ordered_date и total_price.

Это подводит нас ко второй проблеме, которая заключается в том, что Rails не дает нам простого способа параметризации select (то есть использования заполнителя ?), поэтому (насколько я могу судить) вы ' Вам нужно будет сделать это самостоятельно с помощью sanitize_sql_array:

sql_for_select_intersection = sanitize_sql_array([
  "ST_ASEWKT(ST_INTERSECTION(geometry, ?)) AS intersection",
  geometry,
])

Это вернет очищенный фрагмент SQL, например ST_ASEWKT(ST_INTERSECTION(geometry, '...')), который затем можно использовать для указания поля в select:

Trip.where(status: "active").select(:id, sql_for_select_intersection))

Результирующий запрос вернет объекты Trip с атрибутами id и intersection.

...