How to efficiently find the closest locations nearby a given location

Coalialry

New Member
I'm sorry for the vague question title... its going to take a bit of explaining...Basically I'm making a script where a load of business are loaded into a mySQL database with a latitude and longitude. Then I am supplying that script with a latitude an longitude (of the end user) and the script has to calculate the distance from the supplied lat/long to EACH of the entries it gets from the database and order them in order of nearest to furthest.I only realistically need about 10 or 20 "nearest" results, but I can't think of anyway to do this other than to get all the results from the database and run the function on each of them and then array sort.This is what I have already:\[code\]<?phpfunction getDistance($point1, $point2){ $radius = 3958; // Earth's radius (miles) $pi = 3.1415926; $deg_per_rad = 57.29578; // Number of degrees/radian (for conversion) $distance = ($radius * $pi * sqrt( ($point1['lat'] - $point2['lat']) * ($point1['lat'] - $point2['lat']) + cos($point1['lat'] / $deg_per_rad) // Convert these to * cos($point2['lat'] / $deg_per_rad) // radians for cos() * ($point1['long'] - $point2['long']) * ($point1['long'] - $point2['long']) ) / 180); $distance = round($distance,1); return $distance; // Returned using the units used for $radius.}include("../includes/application_top.php");$lat = (is_numeric($_GET['lat'])) ? $_GET['lat'] : 0;$long = (is_numeric($_GET['long'])) ? $_GET['long'] : 0;$startPoint = array("lat"=>$lat,"long"=>$long);$sql = "SELECT * FROM mellow_listings WHERE active=1"; $result = mysql_query($sql);while($row = mysql_fetch_array($result)){ $thedistance = getDistance($startPoint,array("lat"=>$row['lat'],"long"=>$row['long'])); $data[] = array('id' => $row['id'], 'name' => $row['name'], 'description' => $row['description'], 'lat' => $row['lat'], 'long' => $row['long'], 'address1' => $row['address1'], 'address2' => $row['address2'], 'county' => $row['county'], 'postcode' => strtoupper($row['postcode']), 'phone' => $row['phone'], 'email' => $row['email'], 'web' => $row['web'], 'distance' => $thedistance);}// integrate google local search$url = "http://ajax.googleapis.com/ajax/services/search/local?";$url .= "q=Off+licence"; // query$url .= "&v=1.0"; // version number$url .= "&rsz=8"; // number of results$url .= "&key=ABQIAAAAtG" ."Pcon1WB3b0oiqER" ."FZ-TRQgsWYVg721Z" ."IDPMPlc4-CwM9Xt" ."FBSTZxHDVqCffQ2" ."W6Lr4bm1_zXeYoQ"; // api key$url .= "&sll=".$lat.",".$long;// sendRequest// note how referer is set manually$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_REFERER, /* url */);$body = curl_exec($ch);curl_close($ch);// now, process the JSON string$json = json_decode($body, true);foreach($json['responseData']['results'] as $array){ $thedistance = getDistance($startPoint,array("lat"=>$array['lat'],"long"=>$array['lng'])); $data[] = array('id' => '999', 'name' => $array['title'], 'description' => '', 'lat' => $array['lat'], 'long' => $array['lng'], 'address1' => $array['streetAddress'], 'address2' => $array['city'], 'county' => $array['region'], 'postcode' => '', 'phone' => $array['phoneNumbers'][0], 'email' => '', 'web' => $array['url'], 'distance' => $thedistance);}// sort the arrayforeach ($data as $key => $row) {$id[$key] = $row['id'];$distance[$key] = $row['distance'];}array_multisort($distance, SORT_ASC, $data); header("Content-type: text/xml"); echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";echo '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'."\n";echo '<plist version="1.0">'."\n";echo '<array>'."\n";for($i = 0; isset($distance[$i]); $i++){ //echo $data[$i]['id']." -> ".$distance[$i]."<br />"; echo '<dict>'."\n"; foreach($data[$i] as $key => $val){ echo '<key><![CDATA['.$key.']]></key>'."\n"; echo '<string><![CDATA['.htmlspecialchars_decode($val, ENT_QUOTES).']]></string>'."\n"; } echo '</dict>'."\n";}echo '</array>'."\n";echo '</plist>'."\n";?>\[/code\]Now, this runs fast enough with only 2 or 3 businesses in the database, but I'm currently loading 5k businesses into the database and I'm worried that its going to be incredibly slow running this for EACH entry? What do you think?Its not the kind of data I could cache either, as the likelihood of two users having the same lat/long is liable to be incredibly rare, and therefore wouldn't help.What can I do about this?Thanks for any help and any suggestions. They're all much appreciated.
 
Back
Top