Loading src/ElasticSearch/Converter/CriteriaToEsRequest.php +48 −43 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ use IQDEV\Search\Document\Property\PropertyType; use IQDEV\Search\FIlter\Filter; use IQDEV\Search\Filter\FilterCollection; use IQDEV\Search\Filter\FilterGroupCollection; use IQDEV\Search\Filter\FilterKeyword; use IQDEV\Search\Filter\FilterNumber; use IQDEV\Search\Filter\FilterOperator; use IQDEV\Search\Filter\FilterType; use IQDEV\Search\Filter\LogicOperator; Loading Loading @@ -176,6 +178,9 @@ final class CriteriaToEsRequest { $numberFilter = new Query(); if ($filterCollection->isEmpty()) { return $numberFilter; } $ranges = []; foreach ($filterCollection as $filterGroup) { Loading Loading @@ -229,6 +234,11 @@ final class CriteriaToEsRequest private function getKeywordFilter(FilterCollection $filterCollection, array $excludeFilter = []): Query { $keywordFilter = new Query(); if ($filterCollection->isEmpty()) { return $keywordFilter; } foreach ($filterCollection as $filterGroup) { /** @var FilterGroupCollection $filterGroup */ if ($filterGroup->isEmpty()) { Loading Loading @@ -299,24 +309,16 @@ final class CriteriaToEsRequest ) ); [$queryFilters, $postFilters] = $this->groupFilters($criteria->filters()); $getKey = static fn(string $type, string $name): string => sprintf('%s_facet_%s', $type, $name); foreach ($criteria->filters() as $filterGroup) { foreach ($postFilters as $filterGroup) { /** @var FilterGroupCollection $filterGroup */ foreach ($filterGroup as $filter) { /** @var Filter $filter */ $field = $filter->field()->value(); if (in_array( $filter->operator()->value(), [ FilterOperator::LT, FilterOperator::LTE, FilterOperator::GT, FilterOperator::GTE, ], true ) ) { if ($filter->value() instanceof FilterNumber) { continue; } Loading @@ -332,6 +334,7 @@ final class CriteriaToEsRequest continue; } if ($filter->value() instanceof FilterKeyword) { $aggsFiltered = new Aggs($getKey('keyword', $field)); $aggsFiltered->addAggs( AggsFacetTerms::create( Loading @@ -340,8 +343,9 @@ final class CriteriaToEsRequest ) ); $queryKeywordFiltered = new Query(); $keywordFilter = $this->getKeywordFilter($criteria->filters(), [$field]); $numberFilter = $this->getNumberFilter($criteria->filters()); $keywordFilter = $this->getKeywordFilter($postFilters, [$field]); $numberFilter = $this->getNumberFilter($postFilters); if (false === $keywordFilter->isEmpty()) { $nestedFilterKeyword = new Nested(); $nestedFilterKeyword->setPath('search_data') Loading @@ -364,9 +368,11 @@ final class CriteriaToEsRequest $request->getAggs()->add($aggsFiltered); } } } $keywordFilter = $this->getKeywordFilter($criteria->filters()); $numberFilter = $this->getNumberFilter($criteria->filters()); $keywordFilter = $this->getKeywordFilter($postFilters); $numberFilter = $this->getNumberFilter($postFilters); $aggsKeywordFiltered = new Aggs('keyword_facet_filtered'); $aggsKeywordFiltered->addAggs( Loading Loading @@ -419,7 +425,6 @@ final class CriteriaToEsRequest $request->getAggs() ->add($aggsKeywordFiltered) ->add($aggsNumberFiltered); } return $request; } Loading src/ElasticSearch/Converter/EsResponseToResult.php +93 −82 Original line number Diff line number Diff line Loading @@ -35,6 +35,31 @@ final class EsResponseToResult } if (isset($data['aggregations']['keyword_facet']['agg_keyword_facet_code']['buckets'])) { $this->parseKeywordFacet($data, $catalogSearchResult); } if (isset($data['aggregations']['number_facet']['agg_number_facet_code']['buckets'])) { $this->parseNumberFacet($data, $catalogSearchResult); } return $catalogSearchResult; } private function productFromArray(array $data): Product { if (!isset($data['data']['id'])) { throw new \RuntimeException('id is not set'); } $id = $data['data']['id']; $title = $data['data']['title'] ?? ''; $info = $data; return new Product($id, $title, $info); } private function parseKeywordFacet(array $data, Result $catalogSearchResult) { $buckets = $data['aggregations']['keyword_facet']['agg_keyword_facet_code']['buckets']; $bucketsFiltered = []; if (isset($data['aggregations']['keyword_facet_filtered']['all_keyword_facet_filtered']['agg_keyword_facet_code']['buckets'])) { Loading @@ -61,6 +86,7 @@ final class EsResponseToResult } $bucketsFiltered = array_filter($bucketsFiltered); foreach ($buckets as $bucket) { $code = $bucket['key']; $valueBucket = $bucket['agg_keyword_facet_value']['buckets']; Loading @@ -87,7 +113,8 @@ final class EsResponseToResult } } if (isset($data['aggregations']['number_facet']['agg_number_facet_code']['buckets'])) { private function parseNumberFacet(array $data, Result $catalogSearchResult) { $buckets = $data['aggregations']['number_facet']['agg_number_facet_code']['buckets']; $bucketsFiltered = []; Loading Loading @@ -124,20 +151,4 @@ final class EsResponseToResult $catalogSearchResult->getFacets()->add($facet); } } return $catalogSearchResult; } private function productFromArray(array $data): Product { if (!isset($data['data']['id'])) { throw new \RuntimeException('id is not set'); } $id = $data['data']['id']; $title = $data['data']['title'] ?? ''; $info = $data; return new Product($id, $title, $info); } } tests/FIlter/QueryAndPostFilterTest.php 0 → 100644 +649 −0 File added.Preview size limit exceeded, changes collapsed. Show changes tests/FIlter/QueryTest.php +154 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,8 @@ namespace IQDEV\ElasticSearchTests\Filter; use IQDEV\ElasticSearch\Converter\CriteriaToEsRequest; use IQDEV\ElasticSearchTests\AbstractTestCase; use IQDEV\ElasticSearchTests\Helpers\FormatData; use IQDEV\ElasticSearchTests\Service\SearchClient; use IQDEV\Search\Criteria; use IQDEV\Search\Filter\Field; use IQDEV\Search\Filter\Filter; Loading @@ -12,6 +14,7 @@ use IQDEV\Search\Filter\FilterKeyword; use IQDEV\Search\Filter\FilterNumber; use IQDEV\Search\Filter\FilterOperator; use IQDEV\Search\Filter\FilterType; use IQDEV\Search\Query\SearchQuery; /** * Тестирование агрегирующих функций Loading Loading @@ -333,4 +336,155 @@ class QueryTest extends AbstractTestCase $this->assertArray($expected, $request->es()); } public function testGlobalFilterPrice() { $filter = [ 'price' => [ 'key' => 'price', 'min' => 105, 'lower' => 103, ] ]; $criteria = new Criteria(); $filterCollectionPrice = new FilterGroupCollection([ new Filter( new Field($filter['price']['key']), new FilterOperator(FilterOperator::GTE), new FilterNumber($filter['price']['min']) ) ]); $criteria->filters()->add($filterCollectionPrice); $filterCollectionQueryPrice = new FilterGroupCollection([ new Filter( new Field($filter['price']['key']), new FilterOperator(FilterOperator::GTE), new FilterNumber($filter['price']['lower']) ), ]); $filterCollectionQueryPrice->setFilterType(FilterType::query()); $criteria->filters()->add($filterCollectionQueryPrice); $q = new SearchQuery($criteria); $handler = SearchClient::getInstance(); $result = $handler->handle($q)->result; $expected = [ 'hits' => [ 'h2', 'h3', 'p1', ], "facets" => [ 0 => [ "code" => "brand", "label" => null, "type" => "list", "items" => [ "list" => [ 0 => [ "label" => null, "value" => "nike", "count" => 1, "active" => true, ], 1 => [ "label" => null, "value" => "rebook", "count" => 2, "active" => true, ] ], "range" => [], ], ], 1 => [ "code" => "color", "label" => null, "type" => "list", "items" => [ "list" => [ 0 => [ "label" => null, "value" => "green", "count" => 0, "active" => false, ], 1 => [ "label" => null, "value" => "red", "count" => 0, "active" => false, ], 2 => [ "label" => null, "value" => "white", "count" => 3, "active" => true, ], ], "range" => [], ], ], 2 => [ "code" => "size", "label" => null, "type" => "list", "items" => [ "list" => [ 0 => [ "label" => null, "count" => 0, "value" => "43", "active" => false, ], 1 => [ "label" => null, "value" => "xl", "count" => 2, "active" => true, ], 2 => [ "label" => null, "value" => "xxl", "count" => 1, "active" => true, ], ], "range" => [], ], ], 3 => [ "code" => "price", "label" => null, "type" => "range", "items" => [ "list" => [], "range" => [ 0 => [ "label" => null, "count" => 3, "active" => true, "fullRange" => [ "min" => 103.0, "max" => 107.0, ], "activeRange" => [ "min" => 105.0, "max" => 107.0, ] ] ] ] ] ] ]; $this->assertEqualsCanonicalizing($expected, FormatData::formatDataWFacets($result)); } } No newline at end of file Loading
src/ElasticSearch/Converter/CriteriaToEsRequest.php +48 −43 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ use IQDEV\Search\Document\Property\PropertyType; use IQDEV\Search\FIlter\Filter; use IQDEV\Search\Filter\FilterCollection; use IQDEV\Search\Filter\FilterGroupCollection; use IQDEV\Search\Filter\FilterKeyword; use IQDEV\Search\Filter\FilterNumber; use IQDEV\Search\Filter\FilterOperator; use IQDEV\Search\Filter\FilterType; use IQDEV\Search\Filter\LogicOperator; Loading Loading @@ -176,6 +178,9 @@ final class CriteriaToEsRequest { $numberFilter = new Query(); if ($filterCollection->isEmpty()) { return $numberFilter; } $ranges = []; foreach ($filterCollection as $filterGroup) { Loading Loading @@ -229,6 +234,11 @@ final class CriteriaToEsRequest private function getKeywordFilter(FilterCollection $filterCollection, array $excludeFilter = []): Query { $keywordFilter = new Query(); if ($filterCollection->isEmpty()) { return $keywordFilter; } foreach ($filterCollection as $filterGroup) { /** @var FilterGroupCollection $filterGroup */ if ($filterGroup->isEmpty()) { Loading Loading @@ -299,24 +309,16 @@ final class CriteriaToEsRequest ) ); [$queryFilters, $postFilters] = $this->groupFilters($criteria->filters()); $getKey = static fn(string $type, string $name): string => sprintf('%s_facet_%s', $type, $name); foreach ($criteria->filters() as $filterGroup) { foreach ($postFilters as $filterGroup) { /** @var FilterGroupCollection $filterGroup */ foreach ($filterGroup as $filter) { /** @var Filter $filter */ $field = $filter->field()->value(); if (in_array( $filter->operator()->value(), [ FilterOperator::LT, FilterOperator::LTE, FilterOperator::GT, FilterOperator::GTE, ], true ) ) { if ($filter->value() instanceof FilterNumber) { continue; } Loading @@ -332,6 +334,7 @@ final class CriteriaToEsRequest continue; } if ($filter->value() instanceof FilterKeyword) { $aggsFiltered = new Aggs($getKey('keyword', $field)); $aggsFiltered->addAggs( AggsFacetTerms::create( Loading @@ -340,8 +343,9 @@ final class CriteriaToEsRequest ) ); $queryKeywordFiltered = new Query(); $keywordFilter = $this->getKeywordFilter($criteria->filters(), [$field]); $numberFilter = $this->getNumberFilter($criteria->filters()); $keywordFilter = $this->getKeywordFilter($postFilters, [$field]); $numberFilter = $this->getNumberFilter($postFilters); if (false === $keywordFilter->isEmpty()) { $nestedFilterKeyword = new Nested(); $nestedFilterKeyword->setPath('search_data') Loading @@ -364,9 +368,11 @@ final class CriteriaToEsRequest $request->getAggs()->add($aggsFiltered); } } } $keywordFilter = $this->getKeywordFilter($criteria->filters()); $numberFilter = $this->getNumberFilter($criteria->filters()); $keywordFilter = $this->getKeywordFilter($postFilters); $numberFilter = $this->getNumberFilter($postFilters); $aggsKeywordFiltered = new Aggs('keyword_facet_filtered'); $aggsKeywordFiltered->addAggs( Loading Loading @@ -419,7 +425,6 @@ final class CriteriaToEsRequest $request->getAggs() ->add($aggsKeywordFiltered) ->add($aggsNumberFiltered); } return $request; } Loading
src/ElasticSearch/Converter/EsResponseToResult.php +93 −82 Original line number Diff line number Diff line Loading @@ -35,6 +35,31 @@ final class EsResponseToResult } if (isset($data['aggregations']['keyword_facet']['agg_keyword_facet_code']['buckets'])) { $this->parseKeywordFacet($data, $catalogSearchResult); } if (isset($data['aggregations']['number_facet']['agg_number_facet_code']['buckets'])) { $this->parseNumberFacet($data, $catalogSearchResult); } return $catalogSearchResult; } private function productFromArray(array $data): Product { if (!isset($data['data']['id'])) { throw new \RuntimeException('id is not set'); } $id = $data['data']['id']; $title = $data['data']['title'] ?? ''; $info = $data; return new Product($id, $title, $info); } private function parseKeywordFacet(array $data, Result $catalogSearchResult) { $buckets = $data['aggregations']['keyword_facet']['agg_keyword_facet_code']['buckets']; $bucketsFiltered = []; if (isset($data['aggregations']['keyword_facet_filtered']['all_keyword_facet_filtered']['agg_keyword_facet_code']['buckets'])) { Loading @@ -61,6 +86,7 @@ final class EsResponseToResult } $bucketsFiltered = array_filter($bucketsFiltered); foreach ($buckets as $bucket) { $code = $bucket['key']; $valueBucket = $bucket['agg_keyword_facet_value']['buckets']; Loading @@ -87,7 +113,8 @@ final class EsResponseToResult } } if (isset($data['aggregations']['number_facet']['agg_number_facet_code']['buckets'])) { private function parseNumberFacet(array $data, Result $catalogSearchResult) { $buckets = $data['aggregations']['number_facet']['agg_number_facet_code']['buckets']; $bucketsFiltered = []; Loading Loading @@ -124,20 +151,4 @@ final class EsResponseToResult $catalogSearchResult->getFacets()->add($facet); } } return $catalogSearchResult; } private function productFromArray(array $data): Product { if (!isset($data['data']['id'])) { throw new \RuntimeException('id is not set'); } $id = $data['data']['id']; $title = $data['data']['title'] ?? ''; $info = $data; return new Product($id, $title, $info); } }
tests/FIlter/QueryAndPostFilterTest.php 0 → 100644 +649 −0 File added.Preview size limit exceeded, changes collapsed. Show changes
tests/FIlter/QueryTest.php +154 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,8 @@ namespace IQDEV\ElasticSearchTests\Filter; use IQDEV\ElasticSearch\Converter\CriteriaToEsRequest; use IQDEV\ElasticSearchTests\AbstractTestCase; use IQDEV\ElasticSearchTests\Helpers\FormatData; use IQDEV\ElasticSearchTests\Service\SearchClient; use IQDEV\Search\Criteria; use IQDEV\Search\Filter\Field; use IQDEV\Search\Filter\Filter; Loading @@ -12,6 +14,7 @@ use IQDEV\Search\Filter\FilterKeyword; use IQDEV\Search\Filter\FilterNumber; use IQDEV\Search\Filter\FilterOperator; use IQDEV\Search\Filter\FilterType; use IQDEV\Search\Query\SearchQuery; /** * Тестирование агрегирующих функций Loading Loading @@ -333,4 +336,155 @@ class QueryTest extends AbstractTestCase $this->assertArray($expected, $request->es()); } public function testGlobalFilterPrice() { $filter = [ 'price' => [ 'key' => 'price', 'min' => 105, 'lower' => 103, ] ]; $criteria = new Criteria(); $filterCollectionPrice = new FilterGroupCollection([ new Filter( new Field($filter['price']['key']), new FilterOperator(FilterOperator::GTE), new FilterNumber($filter['price']['min']) ) ]); $criteria->filters()->add($filterCollectionPrice); $filterCollectionQueryPrice = new FilterGroupCollection([ new Filter( new Field($filter['price']['key']), new FilterOperator(FilterOperator::GTE), new FilterNumber($filter['price']['lower']) ), ]); $filterCollectionQueryPrice->setFilterType(FilterType::query()); $criteria->filters()->add($filterCollectionQueryPrice); $q = new SearchQuery($criteria); $handler = SearchClient::getInstance(); $result = $handler->handle($q)->result; $expected = [ 'hits' => [ 'h2', 'h3', 'p1', ], "facets" => [ 0 => [ "code" => "brand", "label" => null, "type" => "list", "items" => [ "list" => [ 0 => [ "label" => null, "value" => "nike", "count" => 1, "active" => true, ], 1 => [ "label" => null, "value" => "rebook", "count" => 2, "active" => true, ] ], "range" => [], ], ], 1 => [ "code" => "color", "label" => null, "type" => "list", "items" => [ "list" => [ 0 => [ "label" => null, "value" => "green", "count" => 0, "active" => false, ], 1 => [ "label" => null, "value" => "red", "count" => 0, "active" => false, ], 2 => [ "label" => null, "value" => "white", "count" => 3, "active" => true, ], ], "range" => [], ], ], 2 => [ "code" => "size", "label" => null, "type" => "list", "items" => [ "list" => [ 0 => [ "label" => null, "count" => 0, "value" => "43", "active" => false, ], 1 => [ "label" => null, "value" => "xl", "count" => 2, "active" => true, ], 2 => [ "label" => null, "value" => "xxl", "count" => 1, "active" => true, ], ], "range" => [], ], ], 3 => [ "code" => "price", "label" => null, "type" => "range", "items" => [ "list" => [], "range" => [ 0 => [ "label" => null, "count" => 3, "active" => true, "fullRange" => [ "min" => 103.0, "max" => 107.0, ], "activeRange" => [ "min" => 105.0, "max" => 107.0, ] ] ] ] ] ] ]; $this->assertEqualsCanonicalizing($expected, FormatData::formatDataWFacets($result)); } } No newline at end of file