Skip to content

Commit 136952c

Browse files
Dominik Piekarskiskurfuerst
authored andcommitted
[TASK] Enhance execute() with lazy loading in ElasticSearchQueryBuilder
Results from execute() now satisfy QueryResultInterface and can be used more widely Taken from #66 originally.
1 parent 6a9475b commit 136952c

3 files changed

Lines changed: 426 additions & 6 deletions

File tree

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
<?php
2+
namespace Flowpack\ElasticSearch\ContentRepositoryAdaptor\Eel;
3+
4+
/* *
5+
* This script belongs to the TYPO3 Flow package "Flowpack.ElasticSearch.ContentRepositoryAdaptor". *
6+
* *
7+
* It is free software; you can redistribute it and/or modify it under *
8+
* the terms of the GNU Lesser General Public License, either version 3 *
9+
* of the License, or (at your option) any later version. *
10+
* *
11+
* The TYPO3 project - inspiring people to share! *
12+
* */
13+
14+
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Exception;
15+
use TYPO3\Flow\Persistence\QueryInterface;
16+
17+
/**
18+
* This ElasticSearchQuery object is just used inside ElasticSearchQueryResult->getQuery(), so that pagination
19+
* widgets etc work in the same manner for ElasticSearch results.
20+
*/
21+
class ElasticSearchQuery implements QueryInterface {
22+
23+
/**
24+
* @var ElasticSearchQueryBuilder
25+
*/
26+
protected $queryBuilder;
27+
28+
public function __construct(ElasticSearchQueryBuilder $elasticSearchQueryBuilder) {
29+
$this->queryBuilder = $elasticSearchQueryBuilder;
30+
}
31+
32+
/**
33+
* {@inheritdoc}
34+
*/
35+
public function execute($cacheResult = FALSE) {
36+
return new ElasticSearchQueryResult($this);
37+
}
38+
39+
/**
40+
* {@inheritdoc}
41+
*/
42+
public function count() {
43+
// FIXME Check that results are fetched!
44+
45+
return $this->queryBuilder->getTotalItems();
46+
}
47+
48+
/**
49+
* {@inheritdoc}
50+
*/
51+
public function setLimit($limit) {
52+
if ($limit < 1 || !is_int($limit)) {
53+
throw new \InvalidArgumentException('Expecting integer greater than zero for limit');
54+
}
55+
56+
$this->queryBuilder->limit($limit);
57+
}
58+
59+
/**
60+
* {@inheritdoc}
61+
*/
62+
public function getLimit() {
63+
return $this->queryBuilder->getLimit();
64+
}
65+
66+
/**
67+
* {@inheritdoc}
68+
*/
69+
public function setOffset($offset) {
70+
if ($offset < 1 || !is_int($offset)) {
71+
throw new \InvalidArgumentException('Expecting integer greater than zero for offset');
72+
}
73+
74+
$this->queryBuilder->from($offset);
75+
}
76+
77+
/**
78+
* {@inheritdoc}
79+
*/
80+
public function getOffset() {
81+
return $this->queryBuilder->getFrom();
82+
}
83+
84+
/**
85+
* {@inheritdoc}
86+
*/
87+
public function getType() {
88+
return 'TYPO3\TYPO3CR\Domain\Model\NodeInterface';
89+
}
90+
91+
/**
92+
* {@inheritdoc}
93+
*/
94+
public function setOrderings(array $orderings) {
95+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749035);
96+
}
97+
98+
/**
99+
* {@inheritdoc}
100+
*/
101+
public function getOrderings() {
102+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749036);
103+
}
104+
105+
/**
106+
* {@inheritdoc}
107+
*/
108+
public function matching($constraint) {
109+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749037);
110+
}
111+
112+
/**
113+
* {@inheritdoc}
114+
*/
115+
public function getConstraint() {
116+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749038);
117+
}
118+
119+
/**
120+
* {@inheritdoc}
121+
*/
122+
public function logicalAnd($constraint1) {
123+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749039);
124+
}
125+
126+
/**
127+
* {@inheritdoc}
128+
*/
129+
public function logicalOr($constraint1) {
130+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749040);
131+
}
132+
133+
/**
134+
* {@inheritdoc}
135+
*/
136+
public function logicalNot($constraint) {
137+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749041);
138+
}
139+
140+
/**
141+
* {@inheritdoc}
142+
*/
143+
public function equals($propertyName, $operand, $caseSensitive = TRUE) {
144+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749042);
145+
}
146+
147+
/**
148+
* {@inheritdoc}
149+
*/
150+
public function like($propertyName, $operand, $caseSensitive = TRUE) {
151+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749043);
152+
}
153+
154+
/**
155+
* {@inheritdoc}
156+
*/
157+
public function contains($propertyName, $operand) {
158+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749044);
159+
}
160+
161+
/**
162+
* {@inheritdoc}
163+
*/
164+
public function isEmpty($propertyName) {
165+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749045);
166+
}
167+
168+
/**
169+
* {@inheritdoc}
170+
*/
171+
public function in($propertyName, $operand) {
172+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749046);
173+
}
174+
175+
/**
176+
* {@inheritdoc}
177+
*/
178+
public function lessThan($propertyName, $operand) {
179+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749047);
180+
}
181+
182+
/**
183+
* {@inheritdoc}
184+
*/
185+
public function lessThanOrEqual($propertyName, $operand) {
186+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749048);
187+
}
188+
189+
/**
190+
* {@inheritdoc}
191+
*/
192+
public function greaterThan($propertyName, $operand) {
193+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749049);
194+
}
195+
196+
/**
197+
* {@inheritdoc}
198+
*/
199+
public function greaterThanOrEqual($propertyName, $operand) {
200+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749050);
201+
}
202+
203+
/**
204+
* {@inheritdoc}
205+
*/
206+
public function setDistinct($distinct = TRUE) {
207+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749051);
208+
}
209+
210+
/**
211+
* {@inheritdoc}
212+
*/
213+
public function isDistinct() {
214+
throw new Exception(__FUNCTION__ . ' not implemented', 1421749052);
215+
}
216+
217+
/**
218+
* @return ElasticSearchQueryBuilder
219+
*/
220+
public function getQueryBuilder() {
221+
return $this->queryBuilder;
222+
}
223+
}

