82 lines
2.8 KiB
PHP
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;
|
|
}
|
|
}
|