From 2656b229872f0af44edfab133bee9974624c7a49 Mon Sep 17 00:00:00 2001 From: Vadim Galizyanov Date: Thu, 4 May 2023 15:24:52 +0500 Subject: [PATCH] Added tests for query and post filter --- .../Converter/CriteriaToEsRequest.php | 91 +-- .../Converter/EsResponseToResult.php | 175 ++--- tests/FIlter/QueryAndPostFilterTest.php | 649 ++++++++++++++++++ tests/FIlter/QueryTest.php | 154 +++++ 4 files changed, 944 insertions(+), 125 deletions(-) create mode 100644 tests/FIlter/QueryAndPostFilterTest.php diff --git a/src/ElasticSearch/Converter/CriteriaToEsRequest.php b/src/ElasticSearch/Converter/CriteriaToEsRequest.php index 46cec2b..0150585 100644 --- a/src/ElasticSearch/Converter/CriteriaToEsRequest.php +++ b/src/ElasticSearch/Converter/CriteriaToEsRequest.php @@ -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; @@ -176,6 +178,9 @@ final class CriteriaToEsRequest { $numberFilter = new Query(); + if ($filterCollection->isEmpty()) { + return $numberFilter; + } $ranges = []; foreach ($filterCollection as $filterGroup) { @@ -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()) { @@ -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; } @@ -332,41 +334,45 @@ final class CriteriaToEsRequest continue; } - $aggsFiltered = new Aggs($getKey('keyword', $field)); - $aggsFiltered->addAggs( - AggsFacetTerms::create( - 'agg_special', - 'keyword_facet' - ) - ); - $queryKeywordFiltered = new Query(); - $keywordFilter = $this->getKeywordFilter($criteria->filters(), [$field]); - $numberFilter = $this->getNumberFilter($criteria->filters()); - if (false === $keywordFilter->isEmpty()) { - $nestedFilterKeyword = new Nested(); - $nestedFilterKeyword->setPath('search_data') - ->setQuery($keywordFilter); - $queryKeywordFiltered->filter($nestedFilterKeyword); - } + if ($filter->value() instanceof FilterKeyword) { + $aggsFiltered = new Aggs($getKey('keyword', $field)); + $aggsFiltered->addAggs( + AggsFacetTerms::create( + 'agg_special', + 'keyword_facet' + ) + ); + $queryKeywordFiltered = new Query(); + + $keywordFilter = $this->getKeywordFilter($postFilters, [$field]); + $numberFilter = $this->getNumberFilter($postFilters); + if (false === $keywordFilter->isEmpty()) { + $nestedFilterKeyword = new Nested(); + $nestedFilterKeyword->setPath('search_data') + ->setQuery($keywordFilter); + $queryKeywordFiltered->filter($nestedFilterKeyword); + } - if (false === $numberFilter->isEmpty()) { - $nestedFilterNumber = new Nested(); - $nestedFilterNumber->setPath('search_data') - ->setQuery($numberFilter); - $queryKeywordFiltered->filter($nestedFilterNumber); - } + if (false === $numberFilter->isEmpty()) { + $nestedFilterNumber = new Nested(); + $nestedFilterNumber->setPath('search_data') + ->setQuery($numberFilter); + $queryKeywordFiltered->filter($nestedFilterNumber); + } - if ($queryKeywordFiltered->isEmpty() === false) { - $aggsFiltered->setQuery($queryKeywordFiltered); - } else { - $aggsFiltered->setNested((new Nested())->setPath('search_data')); - } + if ($queryKeywordFiltered->isEmpty() === false) { + $aggsFiltered->setQuery($queryKeywordFiltered); + } else { + $aggsFiltered->setNested((new Nested())->setPath('search_data')); + } - $request->getAggs()->add($aggsFiltered); + $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( @@ -419,7 +425,6 @@ final class CriteriaToEsRequest $request->getAggs() ->add($aggsKeywordFiltered) ->add($aggsNumberFiltered); - } return $request; } diff --git a/src/ElasticSearch/Converter/EsResponseToResult.php b/src/ElasticSearch/Converter/EsResponseToResult.php index 87db6f7..6d734f1 100644 --- a/src/ElasticSearch/Converter/EsResponseToResult.php +++ b/src/ElasticSearch/Converter/EsResponseToResult.php @@ -35,109 +35,120 @@ final class EsResponseToResult } if (isset($data['aggregations']['keyword_facet']['agg_keyword_facet_code']['buckets'])) { - $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'])) { - foreach ($data['aggregations']['keyword_facet_filtered']['all_keyword_facet_filtered']['agg_keyword_facet_code']['buckets'] as $bucket) { - $bucketsFiltered[$bucket['key']] = []; - foreach ($bucket['agg_keyword_facet_value']['buckets'] as $values) { - $bucketsFiltered[$bucket['key']][$values['key']] = $values; - } - } - } + $this->parseKeywordFacet($data, $catalogSearchResult); + } - 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 $filteredBucket) { - if ($filteredBucket['key'] === $code) { - foreach ($filteredBucket['agg_keyword_facet_value']['buckets'] as $values) { - $bucketsFiltered[$code][$values['key']] = $values; - } - } - } - } - } - $bucketsFiltered = array_filter($bucketsFiltered); + if (isset($data['aggregations']['number_facet']['agg_number_facet_code']['buckets'])) { + $this->parseNumberFacet($data, $catalogSearchResult); + } - foreach ($buckets as $bucket) { - $code = $bucket['key']; - $valueBucket = $bucket['agg_keyword_facet_value']['buckets']; + return $catalogSearchResult; + } - $facet = new Facet(new FacetListType(), $code); + private function productFromArray(array $data): Product + { + if (!isset($data['data']['id'])) { + throw new \RuntimeException('id is not set'); + } + $id = $data['data']['id']; - foreach ($valueBucket as $value) { - $count = 0; + $title = $data['data']['title'] ?? ''; + $info = $data; - if (isset($bucketsFiltered[$code][$value['key']])) { - $count = $bucketsFiltered[$code][$value['key']]['doc_count']; - } + return new Product($id, $title, $info); + } - $facet->products->add( - FacetItemList::create( - $value['key'], - $count, - isset($bucketsFiltered[$code][$value['key']]) - ) - ); + 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'])) { + foreach ($data['aggregations']['keyword_facet_filtered']['all_keyword_facet_filtered']['agg_keyword_facet_code']['buckets'] as $bucket) { + $bucketsFiltered[$bucket['key']] = []; + foreach ($bucket['agg_keyword_facet_value']['buckets'] as $values) { + $bucketsFiltered[$bucket['key']][$values['key']] = $values; } + } + } - $catalogSearchResult->getFacets()->add($facet); + 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 $filteredBucket) { + if ($filteredBucket['key'] === $code) { + foreach ($filteredBucket['agg_keyword_facet_value']['buckets'] as $values) { + $bucketsFiltered[$code][$values['key']] = $values; + } + } + } } } + $bucketsFiltered = array_filter($bucketsFiltered); - if (isset($data['aggregations']['number_facet']['agg_number_facet_code']['buckets'])) { - $buckets = $data['aggregations']['number_facet']['agg_number_facet_code']['buckets']; - $bucketsFiltered = []; - if (isset($data['aggregations']['number_facet_filtered']['all_number_facet_filtered']['agg_number_facet_code']['buckets'])) { - foreach ($data['aggregations']['number_facet_filtered']['all_number_facet_filtered']['agg_number_facet_code']['buckets'] as $bucket) { - $bucketsFiltered[$bucket['key']] = $bucket['agg_number_facet_value']; + foreach ($buckets as $bucket) { + $code = $bucket['key']; + $valueBucket = $bucket['agg_keyword_facet_value']['buckets']; + + $facet = new Facet(new FacetListType(), $code); + + foreach ($valueBucket as $value) { + $count = 0; + + if (isset($bucketsFiltered[$code][$value['key']])) { + $count = $bucketsFiltered[$code][$value['key']]['doc_count']; } - } - foreach ($buckets as $bucket) { - $code = $bucket['key']; - $workBucket = $bucket['agg_number_facet_value']; - $selectedBuket = !empty($bucketsFiltered[$code]) ? $bucketsFiltered[$code] : null; - - $facet = new Facet(new FacetRangeType(), $code); - $facetItem = FacetItemRange::create( - FacetItemRangeDTO::create( - $workBucket['min'], - $workBucket['max'], - $workBucket['avg'], - $workBucket['sum'] - ), - $selectedBuket !== null ? FacetItemRangeDTO::create( - $selectedBuket['min'], - $selectedBuket['max'], - $selectedBuket['avg'], - $selectedBuket['sum'] - ) : FacetItemRangeDTO::create(), - $selectedBuket ? $selectedBuket['count'] : 0, - $selectedBuket !== null + $facet->products->add( + FacetItemList::create( + $value['key'], + $count, + isset($bucketsFiltered[$code][$value['key']]) + ) ); - $facet->products->add($facetItem); - - $catalogSearchResult->getFacets()->add($facet); } - } - return $catalogSearchResult; + $catalogSearchResult->getFacets()->add($facet); + } } - private function productFromArray(array $data): Product + private function parseNumberFacet(array $data, Result $catalogSearchResult) { - if (!isset($data['data']['id'])) { - throw new \RuntimeException('id is not set'); - } - $id = $data['data']['id']; + $buckets = $data['aggregations']['number_facet']['agg_number_facet_code']['buckets']; + $bucketsFiltered = []; - $title = $data['data']['title'] ?? ''; - $info = $data; + if (isset($data['aggregations']['number_facet_filtered']['all_number_facet_filtered']['agg_number_facet_code']['buckets'])) { + foreach ($data['aggregations']['number_facet_filtered']['all_number_facet_filtered']['agg_number_facet_code']['buckets'] as $bucket) { + $bucketsFiltered[$bucket['key']] = $bucket['agg_number_facet_value']; + } + } - return new Product($id, $title, $info); + foreach ($buckets as $bucket) { + $code = $bucket['key']; + $workBucket = $bucket['agg_number_facet_value']; + $selectedBuket = !empty($bucketsFiltered[$code]) ? $bucketsFiltered[$code] : null; + + $facet = new Facet(new FacetRangeType(), $code); + $facetItem = FacetItemRange::create( + FacetItemRangeDTO::create( + $workBucket['min'], + $workBucket['max'], + $workBucket['avg'], + $workBucket['sum'] + ), + $selectedBuket !== null ? FacetItemRangeDTO::create( + $selectedBuket['min'], + $selectedBuket['max'], + $selectedBuket['avg'], + $selectedBuket['sum'] + ) : FacetItemRangeDTO::create(), + $selectedBuket ? $selectedBuket['count'] : 0, + $selectedBuket !== null + ); + $facet->products->add($facetItem); + + $catalogSearchResult->getFacets()->add($facet); + } } } diff --git a/tests/FIlter/QueryAndPostFilterTest.php b/tests/FIlter/QueryAndPostFilterTest.php new file mode 100644 index 0000000..2d3b21f --- /dev/null +++ b/tests/FIlter/QueryAndPostFilterTest.php @@ -0,0 +1,649 @@ +setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionBrand); + + + $q = new SearchQuery($criteria); + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * query по сущ бренду + * @return void + */ + public function testQueryExistingBrand() + { + $criteria = new Criteria(); + + $filterCollectionBrand = new FilterGroupCollection([ + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('adidas') + ) + ]); + $filterCollectionBrand->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionBrand); + + + $q = new SearchQuery($criteria); + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 's1', + 's2', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * query по сущ бренду и post_filter по бренду + * @return void + */ + public function testQueryExistingBrandAndPostFilterExistingBrand() + { + $criteria = new Criteria(); + + $filterCollectionBrand = new FilterGroupCollection([ + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('adidas') + ), + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ), + ]); + $filterCollectionBrand + ->setLogicalType(LogicOperator::or()) + ->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionBrand); + + $filterCollectionBrand = new FilterGroupCollection([ + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ), + ]); + $criteria->filters()->add($filterCollectionBrand); + + + $q = new SearchQuery($criteria); + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 's4', + 'h1', + 'h2', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * query по сущ бренду и post_filter по цвету + * @return void + */ + public function testQueryExistingBrandAndPostFilterExistingColor() + { + $criteria = new Criteria(); + + $filterCollectionBrand = new FilterGroupCollection([ + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ), + ]); + $filterCollectionBrand + ->setLogicalType(LogicOperator::or()) + ->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionBrand); + + $filterCollectionColor = new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('white') + ), + ]); + $criteria->filters()->add($filterCollectionColor); + + + $q = new SearchQuery($criteria); + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 'h2', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * query по сущ бренду и цвету и post_filter по бренду + * @return void + */ + public function testQueryExistingBrandAndColorAndPostFilterExistingColor() + { + $criteria = new Criteria(); + + $filterCollectionBrand = new FilterGroupCollection([ + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ), + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('rebook') + ), + ]); + $filterCollectionBrand + ->setLogicalType(LogicOperator::or()) + ->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionBrand); + + $filterCollectionColor = new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('white') + ), + ]); + $filterCollectionColor->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionColor); + + $filterCollectionBrand = new FilterGroupCollection([ + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ), + ]); + $criteria->filters()->add($filterCollectionBrand); + + + $q = new SearchQuery($criteria); + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 'h2', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * query по сущ бренду и post_filter по бренду и цвету + * @return void + */ + public function testQueryExistingBrandAndColorAndPostFilterExistingBrandAndColor() + { + $criteria = new Criteria(); + + $filterCollectionBrand = new FilterGroupCollection([ + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ), + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('rebook') + ), + ]); + $filterCollectionBrand + ->setLogicalType(LogicOperator::or()) + ->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionBrand); + + $filterCollectionColor = new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('white') + ), + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('blue') + ), + ]); + $filterCollectionColor + ->setLogicalType(LogicOperator::or()) + ->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionColor); + + $filterCollectionBrand = new FilterGroupCollection([ + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ), + ]); + $criteria->filters()->add($filterCollectionBrand); + + $filterCollectionColor = new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('white') + ), + ]); + $criteria->filters()->add($filterCollectionColor); + + + $q = new SearchQuery($criteria); + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 'h2', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * query по не сущ цене + * @return void + */ + public function testQueryNonExistentPrice() + { + $criteria = new Criteria(); + + $filterCollectionPrice = new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GTE), + new FilterNumber(108) + ) + ]); + $filterCollectionPrice->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionPrice); + + + $q = new SearchQuery($criteria); + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * query по сущ цене + * @return void + */ + public function testQueryExistingPrice() + { + $criteria = new Criteria(); + + $filterCollectionPrice = new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GTE), + new FilterNumber(105) + ) + ]); + $filterCollectionPrice->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionPrice); + + + $q = new SearchQuery($criteria); + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 'h2', + 'h3', + 'p1', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * query по сущ цене и бренду + * @return void + */ + public function testQueryExistingPriceAndBrand() + { + $criteria = new Criteria(); + + $filterCollection = new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GTE), + new FilterNumber(104) + ), + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ), + ]); + $filterCollection->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollection); + + $q = new SearchQuery($criteria); + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 'h1', + 'h2', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * query по сущ цене и бренду и post_filter по цвету + * @return void + */ + public function testQueryExistingPriceAndBrandAndPostFilterColor() + { + $criteria = new Criteria(); + + $filterCollection = new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GTE), + new FilterNumber(104) + ), + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ), + ]); + $filterCollection->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollection); + + $filterCollectionColor = new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('red') + ), + ]); + $criteria->filters()->add($filterCollectionColor); + + $q = new SearchQuery($criteria); + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 'h1', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * query по сущ цене и бренду и post_filter по цвету и бренду + * @return void + */ + public function testQueryExistingPriceAndBrandAndPostFilterColorAndBrand() + { + $criteria = new Criteria(); + + $filterCollectionPrice = new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LTE), + new FilterNumber(104) + ), + ]); + $filterCollectionPrice->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionPrice); + + $filterCollectionBrand = new FilterGroupCollection([ + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ), + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('adidas') + ), + ]); + $filterCollectionBrand + ->setLogicalType(LogicOperator::or()) + ->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionBrand); + + + $filterCollectionColor = new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('green') + ), + ]); + $criteria->filters()->add($filterCollectionColor); + + $filterCollectionBrand = new FilterGroupCollection([ + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ), + ]); + $criteria->filters()->add($filterCollectionBrand); + + + $q = new SearchQuery($criteria); + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 's4', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * query по сущ цене и бренду и post_filter по цене + * @return void + */ + public function testQueryExistingPriceAndBrandAndPostFilterPrice() + { + $criteria = new Criteria(); + + $filterCollectionPrice = new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LTE), + new FilterNumber(104) + ), + ]); + $filterCollectionPrice->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionPrice); + + $filterCollectionBrand = new FilterGroupCollection([ + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ), + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('adidas') + ), + ]); + $filterCollectionBrand + ->setLogicalType(LogicOperator::or()) + ->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionBrand); + + + $filterCollectionPrice = new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GTE), + new FilterNumber(102) + ), + ]); + $criteria->filters()->add($filterCollectionPrice); + + + $q = new SearchQuery($criteria); + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 's4', + 'h1', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * query по сущ цене и бренду и post_filter по цвету и цене + * @return void + */ + public function testQueryExistingPriceAndBrandAndPostFilterPriceAndColor() + { + $criteria = new Criteria(); + + $filterCollectionPrice = new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LTE), + new FilterNumber(104) + ), + ]); + $filterCollectionPrice->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionPrice); + + $filterCollectionBrand = new FilterGroupCollection([ + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ), + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('adidas') + ), + ]); + $filterCollectionBrand + ->setLogicalType(LogicOperator::or()) + ->setFilterType(FilterType::query()); + $criteria->filters()->add($filterCollectionBrand); + + + $filterCollectionPrice = new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GTE), + new FilterNumber(102) + ), + ]); + $criteria->filters()->add($filterCollectionPrice); + + $filterCollectionColor = new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('green') + ), + ]); + $criteria->filters()->add($filterCollectionColor); + + + $q = new SearchQuery($criteria); + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 's4', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } +} diff --git a/tests/FIlter/QueryTest.php b/tests/FIlter/QueryTest.php index 6441afd..df79ee2 100644 --- a/tests/FIlter/QueryTest.php +++ b/tests/FIlter/QueryTest.php @@ -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; @@ -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; /** * Тестирование агрегирующих функций @@ -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 -- GitLab