使用 Laravel QueryBuilder "when" 并向查询结果添加自定义值
Using Laravel QueryBuilder "when" and add a custom value to Query result
我想做的很简单:
- 当根据用户纬度和经度(在 DB 上)计算的距离高于 int 时,我们通过添加 where 从结果中删除当前用户
- 当距离不高时,我们将自定义值添加到返回的结果
这可以在执行查询后使用 foreach 轻松完成:
foreach($search as $key => $value){
if(distance($value->latitude,$value->longitude,$user->latitude,$user->longitude,"K") > $distance) {
unset($search[$key]);
} else {
$search[$key]->distance = $calculatedDistance
}
}
这种方式的缺点是如果我们有一个大数据库,它会消耗大量的内存和时间,因为我们在查询中做了两倍应该直接做的事情。
我需要做的是让它在查询本身上执行。我不知道该怎么做是:
- 执行查询时直接在查询中添加自定义值,并在查询中的when内进行距离计算,不使用foreach而是直接获取当前原始值进行比较。
我现在在做什么:
->when($distance > 0, function ($query) use($distance, $longitude, $latitude){
$query->where(function ($subQuery) use ($longitude, $latitude,$distance) {
$cDistance = distance((int)$subQuery->value('latitude'),
(int)$subQuery->value('longitude'),
$latitude,
$longitude,
"K");
$subQuery->when(($cDistance > $distance),
function ($subQuery){
$subQuery->where('users.id', '<>', (int)$subQuery->value('id'));
},function ($subQuery) use ($cDistance) {
$subQuery->value((string)$cDistance.' as distance');
}
);
});
$subQuery->value('something')
仅使用查询的第一个原始数据进行测试,而不是对所有行进行测试。
$subQuery->value((string)$cDistance.' as distance');
正在返回错误
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'84.354917445764' in 'field list' (SQL: select 84
.354917445764
as
distance
from users
limit 1)
$sqlDistance = DB::raw('ROUND ( 6371 * acos( cos( radians(' . $latitude . ') )
* cos( radians( doctor_profile.latitude ) )
* cos( radians( doctor_profile.longitude )
- radians(' . $longitude . ') )
+ sin( radians(' . $latitude . ') )
* sin( radians( doctor_profile.latitude ) ) ) )');
内部查询:
->selectRaw("{$sqlDistance} AS distance")
->when($distance > 0, function ($query) use ($distance,$sqlDistance){
$query->havingRaw('{$sqlDistance} <= ?', [$distance]);
})
我想做的很简单: - 当根据用户纬度和经度(在 DB 上)计算的距离高于 int 时,我们通过添加 where 从结果中删除当前用户 - 当距离不高时,我们将自定义值添加到返回的结果
这可以在执行查询后使用 foreach 轻松完成:
foreach($search as $key => $value){
if(distance($value->latitude,$value->longitude,$user->latitude,$user->longitude,"K") > $distance) {
unset($search[$key]);
} else {
$search[$key]->distance = $calculatedDistance
}
}
这种方式的缺点是如果我们有一个大数据库,它会消耗大量的内存和时间,因为我们在查询中做了两倍应该直接做的事情。
我需要做的是让它在查询本身上执行。我不知道该怎么做是: - 执行查询时直接在查询中添加自定义值,并在查询中的when内进行距离计算,不使用foreach而是直接获取当前原始值进行比较。
我现在在做什么:
->when($distance > 0, function ($query) use($distance, $longitude, $latitude){
$query->where(function ($subQuery) use ($longitude, $latitude,$distance) {
$cDistance = distance((int)$subQuery->value('latitude'),
(int)$subQuery->value('longitude'),
$latitude,
$longitude,
"K");
$subQuery->when(($cDistance > $distance),
function ($subQuery){
$subQuery->where('users.id', '<>', (int)$subQuery->value('id'));
},function ($subQuery) use ($cDistance) {
$subQuery->value((string)$cDistance.' as distance');
}
);
});
$subQuery->value('something')
仅使用查询的第一个原始数据进行测试,而不是对所有行进行测试。
$subQuery->value((string)$cDistance.' as distance');
正在返回错误
SQLSTATE[42S22]: Column not found: 1054 Unknown column '84.354917445764' in 'field list' (SQL: select
84
.354917445764
asdistance
fromusers
limit 1)
$sqlDistance = DB::raw('ROUND ( 6371 * acos( cos( radians(' . $latitude . ') )
* cos( radians( doctor_profile.latitude ) )
* cos( radians( doctor_profile.longitude )
- radians(' . $longitude . ') )
+ sin( radians(' . $latitude . ') )
* sin( radians( doctor_profile.latitude ) ) ) )');
内部查询:
->selectRaw("{$sqlDistance} AS distance")
->when($distance > 0, function ($query) use ($distance,$sqlDistance){
$query->havingRaw('{$sqlDistance} <= ?', [$distance]);
})