<?php namespace IQDEV\ElasticSearch\Domain; use IQDEV\ElasticSearch\Search\Aggs\Aggs; use IQDEV\ElasticSearch\Search\Aggs\AggsKeyWordFacet; use IQDEV\ElasticSearch\Search\Aggs\AggsNumberFacet; use IQDEV\ElasticSearch\Search\BoolQuery\FilterKeywordFacet; use IQDEV\ElasticSearch\Search\BoolQuery\FilterNumberFacet; use IQDEV\ElasticSearch\Search\BoolQuery\Query; use IQDEV\ElasticSearch\Search\BoolQuery\Terms; use IQDEV\ElasticSearch\Search\Nested; use IQDEV\ElasticSearch\Search\Pagination; use IQDEV\ElasticSearch\Search\Request; use Elastic\Elasticsearch\Client; use IQDEV\Search\{Filter\Filter, Filter\FilterKeyword, Filter\FilterCategory, Filter\FilterNumber, Query as DQuery, Result, SearchService as DomainSearchService, Sorting\SortingFieldPair as DSortingFieldPair, Sorting\SortingPropertyKeywordPair as DSortingPropertyKeywordPair, Sorting\SortingPropertyNumberPair as DSortingPropertyNumberPair }; use IQDEV\ElasticSearch\Search\Sorting\SortingCollection; use IQDEV\ElasticSearch\Search\Sorting\SortingFieldsPair; use IQDEV\ElasticSearch\Search\Sorting\SortingPropertyKeywordPair; use IQDEV\ElasticSearch\Search\Sorting\SortingPropertyNumberPair; final class SearchService implements DomainSearchService { private Client $esClient; private string $sIndex; public function __construct(Client $esClient, string $sIndex = 'product-test') { $this->esClient = $esClient; $this->sIndex = $sIndex; } public function search(DQuery $q): Result { $request = new Request(); $commonQuery = new Query(); $filterKeyword = new Query(); $filterNumber = new Query(); if ($q->filters) { foreach ($q->filters as $filter) { /** @var Filter $filter */ if ($filter instanceof FilterCategory) { $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; } } } $commonFilter = clone $commonQuery; $commonFilter->setType(Query::TYPE_FILTER); if ($q->pagination) { $request->setPagination( new Pagination($q->pagination->limit, $q->pagination->page) ); } if ($q->sorting && !$q->sorting->isEmpty()) { $oSortingCollection = new SortingCollection(); foreach ($q->sorting as $sorting) { if ($sorting instanceof DSortingFieldPair) { $oSortingCollection->add(new SortingFieldsPair($sorting->by, $sorting->direction)); } if ($sorting instanceof DSortingPropertyKeywordPair) { $oSortingCollection->add(new SortingPropertyKeywordPair($sorting->by, $sorting->direction)); } if ($sorting instanceof DSortingPropertyNumberPair) { $oSortingCollection->add(new SortingPropertyNumberPair($sorting->by, $sorting->direction)); } } $request->setSorting($oSortingCollection); } if ($q->query) { $request->addMatch('full_search_content', ['query' => $q->query]); } if ($filterKeyword->isEmpty() === false) { $nestedFilterKeyword = new Nested(); $nestedFilterKeyword->setPath('search_data') ->setQuery($filterKeyword); } if ($filterNumber->isEmpty() === false) { $nestedFilterNumber = new Nested(); $nestedFilterNumber->setPath('search_data') ->setQuery($filterNumber); } if ($commonQuery->isEmpty() === false) { $nestedFilter = new Nested(); $nestedFilter->setPath('search_data') ->setQuery($commonQuery); $request->getPostFilter()->filter($nestedFilter); $aggsKeywordFiltered = new Aggs('keyword_facet_filtered'); $aggsKeywordFiltered->addAggs(AggsKeyWordFacet::create('all_keyword_facet_filtered', 'keyword_facet')) ->setQuery($commonFilter); $request->getAggs()->add($aggsKeywordFiltered); $aggsNumberFiltered = new Aggs('number_facet_filtered'); $aggsNumberFiltered->addAggs(AggsNumberFacet::create('all_number_facet_filtered', 'number_facet')) ->setQuery($commonFilter); $request->getAggs()->add($aggsNumberFiltered); } $aggsKeyword = AggsKeyWordFacet::create('keyword_facet', 'keyword_facet'); $request->getAggs()->add($aggsKeyword); $aggsNumber = AggsNumberFacet::create('number_facet', 'number_facet'); $request->getAggs()->add($aggsNumber); $response = $this->esClient->search( [ 'index' => $this->sIndex, 'body' => $request->es(), ] ); return SearchResultFactory::createFromResponse($response, $request); } }