|
@@ -1,13 +1,51 @@ |
|
|
class Post < ActiveRecord::Base |
|
|
class Post < ActiveRecord::Base |
|
|
belongs_to :feed |
|
|
belongs_to :feed |
|
|
|
|
|
|
|
|
EARTH_RADIUS_M = 6378000 |
|
|
|
|
|
|
|
|
EARTH_RADIUS_METRES = 6378000 |
|
|
|
|
|
|
|
|
def self.near(lat, lng, radius_m) |
|
|
|
|
|
all( |
|
|
|
|
|
:loc => { |
|
|
|
|
|
'$nearSphere' => [ lng, lat ], |
|
|
|
|
|
'$maxDistance' => radius_m / EARTH_RADIUS_M |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
def self.near(lat, lon, radius_metres) |
|
|
|
|
|
# Santize inputs. Is this necessary? |
|
|
|
|
|
lat = lat.to_f |
|
|
|
|
|
lon = lon.to_f |
|
|
|
|
|
radius_metres = radius_metres.to_i |
|
|
|
|
|
|
|
|
|
|
|
# Calculate distance using the Haversine formula |
|
|
|
|
|
self.find_by_sql(<<-ENDQUERY |
|
|
|
|
|
SELECT |
|
|
|
|
|
p.id, |
|
|
|
|
|
p.title, |
|
|
|
|
|
p.summary, |
|
|
|
|
|
p.url, |
|
|
|
|
|
p.lat, |
|
|
|
|
|
p.lon, |
|
|
|
|
|
p.published, |
|
|
|
|
|
f.title as feed_title, |
|
|
|
|
|
( #{EARTH_RADIUS_METRES} |
|
|
|
|
|
* acos( cos( radians('#{lat}') ) |
|
|
|
|
|
* cos( radians( p.lat ) ) |
|
|
|
|
|
* cos( radians( p.lon ) |
|
|
|
|
|
- radians('#{lon}') ) |
|
|
|
|
|
+ sin( radians('#{lat}') ) |
|
|
|
|
|
* sin( radians( p.lat ) ) ) ) |
|
|
|
|
|
As distance |
|
|
|
|
|
|
|
|
|
|
|
FROM posts p |
|
|
|
|
|
INNER JOIN feeds f |
|
|
|
|
|
ON p.feed_id = f.id |
|
|
|
|
|
|
|
|
|
|
|
WHERE |
|
|
|
|
|
( #{EARTH_RADIUS_METRES} |
|
|
|
|
|
* acos( cos( radians('#{lat}') ) |
|
|
|
|
|
* cos( radians( p.lat ) ) |
|
|
|
|
|
* cos( radians( p.lon ) |
|
|
|
|
|
- radians('#{lon}') ) |
|
|
|
|
|
+ sin( radians('#{lat}') ) |
|
|
|
|
|
* sin( radians( p.lat ) ) ) ) |
|
|
|
|
|
< #{radius_metres} |
|
|
|
|
|
|
|
|
|
|
|
ORDER BY distance |
|
|
|
|
|
|
|
|
|
|
|
ENDQUERY |
|
|
|
|
|
) |
|
|
end |
|
|
end |
|
|
end |
|
|
end |