Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?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);
}
}