1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace DoctrineElastic\Query; |
4
|
|
|
|
5
|
|
|
use DoctrineElastic\Elastic\DoctrineElasticEvents; |
6
|
|
|
use DoctrineElastic\Elastic\SearchParams; |
7
|
|
|
use DoctrineElastic\Elastic\SearchParser; |
8
|
|
|
use DoctrineElastic\ElasticEntityManager; |
9
|
|
|
use DoctrineElastic\Event\QueryEventArgs; |
10
|
|
|
use DoctrineElastic\Hydrate\AnnotationEntityHydrator; |
11
|
|
|
use DoctrineElastic\Mapping\Field; |
12
|
|
|
use DoctrineElastic\Mapping\MetaField; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Class for query execution with entity hydration task |
16
|
|
|
* |
17
|
|
|
* @author Ands |
18
|
|
|
*/ |
19
|
|
|
class ElasticQueryExecutor { |
20
|
|
|
|
21
|
|
|
/** @var AnnotationEntityHydrator */ |
22
|
|
|
private $_hydrator; |
23
|
|
|
|
24
|
|
|
/** @var ElasticEntityManager */ |
25
|
|
|
private $_eem; |
26
|
|
|
|
27
|
|
|
public function __construct(ElasticEntityManager $elasticEntityManager) { |
28
|
|
|
$this->_eem = $elasticEntityManager; |
29
|
|
|
$this->_hydrator = new AnnotationEntityHydrator(); |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Executes a elastic query from $searchParams, creates a hydrated entity $entityClass object |
34
|
|
|
* with the results |
35
|
|
|
* |
36
|
|
|
* @param SearchParams $searchParams |
37
|
|
|
* @param $entityClass |
38
|
|
|
* @return array |
39
|
|
|
*/ |
40
|
|
|
public function execute(SearchParams $searchParams, $entityClass) { |
41
|
|
|
if (!$searchParams->isValid()) { |
42
|
|
|
throw new \InvalidArgumentException('Elastic search params are invalid for request. '); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
$eventArgs = $this->createEventArgs($entityClass); |
46
|
|
|
$this->_eem->getEventManager()->dispatchEvent(DoctrineElasticEvents::beforeQuery, $eventArgs); |
47
|
|
|
|
48
|
|
|
$resultSets = $this->fetchElasticResult($searchParams); |
49
|
|
|
$results = []; |
50
|
|
|
|
51
|
|
|
foreach ($resultSets as $resultSet) { |
52
|
|
|
$results[] = $this->hydrateEntityWith(new $entityClass(), $resultSet); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
$eventArgs->setResults($results); |
56
|
|
|
$this->_eem->getEventManager()->dispatchEvent(DoctrineElasticEvents::postQuery, $eventArgs); |
57
|
|
|
|
58
|
|
|
return $results; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
View Code Duplication |
private function hydrateEntityWith($entity, array $rawData) { |
|
|
|
|
62
|
|
|
$this->_hydrator->hydrate($entity, $rawData); |
63
|
|
|
$this->_hydrator->hydrateByAnnotation($entity, Field::class, $rawData); |
64
|
|
|
$this->_hydrator->hydrateByAnnotation($entity, MetaField::class, $rawData); |
65
|
|
|
|
66
|
|
|
if (isset($rawData['_source'])) { |
67
|
|
|
$this->hydrateEntityWith($entity, $rawData['_source']); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
return $entity; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
private function fetchElasticResult(SearchParams $searchParams) { |
74
|
|
|
$results = []; |
75
|
|
|
$connection = $this->_eem->getConnection(); |
76
|
|
|
|
77
|
|
|
if ($connection->getElasticClient()->indices()->exists(['index' => $searchParams->getIndex()])) { |
78
|
|
|
$arrayParams = SearchParser::parseSearchParams($searchParams); |
79
|
|
|
$results = $connection->search( |
80
|
|
|
$arrayParams['index'], $arrayParams['type'], $arrayParams['body'], $arrayParams |
81
|
|
|
); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
return $results; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* @param $entityClass |
89
|
|
|
* @return QueryEventArgs |
90
|
|
|
*/ |
91
|
|
|
private function createEventArgs($entityClass) { |
92
|
|
|
$eventArgs = new QueryEventArgs(); |
93
|
|
|
$eventArgs->setTargetEntity($entityClass); |
94
|
|
|
$eventArgs->setEntityManager($this->_eem); |
95
|
|
|
|
96
|
|
|
return $eventArgs; |
97
|
|
|
} |
98
|
|
|
} |
99
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.