【问题标题】:Is it possible to use haversine in a laravel eloquent query?是否可以在 laravel 雄辩的查询中使用 hasrsine?
【发布时间】:2016-04-14 09:01:54
【问题描述】:

我创建了一个 api,我可以在其中获得包含 2 个关系的报价:

  • venues belongsToMany 优惠 (manyToMany)
  • days belongsToMany 优惠 (manyToMany)

然后,报价会同步并保存关系,在返回的 json 中,您可以看到日期和地点的对象。

我现在要做的是使用 hasrsine 来获取报价地点 lat/lng 与 hasrsine 值的距离。我目前正在使用这个雄辩的查询来获取具有各自关系的报价:

$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;
    }
}

这非常有效,我没有任何问题。我现在想使用 hasrsine 和附加到要约的地点的位置来获得要约,但我很难了解这将如何在雄辩的查询中发挥作用。

以下是每个关系的模型:

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


}

谁能帮我解决这个问题并提供一些启示?

==== 编辑 ====

这是我需要的带有 Eloquent 查询的 json 示例输出:

查看日期和地点。我希望在下面开始的原始查询中使用它,但我直接查询 days 表,最好直接从 offer 表中查询并加入附件中的场所对象和 days 对象:

$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();

【问题讨论】:

  • 嗯,这怎么可能?
  • 我如何从场地获得价值?我会创建特征,然后将控制器中的特征与场所关系中的值一起使用吗?

标签: php laravel orm eloquent haversine


【解决方案1】:

我假设最终您希望能够根据用户坐标找到优惠?如果您将来获得 10,000 个报价或场地——您不想一个一个地遍历它们并计算距离然后显示最接近的匹配项——那将是根本不可行的。

我建议使用地理空间查询(由 MySQL 支持)——例如。给我 50 个优惠(或场地),位于 X 纬度和 Y 经度半径 5 公里范围内。

不幸的是,Eloquent 不支持地理空间查询,因此您需要使用 DB 外观进行原始查询,但性能会非常好——您会立即获得结果。

在我看来,这是合理的选择。解析整套offer/venues,将距离计算作为Trait来实现是不合理的。

【讨论】:

  • 那么,如果我想获得每个优惠对象的附加场所,那么简单的查询连接就可以了吗?
  • 是的,当然。一旦您获得基于位置的报价 - 您可以简单地加入场地数据。事实上,我过去也做过类似的事情。 MySQL 有特殊的地理定位索引类型——“几何”。它会在几毫秒内为您提供附近优惠的列表!
  • 哦,好吧,我需要根据用户的位置来获取优惠地点的距离,如果在 hasrsine 查询中它在 10000 以内,那么我们可以显示它们。 MySQL 几何可以做到这一点吗?
  • 是的,绝对可以。在此处查看示例:percona.com/blog/2013/10/21/… 此外,您需要在迁移文件中添加 table->engine = 'MyISAM'(当创建提供表时),因为几何索引仅支持 ISAM 存储。
  • Denis Mysenko,我已经编辑了我的问题,因此您可以查看 Eloquent 普通查询的示例。我需要知道的是,是否可以在 laravel 的原始查询中执行此操作?
猜你喜欢
  • 1970-01-01
  • 2018-01-26
  • 2021-07-23
  • 1970-01-01
  • 2017-11-11
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多