tl;博士:
我以为我将所有谷歌地图 API 调用从这个方法移到了客户端。我错过了一些东西,但我不知道是什么。
tl;博士代码
我正在调用该near
方法,它是geocoder gem的一部分。
Location.facilities.near(@center, 50, order: :distance).select(&:item_is_searchable)
这是 Locations 模型中的地理编码器代码:
geocoded_by :full_address
after_validation :geocode
def full_address
string = ""
string << "#{address}\n" if address
string << "#{extended_address}\n" if extended_address
string << "#{city}, " if city
string << "#{state} " if state
string << zip_code if zip_code
string
end
对于地理编码专家来说,这可能是足够的信息来帮助我。如果没有,这里有更多信息。更多信息。
背景故事
我一直在我的 Rails 应用程序中使用 Geocoder gem 并取得了巨大的成功,但现在我遇到了谷歌地图 API 速率限制。
大约一个月前,我遇到了速率限制问题,所以我将大部分请求移到了客户端。我想我错过了什么。
程序流程
- 用户输入他们的搜索
- 浏览器向谷歌地图 API 发送请求
- 谷歌地图 API 返回坐标
- 浏览器将这些坐标发送到服务器
- 服务器搜索坐标附近的位置
- 从找到的位置创建设施和教师列表
- 列表返回浏览器显示
我相信最相关的步骤是 5,因为这是我调用地理编码器 gem 来做我不理解的事情的地方,所以我将对此归零(并抓住一些步骤 4 和 6 的上下文)
地理编码
#searches_controller.rb
def by_location
@search = Search.find_nearby_instructors_and_facilities params[:coordinates]
render :json => @search
end
#search.rb
class Search
include ActiveModel::Serialization
include ActiveModel::SerializerSupport
attr_accessor :facilities, :instructors, :center
def self.find_nearby_instructors_and_facilities(center)
search = Search.new(center)
search.find_nearest if center
search
end
def initialize(center)
@center = center
@instructors = Set.new
@facilities = []
end
def find_nearest
@locations = Location.facilities.near(@center, 50, order: :distance).select(&:item_is_searchable)
@facilities = @locations.map(&:addressable_item)
@facilities.each do |facility|
active_instructors = facility.instructors.select(&:active?)
@instructors.merge(active_instructors)
end
end
end
下面是一个具体的 SQL 语句的例子,它是由 near 方法为坐标生成的(30.267153, -97.74306079999997)
SELECT locations.*, 3958.755864232 * 2 * ASIN(SQRT(POWER(SIN((30.267153 - locations.latitude) * PI() / 180 / 2), 2) + COS(30.267153 * PI() / 180) * COS(locations.latitude * PI() / 180) * POWER(SIN((-97.7430608 - locations.longitude) * PI() / 180 / 2), 2))) AS distance, CAST(DEGREES(ATAN2( RADIANS(locations.longitude - -97.7430608), RADIANS(locations.latitude - 30.267153))) + 360 AS decimal) % 360 AS bearing FROM "locations" WHERE "locations"."addressable_item_type" = 'Facility' AND (locations.latitude BETWEEN 29.54349408444576 AND 30.99081191555424 AND locations.longitude BETWEEN -98.58093480507472 AND -96.90518679492527 AND 3958.755864232 * 2 * ASIN(SQRT(POWER(SIN((30.267153 - locations.latitude) * PI() / 180 / 2), 2) + COS(30.267153 * PI() / 180) * COS(locations.latitude * PI() / 180) * POWER(SIN((-97.7430608 - locations.longitude) * PI() / 180 / 2), 2))) <= 50) ORDER BY distance
如果有更多有用的信息,请告诉我。