Reputation: 5092
[edit] - as pointed out to me in the comments I should have noted that I will be using a LAMP based architecture, meaning a MySQL database. Sorry about forgetting to mention this.
I have to create a PHP backend for an iPhone app. The app sends up the users coords and requests the closes 10 local users.
I'm just wondering what is the most efficient way to determine this, I dont want to have to scan the entire table of users, calculate the distance between their geo-coords and the target & order them from lowest to farthest.
Can anyone suggest a more elegant solution instead of scanning all the users? Thanks for your time.
Upvotes: 2
Views: 157
Reputation: 12592
The most efficient way is to use a spatial index or a space-filling-curve. A spatial index reduce the 2d complexity to a 1d complexity thus it help subdivide the surface. You want to look for Nick's spatial index quadtree hilbert curve blog.
Upvotes: 1
Reputation: 543
Due to earth curve, you must do some calculation
SELECT id, 6371 * ACos(Cos(RADIANS(users.Lat)) * Cos(RADIANS(CurrentLat)) * Cos(RADIANS(CurrentLng) - RADIANS(users.Lng)) + Sin(RADIANS(users.Lat)) * Sin(RADIANS(CurrentLat)) ) AS distance
FROM users
ORDER BY distance
LIMIT 10;
distance
is in Km, if you want Miles, replace 6371 by 3959
Upvotes: 0
Reputation: 51143
You could bucket the users by approximate latitude and longitude (e.g. by whole degrees, or tenths of degrees, or whatever scale is appropriate to the distribution you've got) and then work outward from the querying user's bucket.
Not sure the extra complexity is worth it, though, unless the brute force approach is really a performance hog.
Upvotes: 1
Reputation: 21
There are multiple ways of doing this. Here is one way to do it in a sql query.
$sql = "Select id, abs($currlat - latitude) + abs($currlon - longitude) as distance from geo_loc_table order by distance asc";
The issue with this is that it is not overly efficient. I would recommend getting some form of indexing software that can do the work for you. Sphinx might be a good fit.
Upvotes: 0