2012-01-25 3 views
5

Мне нужна помощь в построении sql-запросов для использования в рельсах с помощью activerecord-postgis-adapter. Я занимаюсь чтением, но теперь я немного застрял, любая помощь будет высоко оценена.Ruby Rails Postgis - Поиск всех точек в многоугольнике

У меня есть две модели События и Areas:

события столбец «геометрия», которая имеет тип точки

class Event < ActiveRecord::Base 
    self.rgeo_factory_generator = RGeo::Geos.factory_generator  
end 

t.spatial "geometry", :limit => {:srid=>4326, :type=>"polygon", :geographic=>true} 

Области имеют столбец «геометрии», которая имеет тип многоугольник

class Area < ActiveRecord::Base 
    self.rgeo_factory_generator = RGeo::Geos.factory_generator 
end 

t.spatial "geometry", :limit => {:srid=>4326, :type=>"point", :geographic=>true} 

Я могу создавать и изображать как события и области на карте Google, так и создавать области, нажимая на карту и сохраняя в базе данных.

Я хочу быть в состоянии сделать последующие 2 запросы:

  1. @ area.events - показать все события в области
  2. @ event.areas - показать все области одно событие является в

Я знаю, что я мог бы спросить немного много здесь, но любая помощь была бы оценена

Большое спасибо

+0

Просто чтобы уточнить ... вы ищете SQL-скрипт для этого или рубинового ответа? Сценарий SQL Postgres для этого относительно прямолинейный (используйте ST_contains), и я могу дать вам полный скрипт, если вы предоставите схему для этих двух таблиц и как они связаны. – Twelfth

+0

Привет, Двенадцатый ... Я хотел бы реализовать его в рельсах, и я не уверен, как это сделать, я думаю, мне бы хотелось, чтобы таблица соединений между областями и Events AreasEvents, например, я хочу иметь возможность просматривать события которые находятся в заданной области, и, учитывая событие, видят все области, в которых он находится, но я не вижу, как это реализовать со стандартными ассоциациями рельсов. Мне нужно, чтобы решение было быстрым, так как будет большое количество событий, поэтому я думаю, что мне нужно использовать ST_contains. Я еще не установил никаких связей между таблицами. Доставить эту помощь? – nodrog

ответ

3

Этот ответ будет немного незавершенным для вас. Я слабый с рубинами на рельсах, но я должен быть в состоянии помочь вам через раздел БД.

У вас есть две таблицы: Область, в которой содержится многоугольник и событие, которое содержит событие как одну точку (это немного сложнее, если событие также является областью, и вы пытаетесь выбрать перекрывающуюся область ... если события - это одиночные точки, это работает).

Select * 
from area a inner join event e on 1=1 

Это собирается создать список каждой области присоединились к каждому событию ... если у вас есть 500 мероприятий и 20 района, это будет запрос будет возвращать 10'000 строки. Теперь вы хотите отфильтровать это только для событий, которые находятся в области, к которой они были присоединены. Мы можем использовать st_contains для этого, как st_contains (многоугольник, точки):

where st_contains(a.polygon,e.point) = 't' 

Если вы запустите это, он должен дать вам. , e. для всех событий в пределах области. Теперь это просто вопрос подсчета того, что вы хотите подсчитать.

select a.id, count(1) 
from area a inner join event e on 1=1 
where st_contains(a.polygon,e.point) = 't' 
group by 1 

Это даст вам список всех ваших областей (по идентификатору) и количество событий в нем. Выключение a.id с помощью e.id даст список идентификаторов событий и их номерной области.

К сожалению, я понятия не имею, как выразить эти запросы в Ruby, но концепции БД, которые вам понадобятся здесь ...

Для соображений скорости вы должны изучить индексирование GIStree, которое Postgres имеет ... индексированные полигоны выполняют экспоненциально лучше.

Edit:

PostGIS является вно файл, который поставляется с Postgres, но не существует в стандартной установке ... вам нужно найти этот файл вно. Они будут устанавливать ряд функций ГИС в вашей базе данных, включая ST_Contains. (функции находятся в базе данных, поэтому убедитесь, что вы устанавливаете функции в используемой вами базе данных)

Вторая вещь, которую устанавливают файлы в PostGIS, является базой данных template_postGIS, которая требуется для типов данных геометрии (геометрия как тип данных не будет существовать до тех пор, пока это не будет установлено).

+0

Вы всегда можете перенести этот тип SQL в 'Area.find_by_sql ('select a. * From area a ...')', чтобы получить объекты из ActiveRecord. BTW, извините, разоряю крутой 666 человек, но кто-то должен был это сделать. –

+0

heh thanks ... Мне просто нужно пойти случайным голосом 10 элементов, чтобы вернуть его;) – Twelfth

+0

спасибо, это здорово ... 2 вопроса, 1, я получаю следующую ошибку https: //gist.github. com/1685908 Я думаю, что все мои данные находятся в SRID, так это потому, что моя база данных не имеет функций postgis? 2. Вы упомянули GIStree, что я сделал быстрый поиск и ничего не нашел, не могли бы вы дать мне ссылку. Еще раз большое спасибо, это настоящая помощь. – nodrog

5

Вот быстрый способ сделать это. Они просто возвратят массивы объектов ActiveRecord.

class Area 
    def events 
    Event.joins("INNER JOIN areas ON areas.id=#{id} AND st_contains(areas.geometry, events.geometry)").all 
    end 
end 

class Event 
    def areas 
    Area.joins("INNER JOIN events ON events.id=#{id} AND st_contains(areas.geometry, events.geometry)").all 
    end 
end 

Возможно, вы должны помнить (кешировать результат), чтобы вы не запрашивали базу данных каждый раз, когда вы вызываете метод. Это должно быть простым; Я оставляю это как упражнение для читателя.

Может быть может быть сложным и обернуть это в истинную прокси-ассоциацию Rails (чтобы вы могли получить все полезные свойства Rails). Я не смотрел на это, хотя. В любом случае это не будет стандартная ассоциация Rails, потому что вы не храните идентификаторы.

Двенадцатое право: вы должны создать пространственные индексы для обеих таблиц. Адаптер Activerecord-postgis-адаптер должен сделать это легко в процессе миграции.

change_table :events do |t| 
    t.index :geometry, :spatial => true 
end 

change_table :areas do |t| 
    t.index :geometry, :spatial => true 
end 

Если у вас возникли проблемы с установкой postgis, я недавно написал кучу записей в блоге на этом материале. Отъезд http://www.daniel-azuma.com/blog/archives/category/tech/georails. Я также являюсь автором адаптеров rgeo и activerecord-postgis-адаптеров, поэтому я рад помочь, если вы застряли на вещах.

+2

спасибо, Дэниэл, это действительно хорошо, да, я получил postgis правильно, ошибки, которые я получал, из-за того, что я думал, что мои столбцы должны быть географическими ... ваши драгоценные камни фантастичны, кстати, огромное спасибо за всю работу, которую вы положили в них. – nodrog

+0

Привет, Даниэль, это лучший ответ, который я нашел. Вы столкнулись с тем, чтобы заставить это работать с прокси-серверами? Отличная серия блога btw и спасибо за всю доброту rgeo :) – nomasprime

Смежные вопросы