简体   繁体   English

使用 PHP 和 MySQL 进行地理位置半径搜索

[英]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 .目前 REST API 由 SLIM 和 MySQL 提供支持。 In Jobs table there are latitude and longitude in every row .在 Jobs 表中,每一行都有纬度和经度。 I have searched for this in here and stumbled upon Geo Distance search with MySQL .我在这里搜索过这个,偶然发现了使用 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 ?如果只有 MySQL 查询就足够了,或者我必须用它设置弹性搜索?
  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 .如果您可以为搜索性能提出任何有用的建议。

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 $lat = 用户纬度

$long = User longitude $long = 用户经度

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;
                }
        }

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.我已经对数据进行了基准测试,发现这比 Mukesh 的答案略快,比 @jision 的答案好 2 倍。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM