Commit 5f2e0f9b authored by Pavel's avatar Pavel
Browse files

логика полной фасетной фильтрации, базовый класс для индексации

parent fa37f21a
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -10,14 +10,16 @@ class ProductDocument implements Document
    private FacetCollection $keywordFacets;
    private FacetCollection $numberFacets;
    private ?string $fullSearchContent = null;
    private array $info;

    private FacetCategory $categoryFacet;

    public function __construct(FacetCategory $categoryFacet)
    public function __construct(FacetCategory $categoryFacet, array $info = [])
    {
        $this->keywordFacets = new FacetCollection();
        $this->numberFacets = new FacetCollection();
        $this->categoryFacet = $categoryFacet;
        $this->info = $info;
    }

    /**
@@ -60,6 +62,7 @@ class ProductDocument implements Document
                'keyword_facet' => $this->getKeywordFacets()->es(),
                'number_facet' => $this->getNumberFacets()->es()
            ],
            'data' => $this->info
        ];

        if ($this->fullSearchContent) {
+20 −6
Original line number Diff line number Diff line
@@ -49,6 +49,20 @@ final class SearchResultFactory
                }
            }

            foreach ($buckets as $bucket) {
                $code = $bucket['key'];
                if (isset($data['aggregations']["keyword_facet_$code"]['agg_special']['agg_keyword_facet_code']['buckets'])) {
                    $bucketsFiltered[$code] = [];
                    foreach ($data['aggregations']["keyword_facet_$code"]['agg_special']['agg_keyword_facet_code']['buckets'] as $filtredBucket) {
                        foreach ($filtredBucket['agg_keyword_facet_value']['buckets'] as $values) {
                            if ($filtredBucket['key'] === $code) {
                                $bucketsFiltered[$code][$values['key']] = $values;
                            }
                        }
                    }
                }
            }

            foreach ($buckets as $bucket) {
                $code        = $bucket['key'];
                $valueBucket = $bucket['agg_keyword_facet_value']['buckets'];
@@ -74,8 +88,8 @@ final class SearchResultFactory
                foreach ($data['aggregations']['number_facet_filtered']['all_number_facet_filtered']['agg_number_facet_code']['buckets'] as $bucket) {
                    $bucketsFiltered[$bucket['key']] = [
                        'data' => $bucket,
                        'min' => $bucket['agg_number_facet_min_value'],
                        'max' => $bucket['agg_number_facet_max_value']
                        'min' => $bucket['agg_number_facet_value']['min'],
                        'max' => $bucket['agg_number_facet_value']['max']
                    ];
                }
            }
@@ -88,13 +102,13 @@ final class SearchResultFactory
                $selectedMin = $selectedMax = null;
                if (isset($bucketsFiltered[$code])) {
                    $count       = $bucketsFiltered[$code]['data']['doc_count'];
                    $selectedMin = $bucketsFiltered[$code]['min']['value'];
                    $selectedMax = $bucketsFiltered[$code]['max']['value'];
                    $selectedMin = $bucketsFiltered[$code]['min'];
                    $selectedMax = $bucketsFiltered[$code]['max'];
                }

                $facet->items->add(FacetItemRange::createFromRange(
                    $bucket['agg_number_facet_min_value']['value'],
                    $bucket['agg_number_facet_max_value']['value'],
                    $bucket['agg_number_facet_value']['min'],
                    $bucket['agg_number_facet_value']['max'],
                    $count,
                    $selectedMin,
                    $selectedMax
+65 −33
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ use IQDEV\ElasticSearch\Search\Pagination;
use IQDEV\ElasticSearch\Search\Request;
use Elastic\Elasticsearch\Client;
use IQDEV\Search\{Filter\Filter,
    Filter\FilterCollection,
    Filter\FilterKeyword,
    Filter\FilterCategory,
    Filter\FilterNumber,
@@ -22,8 +23,7 @@ use IQDEV\Search\{Filter\Filter,
    SearchService as DomainSearchService,
    Sorting\SortingFieldPair as DSortingFieldPair,
    Sorting\SortingPropertyKeywordPair as DSortingPropertyKeywordPair,
    Sorting\SortingPropertyNumberPair as DSortingPropertyNumberPair
};
    Sorting\SortingPropertyNumberPair as DSortingPropertyNumberPair};
use IQDEV\ElasticSearch\Search\Sorting\SortingCollection;
use IQDEV\ElasticSearch\Search\Sorting\SortingFieldsPair;
use IQDEV\ElasticSearch\Search\Sorting\SortingPropertyKeywordPair;
@@ -44,8 +44,6 @@ final class SearchService implements DomainSearchService
    {
        $request       = new Request();
        $commonQuery   = new Query();
        $filterKeyword = new Query();
        $filterNumber  = new Query();

        if ($q->filters) {
            foreach ($q->filters as $filter) {
@@ -54,23 +52,10 @@ final class SearchService implements DomainSearchService
                    $request->getQuery()->must(
                        (new Terms('category_id', $filter->value))
                    );
                    continue;
                }

                if ($filter instanceof FilterNumber) {
                    $oFacet = new FilterNumberFacet($filter->key, $filter->min, $filter->max);
                    $filterNumber->filter($oFacet);
                    $commonQuery->filter($oFacet);
                    continue;
                }

                if ($filter instanceof FilterKeyword) {
                    $oFacet = new FilterKeywordFacet($filter->key, $filter->value);
                    $filterKeyword->filter($oFacet);
                    $commonQuery->filter($oFacet);
                    continue;
                    break;
                }
            }
            $commonQuery = $this->getQuery($q->filters);
        }
        $commonFilter = clone $commonQuery;
        $commonFilter->setType(Query::TYPE_FILTER);
@@ -103,19 +88,46 @@ final class SearchService implements DomainSearchService
            $request->addMatch('full_search_content', ['query' => $q->query]);
        }

        if ($filterKeyword->isEmpty() === false) {
            $nestedFilterKeyword = new Nested();
            $nestedFilterKeyword->setPath('search_data')
                ->setQuery($filterKeyword);
        $getKey = static fn (string $type, string $name): string => sprintf('%s_facet_%s', $type, $name);
        if ($commonQuery->isEmpty() === false) {
            foreach ($q->filters as $filter) {
                /** @var Filter $filter */
                if ($filter instanceof FilterCategory || $filter instanceof FilterNumber) {
                    continue;
                }

        if ($filterNumber->isEmpty() === false) {
            $nestedFilterNumber = new Nested();
            $nestedFilterNumber->setPath('search_data')
                ->setQuery($filterNumber);
                $oFilters = new FilterCollection();

                if ($filter instanceof FilterKeyword) {
                    foreach ($q->filters as $filter2) {
                        if (!($filter2 instanceof Filter) || $filter2 instanceof FilterCategory) {
                            continue;
                        }

                        if ($filter->key() === $filter2->key()) {
                            continue;
                        }
                        $oFilters->add($filter2);
                    }
                }

                $aggsFiltered = new Aggs($getKey('keyword', $filter->key()));
                $aggsFiltered->addAggs(
                    AggsKeyWordFacet::create(
                        'agg_special',
                        'keyword_facet'
                    )
                );

                if (false === $oFilters->isEmpty()) {
                    $aggsFiltered->setQuery($this->getQuery($oFilters));
                } else {
                    $aggsFiltered->setNested((new Nested())->setPath('search_data'));
                }

                $request->getAggs()->add($aggsFiltered);
            }

        if ($commonQuery->isEmpty() === false) {
            $nestedFilter = new Nested();
            $nestedFilter->setPath('search_data')
                ->setQuery($commonQuery);
@@ -148,4 +160,24 @@ final class SearchService implements DomainSearchService

        return SearchResultFactory::createFromResponse($response, $request);
    }

    private function getQuery(FilterCollection $filters): Query
    {
        $commonQuery = new Query();
        foreach ($filters as $filter) {
            if ($filter instanceof FilterNumber) {
                $oFacet = new FilterNumberFacet($filter->key, $filter->min, $filter->max);
                $commonQuery->filter($oFacet);
                continue;
            }

            if ($filter instanceof FilterKeyword) {
                $oFacet = new FilterKeywordFacet($filter->key, $filter->value);
                $commonQuery->filter($oFacet);
                continue;
            }
        }

        return $commonQuery;
    }
}
+44 −0
Original line number Diff line number Diff line
<?php

namespace IQDEV\ElasticSearch\Indexer;

use IQDEV\ElasticSearch\Configuration;
use IQDEV\ElasticSearch\Document\ProductDocument;
use IQDEV\ElasticSearch\Facet\FacetCategory;
use IQDEV\ElasticSearch\Facet\FacetKeyword;
use IQDEV\ElasticSearch\Facet\FacetNumber;

class BaseIndexProvider implements IndexProvider
{
    private array $products;
    private Configuration $configuration;

    public function __construct($products, $configuration)
    {
        $this->configuration = $configuration;
        $this->products = $products;
    }

    public function get(): \Generator
    {
        foreach ($this->products as $product) {
            $document = new ProductDocument(new FacetCategory($product['category']), $product['data'] ?? []);
            foreach ($product['properties'] as $type => $values) {
                foreach ($values as $key => $prop) {
                    if ($type === 'number') {
                        $document->getNumberFacets()->add(new FacetNumber($key, $prop));
                    } else {
                        $document->getKeywordFacets()->add(new FacetKeyword($key, $prop));
                    }
                }
            }
            $document->setFullSearchContent($product['name']);

            yield new Index(
                $this->configuration->getIndexName(),
                $document,
                $product['id']
            );
        }
    }
}
 No newline at end of file
+1 −9
Original line number Diff line number Diff line
@@ -18,17 +18,9 @@ final class AggsNumberFacet
            (new Terms("{$path}.{$facet}.facet_code"))
        );

        $aggFacetValue = new Aggs("agg_{$facet}_min_value");
        $aggFacetValue = new Aggs("agg_{$facet}_value");
        $aggFacetValue->setExtremumTerms(
            (new ExtremumTerms("{$path}.{$facet}.facet_value"))
            ->setOperation('min')
        );
        $aggFacetCode->addAggs($aggFacetValue);

        $aggFacetValue = new Aggs("agg_{$facet}_max_value");
        $aggFacetValue->setExtremumTerms(
            (new ExtremumTerms("{$path}.{$facet}.facet_value"))
                ->setOperation('max')
        );
        $aggFacetCode->addAggs($aggFacetValue);

Loading