Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Bagaimana cara mengurutkan hasil kueri berdasarkan jarak dalam paket Laravel QueryBuilder / MySQL Spatial?

Pertama, mari kita lihat bagaimana melakukan ini dengan pembuat kueri dasar. Kemudian, kita akan membahas cara mengeksekusi kueri ini dengan model 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() fungsi menghitung jarak yang kita dapat mengurutkan hasil. paginate() Laravel's metode melakukan pagination otomatis untuk kami menggunakan page parameter melewati URL permintaan. Baca dokumen pagination untuk informasi lebih lanjut. Dengan fungsi di atas, kita dapat mengambil set hasil paginasi sebagai berikut:

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

...di mana Point adalah Grimzy\LaravelMysqlSpatial\Types\Point kelas dari paket yang kami gunakan, dan 15 adalah jumlah hasil per halaman.

Sekarang, mari kita coba melakukan ini dengan model Eloquent. Kami akan menggunakan cakupan kueri lokal untuk merangkum logika yang diperlukan untuk membuat bagian kueri yang melakukan pengurutan:

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

Implementasi ini menggunakan metadata pada model untuk menambahkan nama tabel dan bidang ke kueri sehingga kami tidak perlu memperbarui metode ini jika berubah. Sekarang kita dapat mengambil himpunan terurut menggunakan model:

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

$sortedDishes adalah turunan dari LengthAwarePaginator Laravel yang membungkus Collection dari model. Jika kita meneruskan hasilnya ke tampilan, berikut cara menampilkannya dalam template Blade:

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

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

Seperti yang ditunjukkan di atas, paginator menyediakan metode praktis yang dapat kita gunakan untuk berpindah antar halaman hasil dengan mudah.

Atau, kita bisa menggunakan permintaan AJAX untuk memuat hasil. Pastikan untuk melewati halaman saat ini + 1 di page parameter data permintaan.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Skrip untuk mengubah semua tabel dan bidang ke susunan utf-8-bin di MYSQL

  2. MySql pilih IN klausa string koma dibatasi

  3. Bagaimana cara kerja HANDLER FOR NOT FOUND dan apa kegunaannya?

  4. PDO PHP masukkan ke DB dari array asosiatif

  5. Menggunakan Python dan MySQL dalam Proses ETL