使用Ruby Geocoder检索附近的用户并返回距离

时间:2015-05-27 13:51:25

标签: sql ruby-on-rails ruby rails-geocoder

是否可以使用Geocoder检索特定半径范围内的附近用户,并使其返回距离计算结果而不必重复显示?

例如,假设我们使用它(在Rails应用程序中):

User.near(@me, 10, units: :km)

它将返回ActiveRecord::Relation,其中包含距用户@me 10公里范围内的所有用户。

如果我现在想要显示包含所有返回用户的列表以及它们与@me的距离,我是否需要使用distance_to逐个重新计算距离,或者是否有办法使Geocoder在添加的模型属性中返回计算的距离(例如)?

2 个答案:

答案 0 :(得分:1)

  

当您运行位置感知查询时,返回的对象有两个   添加的属性:

     
User.near(@me, 10, units: :km).each do |user|
  puts "#{user.name} is #{user.distance} clicks to the #{user.bearing}"
end

答案 1 :(得分:1)

我使用这个嵌入式Ruby版本的逻辑,这在逻辑上类似于上面@maxcal给出的答案。我包括它,因为下面的跟踪与此代码有关。

<% for location in @location.nearbys(20) %>
  <li> <span class="badge"><%= location.distance.round(2) %> miles</span> from here you'll find <strong>
  <%= link_to location.name, location %> </strong> at <%= location.full_address %>.</li>
<% end %> 

但是,我认为答案是Geocoder正在为一组符合记录创建一个临时数据存储。 .distance 是关键变量。

如果我查看跟踪,它会显示初始数据库命中,但循环中的每个项目都没有后续命中。人们可以查看Geocoder代码并确认,但跟踪似乎是确凿的。

  [1m[36m (0.0ms)[0m  [1mSELECT COUNT(*) FROM "reviews" WHERE "reviews"."user_id" = $1[0m  [["user_id", 8]]
  Rendered shared/_user_posted_badge.html.erb (15.6ms)
// Comment Geocoding starts here
  Rendered locations/_map_show.html.erb (0.0ms)
  [1m[35mLocation Load (0.0ms)[0m  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, MOD(CAST((ATAN2( ((locations.longitude - -97.7430608) / 57.2957795), ((locations.latitude - 30.267153) / 57.2957795)) * 57.2957795) + 360 AS decimal), 360) AS bearing FROM "locations" WHERE (locations.latitude BETWEEN 29.977689433778306 AND 30.556616566221695 AND locations.longitude BETWEEN -98.07821040202988 AND -97.40791119797011 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)))) BETWEEN 0.0 AND 20 AND locations.id != 65)  ORDER BY distance ASC
// Geocoding section complete
  [1m[36mPhotograph Exists (0.0ms)[0m  [1mSELECT  1 AS one FROM "photographs" WHERE "photographs"."location_id" = $1 LIMIT 1[0m  [["location_id", 65]]
  [1m[35mPhotograph Load (0.0ms)[0m  SELECT "photographs".* FROM "photographs" WHERE "photographs"."location_id" = $1  ORDER BY "photographs"."created_at" DESC  [["location_id", 65]]