Completed
Push — master ( d3ac62...0cb203 )
by Federico
02:08
created

lib/Elastica/Index.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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