Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Geo Location Radius Search Using PHP and MySQL

I am developing a job portal , in where end users will search for jobs according to their location and proximity radius . Currently the REST APIs are powered by SLIM and MySQL . In Jobs table there are latitude and longitude in every row . I have searched for this in here and stumbled upon Geo Distance search with MySQL .

SELECT latitude, longitude, SQRT(
POW(69.1 * (latitude - $lat), 2) +
POW(69.1 * ($long - $long) * COS(latitude / 57.3), 2)) AS distance
FROM TableName HAVING distance < 25 ORDER BY distance;


Where 

$lat =  User latitude

$long = User longitude

Now I have two other issues .

  1. If Only MySQL query will be sufficient enough or I have to setup Elastic Search with it ?
  2. If there are any library or packages that could help me in this particular problem ?

And If you could suggest anything for the search performance that could be useful .

like image 972
Bikash Dash Avatar asked Apr 28 '15 10:04

Bikash Dash


3 Answers

SELECT latitude, longitude, SQRT(
POW(69.1 * (latitude - $lat), 2) +
POW(69.1 * ($long - longitude) * COS(latitude / 57.3), 2)) AS distance
FROM TableName HAVING distance < 25 ORDER BY distance;

Where

$lat = User latitude

$long = User longitude

like image 167
jision Avatar answered Oct 16 '22 14:10

jision


I have gone with below -

SELECT id,
       name,
       lat,
       lng,
       ROUND((6371 * acos(
                       cos(radians($lat)) * cos(radians(lat)) * cos(radians(lng) - radians($lng)) +
                       sin(radians($lat)) * sin(radians(lat)))), (2)) AS distance
FROM jobs
HAVING distance < 50
ORDER BY distance;

I have done benchmarking with data and found this slightly faster than Mukesh's answer and 2x better than @jision's answer.

like image 24
Bikash Dash Avatar answered Oct 16 '22 14:10

Bikash Dash


You have two option to find job by location 

you required 
1. Search users lat long
2. Job users Posted Lat long (it may be job location or job posted user location from database)
3. Query will be like - 
SELECT zip,Round(((ACOS(SIN('$lat' * PI() / 180) * SIN(latitude * PI() / 180) + COS('$lat' * PI() / 180) * COS(latitude * PI() / 180) * COS(('$lon'-longitude) * PI() / 180)) * 180 / PI()) * 60 * 1.1515),(2)) AS distance FROM Jobs Having distance <= 30 

Else 
1. You have to call all jobs data in single query.

     foreach($joblist as $job){
        $milesresult = $this->calculateDistance($user_lat,$user_lon,$job['latitude'],$jobr['longitude']);
        $miles = explode("-",$vendor['miles']);
         $vendor_max_miles = $miles[1];
        }

2. PHP function for lat long

      function calculateDistance($lat1, $lon1, $lat2, $lon2, $unit) {

            $theta = $lon1 - $lon2;

            $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));

            $dist = acos($dist);

             $dist = rad2deg($dist);

              $miles = $dist * 60 * 1.1515;
            $unit = strtoupper($unit);

            if ($unit == "K") {
              return ($miles * 1.609344);
            } else if ($unit == "N") {
                return ($miles * 0.8684);
              } else {
                  return $miles;
                }
        }
like image 25
Mukesh S Avatar answered Oct 16 '22 12:10

Mukesh S