Completed
Push — master ( c46aad...2418e0 )
by Nicolas
03:11
created

Index::updateDocuments()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
1
<?php
2
namespace Elastica;
3
4
use Elastica\Exception\InvalidException;
5
use Elastica\Exception\ResponseException;
6
use Elastica\Index\Settings as IndexSettings;
7
use Elastica\Index\Stats as IndexStats;
8
use Elastica\ResultSet\BuilderInterface;
9
use Elasticsearch\Endpoints\AbstractEndpoint;
10
use Elasticsearch\Endpoints\DeleteByQuery;
11
use Elasticsearch\Endpoints\Indices\Aliases\Update;
12
use Elasticsearch\Endpoints\Indices\Analyze;
13
use Elasticsearch\Endpoints\Indices\Cache\Clear;
14
use Elasticsearch\Endpoints\Indices\Close;
15
use Elasticsearch\Endpoints\Indices\Create;
16
use Elasticsearch\Endpoints\Indices\Delete;
17
use Elasticsearch\Endpoints\Indices\Exists;
18
use Elasticsearch\Endpoints\Indices\Flush;
19
use Elasticsearch\Endpoints\Indices\ForceMerge;
20
use Elasticsearch\Endpoints\Indices\Mapping\Get;
21
use Elasticsearch\Endpoints\Indices\Open;
22
use Elasticsearch\Endpoints\Indices\Refresh;
23
use Elasticsearch\Endpoints\Indices\Settings\Put;
24
25
/**
26
 * Elastica index object.
27
 *
28
 * Handles reads, deletes and configurations of an index
29
 *
30
 * @author   Nicolas Ruflin <[email protected]>
31
 */
