Fixed: [export] improve memory footprint for filter by Geographical Unit

This commit is contained in:
Julien Fastré 2022-11-03 13:59:16 +01:00
parent 03e765f811
commit 6fd75a175f
5 changed files with 84 additions and 19 deletions

View File

@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Entity\GeographicalUnit;
/**
* Simple GeographialUnit Data Transfer Object.
*
* This allow to get access to id, unitName, unitRefId, and layer's id
*/
class SimpleGeographicalUnitDTO
{
/**
* @readonly
* @psalm-readonly
*/
public int $id;
/**
* @readonly
* @psalm-readonly
*/
public int $layerId;
/**
* @readonly
* @psalm-readonly
*/
public string $unitName;
/**
* @readonly
* @psalm-readonly
*/
public string $unitRefId;
public function __construct(int $id, string $unitName, string $unitRefId, int $layerId)
{
$this->id = $id;
$this->unitName = $unitName;
$this->unitRefId = $unitRefId;
$this->layerId = $layerId;
}
}

View File

@ -205,6 +205,7 @@ class ExportAddressHelper
case 'floor':
case '_lat':
case '_lon':
case 'steps':
case 'postcode_code':
case 'postcode_name':
return static function ($value) use ($sanitizedKey, $translationPrefix) {

View File

@ -41,7 +41,7 @@ class GeographicalUnitRepository implements GeographicalUnitRepositoryInterface
{
return $this->repository
->createQueryBuilder('gu')
->select('PARTIAL gu.{id,unitName,unitRefId,layer}')
->select(sprintf('NEW %s(gu.id, gu.unitName, gu.unitRefId, IDENTITY(gu.layer))', GeographicalUnit\SimpleGeographicalUnitDTO::class))
->addOrderBy('IDENTITY(gu.layer)')
->addOrderBy(('gu.unitName'))
->getQuery()

View File

@ -13,8 +13,10 @@ 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;
use Chill\MainBundle\Repository\GeographicalUnitLayerRepositoryInterface;
use Chill\MainBundle\Repository\GeographicalUnitRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
@ -23,7 +25,7 @@ use Chill\PersonBundle\Export\Declarations;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
/**
@ -33,6 +35,8 @@ class GeographicalUnitStatFilter implements FilterInterface
{
private EntityManagerInterface $em;
private GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository;
private GeographicalUnitRepositoryInterface $geographicalUnitRepository;
private TranslatableStringHelperInterface $translatableStringHelper;
@ -40,10 +44,12 @@ class GeographicalUnitStatFilter implements FilterInterface
public function __construct(
EntityManagerInterface $em,
GeographicalUnitRepositoryInterface $geographicalUnitRepository,
GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository,
TranslatableStringHelperInterface $translatableStringHelper
) {
$this->em = $em;
$this->geographicalUnitRepository = $geographicalUnitRepository;
$this->geographicalUnitLayerRepository = $geographicalUnitLayerRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
@ -62,7 +68,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_units.geom, acp_geog_filter_address.point) = TRUE
LEFT JOIN ' . GeographicalUnit::class . ' acp_geog_filter_units WITH ST_CONTAINS(acp_geog_filter_units.geom, acp_geog_filter_address.point) = TRUE
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
@ -78,7 +84,7 @@ class GeographicalUnitStatFilter implements FilterInterface
$qb
->andWhere($qb->expr()->exists($subQueryDql))
->setParameter('acp_geog_filter_date', $data['date_calc'])
->setParameter('acp_geog_filter_units', $data['units']);
->setParameter('acp_geog_filter_units', array_map(static fn (SimpleGeographicalUnitDTO $unitDTO) => $unitDTO->id, $data['units']));
}
public function applyOn(): string
@ -95,13 +101,13 @@ class GeographicalUnitStatFilter implements FilterInterface
'data' => new DateTimeImmutable('today'),
'input' => 'datetime_immutable',
])
->add('units', EntityType::class, [
->add('units', ChoiceType::class, [
'label' => 'Geographical unit',
'placeholder' => 'Select a geographical unit',
'class' => GeographicalUnit::class,
'choices' => $this->geographicalUnitRepository->findAll(),
'choice_label' => function (GeographicalUnit $item) {
return $this->translatableStringHelper->localize($item->getLayer()->getName()) . ' > ' . $item->getUnitName();
'choice_value' => static fn (SimpleGeographicalUnitDTO $item) => $item->id,
'choice_label' => function (SimpleGeographicalUnitDTO $item) {
return $this->translatableStringHelper->localize($this->geographicalUnitLayerRepository->find($item->layerId)->getName()) . ' > ' . $item->unitName;
},
'attr' => [
'class' => 'select2',
@ -117,8 +123,8 @@ class GeographicalUnitStatFilter implements FilterInterface
'%units' => implode(
', ',
array_map(
function (GeographicalUnit $item) {
return $this->translatableStringHelper->localize($item->getLayer()->getName()) . ' > ' . $item->getUnitName();
function (SimpleGeographicalUnitDTO $item) {
return $this->translatableStringHelper->localize($this->geographicalUnitLayerRepository->find($item->layerId)->getName()) . ' > ' . $item->unitName;
},
$data['units']
)

View File

@ -12,27 +12,33 @@ 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;
use Chill\MainBundle\Repository\GeographicalUnitRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
use Chill\PersonBundle\Export\Declarations;
use DateTimeImmutable;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
class GeographicalUnitFilter implements \Chill\MainBundle\Export\FilterInterface
{
private GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository;
private GeographicalUnitRepositoryInterface $geographicalUnitRepository;
private TranslatableStringHelperInterface $translatableStringHelper;
public function __construct(
GeographicalUnitRepositoryInterface $geographicalUnitRepository,
GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository,
TranslatableStringHelperInterface $translatableStringHelper
) {
$this->geographicalUnitRepository = $geographicalUnitRepository;
$this->geographicalUnitLayerRepository = $geographicalUnitLayerRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
@ -65,7 +71,7 @@ class GeographicalUnitFilter implements \Chill\MainBundle\Export\FilterInterface
$qb->expr()->exists($subQuery)
)
->setParameter('person_filter_geog_date', $data['date_calc'])
->setParameter('person_filter_geog_units', $data['units']);
->setParameter('person_filter_geog_units', array_map(static fn (SimpleGeographicalUnitDTO $unitDTO) => $unitDTO->id, $data['units']));
}
public function applyOn()
@ -82,13 +88,13 @@ class GeographicalUnitFilter implements \Chill\MainBundle\Export\FilterInterface
'data' => new DateTimeImmutable('today'),
'input' => 'datetime_immutable',
])
->add('units', EntityType::class, [
->add('units', ChoiceType::class, [
'label' => 'Geographical unit',
'placeholder' => 'Select a geographical unit',
'class' => GeographicalUnit::class,
'choices' => $this->geographicalUnitRepository->findAll(),
'choice_label' => function (GeographicalUnit $item) {
return $this->translatableStringHelper->localize($item->getLayer()->getName()) . ' > ' . $item->getUnitName();
'choice_value' => static fn (SimpleGeographicalUnitDTO $item) => $item->id,
'choice_label' => function (SimpleGeographicalUnitDTO $item) {
return $this->translatableStringHelper->localize($this->geographicalUnitLayerRepository->find($item->layerId)->getName()) . ' > ' . $item->unitName;
},
'attr' => [
'class' => 'select2',
@ -106,10 +112,10 @@ class GeographicalUnitFilter implements \Chill\MainBundle\Export\FilterInterface
'units' => implode(
', ',
array_map(
function (GeographicalUnit $item) {
return $this->translatableStringHelper->localize($item->getLayer()->getName()) . ' > ' . $item->getUnitName();
function (SimpleGeographicalUnitDTO $item) {
return $this->translatableStringHelper->localize($this->geographicalUnitLayerRepository->find($item->layerId)->getName()) . ' > ' . $item->unitName;
},
$data['units']->toArray()
$data['units']
)
),
],