Можно ли использовать haversine в красноречивом запросе laravel?

Я создал API, где я получаю предложения, в которых есть 2 отношения:

  • объекты принадлежат многим предложениям (много-много)
  • дни принадлежит многим предложениям (много-много)

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

То, что я сейчас пытаюсь сделать, это использовать haversine, чтобы получить расстояние от места проведения предложения lat / lng до значения haversine. В настоящее время я использую этот красноречивый запрос, чтобы получить предложения с соответствующими отношениями:

$mytime = Carbon::now('Europe/London');
$time = $mytime->format('H:i');
$timeInt = $this->hourMinToInteger($time);
$today = $mytime->format('m/d/Y');
$day = strtolower($mytime->format('l'));
$tomorrow = strtolower(Carbon::now()->addDay(1)->format('l'));
$offersWithDays = Offer::with(['days','venues'])->get();

$response = [
'now' => [],
'later' => [],
'tomorrow' => [],
'featured' => []
];

// validOffers are all offers that fall within this stuff
foreach ($offersWithDays as $offerAll) {
$relation = $offerAll->days()->get();

$theDays = array();
foreach ($relation as $theDay) {
$theDayObj = $theDay->day;
array_push($theDays,$theDayObj);
}
extract($theDays);

if ($offerAll->is_featured) {
$response['featured'][] = $offerAll;
}
if (in_array($day,$theDays) && $offerAll->offer_start_time < $time) {
$response['now'][] = $offerAll;
}
if (in_array($day,$theDays) && $offerAll->offer_start_time > $time) {
$response['later'][] = $offerAll;
}
if (in_array($tomorrow,$theDays)) {
$response['tomorrow'][] = $offerAll;
}
}

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

Вот модели для каждого отношения:

День

use Illuminate\Database\Eloquent\Model;

class Day extends Model
{
/**
* Get the offer days for the offer.
*/

protected $fillable = ['start_time','end_time'];

public function offers()
{

return $this->belongsToMany('App\Offer');
}
}

место встречи

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Venue extends Model
{
//
use SoftDeletes;

protected $table = 'venues';

protected $dates = ['deleted_at'];

protected $fillable = ['id','address','description','phone_number','website','name', 'headline','lat','lng','days'];

public static $rules = array(
'name' => ''
);

protected $casts = [
'lat' => 'float(10,8)',
'lng' => 'float(11,8)'
];

public function offers()
{
return $this->belongsToMany('App\Offer','offer_venue');
}

}

Предлагает

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Offer extends Model
{
/**
* The database table used by the model.
*
* @var string
*/

use SoftDeletes;

protected $table = 'offers';

protected $dates = ['deleted_at'];
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $hidden  = ['map_location', 'regular', 'name', 'distance_to_offer'];
protected $fillable = ['id','venue_id','type_id','day', 'venue_address','is_featured','repeater_days','image', 'venue_description', 'offer_headline','offer_subheader','offer_terms','venue_phone_number','venue_website', 'venue_name', 'venue_headline','venue_description','venue_latitude','venue_longitude','offer_when','offer_end_time','offer_start_time','offer_start_date','offer_end_date','featured_date','current_time','current_date'];
public static $rules = array(
'image' => 'image|mimes:jpeg,jpg,png,bmp,gif,svg'
);
protected $casts = [
'is_featured' => 'boolean',
'is_regular' => 'boolean',
'offer_when' => 'array'
];
/**
* Get the offers for the offer.
*/
public function days()
{

return $this->belongsToMany('App\Day','day_offer', 'offer_id', 'day_id');
}

public function types()
{

return $this->belongsToMany('App\Type', 'offer_type');
}

public function venues()
{

return $this->belongsToMany('App\Venue', 'offer_venue', 'offer_id', 'venue_id');
}}

Может ли кто-нибудь помочь мне с этим и пролить немного света?

==== изменить ====

Вот пример вывода JSON с запросом Eloquent, который мне нужен:

введите описание изображения здесь

Смотрите дни и места. Я хочу это в необработанном запросе, который я начал ниже, но у меня есть прямые запросы к таблице дней, было бы лучше сделать запрос непосредственно из таблицы предложений и объединить объекты мест и объекты дней, как в приложении:

$query = DB::table('days AS od')
->select('o.*',
'ot.type',
'od.day',
'v.name AS venue_name',
'v.headline AS venue_headline',
'v.description AS venue_description',
'v.phone_number AS venue_phone_number',
'v.website AS venue_website',
'v.lat AS venue_latitude',
'v.lng AS venue_longitude', 'v.address AS venue_address',
// TODO : remove the 37, -122 lat lng co-ordinate pair that is hardcoded into this string and adjust the radius variable below
DB::raw('3959 * acos( cos( radians(37) ) * cos( radians( v.lat ) ) * cos( radians( v.lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) as distance'))
->join('day_offer AS odp', 'odp.day_id', '=', 'od.id')
->join('offers AS o', 'o.id', '=', 'odp.offer_id')
->join('offer_type AS otp', 'otp.offer_id', '=', 'o.id')
->join('types AS ot', 'ot.id', '=', 'otp.type_id')
->join('venues AS v', 'v.id', '=', 'o.venue_id');

$radius = '10000';
$query->having('distance', '<', $radius);
$query->orderBy('distance', 'desc');
$validOffers = $query->get();

0

Решение

Я предполагаю, что в конце концов вы хотите, чтобы иметь возможность найти предложения на основе пользовательских координат? Если вы получите 10 000 предложений или мест в будущем — вы не хотите проходить их один за другим, рассчитывать расстояние и затем отображать самые близкие совпадения — это было бы просто невозможно.

Я бы предложил геопространственные запросы (поддерживаемые MySQL) — например. дайте мне 50 предложений (или мест), расположенных в радиусе 5 км от широты X и долготы Y.

К сожалению, Eloquent не поддерживает геопространственные запросы, поэтому вам нужно будет выполнять необработанные запросы, используя фасад БД, но производительность будет отличной — вы получите результаты мгновенно.

Это разумный путь, по моему мнению. Разбирая весь набор предложений / мест проведения, выполнение вычисления расстояния как Черта иррационально.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]