3

I have a location object with latitude and longitude attributes and I want to query the database for objects within a specific distance from a current latitude / longitude location.

I read about the 'geocoder' gem which seems to be able to do what I'm looking for, but in order to add the obj.near functionality I need to add geocoding to the object. I don't need geocoding or reverse geocoding at all, just distance queries by coordinates.

can I add the .near functionality to an object with 'geocoder' without adding any geocoding functionality ? is there another or a better way to do what I want ?

Gal Ben-Haim
  • 17,433
  • 22
  • 78
  • 131
  • In order to make such nearest-neightbour queries efficiently you need to have your database support them (by using indexed queries) or prepare your data in some way to make DB able to index it. So please tell us first which DB you use. Also to choose the best approach it would be good to know what precision your project require. – cryo28 Jul 30 '13 at 12:17

2 Answers2

1

Why don't you look at the geocoder source? It's on github. I think the class you are looking for is stores/active_record.rb

Obviously you won't be getting the extensibility or other benefits of using a library but this will give you the code you need.

Edit: This will give you a UDF in mysql that will calculate the distance

DROP FUNCTION IF EXISTS calculateDistance; 
delimiter |
CREATE FUNCTION calculateDistance (originLatitude FLOAT, originLongitude FLOAT, targetLatitude FLOAT, targetLongitude FLOAT) 
returns FLOAT
deterministic
BEGIN
DECLARE radianConversion FLOAT;
DECLARE interim FLOAT;
DECLARE earthRadius FLOAT;

SET radianConversion = 180 / pi() ;/*57.2957795130823;*/
SET interim = SIN(originLatitude/radianConversion) * SIN(targetLatitude/radianConversion) + COS(originLatitude/radianConversion) * COS(targetLatitude/radianConversion) * COS(targetLongitude/radianConversion - originLongitude/radianConversion);

IF interim > 1 THEN
    SET interim = 1;
ELSEIF interim < -1 THEN
    SET interim = -1;
END IF;
SET earthRadius = 6371.0072;
RETURN earthRadius * ACOS(interim);
END|
delimiter ;

select calculateDistance(43.6667,-79.4167,45.5000,-73.5833);

Then you just need to pass the correct values from a method on your class to get this to fire off. Obviously this won't work on Sqlite

toxaq
  • 6,745
  • 3
  • 46
  • 56
0

There is a RailsCast about Geocoder, from what I've seen you need to add latitude and longitude to your model and gecoder will work.

Aldo 'xoen' Giambelluca
  • 12,075
  • 7
  • 33
  • 39