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