diff --git a/src/ElasticSearch/Converter/CriteriaToEsRequest.php b/src/ElasticSearch/Converter/CriteriaToEsRequest.php index d0ea8a6464c16487d1d92220e5b14a476558dd31..46cec2b3824844ad4cca12a737fcbfb80a321eff 100644 --- a/src/ElasticSearch/Converter/CriteriaToEsRequest.php +++ b/src/ElasticSearch/Converter/CriteriaToEsRequest.php @@ -317,39 +317,6 @@ final class CriteriaToEsRequest true ) ) { - $aggsFiltered = new Aggs($getKey('number', $field)); - $aggsFiltered->addAggs( - AggsFacetStats::create( - 'agg_special', - 'number_facet' - ) - ); - - $queryNumberFiltered = new Query(); - $keywordFilter = $this->getKeywordFilter($criteria->filters()); - $numberFilter = $this->getNumberFilter($criteria->filters(), [$field]); - - if (false === $keywordFilter->isEmpty()) { - $nestedFilterKeyword = new Nested(); - $nestedFilterKeyword->setPath('search_data') - ->setQuery($keywordFilter); - $queryNumberFiltered->filter($nestedFilterKeyword); - } - - if (false === $numberFilter->isEmpty()) { - $nestedFilterNumber = new Nested(); - $nestedFilterNumber->setPath('search_data') - ->setQuery($numberFilter); - $queryNumberFiltered->filter($nestedFilterNumber); - } - - if ($queryNumberFiltered->isEmpty() === false) { - $aggsFiltered->setQuery($queryNumberFiltered); - } else { - $aggsFiltered->setNested((new Nested())->setPath('search_data')); - } - - $request->getAggs()->add($aggsFiltered); continue; } diff --git a/src/ElasticSearch/Converter/EsResponseToResult.php b/src/ElasticSearch/Converter/EsResponseToResult.php index 2fc3db6767d86ab94966a0cad56a2aea5cbaac56..87db6f701010bb87a0bab834c0bca34e6a64840e 100644 --- a/src/ElasticSearch/Converter/EsResponseToResult.php +++ b/src/ElasticSearch/Converter/EsResponseToResult.php @@ -97,23 +97,10 @@ final class EsResponseToResult } } - foreach ($buckets as $bucket) { - $code = $bucket['key']; - if (isset($data['aggregations']["number_facet_$code"]['agg_special']['agg_number_facet_code']['buckets'])) { - $bucketsFiltered[$code] = []; - foreach ($data['aggregations']["number_facet_$code"]['agg_special']['agg_number_facet_code']['buckets'] as $filteredBucked) { - if ($filteredBucked['key'] === $code) { - $bucketsFiltered[$code] = $filteredBucked['agg_number_facet_value']; - } - } - } - } - $bucketsFiltered = array_filter($bucketsFiltered); - foreach ($buckets as $bucket) { $code = $bucket['key']; $workBucket = $bucket['agg_number_facet_value']; - $selectedBuket = $bucketsFiltered[$code] ?? null; + $selectedBuket = !empty($bucketsFiltered[$code]) ? $bucketsFiltered[$code] : null; $facet = new Facet(new FacetRangeType(), $code); $facetItem = FacetItemRange::create( @@ -123,14 +110,14 @@ final class EsResponseToResult $workBucket['avg'], $workBucket['sum'] ), - isset($selectedBuket) ? FacetItemRangeDTO::create( + $selectedBuket !== null ? FacetItemRangeDTO::create( $selectedBuket['min'], $selectedBuket['max'], $selectedBuket['avg'], $selectedBuket['sum'] ) : FacetItemRangeDTO::create(), - $selectedBuket['count'] ?? $workBucket['count'], - isset($selectedBuket) + $selectedBuket ? $selectedBuket['count'] : 0, + $selectedBuket !== null ); $facet->products->add($facetItem); diff --git a/tests/FIlter/AggsTest.php b/tests/FIlter/AggsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..94e7aa42a3dcfebf39d34ee56d451cf1a2cd4206 --- /dev/null +++ b/tests/FIlter/AggsTest.php @@ -0,0 +1,965 @@ +filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('category_id'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('t-short') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 'h1', + 'h2', + 'h3' + ], + 'facets' => [ + 0 => [ + 'code' => 'brand', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'nike', + 'count' => 2, + 'active' => true + ], + 1 => [ + 'label' => null, + 'value' => 'rebook', + 'count' => 1, + 'active' => true + ] + ], + 'range' => [] + ] + ], + 1 => [ + 'code' => 'color', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'red', + 'count' => 1, + 'active' => true + ], + 1 => [ + 'label' => null, + 'value' => 'white', + 'count' => 2, + 'active' => true + ] + ], + 'range' => [] + ] + ], + 2 => [ + 'code' => 'size', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'xl', + 'count' => 2, + 'active' => true + ], + 1 => [ + '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' => 104.0, + 'max' => 106.0 + ], + 'activeRange' => [ + 'min' => 104.0, + 'max' => 106.0 + ] + ] + ] + ] + ] + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatDataWFacets($result)); + } + + public function testEmptyKeywordFilter() + { + $criteria = new Criteria(); + + $criteria->filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('category_id'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('t-short') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('white') + ) + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 'h2', + 'h3' + ], + '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' => 1, + 'active' => true + ] + ], + 'range' => [] + ] + ], + 1 => [ + 'code' => 'color', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'red', + 'count' => 1, + 'active' => true + ], + 1 => [ + 'label' => null, + 'value' => 'white', + 'count' => 2, + 'active' => true + ] + ], + 'range' => [] + ] + ], + 2 => [ + 'code' => 'size', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'xl', + 'count' => 1, + 'active' => true + ], + 1 => [ + 'label' => null, + 'value' => 'xxl', + 'count' => 1, + 'active' => true + ] + ], + 'range' => [] + ] + ], + 3 => [ + 'code' => 'price', + 'label' => null, + 'type' => 'range', + 'items' => [ + 'list' => [], + 'range' => [ + 0 => [ + 'label' => null, + 'count' => 2, + 'active' => true, + 'fullRange' => [ + 'min' => 104.0, + 'max' => 106.0 + ], + 'activeRange' => [ + 'min' => 105.0, + 'max' => 106.0 + ] + ] + ] + ] + ] + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatDataWFacets($result)); + } + + public function testRangeFilter() + { + $criteria = new Criteria(); + + $criteria->filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('category_id'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('t-short') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LTE), + new FilterNumber(104.50) + ) + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 'h1', + ], + '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' => 0, + 'active' => false + ] + ], + 'range' => [] + ] + ], + 1 => [ + 'code' => 'color', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'red', + 'count' => 1, + 'active' => true + ], + 1 => [ + 'label' => null, + 'value' => 'white', + 'count' => 0, + 'active' => false + ] + ], + 'range' => [] + ] + ], + 2 => [ + 'code' => 'size', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'xl', + 'count' => 1, + 'active' => true + ], + 1 => [ + 'label' => null, + 'value' => 'xxl', + 'count' => 0, + 'active' => false + ] + ], + 'range' => [] + ] + ], + 3 => [ + 'code' => 'price', + 'label' => null, + 'type' => 'range', + 'items' => [ + 'list' => [], + 'range' => [ + 0 => [ + 'label' => null, + 'count' => 1, + 'active' => true, + 'fullRange' => [ + 'min' => 104.0, + 'max' => 106.0 + ], + 'activeRange' => [ + 'min' => 104.0, + 'max' => 104.0 + ] + ] + ] + ] + ] + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatDataWFacets($result)); + } + + public function testCombineFilter() + { + $criteria = new Criteria(); + + $criteria->filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('category_id'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('t-short') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('black') + ) + ])); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LTE), + new FilterNumber(104) + ) + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [], + 'facets' => [ + 0 => [ + 'code' => 'brand', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'nike', + 'count' => 0, + 'active' => false + ], + 1 => [ + 'label' => null, + 'value' => 'rebook', + 'count' => 0, + 'active' => false + ] + ], + 'range' => [] + ] + ], + 1 => [ + 'code' => 'color', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'red', + 'count' => 1, + 'active' => true + ], + 1 => [ + 'label' => null, + 'value' => 'white', + 'count' => 0, + 'active' => false + ] + ], + 'range' => [] + ] + ], + 2 => [ + 'code' => 'size', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'xl', + 'count' => 0, + 'active' => false + ], + 1 => [ + 'label' => null, + 'value' => 'xxl', + 'count' => 0, + 'active' => false + ] + ], + 'range' => [] + ] + ], + 3 => [ + 'code' => 'price', + 'label' => null, + 'type' => 'range', + 'items' => [ + 'list' => [], + 'range' => [ + 0 => [ + 'label' => null, + 'count' => 0, + 'active' => false, + 'fullRange' => [ + 'min' => 104.0, + 'max' => 106.0 + ], + 'activeRange' => [ + 'min' => null, + 'max' => null + ] + ] + ] + ] + ] + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatDataWFacets($result)); + } + + public function testCombineFilterTwo() + { + $criteria = new Criteria(); + + $criteria->filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('category_id'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('t-short') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('red') + ) + ])); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LTE), + new FilterNumber(105) + ) + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'h1' + ], + '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' => 0, + 'active' => false + ] + ], + 'range' => [] + ] + ], + 1 => [ + 'code' => 'color', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'red', + 'count' => 1, + 'active' => true + ], + 1 => [ + 'label' => null, + 'value' => 'white', + 'count' => 1, + 'active' => true + ] + ], + 'range' => [] + ] + ], + 2 => [ + 'code' => 'size', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'xl', + 'count' => 1, + 'active' => true + ], + 1 => [ + 'label' => null, + 'value' => 'xxl', + 'count' => 0, + 'active' => false + ] + ], + 'range' => [] + ] + ], + 3 => [ + 'code' => 'price', + 'label' => null, + 'type' => 'range', + 'items' => [ + 'list' => [], + 'range' => [ + 0 => [ + 'label' => null, + 'count' => 1, + 'active' => true, + 'fullRange' => [ + 'min' => 104.0, + 'max' => 106.0 + ], + 'activeRange' => [ + 'min' => 104.0, + 'max' => 104.0 + ] + ] + ] + ] + ] + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatDataWFacets($result)); + } + + public function testKeywordFilter() + { + $criteria = new Criteria(); + + $criteria->filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('category_id'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('t-short') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('white') + ) + ])); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('brand'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('nike') + ) + ])); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GT), + new FilterNumber(100) + ) + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'h2' + ], + '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' => 1, + 'active' => true + ] + ], + 'range' => [] + ] + ], + 1 => [ + 'code' => 'color', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'red', + 'count' => 1, + 'active' => true + ], + 1 => [ + 'label' => null, + 'value' => 'white', + 'count' => 1, + 'active' => true + ] + ], + 'range' => [] + ] + ], + 2 => [ + 'code' => 'size', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'xl', + 'count' => 0, + 'active' => false + ], + 1 => [ + 'label' => null, + 'value' => 'xxl', + 'count' => 1, + 'active' => true + ] + ], + 'range' => [] + ] + ], + 3 => [ + 'code' => 'price', + 'label' => null, + 'type' => 'range', + 'items' => [ + 'list' => [], + 'range' => [ + 0 => [ + 'label' => null, + 'count' => 1, + 'active' => true, + 'fullRange' => [ + 'min' => 104.0, + 'max' => 106.0 + ], + 'activeRange' => [ + 'min' => 105.0, + 'max' => 105.0 + ] + ] + ] + ] + ] + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatDataWFacets($result)); + } + + public function testKeywordFilterTwo() + { + $criteria = new Criteria(); + + $criteria->filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('category_id'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('t-short') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('white') + ) + ])); + + $criteria->filters()->add( + (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('reebok') + ) + ])) + ->setLogicalType(LogicOperator::or()) + ); + + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'h2' + ], + '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' => 1, + 'active' => true + ] + ], + 'range' => [] + ] + ], + 1 => [ + 'code' => 'color', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'red', + 'count' => 1, + 'active' => true + ], + 1 => [ + 'label' => null, + 'value' => 'white', + 'count' => 1, + 'active' => true + ] + ], + 'range' => [] + ] + ], + 2 => [ + 'code' => 'size', + 'label' => null, + 'type' => 'list', + 'items' => [ + 'list' => [ + 0 => [ + 'label' => null, + 'value' => 'xl', + 'count' => 0, + 'active' => false + ], + 1 => [ + 'label' => null, + 'value' => 'xxl', + 'count' => 1, + 'active' => true + ] + ], + 'range' => [] + ] + ], + 3 => [ + 'code' => 'price', + 'label' => null, + 'type' => 'range', + 'items' => [ + 'list' => [], + 'range' => [ + 0 => [ + 'label' => null, + 'count' => 1, + 'active' => true, + 'fullRange' => [ + 'min' => 104.0, + 'max' => 106.0 + ], + 'activeRange' => [ + 'min' => 105.0, + 'max' => 105.0 + ] + ] + ] + ] + ] + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatDataWFacets($result)); + } +} \ No newline at end of file diff --git a/tests/FIlter/CommonRangeKeywordsTest.php b/tests/FIlter/CommonRangeKeywordsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2ced2c2e97123dcfb1d7b5ce105c4ea468947b22 --- /dev/null +++ b/tests/FIlter/CommonRangeKeywordsTest.php @@ -0,0 +1,143 @@ +filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('red') + ) + ])); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GT), + new FilterNumber(102) + ) + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'h1' + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по фильтру свойства и цене + * + * @return void + */ + public function testExistByFilterAndMaxPrice(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('red') + ) + ])); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LT), + new FilterNumber(102) + ) + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's2' + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по фильтру свойства и цене + * + * @return void + */ + public function testExistByFilterAndRangePrice(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('red') + ) + ])); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GTE), + new FilterNumber(101) + ), + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LTE), + new FilterNumber(104) + ), + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + $expected = [ + 'hits' => [ + 'h1', + 's2' + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } +} \ No newline at end of file diff --git a/tests/FIlter/KeywordsTest.php b/tests/FIlter/KeywordsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..51acdf6439db9efcb44b2185821597160eeade5f --- /dev/null +++ b/tests/FIlter/KeywordsTest.php @@ -0,0 +1,242 @@ +filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('') + ) + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по фильтру свойства + * + * @return void + */ + public function testExistByFilter(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('red') + ) + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's2', + 'h1' + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по фильтру свойства и категории + * + * @return void + */ + public function testExistByFilterAndCategory(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('category_id'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('shoes') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('red') + ) + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's2', + ] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по нескольким свойствам + * + * @return void + */ + public function testExistByMultipleFilter(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('red') + ), + new Filter( + new Field('size'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('xxl') + ) + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по нескольким свойствам + * + * @return void + */ + public function testExistByMultipleFilter2(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('red') + ), + new Filter( + new Field('size'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('xl') + ) + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'h1' + ] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по нескольким свойствам и категории + * + * @return void + */ + public function testExistByMultipleFilterAndCategory(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('category_id'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('prices') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('color'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('red') + ), + new Filter( + new Field('size'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('xl') + ) + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } +} \ No newline at end of file diff --git a/tests/FIlter/RangeTest.php b/tests/FIlter/RangeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b9f6726439c3ef77184c23ac0867f166a2d76055 --- /dev/null +++ b/tests/FIlter/RangeTest.php @@ -0,0 +1,372 @@ +filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GTE), + new FilterNumber(103) + ), + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's4', + 'h1', + 'h2', + 'h3', + 'p1' + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по мин цене + * + * @return void + */ + public function testExistByMinPrice2(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GT), + new FilterNumber(103.01) + ), + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'h1', + 'h2', + 'h3', + 'p1' + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по мин цене + * + * @return void + */ + public function testExistByMinPrice3(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GT), + new FilterNumber(102.99) + ), + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's4', + 'h1', + 'h2', + 'h3', + 'p1' + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по макс цене + * + * @return void + */ + public function testExistByMaxPrice(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LTE), + new FilterNumber(102) + ), + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's1', + 's2', + 's3', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по макс цене + * + * @return void + */ + public function testExistByMaxPrice2(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LT), + new FilterNumber(102.99) + ), + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's1', + 's2', + 's3', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по макс цене + * + * @return void + */ + public function testExistByMaxPrice3(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LT), + new FilterNumber(101.99) + ), + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's1', + 's2', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по диапазону цен + * + * @return void + */ + public function testExistByRangePrice(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GTE), + new FilterNumber(101) + ), + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LTE), + new FilterNumber(102) + ), + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's2', + 's3', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по диапазону цен + * + * @return void + */ + public function testExistByRangePrice2(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GTE), + new FilterNumber(101.01) + ), + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LTE), + new FilterNumber(102) + ), + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's3', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по диапазону цен + * + * @return void + */ + public function testExistByRangePrice3(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GTE), + new FilterNumber(101) + ), + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LTE), + new FilterNumber(101.99) + ), + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's2', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск элементов по диапазону цен + * + * @return void + */ + public function testExistByRangePrice4(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add(new FilterGroupCollection([ + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::GTE), + new FilterNumber(101.99) + ), + new Filter( + new Field('price'), + new FilterOperator(FilterOperator::LTE), + new FilterNumber(101.99) + ), + ])); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } +} \ No newline at end of file diff --git a/tests/FIlter/SearchItemsTest.php b/tests/FIlter/SearchItemsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7f53c9173351c4b1dcb10f0e57e5e8cd038f7ba4 --- /dev/null +++ b/tests/FIlter/SearchItemsTest.php @@ -0,0 +1,226 @@ +filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('category_id'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('prices') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'p1' + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск всех элементов раздела + * + * @return void + */ + public function testExistByEmptyCategory(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('category_id'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } + + /** + * Поиск всех элементов + * + * @return void + */ + public function testExistAllItems(): void + { + $criteria = new Criteria(); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's1', + 's2', + 's3', + 's4', + 'h1', + 'h2', + 'h3', + 'p1' + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск существующего элемента по части строки поиска + * + * @return void + */ + public function testExistItemsByPart(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('search'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('Nike') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's4', + 'h1', + 'h2', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } + + /** + * Поиск существующего элемента по полному названию + * + * @return void + */ + public function testExistItemsByName(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('search'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('Nike Dri-FIT Strike') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'h1', + 'h2', + 's4' + ] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } + + /** + * Поиск существующего элемента по полному названию + * + * @return void + */ + public function testExistItemsByCyrillicName(): void + { + $criteria = new Criteria(); + + $criteria->filters()->add( + (new FilterGroupCollection([ + new Filter( + new Field('search'), + new FilterOperator(FilterOperator::EQ), + new FilterKeyword('Товар с ценой') + ) + ])) + ->setFilterType(FilterType::query()) + ); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'p1', + ] + ]; + + $this->assertEqualsCanonicalizing($expected, FormatData::formatData($result)); + } +} \ No newline at end of file diff --git a/tests/FIlter/SortTest.php b/tests/FIlter/SortTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a7a28d9f43ebe856774824af911efa08b5f758b3 --- /dev/null +++ b/tests/FIlter/SortTest.php @@ -0,0 +1,305 @@ +sorting()->add(new Order( + new AttrType('category_id'), + new OrderAscType(), + )); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'p1', + 's1', + 's2', + 's3', + 's4', + 'h1', + 'h2', + 'h3', + ] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } + + /** + * Обратная сортировка элементов по категории + * + * @return void + */ + public function testSortByCategoryReverse(): void + { + $criteria = new Criteria(); + + $criteria->sorting()->add(new Order( + new AttrType('category_id'), + new OrderDescType(), + )); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'h1', + 'h2', + 'h3', + 's1', + 's2', + 's3', + 's4', + 'p1', + ] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } + + /** + * Сортировка элементов по свойству + * + * @return void + */ + public function testSortByKeyword(): void + { + $criteria = new Criteria(); + + $criteria->sorting()->add(new Order( + new PropertyType('color', PropertyType::TYPE_KEYWORD), + new OrderAscType(), + )); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's3', + 's1', + 's4', + 's2', + 'h1', + 'h2', + 'h3', + 'p1' + ] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } + + /** + * Сортировка элементов по свойству + * + * @return void + */ + public function testSortByKeywordReverse(): void + { + $criteria = new Criteria(); + + $criteria->sorting()->add(new Order( + new PropertyType('color', PropertyType::TYPE_KEYWORD), + new OrderDescType(), + )); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'h2', + 'h3', + 'p1', + 's2', + 'h1', + 's1', + 's4', + 's3', + ] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } + + /** + * Сортировка элементов по свойству + * + * @return void + */ + public function testSortByNumber(): void + { + $criteria = new Criteria(); + + $criteria->sorting()->add(new Order( + new PropertyType('price', PropertyType::TYPE_NUMBER), + new OrderAscType(), + )); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's1', + 's2', + 's3', + 's4', + 'h1', + 'h2', + 'h3', + 'p1' + ] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } + + /** + * Сортировка элементов по свойству + * + * @return void + */ + public function testSortByNumberReverse(): void + { + $criteria = new Criteria(); + + $criteria->sorting()->add(new Order( + new PropertyType('price', PropertyType::TYPE_NUMBER), + new OrderDescType(), + )); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'p1', + 'h3', + 'h2', + 'h1', + 's4', + 's3', + 's2', + 's1', + ] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } + + /** + * Сортировка элементов по свойству + * + * @return void + */ + public function testSortByCombined(): void + { + $criteria = new Criteria(); + + $criteria->sorting()->add(new Order( + new PropertyType('size', PropertyType::TYPE_KEYWORD), + new OrderAscType(), + )); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 's4', + 's1', + 's2', + 's3', + 'h1', + 'h3', + 'p1', + 'h2', + ] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } + + /** + * Сортировка элементов по свойству + * + * @return void + */ + public function testSortByCombinedReverse(): void + { + $criteria = new Criteria(); + + $criteria->sorting()->add(new Order( + new PropertyType('size', PropertyType::TYPE_KEYWORD), + new OrderDescType(), + )); + + $q = new SearchQuery($criteria); + + $handler = SearchClient::getInstance(); + $result = $handler->handle($q)->result; + + + $expected = [ + 'hits' => [ + 'h2', + 'h1', + 'h3', + 'p1', + 's2', + 's3', + 's1', + 's4', + ] + ]; + + $this->assertEquals($expected, FormatData::formatData($result)); + } +} \ No newline at end of file diff --git a/tests/Helpers/FormatData.php b/tests/Helpers/FormatData.php new file mode 100644 index 0000000000000000000000000000000000000000..dd2808b2fb7877069ff32991ff00f41a1227cdc2 --- /dev/null +++ b/tests/Helpers/FormatData.php @@ -0,0 +1,77 @@ +getProducts(); + $aResult = ['hits' => []]; + foreach ($oProductCollection as $oProduct) { + /** @var Product $oProduct */ + $aResult['hits'][] = $oProduct->id; + } + return $aResult; + } + + public static function formatDataWFacets(Result $result): array + { + $aResult = ['facets' => []]; + $aResult['hits'] = static::formatData($result)['hits']; + foreach ($result->getFacets() as $facet) { + /** @var Facet $facet */ + $dataFacet = [ + 'code' => $facet->getCode(), + 'label' => null, // $facet->getLabel(), + 'type' => $facet->getType() instanceof FacetRangeType ? 'range' : ($facet->getType() instanceof FacetListType ? 'list' : null), + 'items' => [ + 'list' => [], + 'range' => [] + ], + ]; + + $items = $facet->products->sort('getValue'); + foreach ($items as $item) { + if ($item instanceof FacetItemList) { + /** @var FacetItemList $item */ + $dataFacet['items']['list'][] = [ + 'label' => $item->getLabel(), + 'value' => $item->getValue(), + 'count' => $item->getCount(), + 'active' => $item->isActive(), + ]; + } + if ($item instanceof FacetItemRange) { + /** @var FacetItemRange $item */ + + $aData = [ + 'label' => $item->getLabel(), + 'count' => $item->getCount(), + 'active' => $item->isActive(), + ]; + + $aData['fullRange'] = $item->getFullRange(); + $aData['activeRange'] = $item->getSelectedRange(); + + if ($result->getTotal() > 0 && empty(array_filter($aData['activeRange']))) { + $aData['activeRange'] = $aData['fullRange']; + } + + $dataFacet['items']['range'][] = $aData; + } + } + + $aResult['facets'][] = $dataFacet; + } + return $aResult; + } +} \ No newline at end of file