Как переписать этот запрос RGeo с помощью AR/Arel?

У меня есть следующая область, в которой я работал с необработанным SQL:

class DeliveryZone < ActiveRecord::Base
  def self.contains(addressable)
    point = addressable.lonlat
    where(<<-SQL.squish)
    ST_Intersects("delivery_zones"."shape", ST_GeomFromText('#{point}'))
    SQL
  end
end

Где delivery_zones.shape — это geography(Polygon,4326), а point — это geography(Point,4326) для типов PostgreSQL.

В консоли rails это #<RGeo::Geos::CAPIPolygonImpl> и #<RGeo::Geos::CAPIPointImpl> соответственно.

Я хочу написать что-то более похожее на

where(arel_table[:shape].st_intersects(point))

... но это дает мне эту ошибку:

Ошибка выполнения: не поддерживается: RGeo::Geos::CAPIPointImpl

Мне бы очень хотелось помочь получить необработанный SQL из моей модели! Кроме того, я новичок в RGeo/PostGIS, поэтому, пожалуйста, не думайте, что я знаю, что делаю. :D


person neezer    schedule 29.11.2015    source источник


Ответы (2)


Пожалуйста, не думайте, что я знаю, о чем именно вы говорите, но я использую гем squeel для написания запросов в стиле rails с rgeo и activerecord-postgis-adapter. Даниэль Азума написал несколько отличных блогов на эту тему, которые помогли мне начать пару лет назад. Вот первая из серии: http://daniel-azuma.com/articles/georails/part-1

Насколько я понимаю, это может немного помочь:

class DeliveryZone < ActiveRecord::Base
  def self.contains(addressable)
    where{st_intersects(:shape, addressable)}
  end
end

Обратите внимание, что это работает, только если вы установили squeel gem. И если вы хотите уточнить это, возможно, вам следует использовать это вместо этого:

class DeliveryZone < ActiveRecord::Base
  def self.contains(addressable)
    where{st_contains(:shape, addressable)}
  end
end

Рад, что кто-то еще использует рельсы для ГИС. Удачи

person boulder_ruby    schedule 07.01.2016

Вы можете сделать это без arel или squeel:

where("delivery_zones.shape && ?", addressable.lonlat.to_geometry)

В общем, должно работать:

where("point_column && ?", rgeo_object.to_geometry)

Вот пример с моделью City со столбцом точек с именем coordinates, который является st_point. Я хочу запросить все города в ограничивающей рамке, определяемой двумя угловыми точками (ЮВ и СЗ):

box = RGeo::Cartesian::BoundingBox.create_from_points(
        City.first.coordinates, City.last.coordinates)

City.where("coordinates && ?", box.to_geometry)

В чем дело?

> box.to_geometry.to_s
=> "POLYGON ((-90.0674 29.9627, -79.09529 29.9627, -79.09529 36.18375, -90.0674 36.18375, -90.0674 29.9627))"

> City.where("coordinates && ?", box.to_geometry).to_sql
=> "SELECT \"cities\".* FROM \"cities\" WHERE (coordinates && '0020000003000010e60000000100000005c05684504816f007403df67381d7dbf5c053c6193b3a68b2403df67381d7dbf5c053c6193b3a68b2404217851eb851ecc05684504816f007404217851eb851ecc05684504816f007403df67381d7dbf5')"
person tee    schedule 16.03.2016
comment
Если я правильно понимаю, кажется, что это вернет все точки внутри многоугольника, верно? Не только те, которые пересекают линию, создающую ее периметр? Уже неделю ищу точно такую ​​же! - person SethS; 27.01.2017
comment
Да, он вернет все записи с точками (в данном случае столбец coordinates) внутри ограничивающей рамки. - person tee; 28.01.2017