Объем запроса для получения моделей, в которых последняя модель отношений удовлетворяет - PullRequest
0 голосов
/ 02 февраля 2019

Я хочу получить велосипеды, чье последнее (последнее добавленное) связанное местоположение находится в определенной области.Это должно быть сделано с использованием объема запроса scopeBounding($query, $latNorth, $lonEast, $latSouth, $lonWest) на модели велосипеда.У каждого велосипеда есть много мест:

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

То, что у меня есть до сих пор, похоже, не работает вообще, так как я не знаю, как проверять только последние из связанных мест.

public function scopeBounding($query, $latNorth, $lonEast, $latSouth, $lonWest)
{
      return $query->whereHas('locations', function ($q) use ($latNorth, $lonEast, $latSouth, $lonWest)
      {
          $q->whereBetween('latitude', [$latNorth, $latSouth])
            ->whereBetween('longitude', [$lonWest, $lonEast]);
      });
}

Возвращенные велосипеды имеют последние местоположения, которые не соответствуют условию whereBetween.

Выбор местоположения, а не связанных с ним велосипедов, однако работает как ожидалось:

App\Location::whereBetween('latitude', [50, 50.2])->whereBetween('longitude', [11, 12])->get();

ОБНОВЛЕНИЕ:

Модель местоположения имеет поля долготы и широты:

$table->decimal('latitude', 8, 6);
$table->decimal('longitude', 9, 6);

Область используется следующим образом:

$bounding_bikes = Bike::bounding($latNorth, $lonEast, $latSouth, $lonWest)->get();

аналогичный вопрос

Ответы [ 2 ]

0 голосов
/ 02 февраля 2019

Решение, которое я наконец нашел, выглядит для меня очень уродливо, но я не нашел ничего лучшего:

public function scopeBounding($query, $latNorth, $lonEast, $latSouth, $lonWest)
{
      return $query->whereHas('locations', function ($q) use($latNorth, $lonEast, $latSouth, $lonWest) {
        $q->whereRaw('`locations`.`id` = (select `locations`.`id` from `locations` where `bikes`.`id` = `locations`.`bike_id` order by `created_at` desc limit 1)')
          ->whereBetween('latitude', [$latSouth, $latNorth])
          ->whereBetween('longitude', [$lonWest, $lonEast]);
      });
}

Так что я был бы рад любым идеям, как это упростить!

0 голосов
/ 02 февраля 2019

Я думаю, вы должны попробовать что-то вроде получения расстояния между двумя точками конкретного велосипеда, а затем вы можете сделать фильтр по расстоянию.

Я предполагаю, что здесь у вас есть таблица местоположений, а лат и lng должны бытьстолбец в этой таблице.

Это рассчитает расстояние в км

public function scopeBounding($query, $from_latitude, $from_longitude, $distance)
{
  $raw = \DB::raw('ROUND ( ( 6371 * acos( cos( radians('.$from_latitude.') ) * cos( radians( locations.lat ) ) * cos( radians( locations.lng ) - radians('.$from_longitude.') ) + sin( radians('.$from_latitude.') ) * sin( radians( locations.lat ) ) ) ) ) AS distance');

  return $query->select($raw)->orderBy( 'distance', 'asc' )->having('distance', '<=', $distance)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...