Completed
Push — master ( 1b098c...1d169b )
by Nicolas
03:35
created

Index::getName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
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 Elastica\Script\AbstractScript;
10
use Elasticsearch\Endpoints\AbstractEndpoint;
11
use Elasticsearch\Endpoints\DeleteByQuery;
12
use Elasticsearch\Endpoints\Indices\Aliases\Update;
13
use Elasticsearch\Endpoints\Indices\Analyze;
14
use Elasticsearch\Endpoints\Indices\Cache\Clear;
15
use Elasticsearch\Endpoints\Indices\Close;
16
use Elasticsearch\Endpoints\Indices\Create;
17
use Elasticsearch\Endpoints\Indices\Delete;
18
use Elasticsearch\Endpoints\Indices\Exists;
19
use Elasticsearch\Endpoints\Indices\Flush;
20
use Elasticsearch\Endpoints\Indices\ForceMerge;
21
use Elasticsearch\Endpoints\Indices\Mapping\Get;
22
use Elasticsearch\Endpoints\Indices\Open;
23
use Elasticsearch\Endpoints\Indices\Refresh;
24
use Elasticsearch\Endpoints\Indices\Settings\Put;
25
use Elasticsearch\Endpoints\UpdateByQuery;
26
27
/**
28
 * Elastica index object.
29
 *
30
 * Handles reads, deletes and configurations of an index
31
 *
32
 * @author   Nicolas Ruflin <[email protected]>
33
 */
