我正在为Laravel 5.2应用程序构建一些搜索功能。在我的模型中,Event有一个Location,它由纬度和经度值组成。 Location类有一个计算距离$this->distanceTo($that)
的方法。
我希望能够通过各种条件(关键字,类别等)搜索我的事件,然后按距离将结果排序到指定点。所以我的路线看起来像这样:
$query = App\Event::query();
if (Input::has('keyword')) {
$query = $query->where('name', 'like', '%'.Input::get('keyword').'%');
}
if (Input::has('category')) {
$query = $query->where('category_id', Input::get('category'));
}
$events = $query->get();
在我看来,我需要运行此查询,然后对它返回的集合执行排序。但如果有一种方法可以将排序合并到查询本身中,那么它可能会表现得更好。有没有办法做到这一点?
如果没有,那么我仍然需要弄清楚如何对返回的集合执行排序。我知道有一个sortBy()方法可用于集合,但是当我需要按$eventFromCollection->location()->distanceTo($searchLocation)
排序时,我不确定如何将它们组合在一起。对此有何指导?
答案 0 :(得分:1)
我构建了一个类似的功能,并将分享我的经验。
有几种不同的方法可以做到这一点:
我会忽略#1和#3,因为你可以很容易地找到那些“如何做”。
<强> 2。使用PHP:
您必须在sql操作后对结果进行排序。你可以使用这样的东西:
public function distance($lat1, $lon1, $lat2, $lon2, $unit = 'K') {
$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 round(($miles * 1.609344), 2);
} else if ($unit == "N") {
return round(($miles * 0.8684), 2);
} else {
return round($miles, 2);
}
}
这将为您提供两组坐标之间的距离。迭代DB中的结果并使用它对它们进行排序。
<强> 2。使用托管搜索服务:
Algolia对于“搜索”来说是一个非常好的解决方案。它有一个Laravel package可以轻松实现,并且内置Geo search功能。
我根据要求使用2,3和4的组合。