Files
kupshop/bundles/KupShop/CatalogElasticBundle/Util/ElasticSectionsUtil.php
2025-08-02 16:30:27 +02:00

82 lines
2.8 KiB
PHP

<?php
namespace KupShop\CatalogElasticBundle\Util;
use Elastica\Aggregation as Agg;
use Elastica\Query as Q;
use Elastica\Query\BoolQuery;
use KupShop\CatalogBundle\Enum\InStore;
use KupShop\CatalogElasticBundle\Elastica\Query;
use KupShop\RestrictionsBundle\Utils\Restrictions;
readonly class ElasticSectionsUtil
{
protected const MAX_SECTION_COUNT = 10_000;
public function __construct(
protected ElasticaFactory $clientFactory,
protected ElasticSpecs $elasticSpecs,
protected ?Restrictions $restrictions,
) {
}
/** @return array{ count?: int, in_stock_count?: int, in_stock_suppliers_count?: int }[] */
public function fetchProductCounts(array $sectionIds): array
{
$query = new Query();
$query->setSource(false);
$query->setQuery($filters = new BoolQuery());
$filterParams = \FilterParams::createDefault();
$filterParams->setSectionsFilter($sectionIds);
foreach ($this->elasticSpecs->getFilters($filterParams) as $filter) {
$filters->addFilter($filter);
}
if (findModule(\Modules::RESTRICTIONS)) {
$this->elasticSpecs->applyRestrictionFilters($this->restrictions->getRestrictionFilterParams(), $filters);
}
$sectionsAgg = (new Agg\Terms('count'))
->setField('filter_section_recursive')
->setSize(self::MAX_SECTION_COUNT);
// Count all (visible) products in section
$query->addAggregation($sectionsAgg)
// In products in_store (exclusive)
->addAggregation(
(new Agg\Filter('in_stock_count'))
->setFilter(new Q\Term(['in_store' => InStore::InStore->value]))
->addAggregation($sectionsAgg),
)
// In products in_store at suppliers (exclusive) - will be summed up in self::createSectionFromArray
->addAggregation(
(new Agg\Filter('in_stock_suppliers_count'))
->setFilter(new Q\Term(['in_store' => InStore::InStoreSupplier->value]))
->addAggregation($sectionsAgg),
);
$search = $this->clientFactory->createSearch();
$search->setQuery($query);
$searchResult = $search->search();
$result = [];
foreach ($searchResult->getAggregations() as $name => $aggregation) {
if ($innerAgg = $aggregation['count'] ?? null) {
foreach ($innerAgg['buckets'] as $bucket) {
$result[$bucket['key']][$name] = $bucket['doc_count'];
}
continue;
}
foreach ($aggregation['buckets'] as $bucket) {
$result[$bucket['key']][$name] = $bucket['doc_count'];
}
}
return $result;
}
}