fix: improve doctor search performance by optimizing query filters in findWithFilters method
This commit is contained in:
@@ -49,17 +49,25 @@ class DoctorRepository extends ServiceEntityRepository
|
||||
->leftJoin('d.specialties', 's')
|
||||
->leftJoin('d.provinces', 'pr')
|
||||
->leftJoin('d.cities', 'ci')
|
||||
->leftJoin(Clinic::class, 'cl', Join::WITH, 'd MEMBER OF cl.doctors')
|
||||
->leftJoin(DoctorAddress::class, 'ca', Join::WITH, 'ca.clinicId = cl.id AND ca.doctor IS NULL')
|
||||
->distinct();
|
||||
|
||||
if (!empty($filters['state'])) {
|
||||
$qb->andWhere('pr.id = :state OR IDENTITY(ca.province) = :state')
|
||||
->setParameter('state', (int) $filters['state']);
|
||||
$stateId = (int) $filters['state'];
|
||||
$clinicIds = $this->doctorIdsViaClinicLocation('province', $stateId);
|
||||
$qb->andWhere('pr.id = :state' . ($clinicIds ? ' OR d.id IN (:stateClinicDoctorIds)' : ''))
|
||||
->setParameter('state', $stateId);
|
||||
if ($clinicIds) {
|
||||
$qb->setParameter('stateClinicDoctorIds', $clinicIds);
|
||||
}
|
||||
}
|
||||
if (!empty($filters['city'])) {
|
||||
$qb->andWhere('ci.id = :city OR IDENTITY(ca.city) = :city')
|
||||
->setParameter('city', (int) $filters['city']);
|
||||
$cityId = (int) $filters['city'];
|
||||
$clinicIds = $this->doctorIdsViaClinicLocation('city', $cityId);
|
||||
$qb->andWhere('ci.id = :city' . ($clinicIds ? ' OR d.id IN (:cityClinicDoctorIds)' : ''))
|
||||
->setParameter('city', $cityId);
|
||||
if ($clinicIds) {
|
||||
$qb->setParameter('cityClinicDoctorIds', $clinicIds);
|
||||
}
|
||||
}
|
||||
if (!empty($filters['specialty'])) {
|
||||
$qb->andWhere('s.id = :specialty')->setParameter('specialty', (int) $filters['specialty']);
|
||||
@@ -95,6 +103,31 @@ class DoctorRepository extends ServiceEntityRepository
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* IDs of doctors who belong to a clinic whose own address (DoctorAddress with
|
||||
* doctor IS NULL) is in the given city/province. Used so doctors without a
|
||||
* direct address still surface under their clinic's location, without a
|
||||
* per-row correlated subquery on the main search.
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
private function doctorIdsViaClinicLocation(string $field, int $locationId): array
|
||||
{
|
||||
$column = $field === 'city' ? 'ca.city' : 'ca.province';
|
||||
|
||||
$rows = $this->getEntityManager()->createQueryBuilder()
|
||||
->select('cd.id AS doctorId')
|
||||
->from(Clinic::class, 'cl')
|
||||
->join('cl.doctors', 'cd')
|
||||
->join(DoctorAddress::class, 'ca', Join::WITH, 'ca.clinicId = cl.id AND ca.doctor IS NULL')
|
||||
->where(sprintf('IDENTITY(%s) = :loc', $column))
|
||||
->setParameter('loc', $locationId)
|
||||
->getQuery()
|
||||
->getScalarResult();
|
||||
|
||||
return array_values(array_unique(array_map('intval', array_column($rows, 'doctorId'))));
|
||||
}
|
||||
|
||||
public function findByClinicWithFilters(int $clinicId, array $filters): array
|
||||
{
|
||||
$page = max(1, (int) ($filters['page'] ?? 1));
|
||||
|
||||
Reference in New Issue
Block a user