如何在Laravel QueryBuilder / MySQL Spatial软件包中按距离对查询结果进行排序?

火箭

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

(身份证,姓名)

位置(ID,名称,坐标(要点))

dish_location(location_id,dish_id)

现在,我想实现一个API,该API获取用户的位置(纬度,经度),并返回按距离(以公里为单位)排序的菜肴清单。我已经有一种方法需要两个纬度和两个经度并给我距离。但是我相信您可以向我展示一种方法,这是直接在MySQL查询中执行此操作的性能更高的方法。

另外:我想在API中执行“加载更多”功能。因此,我将已经收到的物品计数,或者在这种情况下如何解决?

我正在将其用于MySQL Spatial软件包

西罗西格诺尔

首先,让我们看一下如何使用基本查询构建器执行此操作。然后,我们将讨论如何使用Eloquent模型执行此查询:

function paginateDishesFromPoint(Point $point, $pageSize) 
{
    $distanceField = "ST_Distance_Sphere(locations.coordinates, "
        . "ST_GeomFromText('{$point->toWKT()}') AS distance"; 

    return DB::table('dishes') 
        ->select('dishes.*', DB::raw($distanceField))
        ->join('dish_locations', 'dish_locations.dish_id', '=', 'dishes.id')
        ->join('locations', 'locations.id', '=', 'dish_locations.location_id')
        ->orderBy('distance') 
        ->paginate($pageSize);
}

ST_Distance_Sphere()函数计算我们可以对结果进行排序的距离。Laravel的paginate()方法使用page通过请求URL传递参数为我们执行自动分页阅读分页文档以获取更多信息。使用上面的函数,我们可以按以下方式获取分页的结果集:

$point = new Point($latitude, $longitude); 
$sortedDishes = paginateDishesFromPoint($point, 15); 

...我们使用的程序包中PointGrimzy\LaravelMysqlSpatial\Types\Point在哪里,并且是每页结果的数量。15

现在,让我们尝试使用Eloquent模型来做到这一点。我们将使用本地查询范围来封装创建执行排序的查询部分所需的逻辑:

class Dish extends Model 
{
    ...

    public function locations() 
    {
        return $this->belongsToMany(App\Location::class);
    }

    public function scopeOrderByDistanceFrom($query, Point $point) 
    {
        $relation = $this->locations();
        $locationsTable = $relation->getRelated()->getTable();
        $distanceField = "ST_Distance_Sphere($locationsTable.coordinates, "
        . "ST_GeomFromText('{$point->toWKT()}') AS distance";

        return $query
            ->select($this->getTable() . '.*', DB::raw($distanceField))
            ->join(
                $relation->getTable(), 
                $relation->getQualifiedForeignKeyName(), 
                '=', 
                $relation->getQualifiedParentKeyName()
            )
            ->join(
                $locationsTable,
                $relation->getRelated()->getQualifiedKeyName(),
                '=', 
                $relation->getQualifiedRelatedKeyName()
            )
            ->orderBy('distance');
    }
}

此实现在模型上使用元数据将表名和字段名添加到查询中,因此,如果它们更改了,我们就不需要更新此方法。现在我们可以使用模型来获取有序集合:

$point = new Point($latitude, $longitude); 
$sortedDishes = Dish::orderByDistanceFrom($point)->paginate($pageSize);

$sortedDishesLengthAwarePaginator包装Collection模型的Laravel的实例如果我们将结果传递给视图,请按照以下方法在Blade模板中显示它们:

<ul>
    @foreach($sortedDishes as $dish) 
        <li>{{ $dish->name }} is {{ $dish->distance }} meters away.</li>
    @endforeach
</ul>

<a href="{{ $sortedDishes->nextPageUrl() }}">Load more...</a>

如上所示,分页器提供了方便的方法,我们可以使用它们方便地在分页结果之间移动。

另外,我们可以使用AJAX请求来加载结果。只需确保在请求数据参数中传递当前页面+ 1page

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在doctrine2 queryBuilder中实现ON(... OR ...)mysql查询

使用 DATE_FORMAT() 到 Laravel Querybuilder(或 Eloquent)的 MySQL 查询

如何在Laravel中的QueryBuilder中访问变量

Laravel QueryBuilder中的Postgres函数WITH

如何按日期对查询结果进行排序,然后按MySQL中的特定列值排序

如何在不使用 InvokeThen 的情况下使用 bookshelf js(和 knex querybuilder)将多行插入到 mysql 中?

如何在Laravel QueryBuilder中将子查询链接到外部表

如何将SQL查询转换为Laravel queryBuilder

如何在Typeorm中使用queryBuilder优化查询以选择内容?

如何在Phalcon中使用QueryBuilder和Paginator进行缓存?

如何使用 QueryBuilder 编写正确的查询

如何在mongodb querybuilder中“分组”字段“计数”?

如何在类似Symfony QueryBuilder的类中调用函数

如何在CQ5 Querybuilder中搜索多个Xpath

如何在存储库querybuilder中调用实体的方法

如何使用JFrog CLI按版本号对Artifactory软件包搜索结果进行排序?

如何使用 Laravel QueryBuilder 搜索 OR

如何在MySQL Laravel中存储JSON

如何在Laravel中更新MySQL的数据

Laravel:雄辩的Querybuilder whereTimestamp?

如何在MySQL中按日期对相关结果进行分组和排序

如何在Laravel中将sql转换为QueryBuilder

如何在Laravel QueryBuilder输出中使用in_array?

laravel querybuilder如何在where函数中使用

如何在Yii2中通过queryBuilder构建此sql查询?

如何在mysql查询中按特定顺序排序?

如何在WordPress MySQL查询中按元键值排序?

教义QueryBuilder“ andWhere”查询

Symfony queryBuilder:查询过多