<?php namespace IQDEV\ElasticSearch\Converter\Result; use Elastic\Elasticsearch\Response\Elasticsearch; use IQDEV\ElasticSearch\Configuration; use IQDEV\ElasticSearch\Document\Product; use IQDEV\ElasticSearch\Facet\FacetResult; use IQDEV\ElasticSearch\Facet\FacetType; use IQDEV\ElasticSearch\Facet\Item\FacetItemList; use IQDEV\ElasticSearch\Facet\Item\FacetItemRange; use IQDEV\ElasticSearch\Facet\Item\FacetItemRangeDTO; use IQDEV\ElasticSearch\Result; final class EsResponseToResult { public function fromResponse(Elasticsearch $response, Configuration $configuration): Result { $catalogSearchResult = new Result(); $data = $response->asArray(); if (isset($data['hits']['hits'])) { foreach ($data['hits']['hits'] as $hit) { if (isset($hit['_source'])) { try { $product = $this->productFromArray($hit['_source']); $catalogSearchResult->getProducts()->add($product); } catch (\Throwable $ex) { continue; } } } $catalogSearchResult->setTotal((int)$data['hits']['total']['value']); } 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); } $this->parsePropertyFacet($data, $catalogSearchResult, $configuration); 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'])) { 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; } } } 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); foreach ($buckets as $bucket) { $code = $bucket['key']; $valueBucket = $bucket['agg_keyword_facet_value']['buckets']; $facet = new FacetResult(FacetType::LIST, $code); foreach ($valueBucket as $value) { $count = $value['doc_count']; if (isset($bucketsFiltered[$code][$value['key']])) { $count = $bucketsFiltered[$code][$value['key']]['doc_count']; } elseif (isset($bucketsFiltered[$code])) { $count = 0; } $facet->products->add( FacetItemList::create( $value['key'], $count, isset($bucketsFiltered[$code][$value['key']]) ) ); } $catalogSearchResult->getFacets()->add($facet); } } private function parseNumberFacet(array $data, Result $catalogSearchResult) { $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']; $workBucket = $bucket['agg_number_facet_value']; $selectedBucket = !empty($bucketsFiltered[$code]) ? $bucketsFiltered[$code] : null; $facet = new FacetResult(FacetType::RANGE, $code); $facetItem = FacetItemRange::create( FacetItemRangeDTO::create( $workBucket['min'], $workBucket['max'], $workBucket['avg'], $workBucket['sum'] ), $selectedBucket !== null ? FacetItemRangeDTO::create( $selectedBucket['min'], $selectedBucket['max'], $selectedBucket['avg'], $selectedBucket['sum'] ) : FacetItemRangeDTO::create(), $selectedBucket ? $selectedBucket['count'] : 0, $selectedBucket !== null ); $facet->products->add($facetItem); $catalogSearchResult->getFacets()->add($facet); } } private function parsePropertyFacet(array $data, Result $catalogSearchResult, Configuration $configuration) { $properties = array_keys($configuration->getMapping()['properties']); foreach ($data['aggregations'] as $key => $aggs) { if (!in_array($key, $properties, true)) { continue; } $facet = new FacetResult(FacetType::LIST, $key); $buckets = array_key_exists('buckets', $aggs) ? $aggs['buckets'] : $aggs[$key]['buckets']; foreach ($buckets as $bucket) { $code = $bucket['key']; $count = $bucket['doc_count']; $facet->products->add( FacetItemList::create( $code, $count ) ); } $catalogSearchResult->getFacets()->add($facet); } } }