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

4
我有三个表格: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宝石方法near,但我不确定如何构建这种任务的控制器层。

enter image description here


无关的侧记:上面的实体关系图使用了哪些工具来制作? - Craig Ringer
我只用了Keynote。我通常会画出每个结构以更好地理解。 - Ilya Cherevkov
谢谢。我不确定,因为它看起来很陌生。干得好。 - Craig Ringer
1个回答

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。

请注意,我的示例方法生成一个关系。您可以通过将范围限定为与您的对象匹配的酒店来缩小选择范围。


我知道我来晚了,但是我试用了Postgis,发现它非常好。 - Ilya Cherevkov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接