32
class Index implements SearchableInterface
33
{
34
    /**
35
     * Index name.
36
     *
37
     * @var string Index name
38
     */
39
    protected $_name;
40
41
    /**
42
     * Client object.
43
     *
44
     * @var \Elastica\Client Client object
45
     */
46
    protected $_client;
47
48
    /**
49
     * Creates a new index object.
50
     *
51
     * All the communication to and from an index goes of this object
52
     *
53
     * @param \Elastica\Client $client Client object
54
     * @param string           $name   Index name
55
     */
56
    public function __construct(Client $client, $name)
57
    {
58
        $this->_client = $client;
59
60
        if (!is_scalar($name)) {
61
            throw new InvalidException('Index name should be a scalar type');
62
        }
63
        $this->_name = (string) $name;
64
    }
65
66
    /**
67
     * Returns a type object for the current index with the given name.
68
     *
69
     * @param string $type Type name
70
     *
71
     * @return \Elastica\Type Type object
72
     */
73
    public function getType($type)
74
    {
75
        return new Type($this, $type);
76
    }
77
78
    /**
79
     * Return Index Stats.
80
     *
81
     * @return \Elastica\Index\Stats
82
     */
83
    public function getStats()
84
    {
85
        return new IndexStats($this);
86
    }
87
88
    /**
89
     * Gets all the type mappings for an index.
90
     *
91
     * @return array
92
     */
93 View Code Duplication
    public function getMapping()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
94
    {
95
        $response = $this->requestEndpoint(new Get());
96
        $data = $response->getData();
97
98
        // Get first entry as if index is an Alias, the name of the mapping is the real name and not alias name
99
        $mapping = array_shift($data);
100
101
        if (isset($mapping['mappings'])) {
102
            return $mapping['mappings'];
103
        }
104
105
        return [];
106
    }
107
108
    /**
109
     * Returns the index settings object.
110
     *
111
     * @return \Elastica\Index\Settings Settings object
112
     */
113
    public function getSettings()
114
    {
115
        return new IndexSettings($this);
116
    }
117
118
    /**
119
     * Uses _bulk to send documents to the server.
120
     *
121
     * @param array|\Elastica\Document[] $docs Array of Elastica\Document
122
     *
123
     * @return \Elastica\Bulk\ResponseSet
124
     *
125
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
126
     */
127
    public function updateDocuments(array $docs)
128
    {
129
        foreach ($docs as $doc) {
130
            $doc->setIndex($this->getName());
131
        }
132
133
        return $this->getClient()->updateDocuments($docs);
134
    }
135
136
    /**
137
     * Uses _bulk to send documents to the server.
138
     *
139
     * @param array|\Elastica\Document[] $docs Array of Elastica\Document
140
     *
141
     * @return \Elastica\Bulk\ResponseSet
142
     *
143
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
144
     */
145
    public function addDocuments(array $docs)
146
    {
147
        foreach ($docs as $doc) {
148
            $doc->setIndex($this->getName());
149
        }
150
151
        return $this->getClient()->addDocuments($docs);
152
    }
153
154
    /**
155
     * Deletes entries in the db based on a query.
156
     *
157
     * @param \Elastica\Query|string|array $query   Query object or array
158
     * @param array                        $options Optional params
159
     *
160
     * @return \Elastica\Response
161
     *
162
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/5.0/docs-delete-by-query.html
163
     */
164
    public function deleteByQuery($query, array $options = [])
165
    {
166
        $query = Query::create($query)->getQuery();
167
168
        $endpoint = new DeleteByQuery();
169
        $endpoint->setBody(['query' => is_array($query) ? $query : $query->toArray()]);
170
        $endpoint->setParams($options);
171
172
        return $this->requestEndpoint($endpoint);
173
    }
174
175
    /**
176
     * Deletes the index.
177
     *
178
     * @return \Elastica\Response Response object
179
     */
180
    public function delete()
181
    {
182
        return $this->requestEndpoint(new Delete());
183
    }
184
185
    /**
186
     * Uses _bulk to delete documents from the server.
187
     *
188
     * @param array|\Elastica\Document[] $docs Array of Elastica\Document
189
     *
190
     * @return \Elastica\Bulk\ResponseSet
191
     *
192
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
193
     */
194
    public function deleteDocuments(array $docs)
195
    {
196
        foreach ($docs as $doc) {
197
            $doc->setIndex($this->getName());
198
        }
199
200
        return $this->getClient()->deleteDocuments($docs);
201
    }
202
203
    /**
204
     * Force merges index.
205
     *
206
     * Detailed arguments can be found here in the link
207
     *
208
     * @param array $args OPTIONAL Additional arguments
209
     *
210
     * @return Response
211
     *
212
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html
213
     */
214
    public function forcemerge($args = [])
215
    {
216
        $endpoint = new ForceMerge();
217
        $endpoint->setParams($args);
218
219
        return $this->requestEndpoint($endpoint);
220
    }
221
222
    /**
223
     * Refreshes the index.
224
     *
225
     * @return \Elastica\Response Response object
226
     *
227
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html
228
     */
229
    public function refresh()
230
    {
231
        return $this->requestEndpoint(new Refresh());
232
    }
233
234
    /**
235
     * Creates a new index with the given arguments.
236
     *
237
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html
238
     *
239
     * @param array      $args    OPTIONAL Arguments to use
240
     * @param bool|array $options OPTIONAL
241
     *                            bool=> Deletes index first if already exists (default = false).
242
     *                            array => Associative array of options (option=>value)
243
     *
244
     * @throws \Elastica\Exception\InvalidException
245
     * @throws \Elastica\Exception\ResponseException
246
     *
247
     * @return \Elastica\Response Server response
248
     */
249
    public function create(array $args = [], $options = null)
250
    {
251
        if (is_bool($options) && $options) {
252
            try {
253
                $this->delete();
254
            } catch (ResponseException $e) {
255
                // Table can't be deleted, because doesn't exist
256
            }
257
        } elseif (is_array($options)) {
258
            foreach ($options as $key => $value) {
259
                switch ($key) {
260
                    case 'recreate':
261
                        try {
262
                            $this->delete();
263
                        } catch (ResponseException $e) {
264
                            // Table can't be deleted, because doesn't exist
265
                        }
266
                        break;
267
                    default:
268
                        throw new InvalidException('Invalid option '.$key);
269
                        break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
270
                }
271
            }
272
        }
273
274
        $endpoint = new Create();
275
        $endpoint->setBody($args);
276
277
        return $this->requestEndpoint($endpoint);
278
    }
279
280
    /**
281
     * Checks if the given index is already created.
282
     *
283
     * @return bool True if index exists
284
     */
285
    public function exists()
286
    {
287
        $response = $this->requestEndpoint(new Exists());
288
289
        return $response->getStatus() === 200;
290
    }
291
292
    /**
293
     * @param string|array|\Elastica\Query $query
294
     * @param int|array                    $options
295
     * @param BuilderInterface             $builder
296
     *
297
     * @return Search
298
     */
299
    public function createSearch($query = '', $options = null, BuilderInterface $builder = null)
300
    {
301
        $search = new Search($this->getClient(), $builder);
302
        $search->addIndex($this);
303
        $search->setOptionsAndQuery($options, $query);
304
305
        return $search;
306
    }
307
308
    /**
309
     * Searches in this index.
310
     *
311
     * @param string|array|\Elastica\Query $query   Array with all query data inside or a Elastica\Query object
312
     * @param int|array                    $options OPTIONAL Limit or associative array of options (option=>value)
313
     *
314
     * @return \Elastica\ResultSet with all results inside
315
     *
316
     * @see \Elastica\SearchableInterface::search
317
     */
318
    public function search($query = '', $options = null)
319
    {
320
        $search = $this->createSearch($query, $options);
321
322
        return $search->search();
323
    }
324
325
    /**
326
     * Counts results of query.
327
     *
328
     * @param string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object
329
     *
330
     * @return int number of documents matching the query
331
     *
332
     * @see \Elastica\SearchableInterface::count
333
     */
334
    public function count($query = '')
335
    {
336
        $search = $this->createSearch($query);
337
338
        return $search->count();
0 ignored issues
show
Bug Compatibility introduced by
The expression $search->count(); of type Elastica\ResultSet|integer adds the type Elastica\ResultSet to the return on line 338 which is incompatible with the return type declared by the interface Elastica\SearchableInterface::count of type integer.
Loading history...
339
    }
340
341
    /**
342
     * Opens an index.
343
     *
344
     * @return \Elastica\Response Response object
345
     *
346
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html
347
     */
348
    public function open()
349
    {
350
        return $this->requestEndpoint(new Open());
351
    }
352
353
    /**
354
     * Closes the index.
355
     *
356
     * @return \Elastica\Response Response object
357
     *
358
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html
359
     */
360
    public function close()
361
    {
362
        return $this->requestEndpoint(new Close());
363
    }
364
365
    /**
366
     * Returns the index name.
367
     *
368
     * @return string Index name
369
     */
370
    public function getName()
371
    {
372
        return $this->_name;
373
    }
374
375
    /**
376
     * Returns index client.
377
     *
378
     * @return \Elastica\Client Index client object
379
     */
380
    public function getClient()
381
    {
382
        return $this->_client;
383
    }
384
385
    /**
386
     * Adds an alias to the current index.
387
     *
388
     * @param string $name    Alias name
389
     * @param bool   $replace OPTIONAL If set, an existing alias will be replaced
390
     *
391
     * @return \Elastica\Response Response
392
     *
393
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html
394
     */
395
    public function addAlias($name, $replace = false)
396
    {
397
        $data = ['actions' => []];
398
399
        if ($replace) {
400
            $status = new Status($this->getClient());
401
            foreach ($status->getIndicesWithAlias($name) as $index) {
402
                $data['actions'][] = ['remove' => ['index' => $index->getName(), 'alias' => $name]];
403
            }
404
        }
405
406
        $data['actions'][] = ['add' => ['index' => $this->getName(), 'alias' => $name]];
407
408
        $endpoint = new Update();
409
        $endpoint->setBody($data);
410
411
        return $this->getClient()->requestEndpoint($endpoint);
412
    }
413
414
    /**
415
     * Removes an alias pointing to the current index.
416
     *
417
     * @param string $name Alias name
418
     *
419
     * @return \Elastica\Response Response
420
     *
421
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html
422
     */
423
    public function removeAlias($name)
424
    {
425
        $endpoint = new \Elasticsearch\Endpoints\Indices\Alias\Delete();
426
        $endpoint->setName($name);
427
428
        return $this->requestEndpoint($endpoint);
429
    }
430
431
    /**
432
     * Returns all index aliases.
433
     *
434
     * @return array Aliases
435
     */
436
    public function getAliases()
437
    {
438
        $endpoint = new \Elasticsearch\Endpoints\Indices\Alias\Get();
439
        $endpoint->setName('*');
440
441
        $responseData = $this->requestEndpoint($endpoint)->getData();
442
443
        if (!isset($responseData[$this->getName()])) {
444
            return [];
445
        }
446
447
        $data = $responseData[$this->getName()];
448
        if (!empty($data['aliases'])) {
449
            return array_keys($data['aliases']);
450
        }
451
452
        return [];
453
    }
454
455
    /**
456
     * Checks if the index has the given alias.
457
     *
458
     * @param string $name Alias name
459
     *
460
     * @return bool
461
     */
462
    public function hasAlias($name)
463
    {
464
        return in_array($name, $this->getAliases());
465
    }
466
467
    /**
468
     * Clears the cache of an index.
469
     *
470
     * @return \Elastica\Response Response object
471
     *
472
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-clearcache.html
473
     */
474
    public function clearCache()
475
    {
476
        // TODO: add additional cache clean arguments
477
        return $this->requestEndpoint(new Clear());
478
    }
479
480
    /**
481
     * Flushes the index to storage.
482
     *
483
     * @param array $options
484
     *
485
     * @return Response Response object
486
     *
487
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-flush.html
488
     */
489
    public function flush(array $options = [])
490
    {
491
        $endpoint = new Flush();
492
        $endpoint->setParams($options);
493
494
        return $this->requestEndpoint($endpoint);
495
    }
496
497
    /**
498
     * Can be used to change settings during runtime. One example is to use it for bulk updating.
499
     *
500
     * @param array $data Data array
501
     *
502
     * @return \Elastica\Response Response object
503
     *
504
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html
505
     */
506
    public function setSettings(array $data)
507
    {
508
        $endpoint = new Put();
509
        $endpoint->setBody($data);
510
511
        return $this->requestEndpoint($endpoint);
512
    }
513
514
    /**
515
     * Makes calls to the elasticsearch server based on this index.
516
     *
517
     * @param string       $path   Path to call
518
     * @param string       $method Rest method to use (GET, POST, DELETE, PUT)
519
     * @param array|string $data   OPTIONAL Arguments as array or encoded string
520
     * @param array        $query  OPTIONAL Query params
521
     *
522
     * @return \Elastica\Response Response object
523
     */
524
    public function request($path, $method, $data = [], array $query = [])
525
    {
526
        $path = $this->getName().'/'.$path;
527
528
        return $this->getClient()->request($path, $method, $data, $query);
529
    }
530
531
    /**
532
     * Makes calls to the elasticsearch server with usage official client Endpoint based on this index.
533
     *
534
     * @param AbstractEndpoint $endpoint
535
     *
536
     * @return Response
537
     */
538
    public function requestEndpoint(AbstractEndpoint $endpoint)
539
    {
540
        $cloned = clone $endpoint;
541
        $cloned->setIndex($this->getName());
542
543
        return $this->getClient()->requestEndpoint($cloned);
544
    }
545
546
    /**
547
     * Analyzes a string.
548
     *
549
     * Detailed arguments can be found here in the link
550
     *
551
     * @param string $text String to be analyzed
552
     * @param array  $args OPTIONAL Additional arguments
553
     *
554
     * @return array Server response
555
     *
556
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-analyze.html
557
     */
558
    public function analyze($text, $args = [])
559
    {
560
        $endpoint = new Analyze();
561
        $endpoint->setBody(['text' => $text]);
562
        $endpoint->setParams($args);
563
564
        $data = $this->requestEndpoint($endpoint)->getData();
565
566
        // Support for "Explain" parameter, that returns a different response structure from Elastic
567
        // @see: https://www.elastic.co/guide/en/elasticsearch/reference/current/_explain_analyze.html
568
        if (isset($args['explain']) && $args['explain']) {
569
            return $data['detail'];
570
        }
571
572
        return $data['tokens'];
573
    }
574
}
575