如何获取附近的用户和距离?

Posted

技术标签:

【中文标题】如何获取附近的用户和距离?【英文标题】:How to get nearby users and distances? 【发布时间】:2018-09-05 12:17:47 【问题描述】:

首先我想向您展示当前的数据库结构。有两个表:

用户

身份证 姓名 location_id

位置

身份证 城市 纬度 lng

现在我想实现一个获取附近用户及其距离的 API。喜欢附近的用户:

name:user1,distance:5km,(name:user2,distance:7 km)

【问题讨论】:

您可以在数据库中实现存储过程来计算距离,然后选择有条件和排序的记录,比如最近的不超过5km。如果你使用 PostgreSQL - 看这个postgis.net 同意@ineersa,你当然可以在 Transact SQL 中做到这一点。现在真正的问题是您拥有的用户数量和频率,因为这可能需要一些时间来计算。根据具体情况,您可能希望实现一个表来存储此信息。 【参考方案1】:

你可以这样试试

用户模型

public function location()
    return $this->belongsTo('App\Location');

在 Location 模型中创建一个函数名称rsine,然后创建一个以scopeIsWithinMaxDistance 命名的本地作用域,如下所示

位置模型

/**
 * Scope for adding distance filter
 */
public function scopeIsWithinMaxDistance($query, $rsine, $radius = 5)

    return $query->selectRaw("*, $rsine AS distance")
                 ->whereRaw("$rsine < ?", [$radius])
                 ->orderBy('distance');


/**
 * Sql command for finding distance between 2 coordinates
 */
public static function rsine($coordinates)

    return '(6371 * acos(cos(radians(' . $coordinates['latitude'] . ')) 
    * cos(radians(`lat`)) 
    * cos(radians(`lng`) 
    - radians(' . $coordinates['longitude'] . ')) 
    + sin(radians(' . $coordinates['latitude'] . ')) 
    * sin(radians(`lat`))))';


public static function convertKMToMiles($dist)

    return $dist * 1.609344;

现在在控制器中调用它

$coordinates = ['latitude' => '28.392200', 'longitude' => '77.320801'];

$rsine = Location::rsine($coordinates);

$radius = Location::convertKMToMiles(5); //convert KM to miles

$users = User::with(['location' => function ($query) use ($rsine) 
               $query->selectRaw("*, $rsine AS distance");
         ])->whereHas('location', function ($query) use ($radius, $rsine) 
               $query->isWithinMaxDistance($rsine, $radius);
         )->get();

现在你可以这样打印了

foreach($users as $user)
   $user->name;
   $user->location->city;
   $user->location->distance;

【讨论】:

SQLSTATE[42000]:语法错误或访问冲突:1064 您的 SQL 语法有错误;检查与您的 mysql 服务器版本相对应的手册以获取正确的语法以使用.......... 您需要将radians(latitude) 更改为radians(lat)radians(longitude) 更改为radians(lng) @987654 方法中的@9876543在您的位置表中有latlng 字段。更新答案检查一下 我也试过下面的代码: public static function rsine($coordinates) return Location::select('id', DB::raw(' 6371 * acos( cos( radians(' . $坐标['纬度'] . ') ) * cos( 弧度( lat ) ) * cos( 弧度( lng ) - 弧度(' . $coordinates['longitude'] . ') ) + sin( 弧度(' . $coordinates ['纬度'] . ') ) * sin( 弧度( lat ) ) ) 作为距离'))->get(); SQLSTATE[HY093]:无效参数号:混合命名和位置参数(SQL:选择*,*,[\“距离\”:10723.218919804329,\“距离\”:1285.513973341391 ,\"distance\":1284.2498526350137] AS 距离locations 其中users.location_id = locations.id 和 [\"distance\":10723.218919804329,\"distance\ ":1285.513973341391,\"distance\":1284.2498526350137] > 8.04672 order by distanceasc)", 使用与我的答案相同的方法不要尝试将return Location::select 放入rsine 方法中,并将` 放入弧度(lat)然后尝试。这是一个工作代码,我在项目中使用过它

以上是关于如何获取附近的用户和距离?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 android 中找到附近的应用程序用户?

使用经度和纬度查找给定距离内的所有附近客户

纬度和距离之间的关系

我想通过附近的过滤器和距离的限制从mysql数据库中获取行

如何在 android 应用程序中获取附近用户的列表?

如何使用firebase作为数据库在android中获取附近的用户名?