Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Showing
with 370 additions and 30 deletions
<?php
declare(strict_types=1);
namespace IQDEV\ElasticSearch\Criteria\Match;
use IQDEV\ElasticSearch\Esable;
class QueryMatch implements Esable
{
public function __construct(
private readonly string $key,
private readonly mixed $value,
) {
}
public function es(): array
{
return [
$this->key => [
'query' => $this->value
]
];
}
}
<?php
declare(strict_types=1);
namespace IQDEV\ElasticSearch\Criteria\Match;
use IQDEV\ElasticSearch\Esable;
use Ramsey\Collection\AbstractCollection;
class QueryMatchCollection extends AbstractCollection implements Esable
{
/**
* @inheritDoc
*/
public function getType(): string
{
return QueryMatch::class;
}
public function es(): array
{
$matches = [];
foreach ($this->toArray() as $match) {
/** @var QueryMatch $match */
$matches = array_merge($match->es());
}
return $matches;
}
}
<?php
namespace IQDEV\ElasticSearch\Criteria\Order;
use IQDEV\ElasticSearch\Document\Property\Property;
use IQDEV\ElasticSearch\Esable;
abstract class Order implements Esable
{
public function __construct(
protected Property $property,
protected OrderDirection $direction,
protected array $additionalParams = [],
) {
}
public function getProperty(): Property
{
return $this->property;
}
public function getDirection(): OrderDirection
{
return $this->direction;
}
public function getAdditionalParams(): array
{
return $this->additionalParams;
}
}
<?php
namespace IQDEV\ElasticSearch\Order;
namespace IQDEV\ElasticSearch\Criteria\Order;
use IQDEV\ElasticSearch\Esable;
use Ramsey\Collection\AbstractCollection;
......
<?php
namespace IQDEV\ElasticSearch\Criteria\Order;
enum OrderDirection: string
{
case ASC = 'asc';
case DESC = 'desc';
}
<?php
namespace IQDEV\ElasticSearch\Criteria\Order;
use IQDEV\ElasticSearch\Document\Property\Property;
use IQDEV\ElasticSearch\Document\Property\PropertyType;
use IQDEV\ElasticSearch\Criteria\Order\Type\BaseOrder;
use IQDEV\ElasticSearch\Criteria\Order\Type\KeywordPropertyOrder;
use IQDEV\ElasticSearch\Criteria\Order\Type\NumberPropertyOrder;
class OrderFactory
{
public static function createByProperty(
Property $property,
OrderDirection $direction,
): Order {
return match ($property->getType()) {
PropertyType::KEYWORD => new KeywordPropertyOrder($property, $direction),
PropertyType::NUMBER => new NumberPropertyOrder($property, $direction),
default => new BaseOrder($property, $direction),
};
}
}
<?php
namespace IQDEV\ElasticSearch\Criteria\Order\Type;
use IQDEV\ElasticSearch\Criteria\Order\Order;
class BaseOrder extends Order
{
public function es(): array
{
return array_merge(
[$this->property->getKey() => $this->direction->value],
$this->additionalParams
);
}
}
<?php
namespace IQDEV\ElasticSearch\Order;
namespace IQDEV\ElasticSearch\Criteria\Order\Type;
class OrderKeywordProperty extends Order
use IQDEV\ElasticSearch\Criteria\Order\Order;
class KeywordPropertyOrder extends Order
{
public function es(): array
{
$order = [
'order' => $this->direction::getType(),
'order' => $this->direction->value,
'nested' => [
'path' => 'search_data',
'filter' => [
'bool' => [
'must' => [
'term' => [
'search_data.keyword_facet.facet_code' => $this->by,
]
'search_data.keyword_facet.facet_code' => $this->property->getKey(),
],
],
],
],
],
];
$order = array_merge($order, $this->properties);
return [
'search_data.keyword_facet.facet_value' => $order,
'search_data.keyword_facet.facet_value' => array_merge(
$order,
$this->additionalParams
),
];
}
}
<?php
namespace IQDEV\ElasticSearch\Order;
namespace IQDEV\ElasticSearch\Criteria\Order\Type;
class OrderNumberProperty extends Order
use IQDEV\ElasticSearch\Criteria\Order\Order;
class NumberPropertyOrder extends Order
{
public function es(): array
{
$order = [
'order' => $this->direction::getType(),
'order' => $this->direction->value,
'nested' => [
'path' => 'search_data',
'filter' => [
'bool' => [
'must' => [
'term' => [
'search_data.number_facet.facet_code' => $this->by,
]
'search_data.number_facet.facet_code' => $this->property->getKey(),
],
],
],
],
],
];
$order = array_merge($order, $this->properties);
return [
'search_data.number_facet.facet_value' => $order,
'search_data.number_facet.facet_value' => array_merge(
$order,
$this->additionalParams
),
];
}
}
<?php
namespace IQDEV\ElasticSearch\Criteria;
final class Pagination
{
public function __construct(
public int $limit = 20,
public int $offset = 0
) {
}
}
<?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;
}
......@@ -120,7 +113,7 @@ class ProductDocument implements Document
$result = array_replace_recursive($document, $this->properties);
if (true === $this->skipEmpty) {
$result = ArrayHelper::array_filter_recursive($result);
$result = ArrayHelper::array_filter_recursive($result, static fn ($val) => $val !== null || $val === false);
}
return $result;
......
<?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;
}
}