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\RawIterator; |
15
|
|
|
use ONGR\ElasticsearchBundle\Result\Result; |
16
|
|
|
use ONGR\ElasticsearchDSL\Query\QueryStringQuery; |
17
|
|
|
use ONGR\ElasticsearchDSL\Search; |
18
|
|
|
use ONGR\ElasticsearchDSL\Sort\FieldSort; |
19
|
|
|
use ONGR\ElasticsearchBundle\Result\DocumentIterator; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Document repository class. |
23
|
|
|
*/ |
24
|
|
|
class Repository |
25
|
|
|
{ |
26
|
|
|
/** |
27
|
|
|
* @var Manager |
28
|
|
|
*/ |
29
|
|
|
private $manager; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var string Fully qualified class name |
33
|
|
|
*/ |
34
|
|
|
private $className; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @var string Elasticsearch type name |
38
|
|
|
*/ |
39
|
|
|
private $type; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Constructor. |
43
|
|
|
* |
44
|
|
|
* @param Manager $manager |
45
|
|
|
* @param string $className |
46
|
|
|
*/ |
47
|
|
|
public function __construct($manager, $className) |
48
|
|
|
{ |
49
|
|
|
if (!is_string($className)) { |
50
|
|
|
throw new \InvalidArgumentException('Class name must be a string.'); |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
if (!class_exists($className)) { |
54
|
|
|
throw new \InvalidArgumentException( |
55
|
|
|
sprintf('Cannot create repository for non-existing class "%s".', $className) |
56
|
|
|
); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
$this->manager = $manager; |
60
|
|
|
$this->className = $className; |
61
|
|
|
$this->type = $this->resolveType($className); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* Returns elasticsearch manager used in the repository. |
66
|
|
|
* |
67
|
|
|
* @return Manager |
68
|
|
|
*/ |
69
|
|
|
public function getManager() |
70
|
|
|
{ |
71
|
|
|
return $this->manager; |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* @return array |
76
|
|
|
*/ |
77
|
|
|
public function getType() |
78
|
|
|
{ |
79
|
|
|
return $this->type; |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Returns a single document data by ID or null if document is not found. |
84
|
|
|
* |
85
|
|
|
* @param string $id Document ID to find |
86
|
|
|
* |
87
|
|
|
* @return object |
88
|
|
|
*/ |
89
|
|
|
public function find($id) |
90
|
|
|
{ |
91
|
|
|
return $this->manager->find($this->type, $id); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Returns documents by a set of ids |
96
|
|
|
* |
97
|
|
|
* @param array $ids |
98
|
|
|
* @param string $resultsType |
99
|
|
|
* |
100
|
|
|
* @return array |
101
|
|
|
*/ |
102
|
|
|
public function mget(array $ids, $resultsType = Result::RESULTS_OBJECT) |
103
|
|
|
{ |
104
|
|
|
return $this->manager->mget( |
105
|
|
|
[$this->type => $ids], |
106
|
|
|
[], |
107
|
|
|
$resultsType |
|
|
|
|
108
|
|
|
); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* Finds documents by a set of criteria. |
113
|
|
|
* |
114
|
|
|
* @param array $criteria Example: ['group' => ['best', 'worst'], 'job' => 'medic']. |
115
|
|
|
* @param array|null $orderBy Example: ['name' => 'ASC', 'surname' => 'DESC']. |
116
|
|
|
* @param int|null $limit Example: 5. |
117
|
|
|
* @param int|null $offset Example: 30. |
118
|
|
|
* |
119
|
|
|
* @return array|DocumentIterator The objects. |
120
|
|
|
*/ |
121
|
|
|
public function findBy( |
122
|
|
|
array $criteria, |
123
|
|
|
array $orderBy = [], |
124
|
|
|
$limit = null, |
125
|
|
|
$offset = null |
126
|
|
|
) { |
127
|
|
|
$search = $this->createSearch(); |
128
|
|
|
|
129
|
|
|
if ($limit !== null) { |
130
|
|
|
$search->setSize($limit); |
131
|
|
|
} |
132
|
|
|
if ($offset !== null) { |
133
|
|
|
$search->setFrom($offset); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
foreach ($criteria as $field => $value) { |
137
|
|
|
$search->addQuery( |
138
|
|
|
new QueryStringQuery(is_array($value) ? implode(' OR ', $value) : $value, ['default_field' => $field]) |
139
|
|
|
); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
foreach ($orderBy as $field => $direction) { |
143
|
|
|
$search->addSort(new FieldSort($field, $direction)); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
return $this->execute($search); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* Finds a single document by a set of criteria. |
151
|
|
|
* |
152
|
|
|
* @param array $criteria Example: ['group' => ['best', 'worst'], 'job' => 'medic']. |
153
|
|
|
* @param array|null $orderBy Example: ['name' => 'ASC', 'surname' => 'DESC']. |
154
|
|
|
* |
155
|
|
|
* @return object|null The object. |
156
|
|
|
*/ |
157
|
|
|
public function findOneBy(array $criteria, array $orderBy = []) |
158
|
|
|
{ |
159
|
|
|
$result = $this->findBy($criteria, $orderBy, null, null); |
160
|
|
|
|
161
|
|
|
return $result->first(); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* Returns search instance. |
166
|
|
|
* |
167
|
|
|
* @return Search |
168
|
|
|
*/ |
169
|
|
|
public function createSearch() |
170
|
|
|
{ |
171
|
|
|
return new Search(); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
/** |
175
|
|
|
* Executes given search. |
176
|
|
|
* |
177
|
|
|
* @param Search $search |
178
|
|
|
* @param string $resultsType |
179
|
|
|
* |
180
|
|
|
* @return DocumentIterator|RawIterator|array |
181
|
|
|
* |
182
|
|
|
* @throws \Exception |
183
|
|
|
*/ |
184
|
|
|
public function execute(Search $search, $resultsType = Result::RESULTS_OBJECT) |
185
|
|
|
{ |
186
|
|
|
return $this->manager->execute([$this->type], $search, $resultsType); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Counts documents by given search. |
191
|
|
|
* |
192
|
|
|
* @param Search $search |
193
|
|
|
* @param array $params |
194
|
|
|
* @param bool $returnRaw If set true returns raw response gotten from client. |
195
|
|
|
* |
196
|
|
|
* @return int|array |
197
|
|
|
*/ |
198
|
|
|
public function count(Search $search, array $params = [], $returnRaw = false) |
199
|
|
|
{ |
200
|
|
|
$body = array_merge( |
201
|
|
|
[ |
202
|
|
|
'index' => $this->getManager()->getIndexName(), |
203
|
|
|
'type' => $this->type, |
204
|
|
|
'body' => $search->toArray(), |
205
|
|
|
], |
206
|
|
|
$params |
207
|
|
|
); |
208
|
|
|
|
209
|
|
|
$results = $this |
210
|
|
|
->getManager() |
211
|
|
|
->getClient()->count($body); |
212
|
|
|
|
213
|
|
|
if ($returnRaw) { |
214
|
|
|
return $results; |
215
|
|
|
} else { |
216
|
|
|
return $results['count']; |
217
|
|
|
} |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
/** |
221
|
|
|
* Removes a single document data by ID. |
222
|
|
|
* |
223
|
|
|
* @param string $id Document ID to remove. |
224
|
|
|
* |
225
|
|
|
* @return array |
226
|
|
|
* |
227
|
|
|
* @throws \LogicException |
228
|
|
|
*/ |
229
|
|
|
public function remove($id) |
230
|
|
|
{ |
231
|
|
|
$params = [ |
232
|
|
|
'index' => $this->getManager()->getIndexName(), |
233
|
|
|
'type' => $this->type, |
234
|
|
|
'id' => $id, |
235
|
|
|
]; |
236
|
|
|
|
237
|
|
|
$response = $this->getManager()->getClient()->delete($params); |
238
|
|
|
|
239
|
|
|
return $response; |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* Partial document update. |
244
|
|
|
* |
245
|
|
|
* @param string $id Document id to update. |
246
|
|
|
* @param array $fields Fields array to update. |
247
|
|
|
* @param string $script Groovy script to update fields. |
248
|
|
|
* @param array $params Additional parameters to pass to the client. |
249
|
|
|
* |
250
|
|
|
* @return array |
251
|
|
|
*/ |
252
|
|
|
public function update($id, array $fields = [], $script = null, array $params = []) |
253
|
|
|
{ |
254
|
|
|
$body = array_filter( |
255
|
|
|
[ |
256
|
|
|
'doc' => $fields, |
257
|
|
|
'script' => $script, |
258
|
|
|
] |
259
|
|
|
); |
260
|
|
|
|
261
|
|
|
$params = array_merge( |
262
|
|
|
[ |
263
|
|
|
'id' => $id, |
264
|
|
|
'index' => $this->getManager()->getIndexName(), |
265
|
|
|
'type' => $this->type, |
266
|
|
|
'body' => $body, |
267
|
|
|
], |
268
|
|
|
$params |
269
|
|
|
); |
270
|
|
|
|
271
|
|
|
return $this->getManager()->getClient()->update($params); |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* Resolves elasticsearch type by class name. |
276
|
|
|
* |
277
|
|
|
* @param string $className |
278
|
|
|
* |
279
|
|
|
* @return array |
280
|
|
|
*/ |
281
|
|
|
private function resolveType($className) |
282
|
|
|
{ |
283
|
|
|
return $this->getManager()->getMetadataCollector()->getDocumentType($className); |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* Returns fully qualified class name. |
288
|
|
|
* |
289
|
|
|
* @return string |
290
|
|
|
*/ |
291
|
|
|
public function getClassName() |
292
|
|
|
{ |
293
|
|
|
return $this->className; |
294
|
|
|
} |
295
|
|
|
} |
296
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.