2012-01-25 14 views
5

Chciałbym pomóc w konstruowaniu kwerend sql do wykorzystania w szynach z activerecord-postgis-adapter. Dużo czytałem, ale teraz trochę utknąłem, każda pomoc będzie bardzo cenna.Ruby Rails Postgis - Znajdowanie wszystkich punktów w wielokącie

mam dwa modele Wydarzenia i obszarach:

wydarzenia mają „geometrii” kolumnę, która jest typu punkt

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

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

Obszary mieć „geometrii” kolumnę, która jest typu Polygon

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

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

Potrafię tworzyć i drukować zarówno zdarzenia, jak i obszary na mapie google i tworzyć obszary, klikając mapę i zapisując w bazie danych.

Chcę móc wykonać kroki 2 zapytania:

  1. @ area.events - Pokaż wszystkie wydarzenia w obszarze
  2. @ event.areas - Pokaż wszystkie obszary pojedynczego zdarzenia jest w

wiem, że może być pytanie trochę dużo tutaj, ale każda pomoc będzie mile widziane

Dziękujemy

+0

Aby wyjaśnić ... szukasz skryptu SQL do zrobienia tego lub odpowiedzi rubinowej? Skrypt SQL Postgre to stosunkowo proste (użyj ST_contains) i mogę dać ci pełny skrypt, jeśli podasz schemat dla tych dwóch tabel i jak się one odnoszą. – Twelfth

+0

Witam Dwunaste ... Chciałbym zaimplementować go w szynach, i nie jestem pewien, jak to zrobić, Chyba chciałabym połączyć tabelę między obszarami i Event AreasEvents na przykład, ponieważ chcę móc zobaczyć wydarzenia które znajdują się w danym obszarze, a biorąc pod uwagę wydarzenie, zobacz wszystkie obszary, w których się znajduje, ale nie widzę, jak mógłbym to zaimplementować ze standardowymi skojarzeniami szyn. Potrzebuję szybkiego rozwiązania, ponieważ będzie duża liczba zdarzeń, więc myślę, że muszę użyć ST_contains. Nie zaimplementowałem jeszcze żadnych relacji między tabelami. Dawki tej pomocy? – nodrog

Odpowiedz

3

Ta odpowiedź będzie dla ciebie trochę pracy. Jestem słaba z rubinem na szynach, ale powinienem móc ci pomóc przez sekcję DB.

Masz dwie tabele, obszar, w którym znajduje się wielokąt i wydarzenie, które utrzymuje wydarzenie jako pojedynczy punkt (jest to nieco bardziej skomplikowane, jeśli wydarzenie jest również obszarem i próbujesz wybrać obszar nakładających się obszarów ... jeśli wydarzenia są pojedynczymi punktami, to działa).

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

ten zamierza stworzyć listę każdej dziedzinie dołączył do każdego zdarzenia ... jeśli masz 500 wydarzeń i 20 okolicznych ta kwerenda zwróci 10'000 linie. Teraz chcesz odfiltrować to tak, aby wyświetlać tylko wydarzenia znajdujące się w obszarze, do którego zostały przyłączone. Możemy użyć st_contains do tego jako st_contains (wielokąt, punkt):

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

Jeśli to zrobisz, powinno ci dać. , e. dla wszystkich wydarzeń w okolicy. Teraz liczy się tylko to, co chcesz policzyć.

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 

Zostanie wyświetlona lista wszystkich obszarów (według identyfikatora) i liczba zdarzeń w nim zawartych. Wyłączenie a.id przez e.id da listę identyfikatorów zdarzeń i obszarów numerów, w których się znajdują.

Niestety, nie mam pojęcia, jak wyrazić te zapytania w Ruby, ale potrzebne są pojęcia DB, które będą potrzebne są tutaj ...

Dla rozważań dotyczących prędkości należy sprawdzić indeksowanie GIStree, w którym Postgres ma ... indeksowane wielokąty wykonują wykładniczo lepiej.

Edit:

PostGIS jest plikiem contrib, że pochodzi z PostgreSQL, ale nie istnieje w standardowej instalacji ... trzeba znaleźć tego pliku contrib. Zainstalują one szereg funkcji GIS w bazie danych, w tym ST_Contains. (funkcje znajdują się w bazie danych, więc upewnij się, że instalujesz funkcje w używanym DB)

Drugą rzeczą, którą instalują pliki postGIS, jest baza danych template_postGIS, która jest wymagana dla typów danych geometrii (geom jako typ danych nie będzie istnieć, dopóki nie zostanie zainstalowany).

+0

Zawsze można zawijać ten typ SQL w 'Area.find_by_sql ('select a. * From area a ...')', aby uzyskać obiekty poza ActiveRecord. BTW, przykro mi zepsuć chłodne 666 przedstawicieli, ale ktoś musiał to zrobić. –

+0

heh dzięki ... Będę musiał losowo zestrzelić 10 rzeczy, aby go odzyskać;) – Twelfth

+0

dziękuję, że to jest wspaniałe ... 2 pytania, 1, otrzymuję następujący błąd https: //gist.github. com/1685908 Uważam, że wszystkie moje dane są w SRID, czy to dlatego, że moja dawka bazy danych nie ma funkcji postgis? 2. Wspomniałeś GIStree, że zrobiłem szybkie wyszukiwanie i nic nie znalazłem, możesz podać mi link. Wielkie dzięki znowu to jest prawdziwa pomoc. – nodrog

5

Oto szybki sposób na zrobienie tego. Po prostu zwrócą tablice obiektów 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 

Prawdopodobnie powinieneś zapamiętać (buforować wynik), aby nie pytać o bazę danych za każdym razem, gdy wywołasz tę metodę. To powinno być proste; Zostawiam to jako ćwiczenie dla czytelnika.

To może być może uzyskać wyrafinowane i zawrzeć to w prawdziwym proxy stowarzyszenia Rails (dzięki czemu można uzyskać wszystkie gadżety stowarzyszenia Rails). Nie analizowałem tego. W żadnym wypadku nie byłoby to standardowe stowarzyszenie Rails, ponieważ nie przechowujesz identyfikatorów.

Dwunasta ma rację: należy utworzyć przestrzenne indeksy dla obu tabel. Adapter Activerecord-Postgis powinien ułatwić te czynności podczas migracji.

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

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

Jeśli masz problemy z instalacją postgis, ostatnio napisałam kilka wpisów na blogu. Sprawdź http://www.daniel-azuma.com/blog/archives/category/tech/georails. Jestem również autorem samych rgeo i activerecord-postgis-adapter, więc z chęcią pomogę, jeśli utkniesz w tym temacie.

+2

dzięki Daniel, to jest naprawdę dobre, tak, mam poprawnie zainstalowane błędy postgis, które dostałem gdzie ze względu na myślenie, że moje kolumny powinny być geograficzne ... twoje klejnoty są fantastyczne przy okazji, wielkie dzięki za całą pracę którą wykonałeś w nich. – nodrog

+0

Cześć Daniel, to najlepsza odpowiedź, jaką znalazłem. Czy zdarzyło Ci się, że chciałeś, aby to działało z serwerami proxy stowarzyszenia? Świetna seria blogów i dzięki za całą dobroć rgeo :) – nomasprime