【问题标题】:implementing haversine distance query based on lng and lat实现基于lng和lat的haversine距离查询
【发布时间】:2017-06-18 20:49:06
【问题描述】:

我在开发这个时遇到了问题。

我已经实现了我在模型上运行的这个范围函数

Listing::closest($lat, $lng)->分页(5);

public function scopeClosest($query, $lat, $lng, $distance = 0, $units = 'km')
{

    switch ( $units ) {
        case 'miles':
            //radius of the great circle in miles
            $gr_circle_radius = 3959;
        break;
        case 'km':
            //radius of the great circle in kilometers
            $gr_circle_radius = 6371;
        break;
    }

    return $query->selectRaw(
        '*, ( '.$gr_circle_radius.' * acos( cos( radians('.$lat.') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('.$lng.') ) + sin( radians('.$lat.') ) * sin( radians( lat ) ) ) ) AS distance'
    )->havingRaw("distance < ?", [10] );

}

但是我遇到了这个我现在不知道如何修复的错误

SQLSTATE[42S22]:未找到列:1054 未知列“距离”在“有子句”中(SQL:从 listings 中选择计数(*)作为聚合,距离

似乎 laravel 正在运行 2 个查询,如果我不使用haveRaw(),这就是它的样子

array:2 [▼
  0 => array:3 [▼
    "query" => "select count(*) as aggregate from `listings`"
    "bindings" => []
    "time" => 0.48
  ]
  1 => array:3 [▼
    "query" => "select *, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance from `listings` limit 5 offset 0"
    "bindings" => []
    "time" => 0.97
  ]
]

当我使用 havingRaw 时,似乎 laravel 将其应用于第一个查询,当然它会失败。但为什么它将它应用于第一个查询而不是第二个?

【问题讨论】:

  • 你的要求是什么,你能解释一下吗?您想根据给定的纬度和经度获取最近的 5 个位置吗?
  • 5 只是例子,我需要这个分页
  • 如果是我,我只需运行查询并让用户决定是否应该在 JavaScript 中以公里、英里、联赛、链或其他形式显示结果

标签: php mysql laravel haversine


【解决方案1】:

这就是我在我的情况下所做的......我需要查询半径为 5 公里的距离。我使用whereRawpaginate

$vtl = VehicleTrackerLog::whereRaw("(
                                    111.1111 
                                    *DEGREES(ACOS(COS(RADIANS('-33.873415'))
                                    * COS(RADIANS(lat))
                                    * COS(RADIANS('151.227538' - lng))+ SIN (RADIANS('-33.873415'))         
                                    * SIN(RADIANS(lat))))<=5)"
                                    )->paginate(5);

如果您想要英里数,只需乘以 69.041236 而不是 111.111

【讨论】:

  • 我还没有尝试过,但它看起来很棒,还提供英里作为单位,我用什么代替 111.1111?
  • 英里数除以 1.609344
  • 所以“
猜你喜欢
  • 1970-01-01
  • 2018-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 2014-12-10
  • 1970-01-01
相关资源
最近更新 更多