Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Làm cách nào để sắp xếp kết quả truy vấn theo khoảng cách trong gói Laravel QueryBuilder / MySQL Spatial?

Trước tiên, chúng ta hãy xem cách thực hiện việc này với trình tạo truy vấn cơ bản. Sau đó, chúng ta sẽ thảo luận về cách thực hiện truy vấn này với các mô hình 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() hàm tính toán khoảng cách mà chúng ta có thể sắp xếp kết quả theo. paginate() của Laravel thực hiện phân trang tự động cho chúng tôi bằng cách sử dụng trang page tham số được chuyển qua URL yêu cầu. Đọc tài liệu phân trang để biết thêm thông tin. Với hàm trên, chúng ta có thể tìm nạp một tập hợp kết quả được phân trang như sau:

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

... ở đâu PointGrimzy\LaravelMysqlSpatial\Types\Point lớp từ gói chúng tôi đang sử dụng và 15 là số lượng kết quả trên mỗi trang.

Bây giờ, chúng ta hãy thử làm điều này với các mô hình Eloquent. Chúng tôi sẽ sử dụng phạm vi truy vấn cục bộ để đóng gói logic cần thiết để tạo phần truy vấn thực hiện thứ tự:

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');
    }
}

Việc triển khai này sử dụng siêu dữ liệu trên các mô hình để thêm bảng và tên trường vào truy vấn, vì vậy chúng tôi không cần cập nhật phương pháp này nếu chúng thay đổi. Bây giờ chúng ta có thể tìm nạp tập hợp đã sắp xếp bằng cách sử dụng mô hình:

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

$sortedDishes là một phiên bản của LengthAwarePaginator của Laravel bao bọc một Collection của các mô hình. Nếu chúng tôi chuyển kết quả cho một dạng xem, đây là cách hiển thị chúng trong mẫu Blade:

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

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

Như được hiển thị ở trên, trình phân trang cung cấp các phương pháp tiện lợi mà chúng tôi có thể sử dụng để dễ dàng di chuyển giữa các kết quả được phân trang.

Ngoài ra, chúng ta có thể sử dụng các yêu cầu AJAX để tải kết quả. Chỉ cần đảm bảo vượt qua trang hiện tại + 1 trong trang page tham số của dữ liệu yêu cầu.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bí danh cột động dựa trên giá trị cột

  2. Khóa chính nhiều cột trong MySQL 5

  3. Làm cách nào để lấy danh sách tài khoản người dùng bằng dòng lệnh trong MySQL?

  4. Sử dụng Mysql trong dev / prod và H2 trong thử nghiệm

  5. Sự cố với mã hóa utf-8 bằng PHP + MySQL