1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the ONGR package. |
5
|
|
|
* |
6
|
|
|
* (c) NFQ Technologies UAB <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace ONGR\ElasticsearchBundle\Service; |
13
|
|
|
|
14
|
|
|
use ONGR\ElasticsearchBundle\Result\ArrayIterator; |
15
|
|
|
use ONGR\ElasticsearchBundle\Result\RawIterator; |
16
|
|
|
use ONGR\ElasticsearchBundle\Result\Result; |
17
|
|
|
use ONGR\ElasticsearchDSL\Query\QueryStringQuery; |
18
|
|
|
use ONGR\ElasticsearchDSL\Search; |
19
|
|
|
use ONGR\ElasticsearchDSL\Sort\FieldSort; |
20
|
|
|
use ONGR\ElasticsearchBundle\Result\DocumentIterator; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Document repository class. |
24
|
|
|
*/ |
25
|
|
|
class Repository |
26
|
|
|
{ |
27
|
|
|
/** |
28
|
|
|
* @var Manager |
29
|
|
|
*/ |
30
|
|
|
private $manager; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @var string Fully qualified class name |
34
|
|
|
*/ |
35
|
|
|
private $className; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var string Elasticsearch type name |
39
|
|
|
*/ |
40
|
|
|
private $type; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Constructor. |
44
|
|
|
* |
45
|
|
|
* @param Manager $manager |
46
|
|
|
* @param string $className |
47
|
|
|
*/ |
48
|
|
|
public function __construct($manager, $className) |
49
|
|
|
{ |
50
|
|
|
if (!is_string($className)) { |
51
|
|
|
throw new \InvalidArgumentException('Class name must be a string.'); |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
if (!class_exists($className)) { |
55
|
|
|
throw new \InvalidArgumentException( |
56
|
|
|
sprintf('Cannot create repository for non-existing class "%s".', $className) |
57
|
|
|
); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
$this->manager = $manager; |
61
|
|
|
$this->className = $className; |
62
|
|
|
$this->type = $this->resolveType($className); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Returns elasticsearch manager used in the repository. |
67
|
|
|
* |
68
|
|
|
* @return Manager |
69
|
|
|
*/ |
70
|
|
|
public function getManager() |
71
|
|
|
{ |
72
|
|
|
return $this->manager; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* @return array |
77
|
|
|
*/ |
78
|
|
|
public function getType() |
79
|
|
|
{ |
80
|
|
|
return $this->type; |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* Returns a single document data by ID or null if document is not found. |
85
|
|
|
* |
86
|
|
|
* @param string $id Document ID to find |
87
|
|
|
* @param string $routing Custom routing for the document |
88
|
|
|
* |
89
|
|
|
* @return object |
90
|
|
|
*/ |
91
|
|
|
public function find($id, $routing = null) |
92
|
|
|
{ |
93
|
|
|
return $this->manager->find($this->type, $id, $routing); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Returns documents by a set of ids |
98
|
|
|
* |
99
|
|
|
* @param array $ids |
100
|
|
|
* |
101
|
|
|
* @return DocumentIterator The objects. |
102
|
|
|
*/ |
103
|
|
|
public function findByIds(array $ids) |
104
|
|
|
{ |
105
|
|
|
$args = []; |
106
|
|
|
$manager = $this->getManager(); |
107
|
|
|
$args['body']['docs'] = []; |
108
|
|
|
$args['index'] = $manager->getIndexName(); |
109
|
|
|
$args['type'] = $this->getType(); |
110
|
|
|
|
111
|
|
|
foreach ($ids as $id) { |
112
|
|
|
$args['body']['docs'][] = [ |
113
|
|
|
'_id' => $id |
114
|
|
|
]; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
$mgetResponse = $manager->getClient()->mget($args); |
118
|
|
|
|
119
|
|
|
$return = []; |
120
|
|
|
|
121
|
|
|
foreach ($mgetResponse['docs'] as $item) { |
122
|
|
|
if ($item['found']) { |
123
|
|
|
$return['hits']['hits'][] = $item; |
124
|
|
|
} |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
$return['hits']['total'] = count($return['hits']['hits']); |
128
|
|
|
|
129
|
|
|
return new DocumentIterator($return, $manager); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Finds documents by a set of criteria. |
134
|
|
|
* |
135
|
|
|
* @param array $criteria Example: ['group' => ['best', 'worst'], 'job' => 'medic']. |
136
|
|
|
* @param array|null $orderBy Example: ['name' => 'ASC', 'surname' => 'DESC']. |
137
|
|
|
* @param int|null $limit Example: 5. |
138
|
|
|
* @param int|null $offset Example: 30. |
139
|
|
|
* |
140
|
|
|
* @return array|DocumentIterator The objects. |
141
|
|
|
*/ |
142
|
|
|
public function findBy( |
143
|
|
|
array $criteria, |
144
|
|
|
array $orderBy = [], |
145
|
|
|
$limit = null, |
146
|
|
|
$offset = null |
147
|
|
|
) { |
148
|
|
|
$search = $this->createSearch(); |
149
|
|
|
|
150
|
|
|
if ($limit !== null) { |
151
|
|
|
$search->setSize($limit); |
152
|
|
|
} |
153
|
|
|
if ($offset !== null) { |
154
|
|
|
$search->setFrom($offset); |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
foreach ($criteria as $field => $value) { |
158
|
|
|
$search->addQuery( |
159
|
|
|
new QueryStringQuery(is_array($value) ? implode(' OR ', $value) : $value, ['default_field' => $field]) |
160
|
|
|
); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
foreach ($orderBy as $field => $direction) { |
164
|
|
|
$search->addSort(new FieldSort($field, $direction)); |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
return $this->execute($search); |
|
|
|
|
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* Finds a single document by a set of criteria. |
172
|
|
|
* |
173
|
|
|
* @param array $criteria Example: ['group' => ['best', 'worst'], 'job' => 'medic']. |
174
|
|
|
* @param array|null $orderBy Example: ['name' => 'ASC', 'surname' => 'DESC']. |
175
|
|
|
* |
176
|
|
|
* @return object|null The object. |
177
|
|
|
*/ |
178
|
|
|
public function findOneBy(array $criteria, array $orderBy = []) |
179
|
|
|
{ |
180
|
|
|
$result = $this->findBy($criteria, $orderBy, null, null); |
181
|
|
|
|
182
|
|
|
return $result->first(); |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* Returns search instance. |
187
|
|
|
* |
188
|
|
|
* @return Search |
189
|
|
|
*/ |
190
|
|
|
public function createSearch() |
191
|
|
|
{ |
192
|
|
|
return new Search(); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* Executes given search. |
197
|
|
|
* |
198
|
|
|
* @deprecated Use strict execute functions instead. e.g. executeIterator, executeRawIterator. |
199
|
|
|
* @param Search $search |
200
|
|
|
* @param string $resultsType |
201
|
|
|
* |
202
|
|
|
* @return DocumentIterator|RawIterator|array |
203
|
|
|
* |
204
|
|
|
* @throws \Exception |
205
|
|
|
*/ |
206
|
|
|
public function execute(Search $search, $resultsType = Result::RESULTS_OBJECT) |
207
|
|
|
{ |
208
|
|
|
return $this->manager->execute([$this->type], $search, $resultsType); |
|
|
|
|
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* Parses scroll configuration from raw response. |
214
|
|
|
* |
215
|
|
|
* @param $raw |
216
|
|
|
* @param null $scrollDuration |
217
|
|
|
* |
218
|
|
|
* @return array |
219
|
|
|
*/ |
220
|
|
|
private function getScrollConfiguration($raw, $scrollDuration = null) |
221
|
|
|
{ |
222
|
|
|
$scrollConfig = []; |
223
|
|
View Code Duplication |
if (isset($raw['_scroll_id'])) { |
|
|
|
|
224
|
|
|
$scrollConfig['_scroll_id'] = $raw['_scroll_id']; |
225
|
|
|
$scrollConfig['duration'] = $scrollDuration; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
return $scrollConfig; |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* Returns DocumentIterator with composed Document objects from array response. |
234
|
|
|
* |
235
|
|
|
* @param Search $search |
236
|
|
|
* |
237
|
|
|
* @return DocumentIterator |
238
|
|
|
*/ |
239
|
|
|
public function findDocument(Search $search) |
240
|
|
|
{ |
241
|
|
|
$results = $this->executeSearch($search); |
242
|
|
|
|
243
|
|
|
return new DocumentIterator($results, $this->getManager(), $this->getScrollConfiguration($results)); |
|
|
|
|
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* Returns ArrayIterator with access to unmodified documents directly. |
249
|
|
|
* |
250
|
|
|
* @param Search $search |
251
|
|
|
* |
252
|
|
|
* @return ArrayIterator |
253
|
|
|
*/ |
254
|
|
|
public function findArray(Search $search) |
255
|
|
|
{ |
256
|
|
|
$results = $this->executeSearch($search); |
257
|
|
|
|
258
|
|
|
return new ArrayIterator($results, $this->getManager(), $this->getScrollConfiguration($results)); |
|
|
|
|
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* Returns RawIterator with access to node with all returned values included. |
263
|
|
|
* |
264
|
|
|
* @param Search $search |
265
|
|
|
* |
266
|
|
|
* @return RawIterator |
267
|
|
|
*/ |
268
|
|
|
public function findRaw(Search $search) |
269
|
|
|
{ |
270
|
|
|
$results = $this->executeSearch($search); |
271
|
|
|
|
272
|
|
|
return new RawIterator($results, $this->getManager(), $this->getScrollConfiguration($results)); |
|
|
|
|
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* Executes search to the elasticsearch and returns raw response. |
277
|
|
|
* |
278
|
|
|
* @param Search $search |
279
|
|
|
* |
280
|
|
|
* @return array |
281
|
|
|
*/ |
282
|
|
|
private function executeSearch(Search $search) |
283
|
|
|
{ |
284
|
|
|
return $this->getManager()->search([$this->getType()], $search->toArray(), $search->getQueryParams()); |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
/** |
288
|
|
|
* Counts documents by given search. |
289
|
|
|
* |
290
|
|
|
* @param Search $search |
291
|
|
|
* @param array $params |
292
|
|
|
* @param bool $returnRaw If set true returns raw response gotten from client. |
293
|
|
|
* |
294
|
|
|
* @return int|array |
295
|
|
|
*/ |
296
|
|
|
public function count(Search $search, array $params = [], $returnRaw = false) |
297
|
|
|
{ |
298
|
|
|
$body = array_merge( |
299
|
|
|
[ |
300
|
|
|
'index' => $this->getManager()->getIndexName(), |
301
|
|
|
'type' => $this->type, |
302
|
|
|
'body' => $search->toArray(), |
303
|
|
|
], |
304
|
|
|
$params |
305
|
|
|
); |
306
|
|
|
|
307
|
|
|
$results = $this |
308
|
|
|
->getManager() |
309
|
|
|
->getClient()->count($body); |
310
|
|
|
|
311
|
|
|
if ($returnRaw) { |
312
|
|
|
return $results; |
313
|
|
|
} else { |
314
|
|
|
return $results['count']; |
315
|
|
|
} |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
/** |
319
|
|
|
* Removes a single document data by ID. |
320
|
|
|
* |
321
|
|
|
* @param string $id Document ID to remove |
322
|
|
|
* @param string $routing Custom routing for the document |
323
|
|
|
* |
324
|
|
|
* @return array |
325
|
|
|
* |
326
|
|
|
* @throws \LogicException |
327
|
|
|
*/ |
328
|
|
|
public function remove($id, $routing = null) |
329
|
|
|
{ |
330
|
|
|
$params = [ |
331
|
|
|
'index' => $this->getManager()->getIndexName(), |
332
|
|
|
'type' => $this->type, |
333
|
|
|
'id' => $id, |
334
|
|
|
]; |
335
|
|
|
|
336
|
|
|
if ($routing) { |
|
|
|
|
337
|
|
|
$params['routing'] = $routing; |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
$response = $this->getManager()->getClient()->delete($params); |
341
|
|
|
|
342
|
|
|
return $response; |
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
/** |
346
|
|
|
* Partial document update. |
347
|
|
|
* |
348
|
|
|
* @param string $id Document id to update. |
349
|
|
|
* @param array $fields Fields array to update. |
350
|
|
|
* @param string $script Groovy script to update fields. |
351
|
|
|
* @param array $params Additional parameters to pass to the client. |
352
|
|
|
* |
353
|
|
|
* @return array |
354
|
|
|
*/ |
355
|
|
|
public function update($id, array $fields = [], $script = null, array $params = []) |
356
|
|
|
{ |
357
|
|
|
$body = array_filter( |
358
|
|
|
[ |
359
|
|
|
'doc' => $fields, |
360
|
|
|
'script' => $script, |
361
|
|
|
] |
362
|
|
|
); |
363
|
|
|
|
364
|
|
|
$params = array_merge( |
365
|
|
|
[ |
366
|
|
|
'id' => $id, |
367
|
|
|
'index' => $this->getManager()->getIndexName(), |
368
|
|
|
'type' => $this->type, |
369
|
|
|
'body' => $body, |
370
|
|
|
], |
371
|
|
|
$params |
372
|
|
|
); |
373
|
|
|
|
374
|
|
|
return $this->getManager()->getClient()->update($params); |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
/** |
378
|
|
|
* Resolves elasticsearch type by class name. |
379
|
|
|
* |
380
|
|
|
* @param string $className |
381
|
|
|
* |
382
|
|
|
* @return array |
383
|
|
|
*/ |
384
|
|
|
private function resolveType($className) |
385
|
|
|
{ |
386
|
|
|
return $this->getManager()->getMetadataCollector()->getDocumentType($className); |
387
|
|
|
} |
388
|
|
|
|
389
|
|
|
/** |
390
|
|
|
* Returns fully qualified class name. |
391
|
|
|
* |
392
|
|
|
* @return string |
393
|
|
|
*/ |
394
|
|
|
public function getClassName() |
395
|
|
|
{ |
396
|
|
|
return $this->className; |
397
|
|
|
} |
398
|
|
|
} |
399
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.