1<?php
2
3declare(strict_types = 1);
4
5namespace Elasticsearch;
6
7use Elasticsearch\Common\Exceptions\BadMethodCallException;
8use Elasticsearch\Common\Exceptions\InvalidArgumentException;
9use Elasticsearch\Common\Exceptions\NoNodesAvailableException;
10use Elasticsearch\Common\Exceptions\BadRequest400Exception;
11use Elasticsearch\Common\Exceptions\Missing404Exception;
12use Elasticsearch\Common\Exceptions\TransportException;
13use Elasticsearch\Endpoints\AbstractEndpoint;
14use Elasticsearch\Namespaces\AbstractNamespace;
15use Elasticsearch\Namespaces\CatNamespace;
16use Elasticsearch\Namespaces\ClusterNamespace;
17use Elasticsearch\Namespaces\IndicesNamespace;
18use Elasticsearch\Namespaces\IngestNamespace;
19use Elasticsearch\Namespaces\NamespaceBuilderInterface;
20use Elasticsearch\Namespaces\NodesNamespace;
21use Elasticsearch\Namespaces\RemoteNamespace;
22use Elasticsearch\Namespaces\SnapshotNamespace;
23use Elasticsearch\Namespaces\BooleanRequestWrapper;
24use Elasticsearch\Namespaces\TasksNamespace;
25
26/**
27 * Class Client
28 *
29 * @category Elasticsearch
30 * @package  Elasticsearch
31 * @author   Zachary Tong <zach@elastic.co>
32 * @license  http://www.apache.org/licenses/LICENSE-2.0 Apache2
33 * @link     http://elastic.co
34 */
35class Client
36{
37    const VERSION = '7.0.2';
38
39    /**
40     * @var Transport
41     */
42    public $transport;
43
44    /**
45     * @var array
46     */
47    protected $params;
48
49    /**
50     * @var IndicesNamespace
51     */
52    protected $indices;
53
54    /**
55     * @var ClusterNamespace
56     */
57    protected $cluster;
58
59    /**
60     * @var NodesNamespace
61     */
62    protected $nodes;
63
64    /**
65     * @var SnapshotNamespace
66     */
67    protected $snapshot;
68
69    /**
70     * @var CatNamespace
71     */
72    protected $cat;
73
74    /**
75     * @var IngestNamespace
76     */
77    protected $ingest;
78
79    /**
80     * @var TasksNamespace
81     */
82    protected $tasks;
83
84    /**
85     * @var RemoteNamespace
86     */
87    protected $remote;
88
89    /**
90     * @var callable
91     */
92    protected $endpoints;
93
94    /**
95     * @var NamespaceBuilderInterface[]
96     */
97    protected $registeredNamespaces = [];
98
99    /**
100     * Client constructor
101     *
102     * @param Transport           $transport
103     * @param callable            $endpoint
104     * @param AbstractNamespace[] $registeredNamespaces
105     */
106    public function __construct(Transport $transport, callable $endpoint, array $registeredNamespaces)
107    {
108        $this->transport = $transport;
109        $this->endpoints = $endpoint;
110        $this->indices   = new IndicesNamespace($transport, $endpoint);
111        $this->cluster   = new ClusterNamespace($transport, $endpoint);
112        $this->nodes     = new NodesNamespace($transport, $endpoint);
113        $this->snapshot  = new SnapshotNamespace($transport, $endpoint);
114        $this->cat       = new CatNamespace($transport, $endpoint);
115        $this->ingest    = new IngestNamespace($transport, $endpoint);
116        $this->tasks     = new TasksNamespace($transport, $endpoint);
117        $this->remote    = new RemoteNamespace($transport, $endpoint);
118        $this->registeredNamespaces = $registeredNamespaces;
119    }
120
121    /**
122     * @param  string[] $params
123     * @return callable|array
124     */
125    public function info(array $params = [])
126    {
127        /**
128 * @var callable $endpointBuilder
129*/
130        $endpointBuilder = $this->endpoints;
131
132        /**
133 * @var \Elasticsearch\Endpoints\Info $endpoint
134*/
135        $endpoint = $endpointBuilder('Info');
136        $endpoint->setParams($params);
137
138        return $this->performRequest($endpoint);
139    }
140
141    public function ping(array $params = []): bool
142    {
143        /**
144 * @var callable $endpointBuilder
145*/
146        $endpointBuilder = $this->endpoints;
147
148        /**
149 * @var \Elasticsearch\Endpoints\Ping $endpoint
150*/
151        $endpoint = $endpointBuilder('Ping');
152        $endpoint->setParams($params);
153
154        try {
155            $this->performRequest($endpoint);
156        } catch (Missing404Exception $exception) {
157            return false;
158        } catch (TransportException $exception) {
159            return false;
160        } catch (NoNodesAvailableException $exception) {
161            return false;
162        }
163
164        return true;
165    }
166
167    /**
168     * $params['body']  = (string) The ranking evaluation search definition, including
169     *        search requests, document ratings and ranking metric definition (Required)
170     *        ['index'] = (list) A comma-separated list of index names to search; use `_all` or
171     *        empty string to perform the operation on all indices
172     *        ['ignore_unavailable'] = (boolean) Whether specified concrete indices should be
173     *        ignored when unavailable (missing or closed)
174     *        ['allow_no_indices'] = (boolean) Whether to ignore if a wildcard indices expression
175     *        resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)
176     *        ['expand_wildcards'] = (enum) Whether to expand wildcard expression to concrete indices that are open,
177     *        closed or both.
178     *
179     * @return callable|array
180     */
181    public function rankEval(array $params)
182    {
183        $body = $this->extractArgument($params, 'body');
184        $index = $this->extractArgument($params, 'index');
185
186        /**
187 * @var callable $endpointBuilder
188*/
189        $endpointBuilder = $this->endpoints;
190
191        /**
192 * @var \Elasticsearch\Endpoints\RankEval $endpoint
193*/
194        $endpoint = $endpointBuilder('RankEval');
195        $endpoint->setBody($body)
196            ->setIndex($index);
197        $endpoint->setParams($params);
198
199        return $this->performRequest($endpoint);
200    }
201
202    /**
203     * $params['id']               = (string) The document ID (Required)
204     *        ['index']            = (string) The name of the index (Required)
205     *        ['type']             = (string) The type of the document (use `_all` to fetch the first document matching the ID across all types) (Required)
206     *        ['ignore_missing']   = ??
207     *        ['fields']           = (list) A comma-separated list of fields to return in the response
208     *        ['parent']           = (string) The ID of the parent document
209     *        ['preference']       = (string) Specify the node or shard the operation should be performed on (default: random)
210     *        ['realtime']         = (boolean) Specify whether to perform the operation in realtime or search mode
211     *        ['refresh']          = (boolean) Refresh the shard containing the document before performing the operation
212     *        ['routing']          = (string) Specific routing value
213     *        ['_source']          = (list) True or false to return the _source field or not, or a list of fields to return
214     *        ['_source_exclude']  = (list) A list of fields to exclude from the returned _source field (deprecated in ES 6.6.0)
215     *        ['_source_excludes'] = (list) A list of fields to exclude from the returned _source field
216     *        ['_source_include']  = (list) A list of fields to extract and return from the _source field (deprecated in ES 6.6.0)
217     *        ['_source_includes'] = (list) A list of fields to extract and return from the _source field
218     *
219     * @return callable|array
220     */
221    public function get(array $params)
222    {
223        $id = $this->extractArgument($params, 'id');
224        $index = $this->extractArgument($params, 'index');
225        $type = $this->extractArgument($params, 'type');
226
227        /**
228 * @var callable $endpointBuilder
229*/
230        $endpointBuilder = $this->endpoints;
231
232        /**
233 * @var \Elasticsearch\Endpoints\Get $endpoint
234*/
235        $endpoint = $endpointBuilder('Get');
236        $endpoint->setID($id)
237            ->setIndex($index)
238            ->setType($type);
239        $endpoint->setParams($params);
240
241        return $this->performRequest($endpoint);
242    }
243
244    /**
245     * $params['id']             = (string) The document ID (Required)
246     *        ['index']          = (string) The name of the index (Required)
247     *        ['type']           = (string) The type of the document (use `_all` to fetch the first document matching the ID across all types) (Required)
248     *        ['ignore_missing'] = ??
249     *        ['parent']         = (string) The ID of the parent document
250     *        ['preference']     = (string) Specify the node or shard the operation should be performed on (default: random)
251     *        ['realtime']       = (boolean) Specify whether to perform the operation in realtime or search mode
252     *        ['refresh']        = (boolean) Refresh the shard containing the document before performing the operation
253     *        ['routing']        = (string) Specific routing value
254     *
255     * @return callable|array
256     */
257    public function getSource(array $params)
258    {
259        $id = $this->extractArgument($params, 'id');
260        $index = $this->extractArgument($params, 'index');
261        $type = $this->extractArgument($params, 'type');
262
263        /**
264 * @var callable $endpointBuilder
265*/
266        $endpointBuilder = $this->endpoints;
267
268        /**
269 * @var \Elasticsearch\Endpoints\Get $endpoint
270*/
271        $endpoint = $endpointBuilder('Source\Get');
272        $endpoint->setID($id)
273            ->setIndex($index)
274            ->setType($type);
275        $endpoint->setParams($params);
276
277        return $this->performRequest($endpoint);
278    }
279
280    /**
281     * $params['id']           = (string) The document ID (Required)
282     *        ['index']        = (string) The name of the index (Required)
283     *        ['type']         = (string) The type of the document
284     *        ['consistency']  = (enum) Specific write consistency setting for the operation
285     *        ['parent']       = (string) ID of parent document
286     *        ['refresh']      = (boolean) Refresh the index after performing the operation
287     *        ['replication']  = (enum) Specific replication type
288     *        ['routing']      = (string) Specific routing value
289     *        ['timeout']      = (time) Explicit operation timeout
290     *        ['version_type'] = (enum) Specific version type
291     *
292     * @return callable|array
293     */
294    public function delete(array $params)
295    {
296        $id = $this->extractArgument($params, 'id');
297        $index = $this->extractArgument($params, 'index');
298        $type = $this->extractArgument($params, 'type');
299
300        $this->verifyNotNullOrEmpty("id", $id);
301        $this->verifyNotNullOrEmpty("index", $index);
302
303        /**
304 * @var callable $endpointBuilder
305*/
306        $endpointBuilder = $this->endpoints;
307
308        /**
309 * @var \Elasticsearch\Endpoints\Delete $endpoint
310*/
311        $endpoint = $endpointBuilder('Delete');
312        $endpoint->setID($id)
313            ->setIndex($index)
314            ->setType($type);
315        $endpoint->setParams($params);
316
317        return $this->performRequest($endpoint);
318    }
319
320    /**
321     * $params['_source'] = (list) True or false to return the _source field or not, or a list of fields to return
322     *        ['_source_exclude'] = (array) A list of fields to exclude from the returned _source field (deprecated in ES 6.6.0)
323     *        ['_source_include'] = (array) A list of fields to extract and return from the _source field (deprecated in ES 6.6.0)
324     *        ['_source_excludes'] = (array) A list of fields to exclude from the returned _source field
325     *        ['_source_includes'] = (array) A list of fields to extract and return from the _source field
326     *        ['allow_no_indices'] = (bool) Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)
327     *        ['analyze_wildcard'] = (bool) Specify whether wildcard and prefix queries should be analyzed (default: false)
328     *        ['analyzer'] = (string) The analyzer to use for the query string
329     *        ['conflicts'] = (enum) What to do when the delete-by-query hits version conflicts?
330     *        ['default_operator'] = (enum) The default operator for query string query (AND or OR)
331     *        ['df'] = (string) The field to use as default where no field prefix is given in the query string
332     *        ['expand_wildcards'] = (enum) Whether to expand wildcard expression to concrete indices that are open, closed or both.
333     *        ['from'] = (number) Starting offset (default: 0)
334     *        ['ignore_unavailable'] = (bool) Whether specified concrete indices should be ignored when unavailable (missing or closed)
335     *        ['lenient'] = (bool) Specify whether format-based query failures (such as providing text to a numeric field) should be ignored
336     *        ['preference'] = (string) Specify the node or shard the operation should be performed on (default: random)
337     *        ['q'] = (string) Query in the Lucene query string syntax
338     *        ['refresh'] = (bool) Should the effected indexes be refreshed?
339     *        ['request_cache'] = (bool) Specify if request cache should be used for this request or not, defaults to index level setting
340     *        ['requests_per_second'] = (number) The throttle for this request in sub-requests per second. -1 means no throttle.
341     *        ['routing'] = (array) A comma-separated list of specific routing values
342     *        ['scroll'] = (number) Specify how long a consistent view of the index should be maintained for scrolled search
343     *        ['scroll_size'] = (number) Size on the scroll request powering the update_by_query
344     *        ['search_timeout'] = (number) Explicit timeout for each search request. Defaults to no timeout.
345     *        ['search_type'] = (enum) Search operation type
346     *        ['size'] = (number) Number of hits to return (default: 10)
347     *        ['slices'] = (integer) The number of slices this task should be divided into. Defaults to 1 meaning the task isn't sliced into subtasks.
348     *        ['sort'] = (array) A comma-separated list of <field>:<direction> pairs
349     *        ['stats'] = (array) Specific 'tag' of the request for logging and statistical purposes
350     *        ['terminate_after'] = (number) The maximum number of documents to collect for each shard, upon reaching which the query execution will terminate early.
351     *        ['timeout'] = (number) Time each individual bulk request should wait for shards that are unavailable.
352     *        ['version'] = (bool) Specify whether to return document version as part of a hit
353     *        ['wait_for_active_shards'] = (string) Sets the number of shard copies that must be active before proceeding with the delete by query operation. Defaults to 1, meaning the primary shard only. Set to `all` for all shard copies, otherwise set to any non-negative value less than or equal to the total number of copies for the shard (number of replicas + 1)
354     *        ['wait_for_completion'] = (bool) Should the request should block until the delete-by-query is complete.
355     *
356     * @return callable|array
357     */
358    public function deleteByQuery(array $params = [])
359    {
360        $index = $this->extractArgument($params, 'index');
361
362        $type = $this->extractArgument($params, 'type');
363
364        $body = $this->extractArgument($params, 'body');
365
366        /**
367 * @var callable $endpointBuilder
368*/
369        $endpointBuilder = $this->endpoints;
370
371        /**
372 * @var \Elasticsearch\Endpoints\DeleteByQuery $endpoint
373*/
374        $endpoint = $endpointBuilder('DeleteByQuery');
375        $endpoint->setIndex($index)
376            ->setType($type)
377            ->setBody($body);
378        $endpoint->setParams($params);
379
380        return $this->performRequest($endpoint);
381    }
382
383    /**
384     * $params['task_id'] = (string) The task id to rethrottle (Required)
385     *        ['requests_per_second'] = (number) The throttle to set on this request in floating
386     *        sub-requests per second. -1 means set no throttle. (Required)
387     *
388     * @return callable|array
389     */
390    public function deleteByQueryRethrottle(array $params)
391    {
392        $taskId = $this->extractArgument($params, 'task_id');
393
394        /**
395 * @var callable $endpointBuilder
396*/
397        $endpointBuilder = $this->endpoints;
398
399        /**
400 * @var \Elasticsearch\Endpoints\DeleteByQueryRethrottle $endpoint
401*/
402        $endpoint = $endpointBuilder('DeleteByQueryRethrottle');
403        $endpoint->setTaskId($taskId);
404        $endpoint->setParams($params);
405
406        return $this->performRequest($endpoint);
407    }
408
409    /**
410     * $params['index']              = (list) A comma-separated list of indices to restrict the results
411     *        ['type']               = (list) A comma-separated list of types to restrict the results
412     *        ['min_score']          = (number) Include only documents with a specific `_score` value in the result
413     *        ['preference']         = (string) Specify the node or shard the operation should be performed on (default: random)
414     *        ['routing']            = (string) Specific routing value
415     *        ['source']             = (string) The URL-encoded query definition (instead of using the request body)
416     *        ['body']               = (array) A query to restrict the results (optional)
417     *        ['ignore_unavailable'] = (bool) Whether specified concrete indices should be ignored when unavailable (missing or closed)
418     *        ['allow_no_indices']   = (bool) Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)
419     *        ['expand_wildcards']   = (enum) Whether to expand wildcard expression to concrete indices that are open, closed or both.
420     *
421     * @return callable|array
422     */
423    public function count(array $params = [])
424    {
425        $index = $this->extractArgument($params, 'index');
426        $type = $this->extractArgument($params, 'type');
427        $body = $this->extractArgument($params, 'body');
428
429        /**
430 * @var callable $endpointBuilder
431*/
432        $endpointBuilder = $this->endpoints;
433
434        /**
435 * @var \Elasticsearch\Endpoints\Count $endpoint
436*/
437        $endpoint = $endpointBuilder('Count');
438        $endpoint->setIndex($index)
439            ->setType($type)
440            ->setBody($body);
441        $endpoint->setParams($params);
442
443        return $this->performRequest($endpoint);
444    }
445
446    /**
447     * $params['index']            = (string) Default index for items which don't provide one
448     *        ['type']             = (string) Default document type for items which don't provide one
449     *        ['term_statistics']  = (boolean) Specifies if total term frequency and document frequency should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\"."
450     *        ['field_statistics'] = (boolean) Specifies if document count, sum of document frequencies and sum of total term frequencies should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\"."
451     *        ['fields']           = (list) A comma-separated list of fields to return. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\"."
452     *        ['offsets']          = (boolean) Specifies if term offsets should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\"."
453     *        ['positions']        = (boolean) Specifies if term positions should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\"."
454     *        ['payloads']         = (boolean) Specifies if term payloads should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".
455     *        ['preference']       = (string) Specify the node or shard the operation should be performed on (default: random) .Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".
456     *        ['routing']          = (string) Specific routing value. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".
457     *        ['parent']           = (string) Parent id of documents. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".
458     *        ['realtime']         = (boolean) Specifies if request is real-time as opposed to near-real-time (default: true).
459     *
460     * @return callable|array
461     */
462    public function termvectors(array $params = [])
463    {
464        $index = $this->extractArgument($params, 'index');
465        $type  = $this->extractArgument($params, 'type');
466        $id    = $this->extractArgument($params, 'id');
467        $body  = $this->extractArgument($params, 'body');
468
469        /**
470 * @var callable $endpointBuilder
471*/
472        $endpointBuilder = $this->endpoints;
473
474        /**
475 * @var \Elasticsearch\Endpoints\TermVectors $endpoint
476*/
477        $endpoint = $endpointBuilder('TermVectors');
478        $endpoint->setIndex($index)
479            ->setType($type)
480            ->setID($id)
481            ->setBody($body);
482        $endpoint->setParams($params);
483
484        return $this->performRequest($endpoint);
485    }
486
487    /**
488     * $params['index']            = (string) Default index for items which don't provide one
489     *        ['type']             = (string) Default document type for items which don't provide one
490     *        ['ids']              = (list) A comma-separated list of documents ids. You must define ids as parameter or set \"ids\" or \"docs\" in the request body
491     *        ['term_statistics']  = (boolean) Specifies if total term frequency and document frequency should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\"."
492     *        ['field_statistics'] = (boolean) Specifies if document count, sum of document frequencies and sum of total term frequencies should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\"."
493     *        ['fields']           = (list) A comma-separated list of fields to return. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\"."
494     *        ['offsets']          = (boolean) Specifies if term offsets should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\"."
495     *        ['positions']        = (boolean) Specifies if term positions should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\"."
496     *        ['payloads']         = (boolean) Specifies if term payloads should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".
497     *        ['preference']       = (string) Specify the node or shard the operation should be performed on (default: random) .Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".
498     *        ['routing']          = (string) Specific routing value. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".
499     *        ['parent']           = (string) Parent id of documents. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".
500     *        ['realtime']         = (boolean) Specifies if request is real-time as opposed to near-real-time (default: true).
501     *
502     * @return callable|array
503     */
504    public function mtermvectors(array $params = [])
505    {
506        $index = $this->extractArgument($params, 'index');
507        $type  = $this->extractArgument($params, 'type');
508        $body  = $this->extractArgument($params, 'body');
509
510        /**
511 * @var callable $endpointBuilder
512*/
513        $endpointBuilder = $this->endpoints;
514
515        /**
516 * @var \Elasticsearch\Endpoints\MTermVectors $endpoint
517*/
518        $endpoint = $endpointBuilder('MTermVectors');
519        $endpoint->setIndex($index)
520            ->setType($type)
521            ->setBody($body);
522        $endpoint->setParams($params);
523
524        return $this->performRequest($endpoint);
525    }
526
527    /**
528     * $params['id']         = (string) The document ID (Required)
529     *        ['index']      = (string) The name of the index (Required)
530     *        ['type']       = (string) The type of the document (use `_all` to fetch the first document matching the ID across all types) (Required)
531     *        ['parent']     = (string) The ID of the parent document
532     *        ['preference'] = (string) Specify the node or shard the operation should be performed on (default: random)
533     *        ['realtime']   = (boolean) Specify whether to perform the operation in realtime or search mode
534     *        ['refresh']    = (boolean) Refresh the shard containing the document before performing the operation
535     *        ['routing']    = (string) Specific routing value
536     */
537    public function exists(array $params): bool
538    {
539        $id = $this->extractArgument($params, 'id');
540        $index = $this->extractArgument($params, 'index');
541        $type = $this->extractArgument($params, 'type');
542
543        // manually make this verbose so we can check status code
544        $params['client']['verbose'] = true;
545
546        /**
547 * @var callable $endpointBuilder
548*/
549        $endpointBuilder = $this->endpoints;
550
551        /**
552 * @var \Elasticsearch\Endpoints\Exists $endpoint
553*/
554        $endpoint = $endpointBuilder('Exists');
555        $endpoint->setID($id)
556            ->setIndex($index)
557            ->setType($type);
558
559        $endpoint->setParams($params);
560
561        return BooleanRequestWrapper::performRequest($endpoint, $this->transport);
562    }
563
564    /**
565     * $params['index']           = (string) The name of the index
566     *        ['type']            = (string) The type of the document
567     *        ['fields']          = (list) A comma-separated list of fields to return in the response
568     *        ['parent']          = (string) The ID of the parent document
569     *        ['preference']      = (string) Specify the node or shard the operation should be performed on (default: random)
570     *        ['realtime']        = (boolean) Specify whether to perform the operation in realtime or search mode
571     *        ['refresh']         = (boolean) Refresh the shard containing the document before performing the operation
572     *        ['routing']         = (string) Specific routing value
573     *        ['body']            = (array) Document identifiers; can be either `docs` (containing full document information) or `ids` (when index and type is provided in the URL.
574     *        ['_source']         = (list) True or false to return the _source field or not, or a list of fields to return
575     *        ['_source_exclude'] = (list) A list of fields to exclude from the returned _source field
576     *        ['_source_include'] = (list) A list of fields to extract and return from the _source field
577     *        ['_source_excludes'] = (list) A list of fields to exclude from the returned _source field (deprecated in ES 6.6.0)
578     *        ['_source_includes'] = (list) A list of fields to extract and return from the _source field (deprecated in ES 6.6.0)
579     *
580     * @return callable|array
581     */
582    public function mget(array $params = [])
583    {
584        $index = $this->extractArgument($params, 'index');
585        $type = $this->extractArgument($params, 'type');
586        $body = $this->extractArgument($params, 'body');
587
588        /**
589 * @var callable $endpointBuilder
590*/
591        $endpointBuilder = $this->endpoints;
592
593        /**
594 * @var \Elasticsearch\Endpoints\Mget $endpoint
595*/
596        $endpoint = $endpointBuilder('Mget');
597        $endpoint->setIndex($index)
598            ->setType($type)
599            ->setBody($body);
600        $endpoint->setParams($params);
601
602        return $this->performRequest($endpoint);
603    }
604
605    /**
606     * $params['index']       = (list) A comma-separated list of index names to use as default
607     *        ['type']        = (list) A comma-separated list of document types to use as default
608     *        ['search_type'] = (enum) Search operation type
609     *        ['body']        = (array|string) The request definitions (metadata-search request definition pairs), separated by newlines
610     *
611     * @return callable|array
612     */
613    public function msearch(array $params = [])
614    {
615        $index = $this->extractArgument($params, 'index');
616        $type = $this->extractArgument($params, 'type');
617        $body = $this->extractArgument($params, 'body');
618
619        /**
620 * @var callable $endpointBuilder
621*/
622        $endpointBuilder = $this->endpoints;
623
624        /**
625 * @var \Elasticsearch\Endpoints\Msearch $endpoint
626*/
627        $endpoint = $endpointBuilder('Msearch');
628        $endpoint->setIndex($index)
629            ->setType($type)
630            ->setBody($body);
631        $endpoint->setParams($params);
632
633        return $this->performRequest($endpoint);
634    }
635
636    /**
637     * $params['index']       = (list) A comma-separated list of index names to use as default
638     *        ['type']        = (list) A comma-separated list of document types to use as default
639     *        ['search_type'] = (enum) Search operation type
640     *        ['body']        = (array|string) The request definitions (metadata-search request definition pairs), separated by newlines
641     *        ['max_concurrent_searches'] = (number) Controls the maximum number of concurrent searches the multi search api will execute
642     *
643     * @return callable|array
644     */
645    public function msearchTemplate(array $params = [])
646    {
647        $index = $this->extractArgument($params, 'index');
648        $type = $this->extractArgument($params, 'type');
649        $body = $this->extractArgument($params, 'body');
650
651        /**
652 * @var callable $endpointBuilder
653*/
654        $endpointBuilder = $this->endpoints;
655
656        /**
657 * @var \Elasticsearch\Endpoints\MsearchTemplate $endpoint
658*/
659        $endpoint = $endpointBuilder('MsearchTemplate');
660        $endpoint->setIndex($index)
661            ->setType($type)
662            ->setBody($body);
663        $endpoint->setParams($params);
664
665        return $this->performRequest($endpoint);
666    }
667
668    /**
669     * $params['index']        = (string) The name of the index (Required)
670     *        ['type']         = (string) The type of the document (Required)
671     *        ['id']           = (string) Specific document ID (when the POST method is used)
672     *        ['consistency']  = (enum) Explicit write consistency setting for the operation
673     *        ['parent']       = (string) ID of the parent document
674     *        ['refresh']      = (boolean) Refresh the index after performing the operation
675     *        ['replication']  = (enum) Specific replication type
676     *        ['routing']      = (string) Specific routing value
677     *        ['timeout']      = (time) Explicit operation timeout
678     *        ['timestamp']    = (time) Explicit timestamp for the document
679     *        ['ttl']          = (duration) Expiration time for the document
680     *        ['version']      = (number) Explicit version number for concurrency control
681     *        ['version_type'] = (enum) Specific version type
682     *        ['body']         = (array) The document
683     *
684     * @return callable|array
685     */
686    public function create(array $params)
687    {
688        $id = $this->extractArgument($params, 'id');
689        $index = $this->extractArgument($params, 'index');
690        $type = $this->extractArgument($params, 'type');
691        $body = $this->extractArgument($params, 'body');
692
693        /**
694 * @var callable $endpointBuilder
695*/
696        $endpointBuilder = $this->endpoints;
697
698        /**
699 * @var \Elasticsearch\Endpoints\Create $endpoint
700*/
701        $endpoint = $endpointBuilder('Create');
702        $endpoint->setID($id)
703            ->setIndex($index)
704            ->setType($type)
705            ->setBody($body);
706        $endpoint->setParams($params);
707
708        return $this->performRequest($endpoint);
709    }
710
711    /**
712     * $params['index']       = (string) Default index for items which don't provide one
713     *        ['type']        = (string) Default document type for items which don't provide one
714     *        ['consistency'] = (enum) Explicit write consistency setting for the operation
715     *        ['refresh']     = (boolean) Refresh the index after performing the operation
716     *        ['replication'] = (enum) Explicitly set the replication type
717     *        ['fields']      = (list) Default comma-separated list of fields to return in the response for updates
718     *        ['body']        = (array) The document
719     *
720     * @return callable|array
721     */
722    public function bulk(array $params = [])
723    {
724        $index = $this->extractArgument($params, 'index');
725        $type = $this->extractArgument($params, 'type');
726        $body = $this->extractArgument($params, 'body');
727
728        /**
729 * @var callable $endpointBuilder
730*/
731        $endpointBuilder = $this->endpoints;
732
733        /**
734 * @var \Elasticsearch\Endpoints\Bulk $endpoint
735*/
736        $endpoint = $endpointBuilder('Bulk');
737        $endpoint->setIndex($index)
738            ->setType($type)
739            ->setBody($body);
740        $endpoint->setParams($params);
741
742        return $this->performRequest($endpoint);
743    }
744
745    /**
746     * $params['index']        = (string) The name of the index (Required)
747     *        ['type']         = (string) The type of the document (Required)
748     *        ['id']           = (string) Specific document ID (when the POST method is used)
749     *        ['consistency']  = (enum) Explicit write consistency setting for the operation
750     *        ['op_type']      = (enum) Explicit operation type
751     *        ['parent']       = (string) ID of the parent document
752     *        ['refresh']      = (boolean) Refresh the index after performing the operation
753     *        ['replication']  = (enum) Specific replication type
754     *        ['routing']      = (string) Specific routing value
755     *        ['timeout']      = (time) Explicit operation timeout
756     *        ['timestamp']    = (time) Explicit timestamp for the document
757     *        ['ttl']          = (duration) Expiration time for the document
758     *        ['version']      = (number) Explicit version number for concurrency control
759     *        ['version_type'] = (enum) Specific version type
760     *        ['body']         = (array) The document
761     *
762     * @return callable|array
763     */
764    public function index(array $params)
765    {
766        $id = $this->extractArgument($params, 'id');
767        $index = $this->extractArgument($params, 'index');
768        $type = $this->extractArgument($params, 'type');
769        $body = $this->extractArgument($params, 'body');
770
771        /**
772 * @var callable $endpointBuilder
773*/
774        $endpointBuilder = $this->endpoints;
775
776        /**
777 * @var \Elasticsearch\Endpoints\Index $endpoint
778*/
779        $endpoint = $endpointBuilder('Index');
780        $endpoint->setID($id)
781            ->setIndex($index)
782            ->setType($type)
783            ->setBody($body);
784        $endpoint->setParams($params);
785
786        return $this->performRequest($endpoint);
787    }
788
789    /**
790     * $params['refresh']             = (boolean) Should the effected indexes be refreshed?
791     *        ['timeout']             = (time) Time each individual bulk request should wait for shards that are unavailable
792     *        ['consistency']         = (enum) Explicit write consistency setting for the operation
793     *        ['wait_for_completion'] = (boolean) Should the request should block until the reindex is complete
794     *        ['requests_per_second'] = (float) The throttle for this request in sub-requests per second. 0 means set no throttle
795     *        ['body']                = (array) The search definition using the Query DSL and the prototype for the index request (Required)
796     *
797     * @return callable|array
798     */
799    public function reindex(array $params)
800    {
801        $body = $this->extractArgument($params, 'body');
802
803        /**
804 * @var callable $endpointBuilder
805*/
806        $endpointBuilder = $this->endpoints;
807        /**
808 * @var \Elasticsearch\Endpoints\Reindex $endpoint
809*/
810        $endpoint = $endpointBuilder('Reindex');
811        $endpoint->setBody($body);
812        $endpoint->setParams($params);
813
814        return $this->performRequest($endpoint);
815    }
816
817    /**
818     * $params['task_id'] = (string) The task id to rethrottle (Required)
819     *        ['requests_per_second'] = (number) The throttle to set on this request in floating
820     *        sub-requests per second. -1 means set no throttle (Required)
821     *
822     * @return callable|array
823     */
824    public function reindexRethrottle(array $params)
825    {
826        $taskId = $this->extractArgument($params, 'task_id');
827
828        /**
829 * @var callable $endpointBuilder
830*/
831        $endpointBuilder = $this->endpoints;
832        /**
833 * @var \Elasticsearch\Endpoints\ReindexRethrottle $endpoint
834*/
835        $endpoint = $endpointBuilder('ReindexRethrottle');
836        $endpoint->setTaskId($taskId);
837        $endpoint->setParams($params);
838
839        return $this->performRequest($endpoint);
840    }
841
842    /**
843     * $params['id']                       = (string) The document ID (Required)
844     *        ['index']                    = (string) The name of the index (Required)
845     *        ['type']                     = (string) The type of the document (Required)
846     *        ['analyze_wildcard']         = (boolean) Specify whether wildcards and prefix queries in the query string query should be analyzed (default: false)
847     *        ['analyzer']                 = (string) The analyzer for the query string query
848     *        ['default_operator']         = (enum) The default operator for query string query (AND or OR)
849     *        ['df']                       = (string) The default field for query string query (default: _all)
850     *        ['fields']                   = (list) A comma-separated list of fields to return in the response
851     *        ['lenient']                  = (boolean) Specify whether format-based query failures (such as providing text to a numeric field) should be ignored
852     *        ['lowercase_expanded_terms'] = (boolean) Specify whether query terms should be lowercased
853     *        ['parent']                   = (string) The ID of the parent document
854     *        ['preference']               = (string) Specify the node or shard the operation should be performed on (default: random)
855     *        ['q']                        = (string) Query in the Lucene query string syntax
856     *        ['routing']                  = (string) Specific routing value
857     *        ['source']                   = (string) The URL-encoded query definition (instead of using the request body)
858     *        ['_source']                  = (list) True or false to return the _source field or not, or a list of fields to return
859     *        ['_source_exclude']          = (list) A list of fields to exclude from the returned _source field (deprecated in ES 6.6.0)
860     *        ['_source_include']          = (list) A list of fields to extract and return from the _source field  (deprecated in ES 6.6.0)
861     *        ['_source_excludes']          = (list) A list of fields to exclude from the returned _source field
862     *        ['_source_includes']          = (list) A list of fields to extract and return from the _source field
863     *        ['body']                     = (string) The URL-encoded query definition (instead of using the request body)
864     *
865     * @return callable|array
866     */
867    public function explain(array $params)
868    {
869        $id = $this->extractArgument($params, 'id');
870        $index = $this->extractArgument($params, 'index');
871        $type = $this->extractArgument($params, 'type');
872        $body = $this->extractArgument($params, 'body');
873
874        /**
875 * @var callable $endpointBuilder
876*/
877        $endpointBuilder = $this->endpoints;
878
879        /**
880 * @var \Elasticsearch\Endpoints\Explain $endpoint
881*/
882        $endpoint = $endpointBuilder('Explain');
883        $endpoint->setID($id)
884            ->setIndex($index)
885            ->setType($type)
886            ->setBody($body);
887        $endpoint->setParams($params);
888
889        return $this->performRequest($endpoint);
890    }
891
892    /**
893     * $params['index']                    = (list) A comma-separated list of index names to search; use `_all` or empty string to perform the operation on all indices
894     *        ['type']                     = (list) A comma-separated list of document types to search; leave empty to perform the operation on all types
895     *        ['analyzer']                 = (string) The analyzer to use for the query string
896     *        ['analyze_wildcard']         = (boolean) Specify whether wildcard and prefix queries should be analyzed (default: false)
897     *        ['default_operator']         = (enum) The default operator for query string query (AND or OR)
898     *        ['df']                       = (string) The field to use as default where no field prefix is given in the query string
899     *        ['explain']                  = (boolean) Specify whether to return detailed information about score computation as part of a hit
900     *        ['fields']                   = (list) A comma-separated list of fields to return as part of a hit
901     *        ['from']                     = (number) Starting offset (default: 0)
902     *        ['ignore_indices']           = (enum) When performed on multiple indices, allows to ignore `missing` ones
903     *        ['indices_boost']            = (list) Comma-separated list of index boosts
904     *        ['lenient']                  = (boolean) Specify whether format-based query failures (such as providing text to a numeric field) should be ignored
905     *        ['lowercase_expanded_terms'] = (boolean) Specify whether query terms should be lowercased
906     *        ['preference']               = (string) Specify the node or shard the operation should be performed on (default: random)
907     *        ['q']                        = (string) Query in the Lucene query string syntax
908     *        ['query_cache']              = (boolean) Enable query cache for this request
909     *        ['request_cache']            = (boolean) Enable request cache for this request
910     *        ['routing']                  = (list) A comma-separated list of specific routing values
911     *        ['scroll']                   = (duration) Specify how long a consistent view of the index should be maintained for scrolled search
912     *        ['search_type']              = (enum) Search operation type
913     *        ['size']                     = (number) Number of hits to return (default: 10)
914     *        ['sort']                     = (list) A comma-separated list of <field>:<direction> pairs
915     *        ['source']                   = (string) The URL-encoded request definition using the Query DSL (instead of using request body)
916     *        ['_source']                  = (list) True or false to return the _source field or not, or a list of fields to return
917     *        ['_source_exclude']          = (list) A list of fields to exclude from the returned _source field (deprecated in ES 6.6.0)
918     *        ['_source_include']          = (list) A list of fields to extract and return from the _source field (deprecated in ES 6.6.0)
919     *        ['_source_excludes']         = (list) A list of fields to exclude from the returned _source field
920     *        ['_source_includes']         = (list) A list of fields to extract and return from the _source field
921     *        ['stats']                    = (list) Specific 'tag' of the request for logging and statistical purposes
922     *        ['suggest_field']            = (string) Specify which field to use for suggestions
923     *        ['suggest_mode']             = (enum) Specify suggest mode
924     *        ['suggest_size']             = (number) How many suggestions to return in response
925     *        ['suggest_text']             = (text) The source text for which the suggestions should be returned
926     *        ['timeout']                  = (time) Explicit operation timeout
927     *        ['terminate_after']          = (number) The maximum number of documents to collect for each shard, upon reaching which the query execution will terminate early.
928     *        ['version']                  = (boolean) Specify whether to return document version as part of a hit
929     *        ['body']                     = (array|string) The search definition using the Query DSL
930     *
931     * @return callable|array
932     */
933    public function search(array $params = [])
934    {
935        $index = $this->extractArgument($params, 'index');
936        $type = $this->extractArgument($params, 'type');
937        $body = $this->extractArgument($params, 'body');
938
939        /**
940 * @var callable $endpointBuilder
941*/
942        $endpointBuilder = $this->endpoints;
943
944        /**
945 * @var \Elasticsearch\Endpoints\Search $endpoint
946*/
947        $endpoint = $endpointBuilder('Search');
948        $endpoint->setIndex($index)
949            ->setType($type)
950            ->setBody($body);
951        $endpoint->setParams($params);
952
953        return $this->performRequest($endpoint);
954    }
955
956    /**
957     * $params['index']              = (list) A comma-separated list of index names to search; use `_all` or empty string to perform the operation on all indices
958     *        ['type']               = (list) A comma-separated list of document types to search; leave empty to perform the operation on all types
959     *        ['preference']         = (string) Specify the node or shard the operation should be performed on (default: random)
960     *        ['routing']            = (string) Specific routing value
961     *        ['local']              = (bool) Return local information, do not retrieve the state from master node (default: false)
962     *        ['ignore_unavailable'] = (bool) Whether specified concrete indices should be ignored when unavailable (missing or closed)
963     *        ['allow_no_indices']   = (bool) Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)
964     *        ['expand_wildcards']   = (enum) Whether to expand wildcard expression to concrete indices that are open, closed or both.
965     *
966     * @return callable|array
967     */
968    public function searchShards(array $params = [])
969    {
970        $index = $this->extractArgument($params, 'index');
971        $type = $this->extractArgument($params, 'type');
972
973        /**
974 * @var callable $endpointBuilder
975*/
976        $endpointBuilder = $this->endpoints;
977
978        /**
979 * @var \Elasticsearch\Endpoints\SearchShards $endpoint
980*/
981        $endpoint = $endpointBuilder('SearchShards');
982        $endpoint->setIndex($index)
983            ->setType($type);
984        $endpoint->setParams($params);
985
986        return $this->performRequest($endpoint);
987    }
988
989    /**
990     * $params['index']                    = (list) A comma-separated list of index names to search; use `_all` or empty string to perform the operation on all indices
991     *        ['type']                     = (list) A comma-separated list of document types to search; leave empty to perform the operation on all types
992     *
993     * @return callable|array
994     */
995    public function searchTemplate(array $params = [])
996    {
997        $index = $this->extractArgument($params, 'index');
998        $type = $this->extractArgument($params, 'type');
999        $body = $this->extractArgument($params, 'body');
1000
1001        /**
1002 * @var callable $endpointBuilder
1003*/
1004        $endpointBuilder = $this->endpoints;
1005
1006        /**
1007 * @var \Elasticsearch\Endpoints\Search $endpoint
1008*/
1009        $endpoint = $endpointBuilder('SearchTemplate');
1010        $endpoint->setIndex($index)
1011            ->setType($type)
1012            ->setBody($body);
1013        $endpoint->setParams($params);
1014
1015        return $this->performRequest($endpoint);
1016    }
1017
1018    /**
1019     * $params['scroll_id'] = (string) The scroll ID for scrolled search
1020     *        ['scroll']    = (duration) Specify how long a consistent view of the index should be maintained for scrolled search
1021     *        ['body']      = (string) The scroll ID for scrolled search
1022     *
1023     * @return callable|array
1024     */
1025    public function scroll(array $params = [])
1026    {
1027        $scrollID = $this->extractArgument($params, 'scroll_id');
1028        $body = $this->extractArgument($params, 'body');
1029        $scroll = $this->extractArgument($params, 'scroll');
1030
1031        /**
1032 * @var callable $endpointBuilder
1033*/
1034        $endpointBuilder = $this->endpoints;
1035
1036        /**
1037 * @var \Elasticsearch\Endpoints\Scroll $endpoint
1038*/
1039        $endpoint = $endpointBuilder('Scroll');
1040        $endpoint->setScrollId($scrollID)
1041            ->setBody($body)
1042            ->setParams($params);
1043
1044        return $this->performRequest($endpoint);
1045    }
1046
1047    /**
1048     * $params['body'] = (string) The script to execute
1049     *
1050     * @return callable|array
1051     */
1052    public function scriptsPainlessExecute(array $params = [])
1053    {
1054        $body = $this->extractArgument($params, 'body');
1055
1056        /**
1057 * @var callable $endpointBuilder
1058*/
1059        $endpointBuilder = $this->endpoints;
1060
1061        /**
1062 * @var \Elasticsearch\Endpoints\ScriptsPainlessExecute $endpoint
1063*/
1064        $endpoint = $endpointBuilder('ScriptsPainlessExecute');
1065        $endpoint->setBody($body);
1066        $endpoint->setParams($params);
1067
1068        return $this->performRequest($endpoint);
1069    }
1070
1071    /**
1072     * $params['scroll_id'] = (string) The scroll ID for scrolled search
1073     *        ['scroll']    = (duration) Specify how long a consistent view of the index should be maintained for scrolled search
1074     *        ['body']      = (string) The scroll ID for scrolled search
1075     *
1076     * @return callable|array
1077     */
1078    public function clearScroll(array $params = [])
1079    {
1080        $scrollID = $this->extractArgument($params, 'scroll_id');
1081        $body = $this->extractArgument($params, 'body');
1082
1083        /**
1084 * @var callable $endpointBuilder
1085*/
1086        $endpointBuilder = $this->endpoints;
1087
1088        /**
1089 * @var \Elasticsearch\Endpoints\ClearScroll $endpoint
1090*/
1091        $endpoint = $endpointBuilder('ClearScroll');
1092        $endpoint->setScrollId($scrollID)
1093            ->setBody($body);
1094        $endpoint->setParams($params);
1095
1096        return $this->performRequest($endpoint);
1097    }
1098
1099    /**
1100     * $params['id']                = (string) Document ID (Required)
1101     *        ['index']             = (string) The name of the index (Required)
1102     *        ['type']              = (string) The type of the document (Required)
1103     *        ['consistency']       = (enum) Explicit write consistency setting for the operation
1104     *        ['fields']            = (list) A comma-separated list of fields to return in the response
1105     *        ['lang']              = (string) The script language (default: mvel)
1106     *        ['parent']            = (string) ID of the parent document
1107     *        ['refresh']           = (boolean) Refresh the index after performing the operation
1108     *        ['replication']       = (enum) Specific replication type
1109     *        ['retry_on_conflict'] = (number) Specify how many times should the operation be retried when a conflict occurs (default: 0)
1110     *        ['routing']           = (string) Specific routing value
1111     *        ['script']            = () The URL-encoded script definition (instead of using request body)
1112     *        ['timeout']           = (time) Explicit operation timeout
1113     *        ['timestamp']         = (time) Explicit timestamp for the document
1114     *        ['ttl']               = (duration) Expiration time for the document
1115     *        ['version_type']      = (number) Explicit version number for concurrency control
1116     *        ['body']              = (array) The request definition using either `script` or partial `doc`
1117     *
1118     * @return callable|array
1119     */
1120    public function update(array $params)
1121    {
1122        $id = $this->extractArgument($params, 'id');
1123        $index = $this->extractArgument($params, 'index');
1124        $type = $this->extractArgument($params, 'type');
1125        $body = $this->extractArgument($params, 'body');
1126
1127        /**
1128 * @var callable $endpointBuilder
1129*/
1130        $endpointBuilder = $this->endpoints;
1131
1132        /**
1133 * @var \Elasticsearch\Endpoints\Update $endpoint
1134*/
1135        $endpoint = $endpointBuilder('Update');
1136        $endpoint->setID($id)
1137            ->setIndex($index)
1138            ->setType($type)
1139            ->setBody($body);
1140        $endpoint->setParams($params);
1141
1142        return $this->performRequest($endpoint);
1143    }
1144
1145    /**
1146     * $params['index']                    = (list) A comma-separated list of index names to search; use `_all` or
1147     * empty string to perform the operation on all indices (Required)
1148     *        ['type']                     = (list) A comma-separated list of document types to search; leave empty to
1149     * perform the operation on all types
1150     *        ['analyzer']                 = (string) The analyzer to use for the query string
1151     *        ['analyze_wildcard']         = (boolean) Specify whether wildcard and prefix queries should be analyzed
1152     * (default: false)
1153     *        ['default_operator']         = (enum) The default operator for query string query (AND or OR) (AND,OR)
1154     * (default: OR)
1155     *        ['df']                       = (string) The field to use as default where no field prefix is given in the
1156     * query string
1157     *        ['explain']                  = (boolean) Specify whether to return detailed information about score
1158     * computation as part of a hit
1159     *        ['fields']                   = (list) A comma-separated list of fields to return as part of a hit
1160     *        ['fielddata_fields']         = (list) A comma-separated list of fields to return as the field data
1161     * representation of a field for each hit
1162     *        ['from']                     = (number) Starting offset (default: 0)
1163     *        ['ignore_unavailable']       = (boolean) Whether specified concrete indices should be ignored when
1164     * unavailable (missing or closed)
1165     *        ['allow_no_indices']         = (boolean) Whether to ignore if a wildcard indices expression resolves into
1166     * no concrete indices. (This includes `_all` string or when no indices have been specified)
1167     *        ['conflicts']                = (enum) What to do when the reindex hits version conflicts? (abort,proceed)
1168     * (default: abort)
1169     *        ['expand_wildcards']         = (enum) Whether to expand wildcard expression to concrete indices that are
1170     * open, closed or both. (open,closed,none,all) (default: open)
1171     *        ['lenient']                  = (boolean) Specify whether format-based query failures (such as providing
1172     * text to a numeric field) should be ignored
1173     *        ['lowercase_expanded_terms'] = (boolean) Specify whether query terms should be lowercased
1174     *        ['preference']               = (string) Specify the node or shard the operation should be performed on
1175     * (default: random)
1176     *        ['q']                        = (string) Query in the Lucene query string syntax
1177     *        ['routing']                  = (list) A comma-separated list of specific routing values
1178     *        ['scroll']                   = (duration) Specify how long a consistent view of the index should be
1179     * maintained for scrolled search
1180     *        ['search_type']              = (enum) Search operation type (query_then_fetch,dfs_query_then_fetch)
1181     *        ['search_timeout']           = (time) Explicit timeout for each search request. Defaults to no timeout.
1182     *        ['size']                     = (number) Number of hits to return (default: 10)
1183     *        ['sort']                     = (list) A comma-separated list of <field>:<direction> pairs
1184     *        ['_source']                  = (list) True or false to return the _source field or not, or a list of
1185     * fields to return
1186     *        ['_source_exclude']          = (list) A list of fields to exclude from the returned _source field (deprecated in ES 6.6.0)
1187     *        ['_source_include']          = (list) A list of fields to extract and return from the _source field (deprecated in ES 6.6.0)
1188     *        ['_source_excludes']         = (list) A list of fields to exclude from the returned _source field
1189     *        ['_source_includes']         = (list) A list of fields to extract and return from the _source field
1190     *        ['terminate_after']          = (number) The maximum number of documents to collect for each shard, upon
1191     * reaching which the query execution will terminate early.
1192     *        ['stats']                    = (list) Specific 'tag' of the request for logging and statistical purposes
1193     *        ['suggest_field']            = (string) Specify which field to use for suggestions
1194     *        ['suggest_mode']             = (enum) Specify suggest mode (missing,popular,always) (default: missing)
1195     *        ['suggest_size']             = (number) How many suggestions to return in response
1196     *        ['suggest_text']             = (text) The source text for which the suggestions should be returned
1197     *        ['timeout']                  = (time) Time each individual bulk request should wait for shards that are
1198     * unavailable. (default: 1m)
1199     *        ['track_scores']             = (boolean) Whether to calculate and return scores even if they are not used
1200     * for sorting
1201     *        ['version']                  = (boolean) Specify whether to return document version as part of a hit
1202     *        ['version_type']             = (boolean) Should the document increment the version number (internal) on
1203     * hit or not (reindex)
1204     *        ['request_cache']            = (boolean) Specify if request cache should be used for this request or not,
1205     * defaults to index level setting
1206     *        ['refresh']                  = (boolean) Should the effected indexes be refreshed?
1207     *        ['consistency']              = (enum) Explicit write consistency setting for the operation
1208     * (one,quorum,all)
1209     *        ['scroll_size']              = (integer) Size on the scroll request powering the update_by_query
1210     *        ['wait_for_completion']      = (boolean) Should the request should block until the reindex is complete.
1211     * (default: false)
1212     *        ['body']                     = The search definition using the Query DSL
1213     *
1214     * @return callable|array
1215     */
1216    public function updateByQuery(array $params = [])
1217    {
1218        $index = $this->extractArgument($params, 'index');
1219        $body = $this->extractArgument($params, 'body');
1220        $type = $this->extractArgument($params, 'type');
1221
1222        /**
1223 * @var callable $endpointBuilder
1224*/
1225        $endpointBuilder = $this->endpoints;
1226
1227        /**
1228 * @var \Elasticsearch\Endpoints\UpdateByQuery $endpoint
1229*/
1230        $endpoint = $endpointBuilder('UpdateByQuery');
1231        $endpoint->setIndex($index)
1232            ->setType($type)
1233            ->setBody($body);
1234        $endpoint->setParams($params);
1235
1236        return $this->performRequest($endpoint);
1237    }
1238
1239    /**
1240     * $params['task_id'] = (string) The task id to rethrottle (Required)
1241     *        ['requests_per_second'] = (number) The throttle to set on this request in floating
1242     *        sub-requests per second. -1 means set no throttle (Required)
1243     *
1244     * @return callable|array
1245     */
1246    public function updateByQueryRethrottle(array $params = [])
1247    {
1248        $taskId = $this->extractArgument($params, 'task_id');
1249
1250        /**
1251 * @var callable $endpointBuilder
1252*/
1253        $endpointBuilder = $this->endpoints;
1254
1255        /**
1256 * @var \Elasticsearch\Endpoints\UpdateByQueryRethrottle $endpoint
1257*/
1258        $endpoint = $endpointBuilder('UpdateByQueryRethrottle');
1259        $endpoint->setTaskId($taskId);
1260        $endpoint->setParams($params);
1261
1262        return $this->performRequest($endpoint);
1263    }
1264
1265    /**
1266     * $params['id']   = (string) The script ID (Required)
1267     *
1268     * @return callable|array
1269     */
1270    public function getScript(array $params)
1271    {
1272        $id = $this->extractArgument($params, 'id');
1273
1274        /**
1275 * @var callable $endpointBuilder
1276*/
1277        $endpointBuilder = $this->endpoints;
1278
1279        /**
1280 * @var \Elasticsearch\Endpoints\Script\Get $endpoint
1281*/
1282        $endpoint = $endpointBuilder('Script\Get');
1283        $endpoint->setID($id);
1284        $endpoint->setParams($params);
1285
1286        return $this->performRequest($endpoint);
1287    }
1288
1289    /**
1290     * $params['id']   = (string) The script ID (Required)
1291     *
1292     * @return callable|array
1293     */
1294    public function deleteScript(array $params)
1295    {
1296        $id = $this->extractArgument($params, 'id');
1297
1298        /**
1299 * @var callable $endpointBuilder
1300*/
1301        $endpointBuilder = $this->endpoints;
1302
1303        /**
1304 * @var \Elasticsearch\Endpoints\Script\Delete $endpoint
1305*/
1306        $endpoint = $endpointBuilder('Script\Delete');
1307        $endpoint->setID($id);
1308        $endpoint->setParams($params);
1309
1310        return $this->performRequest($endpoint);
1311    }
1312
1313    /**
1314     * $params['id']   = (string) The script ID (Required)
1315     *
1316     * @return callable|array
1317     */
1318    public function putScript(array $params)
1319    {
1320        $id   = $this->extractArgument($params, 'id');
1321        $body = $this->extractArgument($params, 'body');
1322
1323        /**
1324 * @var callable $endpointBuilder
1325*/
1326        $endpointBuilder = $this->endpoints;
1327
1328        /**
1329 * @var \Elasticsearch\Endpoints\Script\Put $endpoint
1330*/
1331        $endpoint = $endpointBuilder('Script\Put');
1332        $endpoint->setID($id)
1333            ->setBody($body);
1334        $endpoint->setParams($params);
1335
1336        return $this->performRequest($endpoint);
1337    }
1338
1339    /**
1340     * $params['id']   = (string) The search template ID (Required)
1341     *
1342     * @return callable|array
1343     */
1344    public function getTemplate(array $params)
1345    {
1346        $id = $this->extractArgument($params, 'id');
1347
1348        /**
1349 * @var callable $endpointBuilder
1350*/
1351        $endpointBuilder = $this->endpoints;
1352
1353        /**
1354 * @var \Elasticsearch\Endpoints\Template\Get $endpoint
1355*/
1356        $endpoint = $endpointBuilder('Template\Get');
1357        $endpoint->setID($id);
1358        $endpoint->setParams($params);
1359
1360        return $this->performRequest($endpoint);
1361    }
1362
1363    /**
1364     * $params['id']   = (string) The search template ID (Required)
1365     *
1366     * @return callable|array
1367     */
1368    public function deleteTemplate(array $params)
1369    {
1370        $id = $this->extractArgument($params, 'id');
1371
1372        /**
1373 * @var callable $endpointBuilder
1374*/
1375        $endpointBuilder = $this->endpoints;
1376
1377        /**
1378 * @var \Elasticsearch\Endpoints\Template\Delete $endpoint
1379*/
1380        $endpoint = $endpointBuilder('Template\Delete');
1381        $endpoint->setID($id);
1382        $endpoint->setParams($params);
1383
1384        return $this->performRequest($endpoint);
1385    }
1386
1387    /**
1388     * $params['index']              = (list) A comma-separated list of indices to restrict the results
1389     *        ['ignore_unavailable'] = (bool) Whether specified concrete indices should be ignored when unavailable (missing or closed)
1390     *        ['allow_no_indices']   = (bool) Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)
1391     *        ['expand_wildcards']   = (enum) Whether to expand wildcard expression to concrete indices that are open, closed or both.
1392     *
1393     * @return callable|array
1394     */
1395    public function fieldCaps(array $params = [])
1396    {
1397        $index = $this->extractArgument($params, 'index');
1398
1399        /**
1400 * @var callable $endpointBuilder
1401*/
1402        $endpointBuilder = $this->endpoints;
1403
1404        /**
1405 * @var \Elasticsearch\Endpoints\FieldCaps $endpoint
1406*/
1407        $endpoint = $endpointBuilder('FieldCaps');
1408        $endpoint->setIndex($index)
1409            ->setParams($params);
1410
1411        return $this->performRequest($endpoint);
1412    }
1413
1414    /**
1415     * $params['id'] = (string) ID of the template to render
1416     *
1417     * @return callable|array
1418     */
1419    public function renderSearchTemplate(array $params = [])
1420    {
1421        $body = $this->extractArgument($params, 'body');
1422        $id   = $this->extractArgument($params, 'id');
1423
1424        /**
1425 * @var callable $endpointBuilder
1426*/
1427        $endpointBuilder = $this->endpoints;
1428
1429        /**
1430 * @var \Elasticsearch\Endpoints\RenderSearchTemplate $endpoint
1431*/
1432        $endpoint = $endpointBuilder('RenderSearchTemplate');
1433        $endpoint->setBody($body)
1434            ->setID($id);
1435        $endpoint->setParams($params);
1436
1437        return $this->performRequest($endpoint);
1438    }
1439
1440    /**
1441     * Operate on the Indices Namespace of commands
1442     */
1443    public function indices(): IndicesNamespace
1444    {
1445        return $this->indices;
1446    }
1447
1448    /**
1449     * Operate on the Cluster namespace of commands
1450     */
1451    public function cluster(): ClusterNamespace
1452    {
1453        return $this->cluster;
1454    }
1455
1456    /**
1457     * Operate on the Nodes namespace of commands
1458     */
1459    public function nodes(): NodesNamespace
1460    {
1461        return $this->nodes;
1462    }
1463
1464    /**
1465     * Operate on the Snapshot namespace of commands
1466     */
1467    public function snapshot(): SnapshotNamespace
1468    {
1469        return $this->snapshot;
1470    }
1471
1472    /**
1473     * Operate on the Cat namespace of commands
1474     */
1475    public function cat(): CatNamespace
1476    {
1477        return $this->cat;
1478    }
1479
1480    /**
1481     * Operate on the Ingest namespace of commands
1482     */
1483    public function ingest(): IngestNamespace
1484    {
1485        return $this->ingest;
1486    }
1487
1488    /**
1489     * Operate on the Tasks namespace of commands
1490     */
1491    public function tasks(): TasksNamespace
1492    {
1493        return $this->tasks;
1494    }
1495
1496    /**
1497     * Operate on the Remote namespace of commands
1498     */
1499    public function remote(): RemoteNamespace
1500    {
1501        return $this->remote;
1502    }
1503
1504    /**
1505     * Catchall for registered namespaces
1506     *
1507     * @return object
1508     * @throws BadMethodCallException if the namespace cannot be found
1509     */
1510    public function __call(string $name, array $arguments)
1511    {
1512        if (isset($this->registeredNamespaces[$name])) {
1513            return $this->registeredNamespaces[$name];
1514        }
1515        throw new BadMethodCallException("Namespace [$name] not found");
1516    }
1517
1518    /**
1519     * @return null|mixed
1520     */
1521    public function extractArgument(array &$params, string $arg)
1522    {
1523        if (array_key_exists($arg, $params) === true) {
1524            $value = $params[$arg];
1525            $value = is_object($value) ? (array) $value : $value;
1526            unset($params[$arg]);
1527            return $value;
1528        } else {
1529            return null;
1530        }
1531    }
1532
1533    private function verifyNotNullOrEmpty(string $name, $var)
1534    {
1535        if ($var === null) {
1536            throw new InvalidArgumentException("$name cannot be null.");
1537        }
1538
1539        if (is_string($var)) {
1540            if (strlen($var) === 0) {
1541                throw new InvalidArgumentException("$name cannot be an empty string");
1542            }
1543        }
1544
1545        if (is_array($var)) {
1546            if (strlen(implode("", $var)) === 0) {
1547                throw new InvalidArgumentException("$name cannot be an array of empty strings");
1548            }
1549        }
1550    }
1551
1552    /**
1553     * @return callable|array
1554     */
1555    private function performRequest(AbstractEndpoint $endpoint)
1556    {
1557        $promise =  $this->transport->performRequest(
1558            $endpoint->getMethod(),
1559            $endpoint->getURI(),
1560            $endpoint->getParams(),
1561            $endpoint->getBody(),
1562            $endpoint->getOptions()
1563        );
1564
1565        return $this->transport->resultOrFuture($promise, $endpoint->getOptions());
1566    }
1567}
1568