Classes/Flowpack/ElasticSearch/ContentRepositoryAdaptor/Eel/ElasticSearchQueryBuilder.php

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<?php
22
namespace Flowpack\ElasticSearch\ContentRepositoryAdaptor\Eel;
33

4-
54
/* *
65
* This script belongs to the TYPO3 Flow package "Flowpack.ElasticSearch.ContentRepositoryAdaptor". *
76
* *
@@ -69,6 +68,13 @@ class ElasticSearchQueryBuilder implements QueryBuilderInterface, ProtectedConte
6968
*/
7069
protected $unsupportedFieldsInCountRequest = array('fields', 'sort', 'from', 'size');
7170

71+
/**
72+
* Amount of total items in response without limit
73+
*
74+
* @var integer
75+
*/
76+
protected $totalItems;
77+
7278
/**
7379
* The ElasticSearch request, as it is being built up.
7480
* @var array
@@ -203,7 +209,7 @@ public function limit($limit) {
203209
$currentWorkspaceNestingLevel = 1;
204210
$workspace = $this->contextNode->getContext()->getWorkspace();
205211
while ($workspace->getBaseWorkspace() !== NULL) {
206-
$currentWorkspaceNestingLevel ++;
212+
$currentWorkspaceNestingLevel++;
207213
$workspace = $workspace->getBaseWorkspace();
208214
}
209215

@@ -391,11 +397,34 @@ public function log($message = NULL) {
391397
}
392398

393399
/**
394-
* Execute the query and return the list of nodes as result
400+
* @return integer
401+
*/
402+
public function getTotalItems() {
403+
return $this->totalItems;
404+
}
405+
406+
/**
407+
* @return integer
408+
*/
409+
public function getLimit() {
410+
return $this->limit;
411+
}
412+
413+
/**
414+
* @return integer
415+
*/
416+
public function getFrom() {
417+
return $this->from;
418+
}
419+
420+
/**
421+
* Execute the query and return the list of nodes as result.
422+
*
423+
* This method is rather internal; just to be called from the ElasticSearchQueryResult. For the public API, please use execute()
395424
*
396425
* @return array<\TYPO3\TYPO3CR\Domain\Model\NodeInterface>
397426
*/
398-
public function execute() {
427+
public function fetch() {
399428
$timeBefore = microtime(TRUE);
400429
$response = $this->elasticSearchClient->getIndex()->request('GET', '/_search', array(), json_encode($this->request));
401430
$timeAfterwards = microtime(TRUE);
@@ -404,9 +433,11 @@ public function execute() {
404433
$hits = $treatedContent['hits'];
405434

406435
if ($this->logThisQuery === TRUE) {
407-
$this->logger->log('Query Log (' . $this->logMessage . '): ' . json_encode($this->request) . ' -- execution time: ' . (($timeAfterwards-$timeBefore)*1000) . ' ms -- Limit: ' . $this->limit . ' -- Number of results returned: ' . count($hits['hits']) . ' -- Total Results: ' . $hits['total'], LOG_DEBUG);
436+
$this->logger->log('Query Log (' . $this->logMessage . '): ' . json_encode($this->request) . ' -- execution time: ' . (($timeAfterwards - $timeBefore) * 1000) . ' ms -- Limit: ' . $this->limit . ' -- Number of results returned: ' . count($hits['hits']) . ' -- Total Results: ' . $hits['total'], LOG_DEBUG);
408437
}
409438

439+
$this->totalItems = $hits['total'];
440+
410441
if ($hits['total'] === 0) {
411442
return array();
412443
}
@@ -451,6 +482,17 @@ public function execute() {
451482
return array_values($nodes);
452483
}
453484

485+
/**
486+
* Get a query result object for lazy execution of the query
487+
*
488+
* @return \Traversable<\TYPO3\Flow\Persistence\QueryResultInterface>
489+
*/
490+
public function execute() {
491+
$elasticSearchQuery = new ElasticSearchQuery($this);
492+
$result = $elasticSearchQuery->execute();
493+
return $result;
494+
}
495+
454496
/**
455497
* Return the total number of hits for the query.
456498
*
@@ -472,7 +514,7 @@ public function count() {
472514
$count = $treatedContent['count'];
473515

474516
if ($this->logThisQuery === TRUE) {
475-
$this->logger->log('Query Log (' . $this->logMessage . '): ' . json_encode($this->request) . ' -- execution time: ' . (($timeAfterwards-$timeBefore)*1000) . ' ms -- Total Results: ' . $count, LOG_DEBUG);
517+
$this->logger->log('Query Log (' . $this->logMessage . '): ' . json_encode($this->request) . ' -- execution time: ' . (($timeAfterwards - $timeBefore) * 1000) . ' ms -- Total Results: ' . $count, LOG_DEBUG);
476518
}
477519

478520
return $count;

0 commit comments

Comments
 (0)