0

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 速率限制。

大约一个月前,我遇到了速率限制问题,所以我将大部分请求移到了客户端。我想我错过了什么。

程序流程

  1. 用户输入他们的搜索
  2. 浏览器向谷歌地图 API 发送请求
  3. 谷歌地图 API 返回坐标
  4. 浏览器将这些坐标发送到服务器
  5. 服务器搜索坐标附近的位置
  6. 从找到的位置创建设施和教师列表
  7. 列表返回浏览器显示

我相信最相关的步骤是 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

如果有更多有用的信息,请告诉我。

4

0 回答 0