假设我在遗留系统中有以下关系,无法更改它。
我想要的是带医院的省份,并对每一家医院进行最后一年的监测。
注:最后一年意味着不是现在的日期,这意味着我们应该取每家医院的最后一次监测日期,然后从该日期开始计算到该日期为止的12个月。
假设A医院上一次被监测是在2020年-11-01年,那么从2020年到11-01年间的所有监测都应该持续到2019-11-01年。其他医院也一样。
已经用Laravel资源实现了,但是有点慢,而且也不知道如何在资源返回数据之后实现orderBy特性,因为我需要基于监视的分页和排序,现在我通过资源来处理它。
目前,我使用的是hasManyThrough关系,在get之后,我将数据传递给资源收集和处理监控的get。但是这样不能实现排序和分页。
$data = Province::with(['districts.hospitalTypes])->get();
然后,我将数据传递给资源并得到监视,但是如何应用排序和分页,因为排序是基于监视的。而且使用资源的速度比急切的加载要慢一些。我正在寻找一种方法来使用那些标准的“急切加载”。
class ProvinceResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'districts' => DistrictResource::collection($this->whenLoaded("districts"))
];
}
}
class DistrictResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'hospitals' => HospitalTypeResource::collection($this->whenLoaded("hospital_types"))
];
}
}
class HospitalTypeResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$district = $this->village->district;
$oneLastYearRateLog = $this->hospital->last12MonthRageLogs();
$rateLogCount = $oneLastYearRateLog->count();
$oneLastYearMonitoringCount = $this->hospital->last12MonthMonitors()->count();
return [
"id" => $this->hospital->id,
"code" => $this->code,
"name" => $this->name,
"overallRating"=> $rateLogCount == 0 ? 0 : $oneLastYearRateLog->sum('rate') / $rateLogCount,
"ratingsCount" => $oneLastYearMonitoringCount
];
}
}
下面是我在医院的关系模式来做监测。
class Hospital extends Model
{
/**
* Get hospital monitors
*/
public function monitors()
{
return $this->hasMany(Monitoring::class, 'hospital_id', 'id');
}
public function last12MonthMonitors()
{
$lastMonitoring = $this->lastMonitoring();
if($lastMonitoring) {
return $this->monitors()->whereRaw('monitoring_date >= "'. $lastMonitoring->monitoring_date.'" - INTERVAL 12 month');
}
return $this->monitors();
}
private function lastMonitoring()
{
return $this->monitors()->select('monitoring_date')->latest('monitoring_date')->first();
}
/**
* Get rate logs
*/
public function rateLogs()
{
return $this->hasManyThrough(RateLog::class, Monitoring::class, 'hospital_id')
->where('rate', '!=', 'NA');
}
/**
* Get last 12 rate logs
*/
public function last12MonthRageLogs()
{
$lastMonitoring = $this->lastMonitoring();
if($lastMonitoring) {
return $this->rateLogs()->whereRaw('monitoring.monitoring_date >= "'.$lastMonitoring->monitoring_date.'" - INTERVAL 12 month');
}
return $this->rateLogs();
}
发布于 2021-11-30 10:07:50
您似乎并不急于加载hospital
关系。我首先要添加以下内容,这样您就不必为每个HospitalType
运行一个查询了
$data = Province::with(['districts.hospitalTypes.hospital'])->get();
我认为您的查询可能运行得稍微慢一点的原因之一是因为您的lastMonitoring
检查。首先,这个查询将为每个Hospital
运行,其次,您似乎没有存储/缓存该值,因此它实际上将是查询两次。
如果您更新到Laravel 8(minv8.4.2),您将能够为您的有多种关系之一方法使用lastMonitoring
方法,例如:
public function latestMonitoring()
{
return $this->hasOne(Monitoring::class)->latestOfMany('monitoring_date');
}
然后你就可以热切地去加载这种关系了:
$data = Province::with(['districts.hospitalTypes.hospital.latestMonitoring'])->get();
您还需要更新HospitalType
模型中的其他一些方法:
public function monitors()
{
return $this->hasMany(Monitoring::class, 'hospital_id', 'id');
}
/**
* Get rate logs
*/
public function rateLogs()
{
return $this->hasManyThrough(RateLog::class, Monitoring::class, 'hospital_id')
->where('rate', '!=', 'NA');
}
public function latestMonitoring()
{
return $this->hasOne(Monitoring::class, 'hospital_id', 'id')->latestOfMany('monitoring_date');
}
public function last12MonthMonitors()
{
return $this->monitors()->when($this->latestMonitoring, function ($query) {
$query->where('monitoring_date', '>=', $this->latestMonitoring->monitoring_date->subYear());
});
}
/**
* Get last 12 rate logs
*/
public function last12MonthRageLogs()
{
return $this->rateLogs()->when($this->latestMonitoring, function ($query) {
$query->where('monitoring.monitoring_date', '>=', $this->latestMonitoring->monitoring_date->subYear());
});
}
https://stackoverflow.com/questions/70165525
复制相似问题