上一篇文档中选择的扩展,该扩展已有方法whereGeoDistance查询指定经纬度范围内的数据,但是无法根据距离排序,由于依赖于laravel-scout,而该扩展并没有实现Geo的sort,但是经过通过Elasticsearch官方文档及该扩展源码的阅读,还是找到两个途径实现该功能:
1.1在ScoutBuilderServiceProvider的boot中macro排序的sort方法:
public function boot() { \Laravel\Scout\Builder::macro('sortRaw', function (array $value) { $this->orders[] = $value; return $this; }); }
1.2在ElasticEngine的map方法中增加对sort的处理
if (isset($hit['highlight'])) { $model->highlight = new Highlight($hit['highlight']); } if (isset($hit['sort'])) { $model->sort = $hit['sort']; }
1.3调用
$para = $request->input('para'); $position = [130, -20]; $sort_geo_distance = [ '_geo_distance' => [ 'location' => $position, 'order' => 'asc', 'unit' => 'km', 'distance_type' => 'plane', ] ]; $re = Shop::search($para) ->whereGeoDistance('location', $position, '10km') ->sortRaw($sort_geo_distance) ->get();
1.4 由于该方法涉及到扩展源码的修改,所有并不推荐使用,下面是第二种比较通用的实现
2.使用已有的searchRaw方法实现排序
$position = [130, -20]; $sort_geo_distance = [ '_geo_distance' => [ 'location' => $position, 'order' => 'asc', 'unit' => 'km', 'distance_type' => 'plane', ] ]; $query = [ "bool" => [ 'must' => [ 'match' => [ 'name' => $para ] ], "filter" => [ "geo_distance" => [ "distance" => "10000km", "location" => $position ] ] ] ]; $result = Shop::searchRaw([ 'query' => $query, 'sort' => $sort_geo_distance ]);
由于返回结果嵌套太多其他数据,并不直观,所以封装一个方法来对结果进行处理
function format_elastic_result($results) { return Collection::make($results['hits']['hits']) ->map(function ($hit) { $model = $hit['_source']; if (isset($hit['highlight'])) { $model['highlight'] = new Highlight($hit['highlight']); } if (isset($hit['sort'])) { $model['sort'] = $hit['sort']; } return $model; }) ->filter() ->values(); }
© 著作权归作者所有
举报
发表评论
0/200