From cf6430ae9badcbc801f78c10ec062c6bfd1c5c66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 14 Nov 2022 14:22:48 +0100 Subject: [PATCH] Feature: Adapt geographical unit filters and aggregator to use the materialized view, instead of geographical computation (improve performance) --- .../GeographicalUnitStatAggregator.php | 64 ++++++++----------- .../GeographicalUnitAggregator.php | 4 +- .../GeographicalUnitStatFilter.php | 10 +-- .../PersonFilters/GeographicalUnitFilter.php | 4 +- .../translations/messages.fr.yml | 2 + 5 files changed, 33 insertions(+), 51 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/GeographicalUnitStatAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/GeographicalUnitStatAggregator.php index 891ce63e0..9dec0f116 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/GeographicalUnitStatAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/GeographicalUnitStatAggregator.php @@ -12,7 +12,6 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators; use Chill\MainBundle\Entity\Address; -use Chill\MainBundle\Entity\GeographicalUnit; use Chill\MainBundle\Entity\GeographicalUnitLayer; use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Form\Type\ChillDateType; @@ -26,7 +25,6 @@ use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; use UnexpectedValueException; -use function in_array; final class GeographicalUnitStatAggregator implements AggregatorInterface { @@ -49,57 +47,49 @@ final class GeographicalUnitStatAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('acp_geog_agg_location_history', $qb->getAllAliases(), true)) { - $qb->leftJoin('acp.locationHistories', 'acp_geog_agg_location_history'); + $qb->leftJoin('acp.locationHistories', 'acp_geog_agg_location_history'); - $qb->andWhere( - $qb->expr()->andX( - 'acp_geog_agg_location_history.startDate <= :acp_geog_aggregator_date', - $qb->expr()->orX( + $qb->andWhere( + $qb->expr()->andX( + 'acp_geog_agg_location_history.startDate <= :acp_geog_aggregator_date', + $qb->expr()->orX( 'acp_geog_agg_location_history.endDate IS NULL', 'acp_geog_agg_location_history.endDate > :acp_geog_aggregator_date' ) - ) - ); + ) + ); - $qb->setParameter('acp_geog_aggregator_date', $data['date_calc']); - } + $qb->setParameter('acp_geog_aggregator_date', $data['date_calc']); // link between location history and person - if (!in_array('acp_geog_agg_address_person_location', $qb->getAllAliases(), true)) { - $qb->leftJoin( - PersonHouseholdAddress::class, - 'acp_geog_agg_address_person_location', - Join::WITH, - $qb->expr()->andX( - 'IDENTITY(acp_geog_agg_address_person_location.person) = IDENTITY(acp_geog_agg_location_history.personLocation)', - 'acp_geog_agg_address_person_location.validFrom < :acp_geog_aggregator_date', - $qb->expr()->orX( + $qb->leftJoin( + PersonHouseholdAddress::class, + 'acp_geog_agg_address_person_location', + Join::WITH, + $qb->expr()->andX( + 'IDENTITY(acp_geog_agg_address_person_location.person) = IDENTITY(acp_geog_agg_location_history.personLocation)', + 'acp_geog_agg_address_person_location.validFrom < :acp_geog_aggregator_date', + $qb->expr()->orX( 'acp_geog_agg_address_person_location.validTo > :acp_geog_aggregator_date', $qb->expr()->isNull('acp_geog_agg_address_person_location.validTo') ) - ) - ); + ) + ); - $qb->setParameter('acp_geog_aggregator_date', $data['date_calc']); - } + $qb->setParameter('acp_geog_aggregator_date', $data['date_calc']); // we finally find an address - if (!in_array('acp_geog_agg_address', $qb->getAllAliases(), true)) { - $qb->leftJoin( - Address::class, - 'acp_geog_agg_address', - Join::WITH, - 'COALESCE(IDENTITY(acp_geog_agg_address_person_location.address), IDENTITY(acp_geog_agg_location_history.addressLocation)) = acp_geog_agg_address.id' - ); - } + $qb->leftJoin( + Address::class, + 'acp_geog_agg_address', + Join::WITH, + 'COALESCE(IDENTITY(acp_geog_agg_address_person_location.address), IDENTITY(acp_geog_agg_location_history.addressLocation)) = acp_geog_agg_address.id' + ); // and we do a join with units $qb->leftJoin( - GeographicalUnit::class, - 'acp_geog_units', - Join::WITH, - 'ST_CONTAINS(acp_geog_units.geom, acp_geog_agg_address.point) = TRUE' + 'acp_geog_agg_address.geographicalUnits', + 'acp_geog_units' ); $qb->andWhere($qb->expr()->eq('acp_geog_units.layer', ':acp_geog_unit_layer')); diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GeographicalUnitAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GeographicalUnitAggregator.php index 3513625e9..87fe6abb2 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GeographicalUnitAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GeographicalUnitAggregator.php @@ -11,7 +11,6 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\PersonAggregators; -use Chill\MainBundle\Entity\GeographicalUnit; use Chill\MainBundle\Entity\GeographicalUnitLayer; use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Form\Type\ChillDateType; @@ -19,7 +18,6 @@ use Chill\MainBundle\Repository\GeographicalUnitLayerRepositoryInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Export\Declarations; use DateTimeImmutable; -use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use LogicException; use Symfony\Bridge\Doctrine\Form\Type\EntityType; @@ -49,7 +47,7 @@ class GeographicalUnitAggregator implements AggregatorInterface $qb ->leftJoin('person.householdAddresses', 'person_geog_agg_current_household_address') ->leftJoin('person_geog_agg_current_household_address.address', 'person_geog_agg_address') - ->leftJoin(GeographicalUnit::class, 'person_geog_agg_geog_unit', Join::WITH, 'ST_CONTAINS(person_geog_agg_geog_unit.geom, person_geog_agg_address.point) = TRUE') + ->leftJoin('person_geog_agg_address.geographicalUnits', 'person_geog_agg_geog_unit') ->andWhere( $qb->expr()->orX( $qb->expr()->isNull('person_geog_agg_current_household_address'), diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/GeographicalUnitStatFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/GeographicalUnitStatFilter.php index ee420e63e..67355aeca 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/GeographicalUnitStatFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/GeographicalUnitStatFilter.php @@ -12,7 +12,6 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; use Chill\MainBundle\Entity\Address; -use Chill\MainBundle\Entity\GeographicalUnit; use Chill\MainBundle\Entity\GeographicalUnit\SimpleGeographicalUnitDTO; use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Form\Type\ChillDateType; @@ -23,7 +22,6 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress; use Chill\PersonBundle\Export\Declarations; use DateTimeImmutable; -use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; @@ -33,8 +31,6 @@ use Symfony\Component\Form\FormBuilderInterface; */ class GeographicalUnitStatFilter implements FilterInterface { - private EntityManagerInterface $em; - private GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository; private GeographicalUnitRepositoryInterface $geographicalUnitRepository; @@ -42,12 +38,10 @@ class GeographicalUnitStatFilter implements FilterInterface private TranslatableStringHelperInterface $translatableStringHelper; public function __construct( - EntityManagerInterface $em, GeographicalUnitRepositoryInterface $geographicalUnitRepository, GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository, TranslatableStringHelperInterface $translatableStringHelper ) { - $this->em = $em; $this->geographicalUnitRepository = $geographicalUnitRepository; $this->geographicalUnitLayerRepository = $geographicalUnitLayerRepository; $this->translatableStringHelper = $translatableStringHelper; @@ -68,7 +62,7 @@ class GeographicalUnitStatFilter implements FilterInterface WITH IDENTITY(acp_geog_filter_location_history.personLocation) = IDENTITY(acp_geog_filter_address_person_location.person) LEFT JOIN ' . Address::class . ' acp_geog_filter_address WITH COALESCE(IDENTITY(acp_geog_filter_address_person_location.address), IDENTITY(acp_geog_filter_location_history.addressLocation)) = acp_geog_filter_address.id - LEFT JOIN ' . GeographicalUnit::class . ' acp_geog_filter_units WITH ST_CONTAINS(acp_geog_filter_units.geom, acp_geog_filter_address.point) = TRUE + LEFT JOIN acp_geog_filter_address.geographicalUnits acp_geog_filter_units WHERE (acp_geog_filter_location_history.startDate <= :acp_geog_filter_date AND ( acp_geog_filter_location_history.endDate IS NULL OR acp_geog_filter_location_history.endDate < :acp_geog_filter_date @@ -120,7 +114,7 @@ class GeographicalUnitStatFilter implements FilterInterface { return ['Filtered by geographic unit: computed at %date%, only in %units%', [ '%date%' => $data['date_calc']->format('d-m-Y'), - '%units' => implode( + '%units%' => implode( ', ', array_map( function (SimpleGeographicalUnitDTO $item) { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/GeographicalUnitFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/GeographicalUnitFilter.php index 03d9ab568..3d539a442 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/GeographicalUnitFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/GeographicalUnitFilter.php @@ -11,7 +11,6 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Filter\PersonFilters; -use Chill\MainBundle\Entity\GeographicalUnit; use Chill\MainBundle\Entity\GeographicalUnit\SimpleGeographicalUnitDTO; use Chill\MainBundle\Form\Type\ChillDateType; use Chill\MainBundle\Repository\GeographicalUnitLayerRepositoryInterface; @@ -53,8 +52,7 @@ class GeographicalUnitFilter implements \Chill\MainBundle\Export\FilterInterface 'SELECT 1 FROM ' . PersonHouseholdAddress::class . ' person_filter_geog_person_household_address JOIN person_filter_geog_person_household_address.address person_filter_geog_address - JOIN ' . GeographicalUnit::class . ' person_filter_geog_unit - WITH ST_CONTAINS(person_filter_geog_unit.geom, person_filter_geog_address.point) = TRUE + JOIN person_filter_geog_address.geographicalUnits person_filter_geog_unit WHERE person_filter_geog_person_household_address.validFrom <= :person_filter_geog_date AND diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 0b53bd7a5..7c9afba48 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -586,6 +586,8 @@ end period date: Date de fin de la période Filter by current evaluations: Filtrer les évaluations en cours "Filtered by current evaluations": "Filtré: uniquement les évaluations en cours" +'Filtered by geographic unit: computed at %date%, only in %units%': 'Filtré par unité géographique: adresse le %date%, seulement les unités %units%' + ## social actions filters/aggr Filter by treating agent scope: Filtrer les actions par service de l'agent traitant "Filtered by treating agent scope: only %scopes%": "Filtré par service de l'agent traitant: uniquement %scopes%"