我正在尝试按照用户提交的邮政编码和距离,对“事件”按照距离排序。
我附上了我的数据库表及其关系的样本。如您所见,“geom”通过“postcode”与多个地址相关联,并且地址可以与多个表(在此示例中为“事件”表)相关联。
在控制器中,获取了搜索结果后,我们为每个结果计算距离。
这将生成一个数组,其中
在视图中,我们使用以下逻辑来显示适用的记录上的距离。
我尝试了几种方法,但无法更新我的
我还尝试在同一位置使用orderByRaw,虽然没有收到错误提示,但结果未按顺序排序。
我附上了我的数据库表及其关系的样本。如您所见,“geom”通过“postcode”与多个地址相关联,并且地址可以与多个表(在此示例中为“事件”表)相关联。
我正在从最终用户那里获取邮政编码和半径(以英里为单位),以检索适当的事件,以下是我在Eloquent中实现此目标的示例。
/**
* Extend locale method which initially only gets lat/long for given postcode to search
*
* @param \Illuminate\Database\Eloquent\Builder $query The query builder
* @param \App\Http\Requests\SearchRequest $request The search request
* @return void
*/
protected function locale(Builder $query, SearchRequest $request)
{
$postcode = $this->formatPostcode($request->postcode);
$geom = Geom::query()->where('postcode', $postcode)->first();
if (! $geom || Cache::has('postcodeAPIFailed')) {
return;
}
$lat = $geom->geo_location['lat'];
$long = $geom->geo_location['long'];
// Top-left point of bounding box
$lat1 = $lat - ($request->within / 69);
$long1 = $long - $request->within / abs(cos(deg2rad($lat)) * 69);
// Bottom-right point of bounding box
$lat2 = $lat + ($request->within / 69);
$long2 = $long + $request->within / abs(cos(deg2rad($lat)) * 69);
$query->whereHas('address', function (Builder $query) use ($request, $lat, $long, $lat1, $long1, $lat2, $long2) {
$query->whereHas('geom', function (Builder $query) use ($request, $lat, $long, $lat1, $long1, $lat2, $long2) {
$query->whereRaw('st_within(geo_location, envelope(linestring(point(?, ?), point(?, ?))))', [$long1, $lat1, $long2, $lat2]);
});
});
}
在控制器中,获取了搜索结果后,我们为每个结果计算距离。
if ($request->has('postcode')) {
$postcodeDistances = $this->getDistances($results, $request);
}
这将生成一个数组,其中
postcode
为键,distance
为值,即 $postcodeDistances['L1 0AA'] = '3';
,我们将此数组发送到视图。在视图中,我们使用以下逻辑来显示适用的记录上的距离。
@if($postcodeDistances)
<span>
{{ $postcodeDistances[$result->address->postcode] }}
mile{{ $postcodeDistances[$result->address->postcode] != 1 ? 's' : '' }} away
</span>
@endif
我尝试了几种方法,但无法更新我的
function locale()
以按距离排序。我考虑将距离附加到集合中并使用Laravel方法以该方式对集合进行排序,但如果可能的话,从数据库层面实现这一点会更理想。我的第一次尝试是在whereHas('geom')
之后添加一个距离字段,并按新字段排序。
$query->addSelect(\DB::raw("ST_DISTANCE_SPHERE(geo_location, POINT({$long}, {$lat})) AS distance"));
我收到以下错误:SQLSTATE[21000]: Cardinality violation: 1241 Operand should contain 2 column(s) (SQL: select count(*) as aggregate from `event` where (select count(*) from `address` where `address`.`addressable_id` = `event`.`id` and `address`.`addressable_type` = event and (select count(*), ST_DISTANCE_SPHERE(geo_location, POINT(-2.717472, 53.427078)) AS distance from `geom` where `geom`.`postcode` = `address`.`postcode` and st_within(geo_location, envelope(linestring(point(-3.6903924055016, 52.847367855072), point(-1.7445515944984, 54.006788144928))))) >= 1) >= 1 and (select count(*) from `organisation` where `event`.`organisation_id` = `organisation`.`id` and `status` = 1) >= 1 and `event_template_id` is not null and `date_start` >= 2018-07-31 00:00:00 and `status` in (1, 5))
我还尝试在同一位置使用orderByRaw,虽然没有收到错误提示,但结果未按顺序排序。
$query->orderByRaw('ST_DISTANCE_SPHERE(geo_location, POINT(?, ?)) ASC', [$long, $lat]);