34
class Index implements SearchableInterface
35
{
36
    /**
37
     * Index name.
38
     *
39
     * @var string Index name
40
     */
41
    protected $_name;
42
43
    /**
44
     * Client object.
45
     *
46
     * @var \Elastica\Client Client object
47
     */
48
    protected $_client;
49
50
    /**
51
     * Creates a new index object.
52
     *
53
     * All the communication to and from an index goes of this object
54
     *
55
     * @param \Elastica\Client $client Client object
56
     * @param string           $name   Index name
57
     */
58 View Code Duplication
    public function __construct(Client $client, $name)
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...
59
    {
60
        $this->_client = $client;
61
62
        if (!is_scalar($name)) {
63
            throw new InvalidException('Index name should be a scalar type');
64
        }
65
        $this->_name = (string) $name;
66
    }
67
68
    /**
69
     * Returns a type object for the current index with the given name.
70
     *
71
     * @param string $type Type name
72
     *
73
     * @return \Elastica\Type Type object
74
     */
75
    public function getType($type)
76
    {
77
        return new Type($this, $type);
78
    }
79
80
    /**
81
     * Return Index Stats.
82
     *
83
     * @return \Elastica\Index\Stats
84
     */
85
    public function getStats()
86
    {
87
        return new IndexStats($this);
88
    }
89
90
    /**
91
     * Gets all the type mappings for an index.
92
     *
93
     * @return array
94
     */
95 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...
96
    {
97
        $response = $this->requestEndpoint(new Get());
98
        $data = $response->getData();
99
100
        // Get first entry as if index is an Alias, the name of the mapping is the real name and not alias name
101
        $mapping = array_shift($data);
102
103
        if (isset($mapping['mappings'])) {
104
            return $mapping['mappings'];
105
        }
106
107
        return [];
108
    }
109
110
    /**
111
     * Returns the index settings object.
112
     *
113
     * @return \Elastica\Index\Settings Settings object
114
     */
115
    public function getSettings()
116
    {
117
        return new IndexSettings($this);
118
    }
119
120
    /**
121
     * Uses _bulk to send documents to the server.
122
     *
123
     * @param array|\Elastica\Document[] $docs    Array of Elastica\Document
124
     * @param array                      $options Array of query params to use for query. For possible options check es api
125
     *
126
     * @return \Elastica\Bulk\ResponseSet
127
     *
128
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
129
     */
130
    public function updateDocuments(array $docs, array $options = [])
131
    {
132
        foreach ($docs as $doc) {
133
            $doc->setIndex($this->getName());
134
        }
135
136
        return $this->getClient()->updateDocuments($docs, $options);
137
    }
138
139
    /**
140
     * Update entries in the db based on a query.
141
     *
142
     * @param \Elastica\Query|string|array $query   Query object or array
143
     * @param AbstractScript $script Script
144
     * @param array                        $options Optional params
145
     *
146
     * @return \Elastica\Response
147
     *
148
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update-by-query.html
149
     */
150
    public function updateByQuery($query, AbstractScript $script , array $options = [])
151
    {
152
        $query = Query::create($query)->getQuery();
153
154
        $endpoint = new UpdateByQuery();
155
        $body = ['query' => is_array($query)
156
            ? $query
157
            : $query->toArray()];
158
159
        $body['script'] = $script->toArray()['script'];
160
        $endpoint->setBody($body);
161
        $endpoint->setParams($options);
162
163
        return $this->requestEndpoint($endpoint);
164
    }
165
166
    /**
167
     * Uses _bulk to send documents to the server.
168
     *
169
     * @param array|\Elastica\Document[] $docs    Array of Elastica\Document
170
     * @param array                      $options Array of query params to use for query. For possible options check es api
171
     *
172
     * @return \Elastica\Bulk\ResponseSet
173
     *
174
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
175
     */
176
    public function addDocuments(array $docs, array $options = [])
177
    {
178
        foreach ($docs as $doc) {
179
            $doc->setIndex($this->getName());
180
        }
181
182
        return $this->getClient()->addDocuments($docs, $options);
183
    }
184
185
    /**
186
     * Deletes entries in the db based on a query.
187
     *
188
     * @param \Elastica\Query|string|array $query   Query object or array
189
     * @param array                        $options Optional params
190
     *
191
     * @return \Elastica\Response
192
     *
193
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/5.0/docs-delete-by-query.html
194
     */
195
    public function deleteByQuery($query, array $options = [])
196
    {
197
        $query = Query::create($query)->getQuery();
198
199
        $endpoint = new DeleteByQuery();
200
        $endpoint->setBody(['query' => is_array($query) ? $query : $query->toArray()]);
201
        $endpoint->setParams($options);
202
203
        return $this->requestEndpoint($endpoint);
204
    }
205
206
    /**
207
     * Deletes the index.
208
     *
209
     * @return \Elastica\Response Response object
210
     */
211
    public function delete()
212
    {
213
        return $this->requestEndpoint(new Delete());
214
    }
215
216
    /**
217
     * Uses _bulk to delete documents from the server.
218
     *
219
     * @param array|\Elastica\Document[] $docs Array of Elastica\Document
220
     *
221
     * @return \Elastica\Bulk\ResponseSet
222
     *
223
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
224
     */
225
    public function deleteDocuments(array $docs)
226
    {
227
        foreach ($docs as $doc) {
228
            $doc->setIndex($this->getName());
229
        }
230
231
        return $this->getClient()->deleteDocuments($docs);
232
    }
233
234
    /**
235
     * Force merges index.
236
     *
237
     * Detailed arguments can be found here in the link
238
     *
239
     * @param array $args OPTIONAL Additional arguments
240
     *
241
     * @return Response
242
     *
243
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html
244
     */
245
    public function forcemerge($args = [])
246
    {
247
        $endpoint = new ForceMerge();
248
        $endpoint->setParams($args);
249
250
        return $this->requestEndpoint($endpoint);
251
    }
252
253
    /**
254
     * Refreshes the index.
255
     *
256
     * @return \Elastica\Response Response object
257
     *
258
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html
259
     */
260
    public function refresh()
261
    {
262
        return $this->requestEndpoint(new Refresh());
263
    }
264
265
    /**
266
     * Creates a new index with the given arguments.
267
     *
268
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html
269
     *
270
     * @param array      $args    OPTIONAL Arguments to use
271
     * @param bool|array $options OPTIONAL
272
     *                            bool=> Deletes index first if already exists (default = false).
273
     *                            array => Associative array of options (option=>value)
274
     *
275
     * @throws \Elastica\Exception\InvalidException
276
     * @throws \Elastica\Exception\ResponseException
277
     *
278
     * @return \Elastica\Response Server response
279
     */
280
    public function create(array $args = [], $options = null)
281
    {
282
        if (is_bool($options) && $options) {
283
            try {
284
                $this->delete();
285
            } catch (ResponseException $e) {
286
                // Table can't be deleted, because doesn't exist
287
            }
288
        } elseif (is_array($options)) {
289
            foreach ($options as $key => $value) {
290
                switch ($key) {
291
                    case 'recreate':
292
                        try {
293
                            $this->delete();
294
                        } catch (ResponseException $e) {
295
                            // Table can't be deleted, because doesn't exist
296
                        }
297
                        break;
298
                    default:
299
                        throw new InvalidException('Invalid option '.$key);
300
                        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...
301
                }
302
            }
303
        }
304
305
        $endpoint = new Create();
306
        $endpoint->setBody($args);
307
308
        return $this->requestEndpoint($endpoint);
309
    }
310
311
    /**
312
     * Checks if the given index is already created.
313
     *
314
     * @return bool True if index exists
315
     */
316
    public function exists()
317
    {
318
        $response = $this->requestEndpoint(new Exists());
319
320
        return $response->getStatus() === 200;
321
    }
322
323
    /**
324
     * @param string|array|\Elastica\Query $query
325
     * @param int|array                    $options
326
     * @param BuilderInterface             $builder
327
     *
328
     * @return Search
329
     */
330
    public function createSearch($query = '', $options = null, BuilderInterface $builder = null)
331
    {
332
        $search = new Search($this->getClient(), $builder);
333
        $search->addIndex($this);
334
        $search->setOptionsAndQuery($options, $query);
335
336
        return $search;
337
    }
338
339
    /**
340
     * Searches in this index.
341
     *
342
     * @param string|array|\Elastica\Query $query   Array with all query data inside or a Elastica\Query object
343
     * @param int|array                    $options OPTIONAL Limit or associative array of options (option=>value)
344
     *
345
     * @return \Elastica\ResultSet with all results inside
346
     *
347
     * @see \Elastica\SearchableInterface::search
348
     */
349
    public function search($query = '', $options = null)
350
    {
351
        $search = $this->createSearch($query, $options);
352
353
        return $search->search();
354
    }
355
356
    /**
357
     * Counts results of query.
358
     *
359
     * @param string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object
360
     *
361
     * @return int number of documents matching the query
362
     *
363
     * @see \Elastica\SearchableInterface::count
364
     */
365
    public function count($query = '')
366
    {
367
        $search = $this->createSearch($query);
368
369
        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 369 which is incompatible with the return type declared by the interface Elastica\SearchableInterface::count of type integer.
Loading history...
370
    }
371
372
    /**
373
     * Opens an index.
374
     *
375
     * @return \Elastica\Response Response object
376
     *
377
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html
378
     */
379
    public function open()
380
    {
381
        return $this->requestEndpoint(new Open());
382
    }
383
384
    /**
385
     * Closes the index.
386
     *
387
     * @return \Elastica\Response Response object
388
     *
389
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html
390
     */
391
    public function close()
392
    {
393
        return $this->requestEndpoint(new Close());
394
    }
395
396
    /**
397
     * Returns the index name.
398
     *
399
     * @return string Index name
400
     */
401
    public function getName()
402
    {
403
        return $this->_name;
404
    }
405
406
    /**
407
     * Returns index client.
408
     *
409
     * @return \Elastica\Client Index client object
410
     */
411
    public function getClient()
412
    {
413
        return $this->_client;
414
    }
415
416
    /**
417
     * Adds an alias to the current index.
418
     *
419
     * @param string $name    Alias name
420
     * @param bool   $replace OPTIONAL If set, an existing alias will be replaced
421
     *
422
     * @return \Elastica\Response Response
423
     *
424
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html
425
     */
426
    public function addAlias($name, $replace = false)
427
    {
428
        $data = ['actions' => []];
429
430
        if ($replace) {
431
            $status = new Status($this->getClient());
432
            foreach ($status->getIndicesWithAlias($name) as $index) {
433
                $data['actions'][] = ['remove' => ['index' => $index->getName(), 'alias' => $name]];
434
            }
435
        }
436
437
        $data['actions'][] = ['add' => ['index' => $this->getName(), 'alias' => $name]];
438
439
        $endpoint = new Update();
440
        $endpoint->setBody($data);
441
442
        return $this->getClient()->requestEndpoint($endpoint);
443
    }
444
445
    /**
446
     * Removes an alias pointing to the current index.
447
     *
448
     * @param string $name Alias name
449
     *
450
     * @return \Elastica\Response Response
451
     *
452
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html
453
     */
454
    public function removeAlias($name)
455
    {
456
        $endpoint = new \Elasticsearch\Endpoints\Indices\Alias\Delete();
457
        $endpoint->setName($name);
458
459
        return $this->requestEndpoint($endpoint);
460
    }
461
462
    /**
463
     * Returns all index aliases.
464
     *
465
     * @return array Aliases
466
     */
467
    public function getAliases()
468
    {
469
        $endpoint = new \Elasticsearch\Endpoints\Indices\Alias\Get();
470
        $endpoint->setName('*');
471
472
        $responseData = $this->requestEndpoint($endpoint)->getData();
473
474
        if (!isset($responseData[$this->getName()])) {
475
            return [];
476
        }
477
478
        $data = $responseData[$this->getName()];
479
        if (!empty($data['aliases'])) {
480
            return array_keys($data['aliases']);
481
        }
482
483
        return [];
484
    }
485
486
    /**
487
     * Checks if the index has the given alias.
488
     *
489
     * @param string $name Alias name
490
     *
491
     * @return bool
492
     */
493
    public function hasAlias($name)
494
    {
495
        return in_array($name, $this->getAliases());
496
    }
497
498
    /**
499
     * Clears the cache of an index.
500
     *
501
     * @return \Elastica\Response Response object
502
     *
503
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-clearcache.html
504
     */
505
    public function clearCache()
506
    {
507
        // TODO: add additional cache clean arguments
508
        return $this->requestEndpoint(new Clear());
509
    }
510
511
    /**
512
     * Flushes the index to storage.
513
     *
514
     * @param array $options
515
     *
516
     * @return Response Response object
517
     *
518
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-flush.html
519
     */
520
    public function flush(array $options = [])
521
    {
522
        $endpoint = new Flush();
523
        $endpoint->setParams($options);
524
525
        return $this->requestEndpoint($endpoint);
526
    }
527
528
    /**
529
     * Can be used to change settings during runtime. One example is to use it for bulk updating.
530
     *
531
     * @param array $data Data array
532
     *
533
     * @return \Elastica\Response Response object
534
     *
535
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html
536
     */
537
    public function setSettings(array $data)
538
    {
539
        $endpoint = new Put();
540
        $endpoint->setBody($data);
541
542
        return $this->requestEndpoint($endpoint);
543
    }
544
545
    /**
546
     * Makes calls to the elasticsearch server based on this index.
547
     *
548
     * @param string       $path   Path to call
549
     * @param string       $method Rest method to use (GET, POST, DELETE, PUT)
550
     * @param array|string $data   OPTIONAL Arguments as array or encoded string
551
     * @param array        $query  OPTIONAL Query params
552
     *
553
     * @return \Elastica\Response Response object
554
     */
555
    public function request($path, $method, $data = [], array $query = [])
556
    {
557
        $path = $this->getName().'/'.$path;
558
559
        return $this->getClient()->request($path, $method, $data, $query);
560
    }
561
562
    /**
563
     * Makes calls to the elasticsearch server with usage official client Endpoint based on this index.
564
     *
565
     * @param AbstractEndpoint $endpoint
566
     *
567
     * @return Response
568
     */
569
    public function requestEndpoint(AbstractEndpoint $endpoint)
570
    {
571
        $cloned = clone $endpoint;
572
        $cloned->setIndex($this->getName());
573
574
        return $this->getClient()->requestEndpoint($cloned);
575
    }
576
577
    /**
578
     * Analyzes a string.
579
     *
580
     * Detailed arguments can be found here in the link
581
     *
582
     * @param array $body String to be analyzed
583
     * @param array $args OPTIONAL Additional arguments
584
     *
585
     * @return array Server response
586
     *
587
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-analyze.html
588
     */
589
    public function analyze(array $body, $args = [])
590
    {
591
        $endpoint = new Analyze();
592
        $endpoint->setBody($body);
593
        $endpoint->setParams($args);
594
595
        $data = $this->requestEndpoint($endpoint)->getData();
596
597
        // Support for "Explain" parameter, that returns a different response structure from Elastic
598
        // @see: https://www.elastic.co/guide/en/elasticsearch/reference/current/_explain_analyze.html
599
        if (isset($body['explain']) && $body['explain']) {
600
            return $data['detail'];
601
        }
602
603
        return $data['tokens'];
604
    }
605
}
606