在给定半径内搜索相应对象位置的酒店(Gem Geocoder)

时间:2013-03-10 16:51:14

标签: database ruby-on-rails-3 postgresql geolocation

我有3个表:ObjectsLocationsHotels

每个对象都有多个位置,每个位置都有几个酒店(默认半径为20英里)。

我的模型(稍微简化一下,专注于主要事物)

object.rb

attr_accessible :name

has_many :locations
has_many :hotels

location.rb

attr_accessible :name, :address, :longitude, :latitude

has_many :objects
has_many :hotels

hotels.rb

attr_accessible :name, :address, :longitude, :latitude

has_many :objects
has_many :locations

我想创建一个搜索表单,用户可以在其中输入对象的名称搜索半径

输出应该是所有酒店的列表,这些酒店位于距离每个位置中心的给定半径(小于或等于20英里)内,对应于对象。

我想使用Geocoder's gem方法near,但我不确定如何构建此类任务的控制器层。

enter image description here

1 个答案:

答案 0 :(得分:3)

您希望数据库中的空间查询引擎执行这些查询,例如MongoDB或PostGIS(在Postgres中)。我认为您正在寻找的答案取决于您使用的是哪一个。我使用PostGIS来做这些事情并且非常喜欢它。

也就是说,Geocoder可以在没有空间查询引擎的情况下在内部使用它,但它不会那么高效。如果你真的很大,它会停下来。如果你看一下来源:https://github.com/alexreisner/geocoder/blob/master/lib/geocoder/stores/active_record.rb

# skeleton for the controller method
obj = Object.find(name)
locations = obj.locations
near_hotels = locations.map do |loc| 
  locations.hotels.near([loc.latitude, loc.longitude])
end

不确定near方法是否正确地采用了半径参数,但你可以通过基本上复制它来轻松编写自己的方法:

# on the hotel class
def nearby(lat, lon, radius)
    options = self.send(:near_scope_options, lat, lon, radius, {})
    select(options[:select]).where(options[:conditions]).
      order(options[:order])
}

我强烈建议您查看PostGIS。

注意,我的示例方法产生了一种关系。您可以通过确定与您的对象匹配的酒店来缩小您的选择范围。