【问题标题】:How to query distances between two coordinates with Eloquent如何使用 Eloquent 查询两个坐标之间的距离
【发布时间】:2017-08-06 21:41:09
【问题描述】:

我知道这已经被问过很多次了。 但是我没有想出根据自己的需要来制作。

我需要从另一个用户那里查询最近的用户。 基本上,我有一个users 表,该表与users_locations 表有一个one to one 关系,该表有一个纬度和一个经度字段。

所以我看到了这个 https://laravel.io/forum/04-23-2014-convert-this-geolocation-query-to-query-builder-for?page=1 这可能是最好的解决方案。

但我的基本查询是:

\App\Model\User::whereNotIn('id', $ids)
               ->where('status', 1)
               ->whereHas('user_location', function($q) use ($lat, $lng, $radius) {
                    /** This is where I'm stuck to write the query **/
             })->select('id', 'firstname')
               ->get();

我不知道在这种情况下如何实施解决方案。

提前感谢您的帮助

编辑 为了更清楚: 我需要获取半径 5 公里内的用户。

【问题讨论】:

  • 嗯,是的,谢谢,但是我已经有了这个功能,我需要用 MySQL 来做这个,因为我有超过 50000 个用户,在这种情况下,我应该得到所有这些用户,然后计算距离,最后让所有用户保持足够近的距离,这可能会占用太多资源..
  • 您应该真正使用空间索引,但是您可以直接在查询中执行此操作,如此答案中的示例:stackoverflow.com/questions/8994718/…
  • 是的,但我不知道如何在我的实际查询中实现它
  • 你检查过这个帖子吗? stackoverflow.com/questions/37876166/…

标签: php mysql laravel geolocation eloquent


【解决方案1】:

感谢 EddyTheDove 和 Ohgodwhy,我找到了解决方案。

原来如此:

\App\Model\User::whereNotIn('id', $ids)
           ->where('status', 1)
           ->whereHas('user_location', function($q) use ($radius, $coordinates) { 
                  $q->isWithinMaxDistance($coordinates, $radius);
         })->select('id', 'firstname')
           ->get();

在我的 UserLocation 模型中,我有这个本地范围

public function scopeIsWithinMaxDistance($query, $coordinates, $radius = 5) {

    $haversine = "(6371 * acos(cos(radians(" . $coordinates['latitude'] . ")) 
                    * cos(radians(`latitude`)) 
                    * cos(radians(`longitude`) 
                    - radians(" . $coordinates['longitude'] . ")) 
                    + sin(radians(" . $coordinates['latitude'] . ")) 
                    * sin(radians(`latitude`))))";

    return $query->select('id', 'users_id', 'cities_id')
                 ->selectRaw("{$haversine} AS distance")
                 ->whereRaw("{$haversine} < ?", [$radius]);
}

Ohgodwhy 的原始答案在这里: Haversine distance calculation between two points in Laravel

编辑

在 MySQL 中使用存储函数执行它的另一种方法:

    DELIMITER $$
DROP FUNCTION IF EXISTS haversine$$

CREATE FUNCTION haversine(
        lat1 FLOAT, lon1 FLOAT,
        lat2 FLOAT, lon2 FLOAT
     ) RETURNS FLOAT
    NO SQL DETERMINISTIC
    COMMENT 'Returns the distance in degrees on the Earth
             between two known points of latitude and longitude'
BEGIN
    RETURN DEGREES(ACOS(
              COS(RADIANS(lat1)) *
              COS(RADIANS(lat2)) *
              COS(RADIANS(lon2) - RADIANS(lon1)) +
              SIN(RADIANS(lat1)) * SIN(RADIANS(lat2))
            ));
END$$

DELIMITER ;

我乘以 111.045 以将结果转换为公里。 (我不确定这个值是否正确,我发现许多其他值离这个值不远,所以如果有人对此有精确度,那可能会很好)

原文:https://www.plumislandmedia.net/mysql/stored-function-haversine-distance-computation/

然后使用雄辩:

\App\Model\User::whereNotIn('id', $ids)
       ->where('status', 1)
       ->whereHas('user_location', function($q) use ($radius, $coordinates) { 
            $q->whereRaw("111.045*haversine(latitude, longitude, '{$coordinates['latitude']}', '{$coordinates['longitude']}') <= " . $radius]);
     })->select('id', 'firstname')
       ->get();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-06
    • 1970-01-01
    相关资源
    最近更新 更多