Skip to content
<?php
namespace IQDEV\ElasticSearch\Criteria\Query;
use IQDEV\ElasticSearch\Criteria\Criteria;
final class SearchQuery
{
public function __construct(
public Criteria $criteria
) {
}
}
<?php
namespace IQDEV\ElasticSearch\Criteria\Query;
use IQDEV\ElasticSearch\SearchService;
final class SearchQueryHandler
{
public function __construct(
private SearchService $searchService
) {
}
public function handle(SearchQuery $q): SearchQueryResponse
{
$result = $this->searchService->search($q->criteria);
return new SearchQueryResponse($result);
}
}
<?php
namespace IQDEV\ElasticSearch\Criteria\Query;
use IQDEV\ElasticSearch\Result;
final class SearchQueryResponse
{
public function __construct(
public Result $result
) {
}
}
<?php
declare(strict_types=1);
namespace IQDEV\ElasticSearch\Criteria\Search;
use IQDEV\ElasticSearch\Document\Property\Property;
class Search
{
public function __construct(
private readonly Property $property,
private readonly mixed $value,
) {
}
public function getProperty(): Property
{
return $this->property;
}
public function getValue(): mixed
{
return $this->value;
}
}
<?php
namespace IQDEV\ElasticSearch\Criteria\Search;
use Ramsey\Collection\AbstractCollection;
class SearchCollection extends AbstractCollection
{
/**
* @inheritDoc
*/
public function getType(): string
{
return Search::class;
}
}
<?php
declare(strict_types=1);
namespace IQDEV\ElasticSearch\Criteria\Search;
use IQDEV\ElasticSearch\Config\MappingValidator;
use IQDEV\ElasticSearch\Configuration;
use IQDEV\ElasticSearch\Criteria\Match\QueryMatch;
use IQDEV\ElasticSearch\Search\BoolQuery\Query;
use IQDEV\ElasticSearch\Search\BoolQuery\Terms;
use IQDEV\ElasticSearch\Search\Nested;
class SearchQuery
{
public function __construct(
private readonly Search $search,
) {
}
public function toQueryMatch(): QueryMatch
{
return new QueryMatch(
$this->search->getProperty()->getKey(),
$this->search->getValue(),
);
}
public function toMust(Configuration $configuration): Terms|Nested
{
if (MappingValidator::isPropertyExists($configuration, $this->search->getProperty()->getKey())) {
return new Terms($this->search->getProperty()->getKey(), $this->search->getValue());
} else {
$path = 'search_data.keyword_facet';
$nested = new Nested();
$query = new Query();
$query->getFilter()->add(new Terms($path . '.facet_code', $this->search->getProperty()->getKey()));
$query->getFilter()->add(new Terms($path . '.facet_value', $this->search->getValue()));
$nested
->setPath($path)
->setQuery($query);
return $nested;
}
}
}
<?php
namespace IQDEV\ElasticSearch\Document;
final class Product
{
public function __construct(
public string $id,
public string $title,
public array $info = []
) {
}
}
<?php
namespace IQDEV\ElasticSearch\Document;
use Ramsey\Collection\AbstractCollection;
/**
* @extends AbstractCollection<Product>
*/
final class ProductCollection extends AbstractCollection
{
public function getType(): string
{
return Product::class;
}
}
......@@ -4,8 +4,8 @@ namespace IQDEV\ElasticSearch\Document;
use IQDEV\ElasticSearch\Config\MappingValidator;
use IQDEV\ElasticSearch\Configuration;
use IQDEV\ElasticSearch\Facet\FacetCategory;
use IQDEV\ElasticSearch\Facet\FacetCollection;
use IQDEV\ElasticSearch\Facet\Collection\FacetCollection;
use IQDEV\ElasticSearch\Facet\Facet;
use IQDEV\ElasticSearch\Helper\ArrayHelper;
class ProductDocument implements Document
......@@ -17,21 +17,14 @@ class ProductDocument implements Document
private array $info = [];
private bool $skipEmpty = false;
private FacetCategory $categoryFacet;
public function __construct(
FacetCategory $categoryFacet
)
{
private Facet $categoryFacet
) {
$this->keywordFacets = new FacetCollection();
$this->numberFacets = new FacetCollection();
$this->categoryFacet = $categoryFacet;
}
public static function create(FacetCategory $categoryFacet): self
public static function create(Facet $categoryFacet): self
{
return new self($categoryFacet);
}
......@@ -45,9 +38,9 @@ class ProductDocument implements Document
}
/**
* @return FacetCategory
* @return Facet
*/
public function getCategoryFacet(): FacetCategory
public function getCategoryFacet(): Facet
{
return $this->categoryFacet;
}
......
<?php
namespace IQDEV\ElasticSearch\Document\Property;
class Property
{
public function __construct(
protected string $key,
protected PropertyType $type = PropertyType::BASE,
) {
}
public function getKey(): string
{
return $this->key;
}
public function getType(): PropertyType
{
return $this->type;
}
}
<?php
namespace IQDEV\ElasticSearch\Document\Property;
enum PropertyType
{
case BASE;
case KEYWORD;
case NUMBER;
case TEXT;
}
<?php
namespace IQDEV\ElasticSearch\Facet;
namespace IQDEV\ElasticSearch\Facet\Collection;
use IQDEV\ElasticSearch\Esable;
use IQDEV\ElasticSearch\Facet\Facetable;
use Ramsey\Collection\AbstractCollection;
final class FacetCollection extends AbstractCollection implements Esable
{
public function getType(): string
{
return Facet::class;
return Facetable::class;
}
public function es(): array
{
return array_map(static fn(Facet $facet) => $facet->es(), $this->toArray());
return array_map(static fn(Facetable $facet) => $facet->es(), $this->toArray());
}
}
<?php
namespace IQDEV\ElasticSearch\Facet\Collection;
use IQDEV\ElasticSearch\Facet\FacetResult;
use Ramsey\Collection\AbstractCollection;
final class FacetResultCollection extends AbstractCollection
{
/**
* @inheritDoc
*/
public function getType(): string
{
return FacetResult::class;
}
}
......@@ -2,8 +2,18 @@
namespace IQDEV\ElasticSearch\Facet;
use IQDEV\ElasticSearch\Esable;
use IQDEV\ElasticSearch\Document\Property\Property;
interface Facet extends Esable
abstract class Facet implements Facetable
{
public function __construct(
protected Property $property,
protected mixed $value,
) {
}
public function getProperty(): Property
{
return $this->property;
}
}
<?php
namespace IQDEV\ElasticSearch\Facet;
use IQDEV\ElasticSearch\Esable;
final class FacetCategory implements Esable
{
private string $category;
public function __construct(string $category)
{
$this->category = $category;
}
public function es(): array
{
return [
'category_id' => $this->category,
];
}
}
<?php
namespace IQDEV\ElasticSearch\Facet;
use IQDEV\ElasticSearch\Document\Property\Property;
use IQDEV\ElasticSearch\Document\Property\PropertyType;
use IQDEV\ElasticSearch\Facet\Type\BaseFacet;
use IQDEV\ElasticSearch\Facet\Type\KeywordFacet;
use IQDEV\ElasticSearch\Facet\Type\NumberFacet;
class FacetFactory
{
public static function createFromProperty(Property $property, mixed $value): Facet
{
match ($property->getType()) {
PropertyType::KEYWORD => $facet = new KeywordFacet($property, $value),
PropertyType::NUMBER => $facet = new NumberFacet($property, $value),
default => $facet = new BaseFacet($property, $value),
};
return $facet;
}
}
<?php
namespace IQDEV\ElasticSearch\Facet;
final class FacetKeyword implements Facet
{
private string $key;
/** @var string|string[] */
private $value;
/**
* @param string|string[] $value
*/
public function __construct(string $key, $value)
{
$this->key = $key;
$this->value = $value;
}
public function es(): array
{
return [
'facet_code' => $this->key,
'facet_value' => $this->value,
];
}
}
<?php
namespace IQDEV\ElasticSearch\Facet;
final class FacetNumber implements Facet
{
private string $key;
private float $value;
public function __construct(string $key, float $value)
{
$this->key = $key;
$this->value = $value;
}
public function es(): array
{
return [
'facet_code' => $this->key,
'facet_value' => $this->value,
];
}
}
<?php
namespace IQDEV\ElasticSearch\Facet;
use IQDEV\ElasticSearch\Facet\Item\FacetItemCollection;
class FacetResult
{
public FacetItemCollection $products;
protected FacetType $type;
protected string $code;
public function __construct(FacetType $type, string $code)
{
$this->type = $type;
$this->code = $code;
$this->products = new FacetItemCollection();
}
public function getType(): FacetType
{
return $this->type;
}
public function getCode(): string
{
return $this->code;
}
}
<?php
namespace IQDEV\ElasticSearch\Facet;
enum FacetType: string
{
case LIST = 'list';
case RANGE = 'range';
}