基于lng和lat实现haversine距离查询
implementing haversine distance query based on lng and lat
我在开发这个的时候 运行 遇到了问题。
我在 运行 模型
上实现了这个范围函数
Listing::closest($lat, $lng)->paginate(5);
public function scopeClosest($query, $lat, $lng, $distance = 0, $units = 'km')
{
switch ( $units ) {
case 'miles':
//radius of the great circle in miles
$gr_circle_radius = 3959;
break;
case 'km':
//radius of the great circle in kilometers
$gr_circle_radius = 6371;
break;
}
return $query->selectRaw(
'*, ( '.$gr_circle_radius.' * acos( cos( radians('.$lat.') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('.$lng.') ) + sin( radians('.$lat.') ) * sin( radians( lat ) ) ) ) AS distance'
)->havingRaw("distance < ?", [10] );
}
但是我 运行 遇到了这个错误,我现在不知道如何修复
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'distance' in 'having clause' (SQL: select count(*) as aggregate from listings
having distance < 10)
似乎 laravel 是 运行ning 2 个查询,这是我不使用 havingRaw()
时的样子
array:2 [▼
0 => array:3 [▼
"query" => "select count(*) as aggregate from `listings`"
"bindings" => []
"time" => 0.48
]
1 => array:3 [▼
"query" => "select *, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance from `listings` limit 5 offset 0"
"bindings" => []
"time" => 0.97
]
]
当我使用 havingRaw 时,似乎 laravel 将它应用于第一个查询,当然它会失败。但为什么将它应用于第一个查询而不是第二个查询?
这就是我在我的案例中所做的。我需要查询半径为 5 公里的距离。我使用 whereRaw
和 paginate
$vtl = VehicleTrackerLog::whereRaw("(
111.1111
*DEGREES(ACOS(COS(RADIANS('-33.873415'))
* COS(RADIANS(lat))
* COS(RADIANS('151.227538' - lng))+ SIN (RADIANS('-33.873415'))
* SIN(RADIANS(lat))))<=5)"
)->paginate(5);
如果您想要以英里为单位,只需乘以 69.041236 而不是 111.111
我在开发这个的时候 运行 遇到了问题。
我在 运行 模型
上实现了这个范围函数Listing::closest($lat, $lng)->paginate(5);
public function scopeClosest($query, $lat, $lng, $distance = 0, $units = 'km')
{
switch ( $units ) {
case 'miles':
//radius of the great circle in miles
$gr_circle_radius = 3959;
break;
case 'km':
//radius of the great circle in kilometers
$gr_circle_radius = 6371;
break;
}
return $query->selectRaw(
'*, ( '.$gr_circle_radius.' * acos( cos( radians('.$lat.') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('.$lng.') ) + sin( radians('.$lat.') ) * sin( radians( lat ) ) ) ) AS distance'
)->havingRaw("distance < ?", [10] );
}
但是我 运行 遇到了这个错误,我现在不知道如何修复
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'distance' in 'having clause' (SQL: select count(*) as aggregate from
listings
having distance < 10)
似乎 laravel 是 运行ning 2 个查询,这是我不使用 havingRaw()
时的样子array:2 [▼
0 => array:3 [▼
"query" => "select count(*) as aggregate from `listings`"
"bindings" => []
"time" => 0.48
]
1 => array:3 [▼
"query" => "select *, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance from `listings` limit 5 offset 0"
"bindings" => []
"time" => 0.97
]
]
当我使用 havingRaw 时,似乎 laravel 将它应用于第一个查询,当然它会失败。但为什么将它应用于第一个查询而不是第二个查询?
这就是我在我的案例中所做的。我需要查询半径为 5 公里的距离。我使用 whereRaw
和 paginate
$vtl = VehicleTrackerLog::whereRaw("(
111.1111
*DEGREES(ACOS(COS(RADIANS('-33.873415'))
* COS(RADIANS(lat))
* COS(RADIANS('151.227538' - lng))+ SIN (RADIANS('-33.873415'))
* SIN(RADIANS(lat))))<=5)"
)->paginate(5);
如果您想要以英里为单位,只需乘以 69.041236 而不是 111.111