The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes 051
MANIFEST 717
META.json 56
META.yml 45
Makefile.PL 35
README 1424
lib/Search/Elasticsearch/Bulk.pm 1213
lib/Search/Elasticsearch/Client/0_90/Direct/Cluster.pm 1313
lib/Search/Elasticsearch/Client/0_90/Direct/Indices.pm 3636
lib/Search/Elasticsearch/Client/0_90/Direct.pm 3535
lib/Search/Elasticsearch/Client/1_0/Direct/Cat.pm 0354
lib/Search/Elasticsearch/Client/1_0/Direct/Cluster.pm 0218
lib/Search/Elasticsearch/Client/1_0/Direct/Indices.pm 0852
lib/Search/Elasticsearch/Client/1_0/Direct/Nodes.pm 0183
lib/Search/Elasticsearch/Client/1_0/Direct/Snapshot.pm 0190
lib/Search/Elasticsearch/Client/1_0/Direct.pm 01452
lib/Search/Elasticsearch/Client/2_0/Direct/Cat.pm 0354
lib/Search/Elasticsearch/Client/2_0/Direct/Cluster.pm 0206
lib/Search/Elasticsearch/Client/2_0/Direct/Indices.pm 0834
lib/Search/Elasticsearch/Client/2_0/Direct/Nodes.pm 0167
lib/Search/Elasticsearch/Client/2_0/Direct/Snapshot.pm 0190
lib/Search/Elasticsearch/Client/2_0/Direct.pm 01357
lib/Search/Elasticsearch/Client/Direct/Cat.pm 3540
lib/Search/Elasticsearch/Client/Direct/Cluster.pm 2150
lib/Search/Elasticsearch/Client/Direct/Indices.pm 8440
lib/Search/Elasticsearch/Client/Direct/Nodes.pm 1830
lib/Search/Elasticsearch/Client/Direct/Snapshot.pm 1900
lib/Search/Elasticsearch/Client/Direct.pm 153015
lib/Search/Elasticsearch/Cxn/Factory.pm 22
lib/Search/Elasticsearch/Cxn/HTTPTiny.pm 22
lib/Search/Elasticsearch/Cxn/Hijk.pm 810
lib/Search/Elasticsearch/Cxn/LWP.pm 22
lib/Search/Elasticsearch/CxnPool/Sniff.pm 22
lib/Search/Elasticsearch/CxnPool/Static/NoPing.pm 22
lib/Search/Elasticsearch/CxnPool/Static.pm 22
lib/Search/Elasticsearch/Error.pm 1215
lib/Search/Elasticsearch/Logger/LogAny.pm 22
lib/Search/Elasticsearch/Role/API/0_90.pm 811
lib/Search/Elasticsearch/Role/API/1_0.pm 01683
lib/Search/Elasticsearch/Role/API/2_0.pm 01562
lib/Search/Elasticsearch/Role/API.pm 16890
lib/Search/Elasticsearch/Role/Bulk.pm 39
lib/Search/Elasticsearch/Role/Client/Direct/Main.pm 0123
lib/Search/Elasticsearch/Role/Client/Direct.pm 33
lib/Search/Elasticsearch/Role/Client.pm 22
lib/Search/Elasticsearch/Role/Cxn/HTTP.pm 33
lib/Search/Elasticsearch/Role/Cxn.pm 1144
lib/Search/Elasticsearch/Role/CxnPool/Sniff.pm 22
lib/Search/Elasticsearch/Role/CxnPool/Static/NoPing.pm 22
lib/Search/Elasticsearch/Role/CxnPool/Static.pm 22
lib/Search/Elasticsearch/Role/CxnPool.pm 22
lib/Search/Elasticsearch/Role/Is_Sync.pm 22
lib/Search/Elasticsearch/Role/Logger.pm 22
lib/Search/Elasticsearch/Role/Scroll.pm 22
lib/Search/Elasticsearch/Role/Serializer/JSON.pm 22
lib/Search/Elasticsearch/Role/Serializer.pm 22
lib/Search/Elasticsearch/Role/Transport.pm 22
lib/Search/Elasticsearch/Scroll.pm 1010
lib/Search/Elasticsearch/Serializer/JSON/Cpanel.pm 22
lib/Search/Elasticsearch/Serializer/JSON/PP.pm 22
lib/Search/Elasticsearch/Serializer/JSON/XS.pm 22
lib/Search/Elasticsearch/Serializer/JSON.pm 22
lib/Search/Elasticsearch/TestServer.pm 33
lib/Search/Elasticsearch/Transport.pm 43
lib/Search/Elasticsearch/Util/API/Path.pm 22
lib/Search/Elasticsearch/Util/API/QS.pm 3644
lib/Search/Elasticsearch/Util.pm 22
lib/Search/Elasticsearch.pm 1331
t/10_Basic/10_load.t 23
t/30_Logger/10_explicit.t 12
t/30_Logger/20_implicit.t 12
t/30_Logger/40_trace_request.t 21
t/30_Logger/50_trace_response.t 21
t/30_Logger/60_trace_error.t 21
t/30_Logger/70_trace_comment.t 21
t/60_Cxn/20_process_response.t 316
t/70_Helper/10_bulk_add_action.t 236
t/70_Helper/20_bulk_helpers.t 234
t/70_Helper/40_bulk_errors.t 31
t/70_Helper/45_bulk_cxn_errors.t 036
t/author-no-tabs.t 717
t/lib/bad_cacert.pem 021
t/lib/bad_cacert.pm 210
t/lib/es_sync.pl 17
t/lib/es_sync_auth.pl 46
85 files changed (This is a version diff) 535110364
@@ -1,5 +1,56 @@
 Revision history for Search::Elasticsearch
 
+1.20    2015-05-17
+
+        Deprecated:
+        * Search::Elasticsearch::Client::Direct in favour of
+          Search::Elasticsearch::Client::1_0::Direct
+
+        New features:
+        * Added support for structured JSON exceptions in Elasticsearch 2.0
+        * Added support for plugins
+        * Added Search::Elasticsearch::Client::2_0::Direct for the upcoming
+          Elasticsearch 2.0 with these changes:
+            * removed delete_by_query()
+            * removed termvector()
+            * removed indices.delete_mapping()
+            * removed nodes.shutdown()
+            * removed indices.status()
+            * added terminate_after param to search()
+            * added dfs param to termvectors()
+            * removed filter_keys param from indices.clear_cache()
+            * removed full param from indices.flush()
+            * removed force param from indics.optmize()
+            * removed replication param from all CRUD methods
+            * removed mlt() method
+
+        Bug fix:
+        * The bulk buffer was being cleared on a NoNodes exception
+
+        Added class:
+        Added methods:
+        * field_stats()
+
+        Added params:
+        * allow_no_indices, expand_wildcards, ignore_unavailable to cluster.state()
+        * fielddata_fields to search()
+        * master_timeout to indices.get_template() and indices.exists_template()
+        * detect_noop to update()
+        * only_ancient_segments to upgrade()
+        * analyze_wildcards, analyzer, default_operator, df, lenient, lowercase_expanded_terms,
+          and q to count(), search_exists() and indices.validate_query()
+
+        Removed methods:
+        * benchmark.* - never released in Elasticsearch
+
+        Also:
+        * arrays of enum query string params are now flattened as CSV
+        * enum expand_wildcards also accepts: none, all
+        * Search::Elasticsearch is no longer a Moo class
+        * Updated elasticsearch.org URLs to use elastic.co instead
+        * the request body is retained in exceptions
+        * upgraded Hijk to 0.20
+
 1.19    2015-01-15
         Added method:
         * cat.segments()
@@ -11,12 +11,19 @@ lib/Search/Elasticsearch/Bulk.pm
 lib/Search/Elasticsearch/Client/0_90/Direct.pm
 lib/Search/Elasticsearch/Client/0_90/Direct/Cluster.pm
 lib/Search/Elasticsearch/Client/0_90/Direct/Indices.pm
+lib/Search/Elasticsearch/Client/1_0/Direct.pm
+lib/Search/Elasticsearch/Client/1_0/Direct/Cat.pm
+lib/Search/Elasticsearch/Client/1_0/Direct/Cluster.pm
+lib/Search/Elasticsearch/Client/1_0/Direct/Indices.pm
+lib/Search/Elasticsearch/Client/1_0/Direct/Nodes.pm
+lib/Search/Elasticsearch/Client/1_0/Direct/Snapshot.pm
+lib/Search/Elasticsearch/Client/2_0/Direct.pm
+lib/Search/Elasticsearch/Client/2_0/Direct/Cat.pm
+lib/Search/Elasticsearch/Client/2_0/Direct/Cluster.pm
+lib/Search/Elasticsearch/Client/2_0/Direct/Indices.pm
+lib/Search/Elasticsearch/Client/2_0/Direct/Nodes.pm
+lib/Search/Elasticsearch/Client/2_0/Direct/Snapshot.pm
 lib/Search/Elasticsearch/Client/Direct.pm
-lib/Search/Elasticsearch/Client/Direct/Cat.pm
-lib/Search/Elasticsearch/Client/Direct/Cluster.pm
-lib/Search/Elasticsearch/Client/Direct/Indices.pm
-lib/Search/Elasticsearch/Client/Direct/Nodes.pm
-lib/Search/Elasticsearch/Client/Direct/Snapshot.pm
 lib/Search/Elasticsearch/Cxn/Factory.pm
 lib/Search/Elasticsearch/Cxn/HTTPTiny.pm
 lib/Search/Elasticsearch/Cxn/Hijk.pm
@@ -26,11 +33,13 @@ lib/Search/Elasticsearch/CxnPool/Static.pm
 lib/Search/Elasticsearch/CxnPool/Static/NoPing.pm
 lib/Search/Elasticsearch/Error.pm
 lib/Search/Elasticsearch/Logger/LogAny.pm
-lib/Search/Elasticsearch/Role/API.pm
 lib/Search/Elasticsearch/Role/API/0_90.pm
+lib/Search/Elasticsearch/Role/API/1_0.pm
+lib/Search/Elasticsearch/Role/API/2_0.pm
 lib/Search/Elasticsearch/Role/Bulk.pm
 lib/Search/Elasticsearch/Role/Client.pm
 lib/Search/Elasticsearch/Role/Client/Direct.pm
+lib/Search/Elasticsearch/Role/Client/Direct/Main.pm
 lib/Search/Elasticsearch/Role/Cxn.pm
 lib/Search/Elasticsearch/Role/Cxn/HTTP.pm
 lib/Search/Elasticsearch/Role/CxnPool.pm
@@ -119,6 +128,7 @@ t/70_Helper/10_bulk_add_action.t
 t/70_Helper/20_bulk_helpers.t
 t/70_Helper/30_bulk_flush.t
 t/70_Helper/40_bulk_errors.t
+t/70_Helper/45_bulk_cxn_errors.t
 t/70_Helper/50_scroll.t
 t/70_Helper/60_reindex.t
 t/90_Client_Spec/00_print_version.t
@@ -126,7 +136,7 @@ t/author-eol.t
 t/author-no-tabs.t
 t/lib/LogCallback.pl
 t/lib/MockCxn.pm
-t/lib/bad_cacert.pm
+t/lib/bad_cacert.pem
 t/lib/default_cxn.pl
 t/lib/es_sync.pl
 t/lib/es_sync_auth.pl
@@ -45,7 +45,7 @@
             "HTTP::Headers" : "0",
             "HTTP::Request" : "0",
             "HTTP::Tiny" : "0.043",
-            "Hijk" : "0.12",
+            "Hijk" : "0.20",
             "IO::Select" : "0",
             "IO::Socket" : "0",
             "IO::Uncompress::Inflate" : "0",
@@ -68,6 +68,7 @@
             "URI" : "0",
             "namespace::clean" : "0",
             "overload" : "0",
+            "parent" : "0",
             "strict" : "0",
             "warnings" : "0"
          }
@@ -92,14 +93,14 @@
    "release_status" : "stable",
    "resources" : {
       "bugtracker" : {
-         "web" : "https://github.com/elasticsearch/elasticsearch-perl/issues"
+         "web" : "https://github.com/elastic/elasticsearch-perl/issues"
       },
       "repository" : {
          "type" : "git",
-         "url" : "git://github.com/elasticsearch/elasticsearch-perl.git",
-         "web" : "https://github.com/elasticsearch/elasticsearch-perl"
+         "url" : "git://github.com/elastic/elasticsearch-perl.git",
+         "web" : "https://github.com/elastic/elasticsearch-perl"
       }
    },
-   "version" : "1.19"
+   "version" : "1.20"
 }
 
@@ -29,7 +29,7 @@ requires:
   HTTP::Headers: '0'
   HTTP::Request: '0'
   HTTP::Tiny: '0.043'
-  Hijk: '0.12'
+  Hijk: '0.20'
   IO::Select: '0'
   IO::Socket: '0'
   IO::Uncompress::Inflate: '0'
@@ -52,9 +52,10 @@ requires:
   URI: '0'
   namespace::clean: '0'
   overload: '0'
+  parent: '0'
   strict: '0'
   warnings: '0'
 resources:
-  bugtracker: https://github.com/elasticsearch/elasticsearch-perl/issues
-  repository: git://github.com/elasticsearch/elasticsearch-perl.git
-version: '1.19'
+  bugtracker: https://github.com/elastic/elasticsearch-perl/issues
+  repository: git://github.com/elastic/elasticsearch-perl.git
+version: '1.20'
@@ -31,7 +31,7 @@ my %WriteMakefileArgs = (
     "HTTP::Headers" => 0,
     "HTTP::Request" => 0,
     "HTTP::Tiny" => "0.043",
-    "Hijk" => "0.12",
+    "Hijk" => "0.20",
     "IO::Select" => 0,
     "IO::Socket" => 0,
     "IO::Uncompress::Inflate" => 0,
@@ -54,6 +54,7 @@ my %WriteMakefileArgs = (
     "URI" => 0,
     "namespace::clean" => 0,
     "overload" => 0,
+    "parent" => 0,
     "strict" => 0,
     "warnings" => 0
   },
@@ -65,7 +66,7 @@ my %WriteMakefileArgs = (
     "Test::More" => "0.98",
     "lib" => 0
   },
-  "VERSION" => "1.19",
+  "VERSION" => "1.20",
   "test" => {
     "TESTS" => "t/*.t t/10_Basic/*.t t/20_Serializer/*.t t/30_Logger/*.t t/40_Transport/*.t t/50_Cxn_Pool/*.t t/60_Cxn/*.t t/70_Helper/*.t t/90_Client_Spec/*.t"
   }
@@ -81,7 +82,7 @@ my %FallbackPrereqs = (
   "HTTP::Headers" => 0,
   "HTTP::Request" => 0,
   "HTTP::Tiny" => "0.043",
-  "Hijk" => "0.12",
+  "Hijk" => "0.20",
   "IO::Select" => 0,
   "IO::Socket" => 0,
   "IO::Socket::SSL" => 0,
@@ -111,6 +112,7 @@ my %FallbackPrereqs = (
   "lib" => 0,
   "namespace::clean" => 0,
   "overload" => 0,
+  "parent" => 0,
   "strict" => 0,
   "warnings" => 0
 );
@@ -2,7 +2,7 @@ NAME
     Search::Elasticsearch - The official client for Elasticsearch
 
 VERSION
-    version 1.19
+    version 1.20
 
 SYNOPSIS
         use Search::Elasticsearch;
@@ -75,7 +75,7 @@ DESCRIPTION
     supported by elasticsearch.com <http://www.elasticsearch.com>.
     Elasticsearch itself is a flexible and powerful open source, distributed
     real-time search and analytics engine for the cloud. You can read more
-    about it on elasticsearch.org <http://www.elasticsearch.org>.
+    about it on elastic.co <http://www.elastic.co>.
 
 BACKWARDS COMPATIBILITY AND ELASTICSEARCH 0.90.x
     This version of the client supports the Elasticsearch 1.0 branch by
@@ -97,8 +97,8 @@ BACKWARDS COMPATIBILITY AND ELASTICSEARCH 0.90.x
     available for other languages, is to provide robust support for the full
     native Elasticsearch API with as few opinions as possible: you should be
     able to read the Elasticsearch reference documentation
-    <http://www.elasticsearch.org/guide> and understand how to use this
-    client, or any of the other official clients.
+    <http://www.elastic.co/guide> and understand how to use this client, or
+    any of the other official clients.
 
     Should you decide that you want to customize the API, then this client
     provides the basis for your code. It does the hard stuff for you,
@@ -129,11 +129,10 @@ BACKWARDS COMPATIBILITY AND ELASTICSEARCH 0.90.x
 
 INSTALLING ELASTICSEARCH
     You can download the latest version of Elasticsearch from
-    <http://www.elasticsearch.org/download>. See the installation
-    instructions
-    <http://www.elasticsearch.org/guide/reference/setup/installation/> for
-    details. You will need to have a recent version of Java installed,
-    preferably the Java v7 from Sun.
+    <http://www.elastic.co/download>. See the installation instructions
+    <http://www.elastic.co/guide/reference/setup/installation/> for details.
+    You will need to have a recent version of Java installed, preferably the
+    Java v7 from Sun.
 
 CREATING A NEW INSTANCE
     The "new()" method returns a new client which can be used to run
@@ -268,8 +267,8 @@ RUNNING REQUESTS
             }
         );
 
-    See Search::Elasticsearch::Client::Direct for more details about the
-    requests that can be run.
+    See Search::Elasticsearch::Client::1_0::Direct for more details about
+    the requests that can be run.
 
 MODULES
     Each chunk of functionality is handled by a different module, which can
@@ -296,9 +295,20 @@ MODULES
     The class to use for the client functionality, which provides methods
     that can be called to execute requests, such as "search()", "index()" or
     "delete()". The client parses the user's requests and passes them to the
-    "transport" class to be executed. See :
+    "transport" class to be executed.
 
-    *   Search::Elasticsearch::Client::Direct (default, for 1.0 branch)
+    The default version of the client is "1_0::Direct", which can be
+    explicitly specified as follows:
+
+        $e = Search::Elasticsearch->new(
+            client => '1_0::Direct'
+        );
+
+    See :
+
+    *   Search::Elasticsearch::Client::1_0::Direct (default, for 1.0 branch)
+
+    *   Search::Elasticsearch::Client::2_0::Direct (for 2.0 branch)
 
     *   Search::Elasticsearch::Client::0_90::Direct (for 0.90 branch)
 
@@ -475,7 +485,7 @@ SUPPORT
     *   Mailing list
 
         The main Elasticsearch mailing list
-        <http://www.elasticsearch.org/community/forum/>.
+        <http://www.elastic.co/community>.
 
 TEST SUITE
     The full test suite requires a live Elasticsearch node to run, and
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Bulk;
-$Search::Elasticsearch::Bulk::VERSION = '1.19';
+$Search::Elasticsearch::Bulk::VERSION = '1.20';
 use Moo;
 with 'Search::Elasticsearch::Role::Bulk',
     'Search::Elasticsearch::Role::Is_Sync';
@@ -47,16 +47,17 @@ sub flush {
     }
     my $buffer  = $self->_buffer;
     my $results = try {
-        $self->es->bulk( %{ $self->_bulk_args }, body => $buffer );
+        my $res = $self->es->bulk( %{ $self->_bulk_args }, body => $buffer );
+        $self->clear_buffer;
+        return $res;
     }
     catch {
         my $error = $_;
         $self->clear_buffer
-            unless $error->is('Cxn');
+            unless $error->is( 'Cxn', 'NoNodes' );
 
         die $error;
     };
-    $self->clear_buffer;
     $self->_report( $buffer, $results );
     return defined wantarray ? $results : undef;
 }
@@ -107,7 +108,7 @@ Search::Elasticsearch::Bulk - A helper module for the Bulk API and for reindexin
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 SYNOPSIS
 
@@ -150,7 +151,7 @@ version 1.19
 
 =head1 DESCRIPTION
 
-This module provides a wrapper for the L<Search::Elasticsearch::Client::Direct/bulk()>
+This module provides a wrapper for the L<Search::Elasticsearch::Client::1_0::Direct/bulk()>
 method which makes it easier to run multiple create, index, update or delete
 actions in a single request. It also provides a simple interface
 for L<reindexing documents|/REINDEXING DOCUMENTS>.
@@ -193,7 +194,7 @@ Search::Elasticsearch client as the C<es> argument.
 The C<index> and C<type> parameters provide default values for
 C<index> and C<type>, which can be overridden in each action.
 You can also pass any other values which are accepted
-by the L<bulk()|Search::Elasticsearch::Client::Direct/bulk()> method.
+by the L<bulk()|Search::Elasticsearch::Client::1_0::Direct/bulk()> method.
 
 See L</flush()> for more information about the other parameters.
 
@@ -204,7 +205,7 @@ See L</flush()> for more information about the other parameters.
     $result = $bulk->flush;
 
 The C<flush()> method sends all buffered actions to Elasticsearch using
-a L<bulk()|Search::Elasticsearch::Client::Direct/bulk()> request.
+a L<bulk()|Search::Elasticsearch::Client::1_0::Direct/bulk()> request.
 
 =head2 Auto-flushing
 
@@ -362,7 +363,7 @@ they must be specified either in L</new()> or in every action.
     );
 
 The C<create()> helper method allows you to add multiple C<create> actions.
-It accepts the same parameters as L<Search::Elasticsearch::Client::Direct/create()>
+It accepts the same parameters as L<Search::Elasticsearch::Client::1_0::Direct/create()>
 except that the document body should be passed as the C<source> or C<_source>
 parameter, instead of as C<body>.
 
@@ -388,7 +389,7 @@ you can just pass the individual document bodies.
     );
 
 The C<index()> helper method allows you to add multiple C<index> actions.
-It accepts the same parameters as L<Search::Elasticsearch::Client::Direct/index()>
+It accepts the same parameters as L<Search::Elasticsearch::Client::1_0::Direct/index()>
 except that the document body should be passed as the C<source> or C<_source>
 parameter, instead of as C<body>.
 
@@ -401,7 +402,7 @@ parameter, instead of as C<body>.
     );
 
 The C<delete()> helper method allows you to add multiple C<delete> actions.
-It accepts the same parameters as L<Search::Elasticsearch::Client::Direct/delete()>.
+It accepts the same parameters as L<Search::Elasticsearch::Client::1_0::Direct/delete()>.
 
 =head2 C<delete_ids()>
 
@@ -428,7 +429,7 @@ In this case, all you have to do is to pass in a list of IDs.
     );
 
 The C<update()> helper method allows you to add multiple C<update> actions.
-It accepts the same parameters as L<Search::Elasticsearch::Client::Direct/update()>.
+It accepts the same parameters as L<Search::Elasticsearch::Client::1_0::Direct/update()>.
 An update can either use a I<partial doc> which gets merged with an existing
 doc (example 1 above), or can use a C<script> to update an existing doc
 (example 2 above).
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::0_90::Direct::Cluster;
-$Search::Elasticsearch::Client::0_90::Direct::Cluster::VERSION = '1.19';
+$Search::Elasticsearch::Client::0_90::Direct::Cluster::VERSION = '1.20';
 use Moo;
 with 'Search::Elasticsearch::Role::API::0_90';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -17,7 +17,7 @@ Search::Elasticsearch::Client::0_90::Direct::Cluster - A client for running clus
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -47,7 +47,7 @@ Query string parameters:
     C<wait_for_relocating_shards>,
     C<wait_for_status>
 
-See the L<cluster health docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-health.html>
+See the L<cluster health docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/cluster-health.html>
 for more information.
 
 =head2 C<pending_tasks()>
@@ -60,7 +60,7 @@ Query string parameters:
     C<local>,
     C<master_timeout>
 
-See the L<pending tasks docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-pending.html>
+See the L<pending tasks docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/cluster-pending.html>
 for more information.
 
 =head2 C<node_info()>
@@ -87,7 +87,7 @@ Query string parameters:
     C<timeout>,
     C<transport>
 
-See the L<node_info docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-nodes-info.html>
+See the L<node_info docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/cluster-nodes-info.html>
 for more information.
 
 =head2 C<node_stats()>
@@ -102,7 +102,7 @@ heap memory usage or the current number of threads in use.
 
 Stats can be returned for all nodes, or limited to particular nodes
 with the C<node_id> parameter.
-The L<indices_stats|Search::Elasticsearch::Client::Direct::Indices/indices_stats()>
+The L<indices_stats|Search::Elasticsearch::Client::1_0::Direct::Indices/indices_stats()>
 information can also be retrieved on a per-node basis with the C<node_stats()>
 method:
 
@@ -126,7 +126,7 @@ Query string parameters:
     C<thread_pool>,
     C<transport>
 
-See the L<node_stats docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-nodes-stats.html>
+See the L<node_stats docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/cluster-nodes-stats.html>
 for more information.
 
 =head2 C<hot_threads()>
@@ -144,7 +144,7 @@ Query string parameters:
     C<threads>,
     C<type>
 
-See the L<hot_threads docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-nodes-hot-threads.html>
+See the L<hot_threads docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/cluster-nodes-hot-threads.html>
 for more information.
 
 =head2 C<get_settings()>
@@ -154,7 +154,7 @@ for more information.
 The C<get_settings()> method is used to retrieve cluster-wide settings that
 have been set with the L</put_settings()> method.
 
-See the L<cluster settings docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-update-settings.html>
+See the L<cluster settings docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/cluster-update-settings.html>
 for more information.
 
 =head2 C<put_settings()>
@@ -173,7 +173,7 @@ For instance:
         }
     );
 
-See the L<cluster settings docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-update-settings.html>
+See the L<cluster settings docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/cluster-update-settings.html>
  for more information.
 
 =head2 C<state()>
@@ -193,7 +193,7 @@ Query string parameters:
     C<local>,
     C<master_timeout>
 
-See the L<cluster state docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-state.html>
+See the L<cluster state docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/cluster-state.html>
 for more information.
 
 =head2 C<reroute()>
@@ -228,7 +228,7 @@ Query string parameters:
     C<dry_run>,
     C<filter_metadata>
 
-See the L<reroute docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-reroute.html>
+See the L<reroute docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/cluster-reroute.html>
 for more information.
 
 =head2 C<shutdown()>
@@ -244,7 +244,7 @@ Query string parameters:
     C<delay>,
     C<exit>
 
-See the L<shutdown docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-nodes-shutdown.html>
+See the L<shutdown docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/cluster-nodes-shutdown.html>
 for more information.
 
 =head1 AUTHOR
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::0_90::Direct::Indices;
-$Search::Elasticsearch::Client::0_90::Direct::Indices::VERSION = '1.19';
+$Search::Elasticsearch::Client::0_90::Direct::Indices::VERSION = '1.20';
 use Moo;
 with 'Search::Elasticsearch::Role::API::0_90';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -17,7 +17,7 @@ Search::Elasticsearch::Client::0_90::Direct::Indices - A client for running inde
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -48,7 +48,7 @@ Query string parameters:
     C<master_timeout>,
     C<timeout>
 
-See the L<create index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-create-index.html>
+See the L<create index docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-create-index.html>
 for more information.
 
 =head2 C<exists()>
@@ -60,7 +60,7 @@ for more information.
 The C<exists()> method returns C<1> or the empty string to indicate
 whether the specified index or indices exist.
 
-See the L<index exists docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-indices-exists.html>
+See the L<index exists docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-indices-exists.html>
 for more information.
 
 =head2 C<delete()>
@@ -75,7 +75,7 @@ Query string parameters:
     C<master_timeout>,
     C<timeout>
 
-See the L<delete index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-delete-index.html>
+See the L<delete index docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-delete-index.html>
 for more information.
 
 =head2 C<close()>
@@ -91,7 +91,7 @@ Query string parameters:
     C<master_timeout>,
     C<timeout>
 
-See the L<close index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-open-close.html>
+See the L<close index docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-open-close.html>
 for more information.
 
 =head2 C<open()>
@@ -106,7 +106,7 @@ Query string parameters:
     C<master_timeout>,
     C<timeout>
 
-See the L<open index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-open-close.html>
+See the L<open index docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-open-close.html>
 for more information.
 
 =head2 C<clear_cache()>
@@ -132,7 +132,7 @@ Query string parameters:
     C<index>,
     C<recycler>
 
-See the L<clear_cache docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-clearcache.html>
+See the L<clear_cache docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-clearcache.html>
 for more information.
 
 =head2 C<refresh()>
@@ -151,7 +151,7 @@ Query string parameters:
     C<ignore_indices>,
     C<ignore_unavailable>
 
-See the L<refresh index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-refresh.html>
+See the L<refresh index docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-refresh.html>
 for more information.
 
 =head2 C<flush()>
@@ -173,7 +173,7 @@ Query string parameters:
     C<ignore_unavailable>,
     C<refresh>
 
-See the L<flush index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-flush.html>
+See the L<flush index docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-flush.html>
 for more information.
 
 =head2 C<optimize()>
@@ -197,7 +197,7 @@ Query string parameters:
     C<refresh>,
     C<wait_for_merge>
 
-See the L<optimize index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-optimize.html>
+See the L<optimize index docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-optimize.html>
 for more information.
 
 =head2 C<snapshot_index()>
@@ -208,7 +208,7 @@ for more information.
 
 Deprecated.
 
-See the L<snapshot_index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/>
+See the L<snapshot_index docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/>
 for more information.
 
 =head1 MAPPING METHODS
@@ -246,7 +246,7 @@ Query string parameters:
     C<master_timeout>,
     C<timeout>
 
-See the L<put_mapping docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-put-mapping.html>
+See the L<put_mapping docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-put-mapping.html>
 for more information.
 
 =head2 C<get_mapping()>
@@ -259,7 +259,7 @@ for more information.
 The C<get_mapping()> method returns the type definitions for one, more or
 all types in one, more or all indices.
 
-See the L<get_mapping docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-get-mapping.html>
+See the L<get_mapping docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-get-mapping.html>
 for more information.
 
 =head2 C<get_field_mapping()>
@@ -275,7 +275,7 @@ for more information.
 The C<get_field_mapping()> method returns the field definitions for one, more or
 all fields in one, more or all types and indices.
 
-See the L<get_mapping docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html>
+See the L<get_mapping docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-get-field-mapping.html>
 for more information.
 
 =head2 C<exists_type()>
@@ -294,7 +294,7 @@ Query string parameters:
     C<ignore_indices>,
     C<ignore_unavailable>
 
-See the L<exists_type docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-types-exists.html>
+See the L<exists_type docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-types-exists.html>
 for more information.
 
 =head2 C<delete_mapping()>
@@ -310,7 +310,7 @@ that type) in all specified indices.
 Query string parameters:
     C<master_timeout>
 
-See the L<delete_mapping docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-delete-mapping.html>
+See the L<delete_mapping docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-delete-mapping.html>
 for more information.
 
 =head1 ALIAS METHODS
@@ -337,7 +337,7 @@ Query string parameters:
     C<master_timeout>,
     C<timeout>
 
-See the L<update_aliases docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html>
+See the L<update_aliases docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-aliases.html>
 for more information.
 
 =head2 C<get_aliases()>
@@ -354,7 +354,7 @@ the specified indices.
 Query string parameters:
     C<timeout>
 
-See the L<get_aliases docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html>
+See the L<get_aliases docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-aliases.html>
 for more information.
 
 =head2 C<put_alias()>
@@ -380,7 +380,7 @@ Query string parameters:
     C<master_timeout>,
     C<timeout>
 
-See the L<put_alias docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html>
+See the L<put_alias docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-aliases.html>
 for more information.
 
 =head2 C<get_alias()>
@@ -399,7 +399,7 @@ Query string parameters:
     C<ignore_indices>,
     C<ignore_unavailable>
 
-See the L<get_alias docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html>
+See the L<get_alias docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-aliases.html>
 for more information.
 
 =head2 C<exists_alias()>
@@ -418,7 +418,7 @@ Query string parameters:
     C<ignore_indices>,
     C<ignore_unavailable>
 
-See the L<exists_alias docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html>
+See the L<exists_alias docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-aliases.html>
 for more information.
 
 =head2 C<delete_alias()>
@@ -434,7 +434,7 @@ Query string parameters:
     C<master_timeout>,
     C<timeout>
 
-See the L<delete_alias docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html>
+See the L<delete_alias docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-aliases.html>
 for more information.
 
 =head1 SETTINGS METHODS
@@ -459,7 +459,7 @@ indices or all indices. For instance:
 Query string parameters:
     C<master_timeout>
 
-See the L<put_settings docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-update-settings.html>
+See the L<put_settings docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-update-settings.html>
 for more information.
 
 =head2 C<get_settings()>
@@ -471,7 +471,7 @@ for more information.
 The C<get_settings()> method retrieves the index settings for the specified
 indices or all indices.
 
-See the L<get_settings docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-get-settings.html>
+See the L<get_settings docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-get-settings.html>
 for more information.
 
 =head1 TEMPLATE METHODS
@@ -490,7 +490,7 @@ Query string parameters:
     C<order>,
     C<timeout>
 
-See the L<put_template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html>
+See the L<put_template docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-templates.html>
 for more information.
 
 =head2 C<get_template()>
@@ -501,7 +501,7 @@ for more information.
 
 The C<get_template()> method is used to retrieve a named template.
 
-See the L<get_template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html>
+See the L<get_template docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-templates.html>
 for more information.
 
 =head2 C<delete_template()>
@@ -516,7 +516,7 @@ Query string parameters:
     C<master_timeout>,
     C<timeout>
 
-See the L<delete_template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html>
+See the L<delete_template docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-templates.html>
 for more information.
 
 =head1 WARMER METHODS
@@ -545,7 +545,7 @@ to user searches.  For instance:
 Query string parameters:
     C<master_timeout>
 
-See the L<put_warmer docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html>
+See the L<put_warmer docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-warmers.html>
 for more information.
 
 =head2 C<get_warmer()>
@@ -557,7 +557,7 @@ for more information.
 
 The C<get_warmer()> method is used to retrieve warmers by name.
 
-See the L<get_warmer docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html>
+See the L<get_warmer docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-warmers.html>
 for more information.
 
 =head2 C<delete_warmer()>
@@ -572,7 +572,7 @@ The C<delete_warmer()> method is used to delete warmers by name.
 Query string parameters:
     C<master_timeout>
 
-See the L<delete_warmer docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html>
+See the L<delete_warmer docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-warmers.html>
 for more information.
 
 =head1 STATS METHODS
@@ -612,7 +612,7 @@ Query string parameters:
     C<store>,
     C<warmer>
 
-See the L<stats docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-stats.html>
+See the L<stats docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-stats.html>
 for more information.
 
 =head2 C<status()>
@@ -631,7 +631,7 @@ Query string parameters:
     C<recovery>,
     C<snapshot>
 
-See the L<status docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-status.html>
+See the L<status docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-status.html>
 for more information.
 
 =head2 C<segments()>
@@ -649,7 +649,7 @@ Query string parameters:
     C<ignore_indices>,
     C<ignore_unavailable>
 
-See the L<segments docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-segments.html>
+See the L<segments docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-segments.html>
 for more information.
 
 =head1 QUERY AND ANALYSIS METHODS
@@ -676,7 +676,7 @@ Query string parameters:
     C<text>,
     C<tokenizer>
 
-See the L<analyze docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-analyze.html>
+See the L<analyze docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-analyze.html>
 for more information.
 
 =head2 C<validate_query()>
@@ -699,7 +699,7 @@ Query string parameters:
     C<q>,
     C<source>
 
-See the L<validate_query docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-validate.html>
+See the L<validate_query docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-validate.html>
 for more information.
 
 =head1 AUTHOR
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::0_90::Direct;
-$Search::Elasticsearch::Client::0_90::Direct::VERSION = '1.19';
+$Search::Elasticsearch::Client::0_90::Direct::VERSION = '1.20';
 use Moo;
 with 'Search::Elasticsearch::Role::API::0_90';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -47,7 +47,7 @@ around 'clear_scroll' => sub {
 #===================================
     my $orig = shift;
     my ( $self, $params ) = parse_params(@_);
-    $params->{scroll_id}||=delete $params->{body};
+    $params->{scroll_id} ||= delete $params->{body};
     $orig->( $self, $params );
 };
 
@@ -115,11 +115,11 @@ sub _build_namespace {
 
 =head1 NAME
 
-Search::Elasticsearch::Client::0_90::Direct - Thin client with full support for Elasticsearch APIs
+Search::Elasticsearch::Client::0_90::Direct - Thin client with full support for Elasticsearch 0.90 APIs
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 SYNOPSIS
 
@@ -176,7 +176,7 @@ Cluster-level requests:
 
 =head1 DESCRIPTION
 
-The L<Search::Elasticsearch::Client::Direct> class provides the default
+The L<Search::Elasticsearch::Client::1_0::Direct> class provides the default
 client that is returned by:
 
     $e = Search::Elasticsearch->new;
@@ -200,7 +200,7 @@ be used as follows:
         client => '0_90::Direct'
     );
 
-See L<Search::Elasticsearch::Client::Direct> for the default client.
+See L<Search::Elasticsearch::Client::1_0::Direct> for the default client.
 
 =head1 CONVENTIONS
 
@@ -353,7 +353,7 @@ Query string parameters:
     C<version>,
     C<version_type>
 
-See the L<index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-index_.html>
+See the L<index docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/docs-index_.html>
 for more information.
 
 =head2 C<create()>
@@ -384,7 +384,7 @@ Query string parameters:
     C<version>,
     C<version_type>
 
-See the L<create docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-create.html>
+See the L<create docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/docs-create.html>
 for more information.
 
 =head2 C<get()>
@@ -409,7 +409,7 @@ Query string parameters:
     C<refresh>,
     C<routing>
 
-See the L<get docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-get.html>
+See the L<get docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/docs-get.html>
 for more information.
 
 =head2 C<get_source()>
@@ -434,7 +434,7 @@ Query string parameters:
     C<refresh>,
     C<routing>
 
-See the L<get_source docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-get.html>
+See the L<get_source docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/docs-get.html>
 for more information.
 
 =head2 C<exists()>
@@ -455,7 +455,7 @@ Query string parameters:
     C<refresh>,
     C<routing>
 
-See the L<exists docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-get.html>
+See the L<exists docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/docs-get.html>
 for more information.
 
 =head2 C<delete()>
@@ -479,7 +479,7 @@ Query string parameters:
     C<version>,
     C<version_type>
 
-See the L<delete docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-delete.html>
+See the L<delete docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/docs-delete.html>
 for more information.
 
 =head2 C<update()>
@@ -536,7 +536,7 @@ Query string parameters:
     C<version>,
     C<version_type>
 
-See the L<update docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-update.html>
+See the L<update docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/docs-update.html>
 for more information.
 
 =head1 BULK DOCUMENT CRUD METHODS
@@ -622,7 +622,7 @@ Query string parameters:
     C<timeout>,
     C<type>
 
-See the L<bulk docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-bulk.html>
+See the L<bulk docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/docs-bulk.html>
 for more information.
 
 =head2 C<bulk_helper()>
@@ -678,7 +678,7 @@ Query string parameters:
     C<realtime>,
     C<refresh>
 
-See the L<mget docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-multi-get.html>
+See the L<mget docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/docs-multi-get.html>
 for more information.
 
 =head2 C<delete_by_query()>
@@ -722,7 +722,7 @@ Query string parameters:
     C<source>,
     C<timeout>
 
-See the L<delete_by_query docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-delete-by-query.html>
+See the L<delete_by_query docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/docs-delete-by-query.html>
 for more information.
 
 =head1 SEARCH METHODS
@@ -742,23 +742,23 @@ and of one, more or all types:
 The C<search()> method searches for matching documents in one or more
 indices.  It is just as easy to search a single index as it is to search
 all the indices in your cluster.  It can also return
-L<facets|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets.thml>
+L<facets|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-facets.thml>
 (aggregations on particular fields),
-L<highlighted snippets|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-highlighting.html>
-and L<did-you-mean|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters-phrase.html>
-or L<search-as-you-type|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters-completion.html>
+L<highlighted snippets|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-highlighting.html>
+and L<did-you-mean|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-suggesters-phrase.html>
+or L<search-as-you-type|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-suggesters-completion.html>
 suggestions.
 
-The I<lite> L<version of search|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-uri-request.html>
+The I<lite> L<version of search|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-uri-request.html>
 allows you to specify a query string in the C<q> parameter, using the
 Lucene query string syntax:
 
     $results = $e->search( q => 'title:(elasticsearch clients)');
 
 However, the preferred way to search is by using the
-L<Query DSL|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html>
+L<Query DSL|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/query-dsl.html>
 to create a query, and passing that C<query> in the
-L<request body|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-body.html>:
+L<request body|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-request-body.html>:
 
     $results = $e->search(
         body => {
@@ -802,7 +802,7 @@ Query string parameters:
     C<timeout>,
     C<version>
 
-See the L<search reference|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-body.html>
+See the L<search reference|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-request-body.html>
 for more information.
 
 Also see L<Search::Elasticsearch::Transport/send_get_body_as>.
@@ -837,7 +837,7 @@ Query string parameters:
     C<routing>,
     C<source>
 
-See the L<count docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-count.html>
+See the L<count docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-count.html>
 for more information.
 
 =head2 C<scroll()>
@@ -863,8 +863,8 @@ Query string parameters:
     C<scroll>,
     C<scroll_id>
 
-See the L<scroll docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-scroll.html>
-and the L<search_type docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search.html/search-request-search-type.html>
+See the L<scroll docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-request-scroll.html>
+and the L<search_type docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search.html/search-request-search-type.html>
 for more information.
 
 =head2 C<clear_scroll()>
@@ -915,7 +915,7 @@ request).  For instance:
 Query string parameters:
     C<search_type>
 
-See the L<msearch docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-multi-search.html>
+See the L<msearch docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-multi-search.html>
 for more information.
 
 =head2 C<explain()>
@@ -960,7 +960,7 @@ Query string parameters:
     C<routing>,
     C<source>
 
-See the L<explain docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-explain.html>
+See the L<explain docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-explain.html>
 for more information.
 
 =head2 C<percolate()>
@@ -993,7 +993,7 @@ C<_source> field of the document under the C<doc> key:
 Query string parameters:
     C<prefer_local>
 
-See the L<percolate docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-percolate.html>
+See the L<percolate docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-percolate.html>
 for more information.
 
 =head2 C<suggest()>
@@ -1006,8 +1006,8 @@ for more information.
     );
 
 The C<suggest()> method is used to run
-L<did-you-mean|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesteres-phrase.html>
-or L<search-as-you-type|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters-completion.html>
+L<did-you-mean|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-suggesteres-phrase.html>
+or L<search-as-you-type|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-suggesters-completion.html>
 suggestion requests, which can also be run as part of a L</search()> request.
 
     $results = $e->suggest(
@@ -1043,7 +1043,7 @@ Query string parameters:
     );
 
 The C<mlt()> method runs a
-L<more-like-this query|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html>
+L<more-like-this query|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/query-dsl-mlt-query.html>
 to find other documents which are similar to the specified document.
 
 Query string parameters:
@@ -1066,7 +1066,7 @@ Query string parameters:
     C<search_types>,
     C<stop_words>
 
-See the L<mlt docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-more-like-this.html>
+See the L<mlt docs|http://www.elastic.co/guide/en/elasticsearch/reference/0.90/search-more-like-this.html>
 for more information.
 
 =head1 AUTHOR
@@ -1085,5 +1085,5 @@ This is free software, licensed under:
 
 __END__
 
-# ABSTRACT: Thin client with full support for Elasticsearch APIs
+# ABSTRACT: Thin client with full support for Elasticsearch 0.90 APIs
 
@@ -0,0 +1,354 @@
+package Search::Elasticsearch::Client::1_0::Direct::Cat;
+$Search::Elasticsearch::Client::1_0::Direct::Cat::VERSION = '1.20';
+use Moo;
+with 'Search::Elasticsearch::Role::API::1_0';
+with 'Search::Elasticsearch::Role::Client::Direct';
+use Search::Elasticsearch::Util qw(parse_params);
+use namespace::clean;
+__PACKAGE__->_install_api('cat');
+
+#===================================
+sub help {
+#===================================
+    my ( $self, $params ) = parse_params(@_);
+    $params->{help} = 1;
+    my $defn = $self->api->{'cat.help'};
+    $self->perform_request( $defn, $params );
+}
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Client::1_0::Direct::Cat - A client for running cat debugging requests
+
+=head1 VERSION
+
+version 1.20
+
+=head1 DESCRIPTION
+
+The C<cat> API in Elasticsearch provides information about your
+cluster and indices in a simple, easy to read text format, intended
+for human consumption.
+
+These APIs have a number of parameters in common:
+
+=over
+
+=item * C<help>
+
+Returns help about the API, eg:
+
+    say $e->cat->allocation(help => 1);
+
+=item * C<v>
+
+Includes the column headers in the output:
+
+    say $e->cat->allocation(v => 1);
+
+=item * C<h>
+
+Accepts a list of column names to be output, eg:
+
+    say $e->cat->indices(h => ['health','index']);
+
+=item * C<bytes>
+
+Formats byte-based values as bytes (C<b>), kilobytes (C<k>), megabytes
+(C<m>) or gigabytes (C<g>)
+
+=back
+
+It does L<Search::Elasticsearch::Role::Client::Direct>.
+
+=head1 METHODS
+
+=head2 C<help()>
+
+    say $e->cat->help;
+
+Returns the list of supported C<cat> APIs
+
+=head2 C<aliases()>
+
+    say $e->cat->aliases(
+        name => 'name' | \@names    # optional
+    );
+
+Returns information about index aliases, optionally limited to the specified
+index/alias names.
+
+Query string parameters:
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat aliases docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-aliases.html>
+for more information.
+
+=head2 C<allocation()>
+
+    say $e->cat->allocation(
+        node_id => 'node' | \@nodes    # optional
+    );
+
+Provides a snapshot of how shards have located around the cluster and the
+state of disk usage.
+
+Query string parameters:
+    C<bytes>,
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat allocation docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-allocation.html>
+for more information.
+
+=head2 C<count()>
+
+    say $e->cat->count(
+        index => 'index' | \@indices    # optional
+    );
+
+Provides quick access to the document count of the entire cluster, or
+individual indices.
+
+Query string parameters:
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat count docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-count.html>
+for more information.
+
+=head2 C<fielddata()>
+
+    say $e->cat->fielddata(
+        fields => 'field' | \@fields    # optional
+    );
+
+Shows the amount of memory used by each of the specified `fields` (or all
+fields) loaded into fielddata.
+
+Query string parameters:
+    C<bytes>,
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat fielddata docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-fielddata.html>
+for more information.
+
+=head2 C<health()>
+
+    say $e->cat->health();
+
+Provides a snapshot of how shards have located around the cluster and the
+state of disk usage.
+
+Query string parameters:
+    C<bytes>,
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<ts>,
+    C<v>
+
+See the L<cat health docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-health.html>
+for more information.
+
+=head2 C<indices()>
+
+    say $e->cat->indices(
+        index => 'index' | \@indices    # optional
+    );
+
+Provides a summary of index size and health for the whole cluster
+or individual indices
+
+Query string parameters:
+    C<bytes>,
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<pri>,
+    C<v>
+
+See the L<cat indices docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-indices.html>
+for more information.
+
+=head2 C<master()>
+
+    say $e->cat->master();
+
+Displays the master’s node ID, bound IP address, and node name.
+
+Query string parameters:
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat master docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-master.html>
+for more information.
+
+=head2 C<nodes()>
+
+    say $e->cat->nodes();
+
+Provides a snapshot of all of the nodes in your cluster.
+
+Query string parameters:
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat nodes docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-nodes.html>
+for more information.
+
+=head2 C<pending_tasks()>
+
+    say $e->cat->pending_tasks();
+
+Returns any cluster-level tasks which are queued on the master.
+
+Query string parameters:
+    C<local>,
+    C<master_timeout>,
+    C<h>,
+    C<help>,
+    C<v>
+
+See the L<cat pending-tasks docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-pending-tasks.html>
+for more information.
+
+=head2 C<plugins()>
+
+    say $e->cat->plugins();
+
+Returns information about plugins installed on each node.
+
+Query string parameters:
+    C<local>,
+    C<master_timeout>,
+    C<h>,
+    C<help>,
+    C<v>
+
+See the L<cat plugins docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-plugins.html>
+for more information.
+
+=head2 C<recovery()>
+
+    say $e->cat->recovery(
+        index => 'index' | \@indices    # optional
+    );
+
+Provides a is a view of shard replication. It will show information
+anytime data from at least one shard is copying to a different node.
+It can also show up on cluster restarts. If your recovery process seems
+stuck, try it to see if there’s any movement using C<recovery()>.
+
+Query string parameters:
+    C<bytes>,
+    C<h>,
+    C<help>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat recovery docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-recovery.html>
+for more information.
+
+=head2 C<segments()>
+
+    say $e->cat->segments(
+        index => 'index' | \@indices    # optional
+    );
+
+Provides low level information about the segments in the shards of an index.
+
+Query string parameters:
+    C<h>,
+    C<help>,
+    C<v>
+
+See the L<cat shards docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-segments.html>
+for more information.
+
+=head2 C<shards()>
+
+    say $e->cat->shards(
+        index => 'index' | \@indices    # optional
+    );
+
+Provides a detailed view of what nodes contain which shards, the state and
+size of each shard.
+
+Query string parameters:
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat shards docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-shards.html>
+for more information.
+
+=head2 C<thread_pool()>
+
+    say $e->cat->thread_pool(
+        index => 'index' | \@indices    # optional
+    );
+
+Shows cluster wide thread pool statistics per node. By default the C<active>,
+C<queue> and C<rejected> statistics are returned for the C<bulk>, C<index> and
+C<search> thread pools.
+
+Query string parameters:
+    C<full_id>,
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat thread_pool docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-thread-pool.html>
+for more information.
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: A client for running cat debugging requests
+
@@ -0,0 +1,218 @@
+package Search::Elasticsearch::Client::1_0::Direct::Cluster;
+$Search::Elasticsearch::Client::1_0::Direct::Cluster::VERSION = '1.20';
+use Moo;
+with 'Search::Elasticsearch::Role::API::1_0';
+with 'Search::Elasticsearch::Role::Client::Direct';
+__PACKAGE__->_install_api('cluster');
+
+sub node_info     { _deprecated( 'node_info',     'info' ) }
+sub node_stats    { _deprecated( 'node_stats',    'stats' ) }
+sub hot_threads   { _deprecated( 'hot_threads',   'hot_threads' ) }
+sub node_shutdown { _deprecated( 'node_shutdown', 'shutdown' ) }
+
+#===================================
+sub _deprecated {
+#===================================
+    my ( $old, $new ) = @_;
+    die "The method \$es->cluster->$old() has moved to \$es->nodes->$new()";
+}
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Client::1_0::Direct::Cluster - A client for running cluster-level requests
+
+=head1 VERSION
+
+version 1.20
+
+=head1 DESCRIPTION
+
+This module provides methods to make cluster-level requests, such as
+getting and setting cluster-level settings, manually rerouting shards,
+and retrieving for monitoring purposes.
+
+It does L<Search::Elasticsearch::Role::Client::Direct>.
+
+=head1 METHODS
+
+=head2 C<health()>
+
+    $response = $e->cluster->health(
+        index   => 'index' | \@indices  # optional
+    );
+
+The C<health()> method is used to retrieve information about the cluster
+health, returning C<red>, C<yellow> or C<green> to indicate the state
+of the cluster, indices or shards.
+
+Query string parameters:
+    C<level>,
+    C<local>,
+    C<master_timeout>,
+    C<timeout>,
+    C<wait_for_active_shards>,
+    C<wait_for_nodes>,
+    C<wait_for_relocating_shards>,
+    C<wait_for_status>
+
+See the L<cluster health docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-health.html>
+for more information.
+
+=head2 C<stats()>
+
+    $response = $e->cluster->stats(
+        node_id => 'node' | \@nodes     # optional
+    );
+
+Returns high-level cluster stats, optionally limited to the listed nodes.
+
+Query string parameters:
+    C<flat_settings>,
+    C<human>
+
+See the L<cluster stats docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-stats.html>
+for more information.
+
+=head2 C<get_settings()>
+
+    $response = $e->cluster->get_settings()
+
+The C<get_settings()> method is used to retrieve cluster-wide settings that
+have been set with the L</put_settings()> method.
+
+Query string parameters:
+    C<flat_settings>,
+    C<master_timeout>,
+    C<timeout>
+
+See the L<cluster settings docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-update-settings.html>
+for more information.
+
+=head2 C<put_settings()>
+
+    $response = $e->cluster->put_settings( %settings );
+
+The C<put_settings()> method is used to set cluster-wide settings, either
+transiently (which don't survive restarts) or permanently (which do survive
+restarts).
+
+For instance:
+
+    $response = $e->cluster->put_settings(
+        body => {
+            transient => { "discovery.zen.minimum_master_nodes" => 5 }
+        }
+    );
+
+Query string parameters:
+    C<flat_settings>
+
+See the L<cluster settings docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-update-settings.html>
+ for more information.
+
+=head2 C<state()>
+
+    $response = $e->cluster->state(
+        metric => $metric | \@metrics   # optional
+        index  => $index  | \@indices   # optional
+    );
+
+The C<state()> method returns the current cluster state from the master node,
+or from the responding node if C<local> is set to C<true>.
+
+It returns all metrics by default, but these can be limited to any of:
+    C<_all>,
+    C<blocks>,
+    C<metadata>,
+    C<nodes>,
+    C<routing_table>
+
+Metrics for indices can be limited to particular indices with the C<index>
+parameter.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<flat_settings>,
+    C<ignore_unavailable>,
+    C<local>,
+    C<master_timeout>
+
+See the L<cluster state docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-state.html>
+for more information.
+
+=head2 C<pending_tasks()>
+
+    $response = $e->cluster->pending_tasks();
+
+Returns a list of cluster-level tasks still pending on the master node.
+
+Query string parameters:
+    C<local>,
+    C<master_timeout>
+
+See the L<pending tasks docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-pending.html>
+for more information.
+
+=head2 C<reroute()>
+
+    $e->cluster->reroute(
+        body => { commands }
+    );
+
+The C<reroute()> method is used to manually reallocate shards from one
+node to another.  The C<body> should contain the C<commands> indicating
+which changes should be made. For instance:
+
+    $e->cluster->reroute(
+        body => {
+            commands => [
+                { move => {
+                    index     => 'test',
+                    shard     => 0,
+                    from_node => 'node_1',
+                    to_node   => 'node_2
+                }},
+                { allocate => {
+                    index     => 'test',
+                    shard     => 1,
+                    node      => 'node_3'
+                }}
+            ]
+        }
+    );
+
+Query string parameters:
+    C<dry_run>,
+    C<explain>,
+    C<master_timeout>,
+    C<metric>,
+    C<timeout>
+
+See the L<reroute docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-reroute.html>
+for more information.
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: A client for running cluster-level requests
+
@@ -0,0 +1,852 @@
+package Search::Elasticsearch::Client::1_0::Direct::Indices;
+$Search::Elasticsearch::Client::1_0::Direct::Indices::VERSION = '1.20';
+use Moo;
+with 'Search::Elasticsearch::Role::API::1_0';
+with 'Search::Elasticsearch::Role::Client::Direct';
+__PACKAGE__->_install_api('indices');
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Client::1_0::Direct::Indices - A client for running index-level requests
+
+=head1 VERSION
+
+version 1.20
+
+=head1 DESCRIPTION
+
+This module provides methods to make index-level requests, such as
+creating and deleting indices, managing type mappings, index settings,
+warmers, index templates and aliases.
+
+It does L<Search::Elasticsearch::Role::Client::Direct>.
+
+=head1 INDEX METHODS
+
+=head2 C<create()>
+
+    $result = $e->indices->create(
+        index => 'my_index'             # required
+
+        body  => {                      # optional
+            index settings
+            mappings
+            warmers
+        }
+    );
+
+The C<create()> method is used to create an index. Optionally, index
+settings, type mappings and index warmers can be added at the same time.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<create index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html>
+for more information.
+
+=head2 C<get()>
+
+    $response = $e->indices->get(
+        index   => 'index'   | \@indices    # optional
+        feature => 'feature' | \@features   # optional
+    );
+
+Returns the aliases, settings, mappings, and warmers for the specified indices.
+The C<feature> parameter can be set to none or more of: C<_settings>, C<_mappings>,
+C<_warmers> and C<_aliases>.
+
+See the L<get index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-index.html>.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+=head2 C<exists()>
+
+    $bool = $e->indices->exists(
+        index => 'index' | \@indices    # required
+    );
+
+The C<exists()> method returns C<1> or the empty string to indicate
+whether the specified index or indices exist.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<index exists docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-indices-exists.html>
+for more information.
+
+=head2 C<delete()>
+
+    $response = $e->indices->delete(
+        index => 'index' | \@indices    # required
+    );
+
+The C<delete()> method deletes the specified indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<master_timeout>,
+    C<timeout>
+
+See the L<delete index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-delete-index.html>
+for more information.
+
+=head2 C<close()>
+
+    $response = $e->indices->close(
+        index => 'index' | \@indices    # required
+    );
+
+The C<close()> method closes the specified indices, reducing resource usage
+but allowing them to be reopened later.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>
+    C<master_timeout>,
+    C<timeout>
+
+See the L<close index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html>
+for more information.
+
+=head2 C<open()>
+
+    $response = $e->indices->open(
+        index => 'index' | \@indices    # required
+    );
+
+The C<open()> method opens closed indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>
+    C<master_timeout>,
+    C<timeout>
+
+See the L<open index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html>
+for more information.
+
+=head2 C<clear_cache()>
+
+    $response = $e->indices->clear_cache(
+        index => 'index' | \@indices        # optional
+    );
+
+The C<clear_cache()> method is used to clear the in-memory filter, fielddata,
+or id cache for the specified indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<fielddata>,
+    C<fields>,
+    C<filter>,
+    C<filter_cache>,
+    C<filter_keys>,
+    C<id>,
+    C<id_cache>,
+    C<ignore_unavailable>,
+    C<query_cache>,
+    C<recycler>
+
+See the L<clear_cache docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-clearcache.html>
+for more information.
+
+=head2 C<refresh()>
+
+    $response = $e->indices->refresh(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<refresh()> method refreshes the specified indices (or all indices),
+allowing recent changes to become visible to search. This process normally
+happens automatically once every second by default.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<force>,
+    C<ignore_unavailable>
+
+See the L<refresh index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html>
+for more information.
+
+=head2 C<flush()>
+
+    $response = $e->indices->flush(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<flush()> method causes the specified indices (or all indices) to be
+written to disk with an C<fsync>, and clears out the transaction log.
+This process normally happens automatically.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<force>,
+    C<full>,
+    C<ignore_unavailable>,
+    C<wait_if_ongoing>
+
+See the L<flush index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-flush.html>
+for more information.
+
+=head2 C<optimize()>
+
+    $response = $e->indices->optimize(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<optimize()> method rewrites all the data in an index into at most
+C<max_num_segments>.  This is a very heavy operation and should only be run
+with care, and only on indices that are no longer being updated.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<flush>,
+    C<ignore_unavailable>,
+    C<max_num_segments>,
+    C<only_expunge_deletes>,
+    C<wait_for_merge>
+
+See the L<optimize index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-optimize.html>
+for more information.
+
+=head2 C<get_upgrade()>
+
+    $response = $e->indices->get_upgrade(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<get_upgrade()> method returns information about which indices need to be
+upgraded, which can be done with the C<upgrade()> method.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<human>,
+    C<ignore_unavailable>
+
+See the L<upgrade docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-upgrade.html>
+for more information.
+
+=head2 C<upgrade()>
+
+    $response = $e->indices->upgrade(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<upgrade()> method upgrades all segments in the specified indices to the latest format.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<only_ancient_segments>,
+    C<wait_for_completion>
+
+See the L<upgrade docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-upgrade.html>
+for more information.
+
+=head1 MAPPING METHODS
+
+=head2 C<put_mapping()>
+
+    $response = $e->indices->put_mapping(
+        index => 'index' | \@indices    # optional,
+        type  => 'type',                # required
+
+        body  => { mapping }            # required
+    )
+
+The C<put_mapping()> method is used to create or update a type
+mapping on an existing index.  Mapping updates are allowed to add new
+fields, but not to overwrite or change existing fields.
+
+For instance:
+
+    $response = $e->indices->put_mapping(
+        index   => 'users',
+        type    => 'user',
+        body    => {
+            user => {
+                properties => {
+                    name => { type => 'string'  },
+                    age  => { type => 'integer' }
+                }
+            }
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<ignore_conflicts>,
+    C<master_timeout>,
+    C<timeout>
+
+See the L<put_mapping docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html>
+for more information.
+
+=head2 C<get_mapping()>
+
+    $result = $e->indices->get_mapping(
+        index => 'index' | \@indices    # optional,
+        type  => 'type'  | \@types      # optional
+    );
+
+The C<get_mapping()> method returns the type definitions for one, more or
+all types in one, more or all indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<get_mapping docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-mapping.html>
+for more information.
+
+=head2 C<get_field_mapping()>
+
+    $result = $e->indices->get_field_mapping(
+        index => 'index' | \@indices    # optional,
+        type  => 'type'  | \@types      # optional,
+        field => 'field' | \@fields     # required
+
+        include_defaults => 0 | 1
+    );
+
+The C<get_field_mapping()> method returns the field definitions for one, more or
+all fields in one, more or all types and indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<include_defaults>,
+    C<local>
+
+See the L<get_mapping docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html>
+for more information.
+
+=head2 C<exists_type()>
+
+    $bool = $e->indices->exists_type(
+        index => 'index' | \@indices    # required,
+        type  => 'type'  | \@types      # required
+    );
+
+The C<exists_type()> method checks for the existence of all specified types
+in all specified indices, and returns C<1> or the empty string.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<exists_type docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-types-exists.html>
+for more information.
+
+=head2 C<delete_mapping()>
+
+    $response = $e->indices->delete_mapping(
+        index => 'index' | \@indices    # required,
+        type  => 'type'  | \@types      # required
+    );
+
+The C<delete_mapping()> method deletes the type mappings (and all documents of
+that type) in all specified indices.
+
+Query string parameters:
+    C<master_timeout>
+
+See the L<delete_mapping docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-delete-mapping.html>
+for more information.
+
+=head1 ALIAS METHODS
+
+=head2 C<update_aliases()>
+
+    $response = $e->indices->update_aliases(
+        body => { actions }             # required
+    );
+
+The C<update_aliases()> method changes (by adding or removing) multiple
+index aliases atomically. For instance:
+
+    $response = $e->indices->update_aliases(
+        body => {
+            actions => [
+                { add    => { alias => 'current', index => 'logs_2013_09' }},
+                { remove => { alias => 'current', index => 'logs_2013_08' }}
+            ]
+        }
+    );
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<update_aliases docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html>
+for more information.
+
+=head2 C<get_aliases()>
+
+    $result = $e->indices->get_aliases(
+        index   => 'index' | \@indices,     # optional
+        alias   => 'alias' | \@aliases      # optional
+    );
+
+The C<get_aliases()> method returns a list of aliases per index for all
+the specified indices.
+
+Query string parameters:
+    C<local>,
+    C<timeout>
+
+See the L<get_aliases docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html>
+for more information.
+
+=head2 C<put_alias()>
+
+    $response = $e->indices->put_alias(
+        index => 'index' | \@indices,       # required
+        name  => 'alias',                   # required
+
+        body  => { alias defn }             # optional
+    );
+
+The C<put_alias()> method creates an index alias. For instance:
+
+    $response = $e->indices->put_alias(
+        index => 'my_index',
+        name  => 'twitter',
+        body => {
+            filter => { term => { user_id => 'twitter' }}
+        }
+    );
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<put_alias docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html>
+for more information.
+
+=head2 C<get_alias()>
+
+    $result = $e->indices->get_alias(
+        index   => 'index' | \@indices,     # optional
+        name    => 'alias' | \@aliases      # optional
+    );
+
+The C<get_alias()> method returns the alias definitions for the specified
+aliases in the specified indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<get_alias docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html>
+for more information.
+
+=head2 C<exists_alias()>
+
+    $bool = $e->indices->exists_alias(
+        index   => 'index' | \@indices,     # optional
+        name    => 'alias' | \@aliases      # optional
+    );
+
+The C<exists_alias()> method returns C<1> or the empty string depending on
+whether the specified aliases exist in the specified indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<exists_alias docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html>
+for more information.
+
+=head2 C<delete_alias()>
+
+    $response = $e->indices->delete_alias(
+        index   => 'index' | \@indices        # required,
+        name    => 'alias' | \@aliases        # required
+    );
+
+The C<delete_alias()> method deletes one or more aliases from one or more
+indices.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<delete_alias docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html>
+for more information.
+
+=head1 SETTINGS METHODS
+
+=head2 C<put_settings()>
+
+    $response = $e->indices->put_settings(
+        index   => 'index' | \@indices      # optional
+
+        body    => { settings }
+    );
+
+The C<put_settings()> method sets the index settings for the specified
+indices or all indices. For instance:
+
+    $response = $e->indices->put_settings(
+        body => {
+            "index.refresh_interval" => -1
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<flat_settings>,
+    C<ignore_unavailable>,
+    C<master_timeout>
+
+See the L<put_settings docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html>
+for more information.
+
+=head2 C<get_settings()>
+
+    $result = $e->indices->get_settings(
+        index   => 'index' | \@indices      # optional
+        name    => 'name'  | \@names        # optional
+    );
+
+The C<get_settings()> method retrieves the index settings for the specified
+indices or all indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<flat_settings>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<get_settings docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-settings.html>
+for more information.
+
+=head1 TEMPLATE METHODS
+
+=head2 C<put_template()>
+
+    $response = $e->indices->put_template(
+        name => 'template'                  # required
+        body => { template defn }           # required
+    );
+
+The C<put_template()> method is used to create or update index templates.
+
+Query string parameters:
+    C<create>,
+    C<flat_settings>,
+    C<master_timeout>,
+    C<op_type>,
+    C<order>,
+    C<timeout>,
+    C<version>,
+    C<version_type>
+
+See the L<put_template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html>
+for more information.
+
+=head2 C<get_template()>
+
+    $result = $e->indices->get_template(
+        name  => 'template'                 # optional
+    );
+
+The C<get_template()> method is used to retrieve a named template.
+
+Query string parameters:
+    C<flat_settings>,
+    C<local>,
+    C<master_timeout>
+
+See the L<get_template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html>
+for more information.
+
+=head2 C<exists_template()>
+
+    $result = $e->indices->exists_template(
+        name  => 'template'                 # required
+    );
+
+The C<exists_template()> method is used to check whether the named template exists.
+
+Query string parameters:
+    C<local>,
+    C<master_timeout>
+
+See the L<get_template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html>
+for more information.
+
+=head2 C<delete_template()>
+
+    $response = $e->indices->delete_template(
+        name  => 'template'                 # required
+    );
+
+The C<delete_template()> method is used to delete a named template.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>,
+    C<version>,
+    C<version_type>
+
+See the L<delete_template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html>
+for more information.
+
+=head1 WARMER METHODS
+
+=head2 C<put_warmer()>
+
+    $response = $e->indices->put_warmer(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+        name    => 'warmer',                # required
+
+        body    => { warmer defn }          # required
+    );
+
+The C<put_warmer()> method is used to create or update named warmers which
+are used to I<warm up> new segments in the index before they are exposed
+to user searches.  For instance:
+
+    $response = $e->indices->put_warmer(
+        index   => 'my_index',
+        name    => 'date_field_warmer',
+        body    => {
+            sort => 'date'
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<master_timeout>
+
+See the L<put_warmer docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-warmers.html>
+for more information.
+
+=head2 C<get_warmer()>
+
+    $response = $e->indices->get_warmer(
+        index   => 'index'  | \@indices,    # optional
+        type    => 'type'   | \@types,      # optional
+        name    => 'warmer' | \@warmers,    # optional
+    );
+
+The C<get_warmer()> method is used to retrieve warmers by name.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<get_warmer docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-warmers.html>
+for more information.
+
+=head2 C<delete_warmer()>
+
+    $response = $e->indices->get_warmer(
+        index   => 'index'  | \@indices,    # required
+        name    => 'warmer' | \@warmers,    # required
+    );
+
+The C<delete_warmer()> method is used to delete warmers by name.
+
+Query string parameters:
+    C<master_timeout>
+
+See the L<delete_warmer docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-warmers.html>
+for more information.
+
+=head1 STATS METHODS
+
+=head2 C<stats()>
+
+    $result = $e->indices->stats(
+        index   => 'index'  | \@indices      # optional
+        metric  => 'metric' | \@metrics      # optional
+    );
+
+The C<stats()> method returns statistical information about one, more or all
+indices. By default it returns all metrics, but you can limit which metrics
+are returned by specifying the C<metric>.
+
+Allowed metrics are:
+    C<_all>,
+    C<completion>
+    C<docs>,
+    C<fielddata>,
+    C<filter_cache>,
+    C<flush>,
+    C<get>,
+    C<id_cache>,
+    C<indexing>,
+    C<merge>,
+    C<percolate>,
+    C<query_cache>,
+    C<refresh>,
+    C<search>,
+    C<segments>,
+    C<store>,
+    C<warmer>
+
+Query string parameters:
+    C<completion_fields>,
+    C<fielddata_fields>,
+    C<fields>,
+    C<groups>,
+    C<human>,
+    C<level>,
+    C<types>
+
+See the L<stats docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-stats.html>
+for more information.
+
+=head2 C<recovery()>
+
+    $result = $e->indices->recovery(
+        index   => 'index' | \@indices      # optional
+    );
+
+Provides insight into on-going shard recoveries.
+
+Query string parameters:
+    C<active_only>,
+    C<detailed>,
+    C<human>
+
+See the L<recovery docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-recovery.html>
+for more information.
+
+=head2 C<segments()>
+
+    $result = $e->indices->segments(
+        index   => 'index' | \@indices      # optional
+    );
+
+The C<segments()> method is used to return information about the segments
+that an index contains.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<human>,
+    C<ignore_unavailable>
+
+See the L<segments docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-segments.html>
+for more information.
+
+=head1 QUERY AND ANALYSIS METHODS
+
+=head2 C<analyze()>
+
+    $result = $e->indices->analyze(
+        index   => 'index'                  # optional,
+        body    => 'text to analyze'
+    );
+
+The C<analyze()> method passes the text in the C<body> through the specified
+C<analyzer>, C<tokenizer> or token C<filter> - which may be global, or associated
+with a particular index or field - and returns the tokens.  Very useful
+for debugging analyzer configurations.
+
+Query string parameters:
+    C<analyzer>,
+    C<char_filters>,
+    C<field>,
+    C<filters>,
+    C<format>,
+    C<prefer_local>,
+    C<text>,
+    C<tokenizer>
+
+See the L<analyze docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-analyze.html>
+for more information.
+
+=head2 C<validate_query()>
+
+    $result = $e->indices->validate_query(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+
+        body    => { query }
+    );
+
+The C<validate_query()> method accepts a query in the C<body> and checks
+whether the query is valid or not.  Most useful when C<explain> is set
+to C<true>, in which case it includes an execution plan in the output.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<analyze_wildcard>,
+    C<analyzer>,
+    C<default_operator>,
+    C<df>,
+    C<expand_wildcards>,
+    C<explain>,
+    C<ignore_unavailable>,
+    C<lenient>,
+    C<lowercase_expanded_terms>,
+    C<q>
+
+See the L<validate_query docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-validate.html>
+for more information.
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: A client for running index-level requests
+
@@ -0,0 +1,183 @@
+package Search::Elasticsearch::Client::1_0::Direct::Nodes;
+$Search::Elasticsearch::Client::1_0::Direct::Nodes::VERSION = '1.20';
+use Moo;
+with 'Search::Elasticsearch::Role::API::1_0';
+with 'Search::Elasticsearch::Role::Client::Direct';
+__PACKAGE__->_install_api('nodes');
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Client::1_0::Direct::Nodes - A client for running node-level requests
+
+=head1 VERSION
+
+version 1.20
+
+=head1 DESCRIPTION
+
+This module provides methods to make node-level requests, such as
+retrieving node info and stats.
+
+It does L<Search::Elasticsearch::Role::Client::Direct>.
+
+=head1 METHODS
+
+=head2 C<info()>
+
+    $response = $e->nodes->info(
+        node_id => $node_id | \@node_ids       # optional
+        metric  => $metric  | \@metrics        # optional
+    );
+
+The C<info()> method returns static information about the nodes in the
+cluster, such as the configured maximum number of file handles, the maximum
+configured heap size or the threadpool settings.
+
+Allowed metrics are:
+    C<http>,
+    C<jvm>,
+    C<network>,
+    C<os>,
+    C<plugin>,
+    C<process>,
+    C<settings>,
+    C<thread_pool>,
+    C<transport>
+
+Query string parameters:
+    C<flat_settings>,
+    C<human>
+
+See the L<node_info docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-nodes-info.html>
+for more information.
+
+=head2 C<stats()>
+
+    $response = $e->nodes->stats(
+        node_id      => $node_id    | \@node_ids       # optional
+        metric       => $metric     | \@metrics        # optional
+        index_metric => $ind_metric | \@ind_metrics    # optional
+    );
+
+The C<stats()> method returns statistics about the nodes in the
+cluster, such as the number of currently open file handles, the current
+heap memory usage or the current number of threads in use.
+
+Stats can be returned for all nodes, or limited to particular nodes
+with the C<node_id> parameter. By default all metrics are returned, but
+these can be limited to those specified in the C<metric> parameter.
+
+Allowed metrics are:
+    C<_all>,
+    C<breaker>,
+    C<fs>,
+    C<http>,
+    C<indices>,
+    C<jvm>,
+    C<network>,
+    C<os>,
+    C<process>,
+    C<thread_pool>,
+    C<transport>
+
+If the C<indices> metric (or C<_all>) is specified, then
+L<indices_stats|Search::Elasticsearch::Client::1_0::Direct::Indices/indices_stats()>
+information is returned on a per-node basis. Which indices stats are
+returned can be controlled with the C<index_metric> parameter:
+
+    $response = $e->cluster->node_stats(
+        node_id       => 'node_1',
+        metric        => ['indices','fs']
+        index_metric  => ['docs','fielddata']
+    );
+
+Allowed index metrics are:
+    C<_all>,
+    C<completion>
+    C<docs>,
+    C<fielddata>,
+    C<filter_cache>,
+    C<flush>,
+    C<get>,
+    C<id_cache>,
+    C<indexing>,
+    C<merge>,
+    C<percolate>,
+    C<query_cache>,
+    C<refresh>,
+    C<search>,
+    C<segments>,
+    C<store>,
+    C<warmer>
+
+Query string parameters:
+    C<completion_fields>,
+    C<fielddata_fields>,
+    C<fields>,
+    C<groups>,
+    C<human>,
+    C<level>,
+    C<types>
+
+See the L<node_stats docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-nodes-stats.html>
+for more information.
+
+=head2 C<hot_threads()>
+
+    $response = $e->nodes->hot_threads(
+        node_id => $node_id | \@node_ids       # optional
+    )
+
+The C<hot_threads()> method is a useful tool for diagnosing busy nodes. It
+takes a snapshot of which threads are consuming the most CPU.
+
+Query string parameters:
+    C<ignore_idle_threads>,
+    C<interval>,
+    C<snapshots>,
+    C<threads>,
+    C<type>
+
+See the L<hot_threads docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-nodes-hot-threads.html>
+for more information.
+
+=head2 C<shutdown()>
+
+    $e->nodes->shutdown(
+        node_id => $node_id | \@node_ids    # optional
+    );
+
+The C<shutdown()> method is used to shutdown one or more nodes, or the whole
+cluster.
+
+Query string parameters:
+    C<delay>,
+    C<exit>
+
+See the L<shutdown docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-nodes-shutdown.html>
+for more information.
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: A client for running node-level requests
+
@@ -0,0 +1,190 @@
+package Search::Elasticsearch::Client::1_0::Direct::Snapshot;
+$Search::Elasticsearch::Client::1_0::Direct::Snapshot::VERSION = '1.20';
+use Moo;
+with 'Search::Elasticsearch::Role::API::1_0';
+with 'Search::Elasticsearch::Role::Client::Direct';
+__PACKAGE__->_install_api('snapshot');
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Client::1_0::Direct::Snapshot - A client for managing snapshot/restore
+
+=head1 VERSION
+
+version 1.20
+
+=head1 DESCRIPTION
+
+This module provides methods to manage snapshot/restore, or backups.
+It can create, get and delete configured backup repositories, and
+create, get, delete and restore snapshots of your cluster or indices.
+
+It does L<Search::Elasticsearch::Role::Client::Direct>.
+
+=head1 METHODS
+
+=head2 C<create_repository()>
+
+    $e->snapshot->create_repository(
+        repository  => 'repository',        # required
+        body        => { defn }             # required
+    );
+
+Create a repository for backups.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>,
+    C<verify>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<get_repository()>
+
+    $e->snapshot->get_repository(
+        repository  => 'repository' | \@repositories    # optional
+    );
+
+Retrieve existing repositories.
+
+Query string parameters:
+    C<local>,
+    C<master_timeout>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<verify_repository()>
+
+    $e->snapshot->verify_repository(
+        repository  => 'repository' # required
+    );
+
+Verify existing repository.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<delete_repository()>
+
+    $e->snapshot->delete_repository(
+        repository  => 'repository' | \@repositories    # required
+    );
+
+Delete repositories by name.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<create()>
+
+    $e->snapshot->create(
+        repository  => 'repository',     # required
+        snapshot    => 'snapshot',       # required,
+
+        body        => { snapshot defn } # optional
+    );
+
+Create a snapshot of the whole cluster or individual indices in the named
+repository.
+
+Query string parameters:
+    C<master_timeout>,
+    C<wait_for_completion>
+
+=head2 C<get()>
+
+    $e->snapshot->get(
+        repository  => 'repository'                   # required
+        snapshot    => 'snapshot'   | \@snapshots     # required
+    );
+
+Retrieve snapshots in the named repository.
+
+Query string parameters:
+    C<master_timeout>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<delete()>
+
+    $e->snapshot->delete(
+        repository  => 'repository',              # required
+        snapshot    => 'snapshot'                 # required
+    );
+
+Delete snapshot in the named repository.
+
+Query string parameters:
+    C<master_timeout>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<restore()>
+
+    $e->snapshot->restore(
+        repository  => 'repository',              # required
+        snapshot    => 'snapshot'                 # required
+
+        body        => { what to restore }        # optional
+    );
+
+Restore a named snapshot.
+
+Query string parameters:
+    C<master_timeout>,
+    C<wait_for_completion>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<status()>
+
+    $result = $e->snapshot->status(
+        repository  => 'repository',              # optional
+        snapshot    => 'snapshot' | \@snapshots   # optional
+    );
+
+Returns status information about the specified snapshots.
+
+Query string parameters:
+    C<master_timeout>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: A client for managing snapshot/restore
+
@@ -0,0 +1,1452 @@
+package Search::Elasticsearch::Client::1_0::Direct;
+$Search::Elasticsearch::Client::1_0::Direct::VERSION = '1.20';
+sub _namespace {__PACKAGE__}
+
+use Moo;
+with 'Search::Elasticsearch::Role::API::1_0';
+with 'Search::Elasticsearch::Role::Client::Direct';
+with 'Search::Elasticsearch::Role::Client::Direct::Main';
+
+__PACKAGE__->_install_api('');
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Client::1_0::Direct - Thin client with full support for Elasticsearch 1.x APIs
+
+=head1 VERSION
+
+version 1.20
+
+=head1 SYNOPSIS
+
+Create a client:
+
+    use Search::Elasticsearch;
+    my $e = Search::Elasticsearch->new(
+        client => '1_0::Direct'          # default
+    );
+
+Index a doc:
+
+    $e->index(
+        index   => 'my_index',
+        type    => 'blog_post',
+        id      => 123,
+        body    => {
+            title   => "Elasticsearch clients",
+            content => "Interesting content...",
+            date    => "2013-09-23"
+        }
+    );
+
+Get a doc:
+
+    $e->get(
+        index   => 'my_index',
+        type    => 'my_type',
+        id      => 123
+    );
+
+Search for docs:
+
+    $results = $e->search(
+        index   => 'my_index',
+        body    => {
+            query => {
+                match => {
+                    title => "elasticsearch"
+                }
+            }
+        }
+    );
+
+Index-level requests:
+
+    $e->indices->create( index => 'my_index' );
+    $e->indices->delete( index => 'my_index' )
+
+Cluster-level requests:
+
+    $health = $e->cluster->health;
+
+Node-level requests:
+
+    $info  = $e->nodes->info;
+    $stats = $e->nodes->stats;
+
+Snapshot and restore:
+
+    $e->snapshot->create_repository(
+        repository => 'my_backups',
+        type       => 'fs',
+        settings   => {
+            location => '/mnt/backups'
+        }
+    );
+
+    $e->snapshot->create(
+        repository => 'my_backups',
+        snapshot   => 'backup_2014'
+    );
+
+`cat` debugging:
+
+    say $e->cat->allocation;
+    say $e->cat->health;
+
+=head1 DESCRIPTION
+
+The L<Search::Elasticsearch::Client::1_0::Direct> class provides the default
+client that is returned by:
+
+    $e = Search::Elasticsearch->new;
+
+It is intended to be as close as possible to the native REST API that
+Elasticsearch uses, so that it is easy to translate the
+L<Elasticsearch reference documentation|http://www.elasticsearch/guide>
+for an API to the equivalent in this client.
+
+This class provides the methods for L<document CRUD|/DOCUMENT CRUD METHODS>,
+L<bulk document CRUD|/BULK DOCUMENT CRUD METHODS> and L<search|/SEARCH METHODS>.
+It also provides access to clients for managing L<indices|/indices()>
+and the L<cluster|/cluster()>.
+
+=head1 BACKWARDS COMPATIBILITY AND ELASTICSEARCH 0.90.x
+
+This version of the client supports the Elasticsearch 1.0 branch by
+default, which is not backwards compatible with the 0.90 branch.
+
+If you need to talk to a version of Elasticsearch before 1.0.0,
+please use L<Search::Elasticsearch::Client::0_90::Direct> as follows:
+
+    $es = Search::Elasticsearch->new(
+        client => '0_90::Direct'
+    );
+
+=head1 ELASTICSEARCH 2.x
+
+A client compatible with the as-yet-unreleased version 2.x of Elasticsearch is
+available as:
+
+    $es = Search::Elasticsearch->new(
+        client => '2_0::Direct'
+    );
+
+This will become the new default client once Elasticsearch 2.0.0 has been released.
+
+See L<Search::Elasticsearch::Client::2_0::Direct> for docs about the 2.x compatible
+client.
+
+=head1 CONVENTIONS
+
+=head2 Parameter passing
+
+Parameters can be passed to any request method as a list or as a hash
+reference. The following two statements are equivalent:
+
+    $e->search( size => 10 );
+    $e->search({size => 10});
+
+=head2 Path parameters
+
+Any values that should be included in the URL path, eg C</{index}/{type}>
+should be passed as top level parameters:
+
+    $e->search( index => 'my_index', type => 'my_type' );
+
+Alternatively, you can specify a C<path> parameter directly:
+
+    $e->search( path => '/my_index/my_type' );
+
+=head2 Query-string parameters
+
+Any values that should be included in the query string should be passed
+as top level parameters:
+
+    $e->search( size => 10 );
+
+If you pass in a C<\%params> hash, then it will be included in the
+query string parameters without any error checking. The following:
+
+    $e->search( size => 10, params => { from => 5, size => 5 })
+
+would result in this query string:
+
+    ?from=5&size=10
+
+=head2 Body parameter
+
+The request body should be passed in the C<body> key:
+
+    $e->search(
+        body => {
+            query => {...}
+        }
+    );
+
+The body can also be a UTF8-decoded string, which will be converted into
+UTF-8 bytes and passed as is:
+
+    $e->indices->analyze( body => "The quick brown fox");
+
+=head2 Ignore parameter
+
+Normally, any HTTP status code outside the 200-299 range will result in
+an error being thrown.  To suppress these errors, you can specify which
+status codes to ignore in the C<ignore> parameter.
+
+    $e->indices->delete(
+        index  => 'my_index',
+        ignore => 404
+    );
+
+This is most useful for
+L<Missing|Search::Elasticsearch::Error/Search::Elasticsearch::Error::Missing> errors, which
+are triggered by a C<404> status code when some requested resource does
+not exist.
+
+Multiple error codes can be specified with an array:
+
+    $e->indices->delete(
+        index  => 'my_index',
+        ignore => [404,409]
+    );
+
+=head1 CONFIGURATION
+
+=head2 C<bulk_helper_class>
+
+The class to use for the L</bulk_helper()> method. Defaults to
+L<Search::Elasticsearch::Bulk>.
+
+=head2 C<scroll_helper_class>
+
+The class to use for the L</scroll_helper()> method. Defaults to
+L<Search::Elasticsearch::Scroll>.
+
+=head1 GENERAL METHODS
+
+=head2 C<info()>
+
+    $info = $e->info
+
+Returns information about the version of Elasticsearch that the responding node
+is running.
+
+=head2 C<ping()>
+
+    $e->ping
+
+Pings a node in the cluster and returns C<1> if it receives a C<200>
+response, otherwise it throws an error.
+
+=head2 C<indices()>
+
+    $indices_client = $e->indices;
+
+Returns an L<Search::Elasticsearch::Client::1_0::Direct::Indices> object which can be used
+for managing indices, eg creating, deleting indices, managing mapping,
+index settings etc.
+
+=head2 C<cluster()>
+
+    $cluster_client = $e->cluster;
+
+Returns an L<Search::Elasticsearch::Client::1_0::Direct::Cluster> object which can be used
+for managing the cluster, eg cluster-wide settings and cluster health.
+
+=head2 C<nodes()>
+
+    $node_client = $e->nodes;
+
+Returns an L<Search::Elasticsearch::Client::1_0::Direct::Nodes> object which can be used
+to retrieve node info and stats.
+
+=head2 C<snapshot()>
+
+    $snapshot_client = $e->snapshot;
+
+Returns an L<Search::Elasticsearch::Client::1_0::Direct::Snapshot> object which
+is used for managing backup repositories and creating and restoring
+snapshots.
+
+=head2 C<cat()>
+
+    $cat_client = $e->cat;
+
+Returns an L<Search::Elasticsearch::Client::1_0::Direct::Cat> object which can be used
+to retrieve simple to read text info for debugging and monitoring an
+Elasticsearch cluster.
+
+=head1 DOCUMENT CRUD METHODS
+
+These methods allow you to perform create, index, update and delete requests
+for single documents:
+
+=head2 C<index()>
+
+    $response = $e->index(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # optional, otherwise auto-generated
+
+        body    => { document }         # required
+    );
+
+The C<index()> method is used to index a new document or to reindex
+an existing document.
+
+Query string parameters:
+    C<consistency>,
+    C<op_type>,
+    C<parent>,
+    C<refresh>,
+    C<replication>,
+    C<routing>,
+    C<timeout>,
+    C<timestamp>,
+    C<ttl>,
+    C<version>,
+    C<version_type>
+
+See the L<index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html>
+for more information.
+
+=head2 C<create()>
+
+    $response = $e->create(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # optional, otherwise auto-generated
+
+        body    => { document }         # required
+    );
+
+The C<create()> method works exactly like the L</index()> method, except
+that it will throw a C<Conflict> error if a document with the same
+C<index>, C<type> and C<id> already exists.
+
+Query string parameters:
+    C<consistency>,
+    C<op_type>,
+    C<parent>,
+    C<refresh>,
+    C<replication>,
+    C<routing>,
+    C<timeout>,
+    C<timestamp>,
+    C<ttl>,
+    C<version>,
+    C<version_type>
+
+See the L<create docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-create.html>
+for more information.
+
+=head2 C<get()>
+
+    $response = $e->get(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # required
+    );
+
+The C<get()> method will retrieve the document with the specified
+C<index>, C<type> and C<id>, or will throw a C<Missing> error.
+
+Query string parameters:
+    C<_source>,
+    C<_source_exclude>,
+    C<_source_include>,
+    C<fields>,
+    C<parent>,
+    C<preference>,
+    C<realtime>,
+    C<refresh>,
+    C<routing>,
+    C<version>,
+    C<version_type>
+
+See the L<get docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-get.html>
+for more information.
+
+=head2 C<get_source()>
+
+    $response = $e->get_source(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # required
+    );
+
+The C<get_source()> method works just like the L</get()> method except that
+it returns just the C<_source> field (the value of the C<body> parameter
+in the L</index()> method) instead of returning the C<_source> field
+plus the document metadata, ie the C<_index>, C<_type> etc.
+
+Query string parameters:
+    C<_source>,
+    C<_source_exclude>,
+    C<_source_include>,
+    C<parent>,
+    C<preference>,
+    C<realtime>,
+    C<refresh>,
+    C<routing>,
+    C<version>,
+    C<version_type>
+
+See the L<get_source docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-get.html>
+for more information.
+
+=head2 C<exists()>
+
+    $response = $e->exists(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # required
+    );
+
+The C<exists()> method returns C<1> if a document with the specified
+C<index>, C<type> and C<id> exists, or an empty string if it doesn't.
+
+Query string parameters:
+    C<parent>,
+    C<preference>,
+    C<realtime>,
+    C<refresh>,
+    C<routing>
+
+See the L<exists docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-get.html>
+for more information.
+
+=head2 C<delete()>
+
+    $response = $e->delete(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # required
+    );
+
+The C<delete()> method will delete the document with the specified
+C<index>, C<type> and C<id>, or will throw a C<Missing> error.
+
+Query string parameters:
+    C<consistency>,
+    C<parent>,
+    C<refresh>,
+    C<replication>,
+    C<routing>,
+    C<timeout>,
+    C<version>,
+    C<version_type>
+
+See the L<delete docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete.html>
+for more information.
+
+=head2 C<update()>
+
+    $response = $e->update(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # required
+
+        body    => { update }           # required
+    );
+
+The C<update()> method updates a document with the corresponding
+C<index>, C<type> and C<id> if it exists. Updates can be performed either by:
+
+=over
+
+=item * providing a partial document to be merged in to the existing document:
+
+    $response = $e->update(
+        ...,
+        body => {
+            doc => { new_field => 'new_value'},
+        }
+    );
+
+=item * or with a script:
+
+    $response = $e->update(
+        ...,
+        body => {
+            script => "ctx._source.counter += incr",
+            params => { incr => 5 }
+        }
+    );
+
+=back
+
+Query string parameters:
+    C<consistency>,
+    C<fields>,
+    C<lang>,
+    C<parent>,
+    C<realtime>,
+    C<refresh>,
+    C<replication>,
+    C<retry_on_conflict>,
+    C<routing>,
+    C<script>,
+    C<script_id>,
+    C<scripted_upsert>,
+    C<timeout>,
+    C<timestamp>,
+    C<ttl>,
+    C<version>,
+    C<version_type>
+
+See the L<update docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html>
+for more information.
+
+=head2 C<termvectors()>
+
+    $results = $e->termvectors(
+        index   => $index,          # required
+        type    => $type,           # required
+
+        id      => $id,             # optional
+        body    => {...}            # optional
+    )
+
+The C<termvectors()> method retrieves term and field statistics, positions,
+offsets and payloads for the specified document, assuming that termvectors
+have been enabled.
+
+Query string parameters:
+    C<dfs>,
+    C<field_statistics>,
+    C<fields>,
+    C<offsets>,
+    C<parent>,
+    C<payloads>,
+    C<positions>,
+    C<preference>,
+    C<realtime>,
+    C<routing>,
+    C<term_statistics>,
+    C<version>,
+    C<version_type>
+
+See the L<termvector docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-termvectors.html>
+for more information.
+
+=head1 BULK DOCUMENT CRUD METHODS
+
+The bulk document CRUD methods are used for running multiple CRUD actions
+within a single request.  By reducing the number of network requests
+that need to be made, bulk requests greatly improve performance.
+
+=head2 C<bulk()>
+
+    $response = $e->bulk(
+        index   => 'index_name',        # required if type specified
+        type    => 'type_name',         # optional
+
+        body    => [ actions ]          # required
+    );
+
+See L<Search::Elasticsearch::Bulk> and L</bulk_helper()> for a helper module that makes
+bulk indexing simpler to use.
+
+The C<bulk()> method can perform multiple L</index()>, L</create()>,
+L</delete()> or L</update()> actions with a single request. The C<body>
+parameter expects an array containing the list of actions to perform.
+
+An I<action> consists of an initial metadata hash ref containing the action
+type, plus the associated metadata, eg :
+
+    { delete => { _index => 'index', _type => 'type', _id => 123 }}
+
+The C<index> and C<create> actions then expect a hashref containing
+the document itself:
+
+    { create => { _index => 'index', _type => 'type', _id => 123 }},
+    { title => "A newly created document" }
+
+And the C<update> action expects a hashref containing the update commands,
+eg:
+
+    { update => { _index => 'index', _type => 'type', _id => 123 }},
+    { script => "ctx._source.counter+=1" }
+
+Each action can include the same parameters that you would pass to
+the equivalent L</index()>, L</create()>, L</delete()> or L</update()>
+request, except that C<_index>, C<_type> and C<_id> must be specified with
+the preceding underscore. All other parameters can be specified with or
+without the underscore.
+
+For instance:
+
+    $response = $e->bulk(
+        index   => 'index_name',        # default index name
+        type    => 'type_name',         # default type name
+        body    => [
+
+            # create action
+            { create => {
+                _index => 'not_the_default_index',
+                _type  => 'not_the_default_type',
+                _id    => 123
+            }},
+            { title => 'Foo' },
+
+            # index action
+            { index => { _id => 124 }},
+            { title => 'Foo' },
+
+            # delete action
+            { delete => { _id => 125 }},
+
+            # update action
+            { update => { _id => 126 }},
+            { script => "ctx._source.counter+1" }
+        ]
+    );
+
+Each action is performed separately. One failed action will not
+cause the others to fail as well.
+
+Query string parameters:
+    C<consistency>,
+    C<refresh>,
+    C<replication>,
+    C<timeout>
+
+See the L<bulk docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html>
+for more information.
+
+=head2 C<bulk_helper()>
+
+    $bulk_helper = $e->bulk_helper( @args );
+
+Returns a new instance of the class specified in the L</bulk_helper_class>,
+which defaults to L<Search::Elasticsearch::Bulk>.
+
+=head2 C<mget()>
+
+    $results = $e->mget(
+        index   => 'default_index',     # optional, required when type specified
+        type    => 'default_type',      # optional
+
+        body    => { docs or ids }      # required
+    );
+
+The C<mget()> method will retrieve multiple documents with a single request.
+The C<body> consists of an array of documents to retrieve:
+
+    $results = $e->mget(
+        index   => 'default_index',
+        type    => 'default_type',
+        body    => {
+            docs => [
+                { _id => 1},
+                { _id => 2, _type => 'not_the_default_type' }
+            ]
+        }
+    );
+
+You can also pass any of the other parameters that the L</get()> request
+accepts.
+
+If you have specified an C<index> and C<type>, you can just include the
+C<ids> of the documents to retrieve:
+
+    $results = $e->mget(
+        index   => 'default_index',
+        type    => 'default_type',
+        body    => {
+            ids => [ 1, 2, 3]
+        }
+    );
+
+Query string parameters:
+    C<_source>,
+    C<_source_exclude>,
+    C<_source_include>,
+    C<fields>,
+    C<preference>,
+    C<realtime>,
+    C<refresh>
+
+See the L<mget docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-get.html>
+for more information.
+
+=head2 C<delete_by_query()>
+
+    $result = $e->delete_by_query(
+        index => 'index' | \@indices,   # required
+        type  => 'type'  | \@types,     # optional
+
+        body  => { query }              # required
+
+    );
+
+The C<delete_by_query()> method deletes all documents which match the
+query.  For instance, to delete all documents from 2012:
+
+    $result = $e->delete_by_query(
+        body  => {
+            query => {
+                range => {
+                    date => {
+                        gte => '2012-01-01',
+                        lt  => '2013-01-01'
+                    }
+                }
+            }
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<analyzer>,
+    C<consistency>,
+    C<default_operator>,
+    C<df>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<q>,
+    C<replication>,
+    C<routing>,
+    C<timeout>
+
+See the L<delete_by_query docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete-by-query.html>
+for more information.
+
+=head2 C<mtermvectors()>
+
+    $results = $e->mtermvectors(
+        index   => $index,          # required if type specified
+        type    => $type,           # optional
+
+        body    => { }              # optional
+    )
+
+Runs multiple L</termvector()> requests in a single request, eg:
+
+    $results = $e->mtermvectors(
+        index   => 'test',
+        body    => {
+            docs => [
+                { _type => 'test', _id => 1, fields => ['text'] },
+                { _type => 'test', _id => 2, payloads => 1 },
+            ]
+        }
+    );
+
+Query string parameters:
+    C<field_statistics>,
+    C<fields>,
+    C<ids>,
+    C<offsets>,
+    C<parent>,
+    C<payloads>,
+    C<positions>,
+    C<preference>,
+    C<realtime>,
+    C<routing>,
+    C<term_statistics>,
+    C<version>,
+    C<version_type>
+
+See the L<mtermvectors docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-termvectors.html>
+for more information.
+
+=head1 SEARCH METHODS
+
+The search methods are used for querying documents in one, more or all indices
+and of one, more or all types:
+
+=head2 C<search()>
+
+    $results = $e->search(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+
+        body    => { search params }        # optional
+    );
+
+The C<search()> method searches for matching documents in one or more
+indices.  It is just as easy to search a single index as it is to search
+all the indices in your cluster.  It can also return
+L<aggregations|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html>
+L<highlighted snippets|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-highlighting.html>
+and L<did-you-mean|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-phrase.html>
+or L<search-as-you-type|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html>
+suggestions.
+
+The I<lite> L<version of search|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html>
+allows you to specify a query string in the C<q> parameter, using the
+Lucene query string syntax:
+
+    $results = $e->search( q => 'title:(elasticsearch clients)');
+
+However, the preferred way to search is by using the
+L<Query DSL|http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html>
+to create a query, and passing that C<query> in the
+L<request body|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html>:
+
+    $results = $e->search(
+        body => {
+            query => {
+                match => { title => 'Elasticsearch clients'}
+            }
+        }
+    );
+
+Query string parameters:
+    C<_source>,
+    C<_source_exclude>,
+    C<_source_include>,
+    C<allow_no_indices>,
+    C<analyze_wildcard>,
+    C<analyzer>,
+    C<default_operator>,
+    C<df>,
+    C<expand_wildcards>,
+    C<explain>,
+    C<fielddata_fields>,
+    C<fields>,
+    C<from>,
+    C<ignore_unavailable>,
+    C<lenient>,
+    C<lowercase_expanded_terms>,
+    C<preference>,
+    C<q>,
+    C<query_cache>,
+    C<routing>,
+    C<scroll>,
+    C<search_type>,
+    C<size>,
+    C<sort>,
+    C<stats>,
+    C<suggest_field>,
+    C<suggest_mode>,
+    C<suggest_size>,
+    C<suggest_text>,
+    C<terminate_after>,
+    C<timeout>,
+    C<track_scores>,
+    C<version>
+
+See the L<search reference|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html>
+for more information.
+
+Also see L<Search::Elasticsearch::Transport/send_get_body_as>.
+
+=head2 C<search_exists()>
+
+The C<search_exists()> method is a quick version of search which can be
+used to find out whether there are matching search results or not.
+It doesn't return any results itself.
+
+    $results = $e->search_exists(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+
+        body    => { search params }        # optional
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<analyze_wildcard>,
+    C<analyzer>,
+    C<default_operator>,
+    C<df>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<lenient>,
+    C<lowercase_expanded_terms>,
+    C<min_score>,
+    C<preference>,
+    C<q>,
+    C<routing>
+
+See the L<search exists reference|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-exists.html>
+for more information.
+
+=head2 C<count()>
+
+    $results = $e->count(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+
+        body    => { query }                # optional
+    )
+
+The C<count()> method returns the total count of all documents matching the
+query:
+
+    $results = $e->count(
+        body => {
+            query => {
+                match => { title => 'Elasticsearch clients' }
+            }
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<analyze_wildcard>,
+    C<analyzer>,
+    C<default_operator>,
+    C<df>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<lenient>,
+    C<lowercase_expanded_terms>,
+    C<min_score>,
+    C<preference>,
+    C<q>,
+    C<routing>
+
+See the L<count docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-count.html>
+for more information.
+
+=head2 C<search_template()>
+
+    $results = $e->search_template(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+
+        body    => { search params }        # optional
+    );
+
+Perform a search by specifying a template (either predefined or defined
+within the C<body>) and parameters to use with the template, eg:
+
+    $results = $e->search_template(
+        template => {
+            query => {
+                match => {
+                    "{{my_field}}" => "{{my_value}}"
+                }
+            },
+            size => "{{my_size}}"
+        },
+        params => {
+            my_field => 'foo',
+            my_value => 'bar',
+            my_size  => 5
+        }
+    );
+
+See the L<search template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html>
+for more information.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<preference>,
+    C<scroll>,
+    C<search_type>
+
+=head2 C<scroll()>
+
+    $results = $e->scroll(
+        scroll      => '1m',
+        scroll_id   => $id
+    );
+
+When a L</search()> has been performed with the
+C<scroll> parameter, the C<scroll()>
+method allows you to keep pulling more results until the results
+are exhausted.
+
+B<NOTE:> you will almost always want to set the
+C<search_type> to C<scan> in your
+original C<search()> request.
+
+See L</scroll_helper()> and L<Search::Elasticsearch::Scroll> for a helper utility
+which makes managing scroll requests much easier.
+
+Query string parameters:
+    C<scroll>,
+    C<scroll_id>
+
+See the L<scroll docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-scroll.html>
+and the L<search_type docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search.html/search-request-search-type.html>
+for more information.
+
+=head2 C<clear_scroll()>
+
+    $response = $e->clear_scroll(
+        scroll_id => $id | \@ids    # required
+    );
+
+Or
+
+    $response = $e->clear_scroll(
+        body => $id
+    );
+
+The C<clear_scroll()> method can clear unfinished scroll requests, freeing
+up resources on the server.
+
+=head2 C<scroll_helper()>
+
+    $scroll_helper = $e->scroll_helper( @args );
+
+Returns a new instance of the class specified in the L</scroll_helper_class>,
+which defaults to L<Search::Elasticsearch::Scroll>.
+
+=head2 C<msearch()>
+
+    $results = $e->msearch(
+        index   => 'default_index' | \@indices,     # optional
+        type    => 'default_type'  | \@types,       # optional
+
+        body    => [ searches ]                     # required
+    );
+
+The C<msearch()> method allows you to perform multiple searches in a single
+request.  Similar to the L</bulk()> request, each search request in the
+C<body> consists of two hashes: the metadata hash then the search request
+hash (the same data that you'd specify in the C<body> of a L</search()>
+request).  For instance:
+
+    $results = $e->msearch(
+        index   => 'default_index',
+        type    => ['default_type_1', 'default_type_2'],
+        body => [
+            # uses defaults
+            {},
+            { query => { match_all => {} }},
+
+            # uses a custom index
+            { index => 'not_the_default_index' },
+            { query => { match_all => {} }}
+        ]
+    );
+
+Query string parameters:
+    C<search_type>
+
+See the L<msearch docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-multi-search.html>
+for more information.
+
+=head2 C<explain()>
+
+    $response = $e->explain(
+        index   => 'my_index',  # required
+        type    => 'my_type',   # required
+        id      => 123,         # required
+
+        body    => { search }   # required
+    );
+
+The C<explain()> method explains why the specified document did or
+did not match a query, and how the relevance score was calculated.
+For instance:
+
+    $response = $e->explain(
+        index   => 'my_index',
+        type    => 'my_type',
+        id      => 123,
+        body    => {
+            query => {
+                match => { title => 'Elasticsearch clients' }
+            }
+        }
+    );
+
+Query string parameters:
+    C<_source>,
+    C<_source_exclude>,
+    C<_source_include>,
+    C<analyze_wildcard>,
+    C<analyzer>,
+    C<default_operator>,
+    C<df>,
+    C<fields>,
+    C<lenient>,
+    C<lowercase_expanded_terms>,
+    C<parent>,
+    C<preference>,
+    C<q>,
+    C<routing>
+
+See the L<explain docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-explain.html>
+for more information.
+
+=head2 C<field_stats()>
+
+    $response = $e->field_stats(
+        index   => 'index'   | \@indices,   # optional
+        fields  => 'field'   | \@fields,    # optional
+        level   => 'cluster' | 'indices',   # optional
+    );
+
+The C<field-stats> API returns statistical properties of a field
+(such as min and max values) without executing a search.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<fields>,
+    C<ignore_unavailable>,
+    C<level>
+
+See the L<field-stats docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-field-stats.html>
+for more information.
+
+=head2 C<search_shards()>
+
+    $response = $e->search_shards(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+    )
+
+The C<search_shards()> method returns information about which shards on
+which nodes will execute a search request.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>,
+    C<preference>,
+    C<routing>
+
+See the L<search-shards docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-shards.html>
+for more information.
+
+=head1 PERCOLATION METHODS
+
+=head2 C<percolate()>
+
+    $results = $e->percolate(
+        index   => 'my_index',      # required
+        type    => 'my_type',       # required
+
+        body    => { percolation }  # required
+    );
+
+Percolation is search inverted: instead of finding docs which match a
+particular query, it finds queries which match a particular document, eg
+for I<alert-me-when> functionality.
+
+The C<percolate()> method runs a percolation request to find the
+queries matching a particular document. In the C<body> you should pass the
+C<_source> field of the document under the C<doc> key:
+
+    $results = $e->percolate(
+        index   => 'my_index',
+        type    => 'my_type',
+        body    => {
+            doc => {
+                title => 'Elasticsearch rocks'
+            }
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<percolate_format>,
+    C<percolate_index>,
+    C<percolate_preference>,
+    C<percolate_routing>,
+    C<percolate_type>,
+    C<preference>,
+    C<routing>,
+    C<version>,
+    C<version_type>
+
+See the L<percolate docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-percolate.html>
+for more information.
+
+=head2 C<count_percolate()>
+
+    $results = $e->count_percolate(
+        index   => 'my_index',      # required
+        type    => 'my_type',       # required
+
+        body    => { percolation }  # required
+    );
+
+The L</count_percolate()> request works just like the L</percolate()>
+request except that it returns a count of all matching queries, instead
+of the queries themselves.
+
+    $results = $e->count_percolate(
+        index   => 'my_index',
+        type    => 'my_type',
+        body    => {
+            doc => {
+                title => 'Elasticsearch rocks'
+            }
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<percolate_index>,
+    C<percolate_type>,
+    C<preference>,
+    C<routing>,
+    C<version>,
+    C<version_type>
+
+See the L<percolate docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-percolate.html>
+for more information.
+
+=head2 C<mpercolate()>
+
+    $results = $e->mpercolate(
+        index   => 'my_index',               # required if type
+        type    => 'my_type',                # optional
+
+        body    => [ percolation requests ]  # required
+    );
+
+Multi-percolation allows multiple L</percolate()> requests to be run
+in a single request.
+
+    $results = $e->mpercolate(
+        index   => 'my_index',
+        type    => 'my_type',
+        body    => [
+            # first request
+            { percolate => {
+                index => 'twitter',
+                type  => 'tweet'
+            }},
+            { doc => {message => 'some_text' }},
+
+            # second request
+            { percolate => {
+                index => 'twitter',
+                type  => 'tweet',
+                id    => 1
+            }},
+            {},
+        ]
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>
+
+See the L<mpercolate docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-percolate.html>
+for more information.
+
+=head2 C<suggest()>
+
+    $results = $e->suggest(
+        index   => 'index' | \@indices,     # optional
+
+        body    => { suggest request }      # required
+    );
+
+The C<suggest()> method is used to run
+L<did-you-mean|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesteres-phrase.html>
+or L<search-as-you-type|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html>
+suggestion requests, which can also be run as part of a L</search()> request.
+
+    $results = $e->suggest(
+        index   => 'my_index',
+        body    => {
+            my_suggestions => {
+                phrase  => {
+                    text    => 'johnny walker',
+                    field   => 'title'
+                }
+            }
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<preference>,
+    C<routing>
+
+=head2 C<mlt()>
+
+    $results = $e->mlt(
+        index   => 'my_index',  # required
+        type    => 'my_type',   # required
+        id      => 123,         # required
+
+        body    => { search }   # optional
+    );
+
+The C<mlt()> method runs a
+L<more-like-this query|http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html>
+to find other documents which are similar to the specified document.
+
+Query string parameters:
+    C<boost_terms>,
+    C<max_doc_freq>,
+    C<max_query_terms>,
+    C<max_word_length>,
+    C<min_doc_freq>,
+    C<min_term_freq>,
+    C<min_word_length>,
+    C<mlt_fields>,
+    C<percent_terms_to_match>,
+    C<routing>,
+    C<search_from>,
+    C<search_indices>,
+    C<search_scroll>,
+    C<search_size>,
+    C<search_source>,
+    C<search_type>,
+    C<search_types>,
+    C<stop_words>
+
+See the L<mlt docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-more-like-this.html>
+for more information.
+
+=HEAD1 INDEXED SCRIPT METHODS
+
+If dynamic scripting is enabled, Elasticsearch allows you to store scripts in an internal index known as
+C<.scripts> and reference them by id. The methods to manage indexed scripts are as follows:
+
+=head2 C<put_script()>
+
+    $result  = $e->put_script(
+        lang => 'lang',     # required
+        id   => 'id',       # required
+        body => { script }  # required
+    );
+
+The C<put_script()> method is used to store a script in the C<.scripts> index. For instance:
+
+    $result  = $e->put_scripts(
+        lang => 'groovy',
+        id   => 'hello_world',
+        body => {
+          script => q(return "hello world");
+        }
+    );
+
+Query string parameters:
+    C<op_type>,
+    C<version>,
+    C<version_type>
+
+See the L<indexed scripts docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
+
+=head2 C<get_script()>
+
+    $script = $e->get_script(
+        lang => 'lang',     # required
+        id   => 'id',       # required
+    );
+
+Retrieve the indexed script from the C<.scripts> index.
+
+Query string parameters:
+    C<version>,
+    C<version_type>
+
+See the L<indexed scripts docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
+
+=head2 C<delete_script()>
+
+    $script = $e->delete_script(
+        lang => 'lang',     # required
+        id   => 'id',       # required
+    );
+
+Delete the indexed script from the C<.scripts> index.
+
+Query string parameters:
+    C<version>,
+    C<version_type>
+
+See the L<indexed scripts docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
+
+=HEAD1 INDEXED SEARCH TEMPLATE METHODS
+
+Mustache templates can be used to create search requests.  These templates can
+be stored in the C<.scripts> index and retrieved by ID. The methods to
+manage indexed scripts are as follows:
+
+=head2 C<put_template()>
+
+    $result  = $e->put_template(
+        id   => 'id',                       # required
+        body => { template } || "template"  # required
+    );
+
+The C<put_template()> method is used to store a template in the C<.scripts> index.
+For instance:
+
+    $result  = $e->put_template(
+        id   => 'hello_world',
+        body => {
+          template => {
+            query => {
+              match => {
+                title => "hello world"
+              }
+            }
+          }
+      }
+    );
+
+Query string parameters: None
+
+See the L<indexed search template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
+
+=head2 C<get_template()>
+
+    $script = $e->get_template(
+        id   => 'id',       # required
+    );
+
+Retrieve the indexed template from the C<.scripts> index.
+
+Query string parameters:
+    C<version>,
+    C<version_type>
+
+See the L<indexed search template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
+
+=head2 C<delete_template()>
+
+    $script = $e->delete_template(
+        id   => 'id',       # required
+    );
+
+Delete the indexed template from the C<.scripts> index.
+
+Query string parameters: None
+
+See the L<indexed search template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: Thin client with full support for Elasticsearch 1.x APIs
+
@@ -0,0 +1,354 @@
+package Search::Elasticsearch::Client::2_0::Direct::Cat;
+$Search::Elasticsearch::Client::2_0::Direct::Cat::VERSION = '1.20';
+use Moo;
+with 'Search::Elasticsearch::Role::API::2_0';
+with 'Search::Elasticsearch::Role::Client::Direct';
+use Search::Elasticsearch::Util qw(parse_params);
+use namespace::clean;
+__PACKAGE__->_install_api('cat');
+
+#===================================
+sub help {
+#===================================
+    my ( $self, $params ) = parse_params(@_);
+    $params->{help} = 1;
+    my $defn = $self->api->{'cat.help'};
+    $self->perform_request( $defn, $params );
+}
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Client::2_0::Direct::Cat - A client for running cat debugging requests
+
+=head1 VERSION
+
+version 1.20
+
+=head1 DESCRIPTION
+
+The C<cat> API in Elasticsearch provides information about your
+cluster and indices in a simple, easy to read text format, intended
+for human consumption.
+
+These APIs have a number of parameters in common:
+
+=over
+
+=item * C<help>
+
+Returns help about the API, eg:
+
+    say $e->cat->allocation(help => 1);
+
+=item * C<v>
+
+Includes the column headers in the output:
+
+    say $e->cat->allocation(v => 1);
+
+=item * C<h>
+
+Accepts a list of column names to be output, eg:
+
+    say $e->cat->indices(h => ['health','index']);
+
+=item * C<bytes>
+
+Formats byte-based values as bytes (C<b>), kilobytes (C<k>), megabytes
+(C<m>) or gigabytes (C<g>)
+
+=back
+
+It does L<Search::Elasticsearch::Role::Client::Direct>.
+
+=head1 METHODS
+
+=head2 C<help()>
+
+    say $e->cat->help;
+
+Returns the list of supported C<cat> APIs
+
+=head2 C<aliases()>
+
+    say $e->cat->aliases(
+        name => 'name' | \@names    # optional
+    );
+
+Returns information about index aliases, optionally limited to the specified
+index/alias names.
+
+Query string parameters:
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat aliases docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-aliases.html>
+for more information.
+
+=head2 C<allocation()>
+
+    say $e->cat->allocation(
+        node_id => 'node' | \@nodes    # optional
+    );
+
+Provides a snapshot of how shards have located around the cluster and the
+state of disk usage.
+
+Query string parameters:
+    C<bytes>,
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat allocation docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-allocation.html>
+for more information.
+
+=head2 C<count()>
+
+    say $e->cat->count(
+        index => 'index' | \@indices    # optional
+    );
+
+Provides quick access to the document count of the entire cluster, or
+individual indices.
+
+Query string parameters:
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat count docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-count.html>
+for more information.
+
+=head2 C<fielddata()>
+
+    say $e->cat->fielddata(
+        fields => 'field' | \@fields    # optional
+    );
+
+Shows the amount of memory used by each of the specified `fields` (or all
+fields) loaded into fielddata.
+
+Query string parameters:
+    C<bytes>,
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat fielddata docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-fielddata.html>
+for more information.
+
+=head2 C<health()>
+
+    say $e->cat->health();
+
+Provides a snapshot of how shards have located around the cluster and the
+state of disk usage.
+
+Query string parameters:
+    C<bytes>,
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<ts>,
+    C<v>
+
+See the L<cat health docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-health.html>
+for more information.
+
+=head2 C<indices()>
+
+    say $e->cat->indices(
+        index => 'index' | \@indices    # optional
+    );
+
+Provides a summary of index size and health for the whole cluster
+or individual indices
+
+Query string parameters:
+    C<bytes>,
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<pri>,
+    C<v>
+
+See the L<cat indices docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-indices.html>
+for more information.
+
+=head2 C<master()>
+
+    say $e->cat->master();
+
+Displays the master’s node ID, bound IP address, and node name.
+
+Query string parameters:
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat master docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-master.html>
+for more information.
+
+=head2 C<nodes()>
+
+    say $e->cat->nodes();
+
+Provides a snapshot of all of the nodes in your cluster.
+
+Query string parameters:
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat nodes docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-nodes.html>
+for more information.
+
+=head2 C<pending_tasks()>
+
+    say $e->cat->pending_tasks();
+
+Returns any cluster-level tasks which are queued on the master.
+
+Query string parameters:
+    C<local>,
+    C<master_timeout>,
+    C<h>,
+    C<help>,
+    C<v>
+
+See the L<cat pending-tasks docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-pending-tasks.html>
+for more information.
+
+=head2 C<plugins()>
+
+    say $e->cat->plugins();
+
+Returns information about plugins installed on each node.
+
+Query string parameters:
+    C<local>,
+    C<master_timeout>,
+    C<h>,
+    C<help>,
+    C<v>
+
+See the L<cat plugins docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-plugins.html>
+for more information.
+
+=head2 C<recovery()>
+
+    say $e->cat->recovery(
+        index => 'index' | \@indices    # optional
+    );
+
+Provides a view of shard replication. It will show information
+anytime data from at least one shard is copying to a different node.
+It can also show up on cluster restarts. If your recovery process seems
+stuck, try it to see if there’s any movement using C<recovery()>.
+
+Query string parameters:
+    C<bytes>,
+    C<h>,
+    C<help>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat recovery docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-recovery.html>
+for more information.
+
+=head2 C<segments()>
+
+    say $e->cat->segments(
+        index => 'index' | \@indices    # optional
+    );
+
+Provides low level information about the segments in the shards of an index.
+
+Query string parameters:
+    C<h>,
+    C<help>,
+    C<v>
+
+See the L<cat shards docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-segments.html>
+for more information.
+
+=head2 C<shards()>
+
+    say $e->cat->shards(
+        index => 'index' | \@indices    # optional
+    );
+
+Provides a detailed view of what nodes contain which shards, the state and
+size of each shard.
+
+Query string parameters:
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat shards docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-shards.html>
+for more information.
+
+=head2 C<thread_pool()>
+
+    say $e->cat->thread_pool(
+        index => 'index' | \@indices    # optional
+    );
+
+Shows cluster wide thread pool statistics per node. By default the C<active>,
+C<queue> and C<rejected> statistics are returned for the C<bulk>, C<index> and
+C<search> thread pools.
+
+Query string parameters:
+    C<full_id>,
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat thread_pool docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-thread-pool.html>
+for more information.
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: A client for running cat debugging requests
+
@@ -0,0 +1,206 @@
+package Search::Elasticsearch::Client::2_0::Direct::Cluster;
+$Search::Elasticsearch::Client::2_0::Direct::Cluster::VERSION = '1.20';
+use Moo;
+with 'Search::Elasticsearch::Role::API::2_0';
+with 'Search::Elasticsearch::Role::Client::Direct';
+__PACKAGE__->_install_api('cluster');
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Client::2_0::Direct::Cluster - A client for running cluster-level requests
+
+=head1 VERSION
+
+version 1.20
+
+=head1 DESCRIPTION
+
+This module provides methods to make cluster-level requests, such as
+getting and setting cluster-level settings, manually rerouting shards,
+and retrieving for monitoring purposes.
+
+It does L<Search::Elasticsearch::Role::Client::Direct>.
+
+=head1 METHODS
+
+=head2 C<health()>
+
+    $response = $e->cluster->health(
+        index   => 'index' | \@indices  # optional
+    );
+
+The C<health()> method is used to retrieve information about the cluster
+health, returning C<red>, C<yellow> or C<green> to indicate the state
+of the cluster, indices or shards.
+
+Query string parameters:
+    C<level>,
+    C<local>,
+    C<master_timeout>,
+    C<timeout>,
+    C<wait_for_active_shards>,
+    C<wait_for_nodes>,
+    C<wait_for_relocating_shards>,
+    C<wait_for_status>
+
+See the L<cluster health docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-health.html>
+for more information.
+
+=head2 C<stats()>
+
+    $response = $e->cluster->stats(
+        node_id => 'node' | \@nodes     # optional
+    );
+
+Returns high-level cluster stats, optionally limited to the listed nodes.
+
+Query string parameters:
+    C<flat_settings>,
+    C<human>
+
+See the L<cluster stats docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-stats.html>
+for more information.
+
+=head2 C<get_settings()>
+
+    $response = $e->cluster->get_settings()
+
+The C<get_settings()> method is used to retrieve cluster-wide settings that
+have been set with the L</put_settings()> method.
+
+Query string parameters:
+    C<flat_settings>,
+    C<master_timeout>,
+    C<timeout>
+
+See the L<cluster settings docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-update-settings.html>
+for more information.
+
+=head2 C<put_settings()>
+
+    $response = $e->cluster->put_settings( %settings );
+
+The C<put_settings()> method is used to set cluster-wide settings, either
+transiently (which don't survive restarts) or permanently (which do survive
+restarts).
+
+For instance:
+
+    $response = $e->cluster->put_settings(
+        body => {
+            transient => { "discovery.zen.minimum_master_nodes" => 5 }
+        }
+    );
+
+Query string parameters:
+    C<flat_settings>
+
+See the L<cluster settings docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-update-settings.html>
+ for more information.
+
+=head2 C<state()>
+
+    $response = $e->cluster->state(
+        metric => $metric | \@metrics   # optional
+        index  => $index  | \@indices   # optional
+    );
+
+The C<state()> method returns the current cluster state from the master node,
+or from the responding node if C<local> is set to C<true>.
+
+It returns all metrics by default, but these can be limited to any of:
+    C<_all>,
+    C<blocks>,
+    C<metadata>,
+    C<nodes>,
+    C<routing_table>
+
+Metrics for indices can be limited to particular indices with the C<index>
+parameter.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<flat_settings>,
+    C<ignore_unavailable>,
+    C<local>,
+    C<master_timeout>
+
+See the L<cluster state docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-state.html>
+for more information.
+
+=head2 C<pending_tasks()>
+
+    $response = $e->cluster->pending_tasks();
+
+Returns a list of cluster-level tasks still pending on the master node.
+
+Query string parameters:
+    C<local>,
+    C<master_timeout>
+
+See the L<pending tasks docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-pending.html>
+for more information.
+
+=head2 C<reroute()>
+
+    $e->cluster->reroute(
+        body => { commands }
+    );
+
+The C<reroute()> method is used to manually reallocate shards from one
+node to another.  The C<body> should contain the C<commands> indicating
+which changes should be made. For instance:
+
+    $e->cluster->reroute(
+        body => {
+            commands => [
+                { move => {
+                    index     => 'test',
+                    shard     => 0,
+                    from_node => 'node_1',
+                    to_node   => 'node_2
+                }},
+                { allocate => {
+                    index     => 'test',
+                    shard     => 1,
+                    node      => 'node_3'
+                }}
+            ]
+        }
+    );
+
+Query string parameters:
+    C<dry_run>,
+    C<explain>,
+    C<master_timeout>,
+    C<metric>,
+    C<timeout>
+
+See the L<reroute docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-reroute.html>
+for more information.
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: A client for running cluster-level requests
+
@@ -0,0 +1,834 @@
+package Search::Elasticsearch::Client::2_0::Direct::Indices;
+$Search::Elasticsearch::Client::2_0::Direct::Indices::VERSION = '1.20';
+use Moo;
+with 'Search::Elasticsearch::Role::API::2_0';
+with 'Search::Elasticsearch::Role::Client::Direct';
+__PACKAGE__->_install_api('indices');
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Client::2_0::Direct::Indices - A client for running index-level requests
+
+=head1 VERSION
+
+version 1.20
+
+=head1 DESCRIPTION
+
+This module provides methods to make index-level requests, such as
+creating and deleting indices, managing type mappings, index settings,
+warmers, index templates and aliases.
+
+It does L<Search::Elasticsearch::Role::Client::Direct>.
+
+=head1 INDEX METHODS
+
+=head2 C<create()>
+
+    $result = $e->indices->create(
+        index => 'my_index'             # required
+
+        body  => {                      # optional
+            index settings
+            mappings
+            warmers
+        }
+    );
+
+The C<create()> method is used to create an index. Optionally, index
+settings, type mappings and index warmers can be added at the same time.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<create index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html>
+for more information.
+
+=head2 C<get()>
+
+    $response = $e->indices->get(
+        index   => 'index'   | \@indices    # optional
+        feature => 'feature' | \@features   # optional
+    );
+
+Returns the aliases, settings, mappings, and warmers for the specified indices.
+The C<feature> parameter can be set to none or more of: C<_settings>, C<_mappings>,
+C<_warmers> and C<_aliases>.
+
+See the L<get index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-index.html>.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+=head2 C<exists()>
+
+    $bool = $e->indices->exists(
+        index => 'index' | \@indices    # required
+    );
+
+The C<exists()> method returns C<1> or the empty string to indicate
+whether the specified index or indices exist.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<index exists docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-indices-exists.html>
+for more information.
+
+=head2 C<delete()>
+
+    $response = $e->indices->delete(
+        index => 'index' | \@indices    # required
+    );
+
+The C<delete()> method deletes the specified indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<master_timeout>,
+    C<timeout>
+
+See the L<delete index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-delete-index.html>
+for more information.
+
+=head2 C<close()>
+
+    $response = $e->indices->close(
+        index => 'index' | \@indices    # required
+    );
+
+The C<close()> method closes the specified indices, reducing resource usage
+but allowing them to be reopened later.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>
+    C<master_timeout>,
+    C<timeout>
+
+See the L<close index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html>
+for more information.
+
+=head2 C<open()>
+
+    $response = $e->indices->open(
+        index => 'index' | \@indices    # required
+    );
+
+The C<open()> method opens closed indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>
+    C<master_timeout>,
+    C<timeout>
+
+See the L<open index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html>
+for more information.
+
+=head2 C<clear_cache()>
+
+    $response = $e->indices->clear_cache(
+        index => 'index' | \@indices        # optional
+    );
+
+The C<clear_cache()> method is used to clear the in-memory filter, fielddata,
+or id cache for the specified indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<fielddata>,
+    C<fields>,
+    C<filter>,
+    C<filter_cache>,
+    C<id>,
+    C<id_cache>,
+    C<ignore_unavailable>,
+    C<query_cache>,
+    C<recycler>
+
+See the L<clear_cache docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-clearcache.html>
+for more information.
+
+=head2 C<refresh()>
+
+    $response = $e->indices->refresh(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<refresh()> method refreshes the specified indices (or all indices),
+allowing recent changes to become visible to search. This process normally
+happens automatically once every second by default.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<force>,
+    C<ignore_unavailable>
+
+See the L<refresh index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html>
+for more information.
+
+=head2 C<flush()>
+
+    $response = $e->indices->flush(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<flush()> method causes the specified indices (or all indices) to be
+written to disk with an C<fsync>, and clears out the transaction log.
+This process normally happens automatically.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<force>,
+    C<ignore_unavailable>,
+    C<wait_if_ongoing>
+
+See the L<flush index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-flush.html>
+for more information.
+
+=head2 C<optimize()>
+
+    $response = $e->indices->optimize(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<optimize()> method rewrites all the data in an index into at most
+C<max_num_segments>.  This is a very heavy operation and should only be run
+with care, and only on indices that are no longer being updated.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<flush>,
+    C<ignore_unavailable>,
+    C<max_num_segments>,
+    C<only_expunge_deletes>,
+    C<wait_for_merge>
+
+See the L<optimize index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-optimize.html>
+for more information.
+
+=head2 C<get_upgrade()>
+
+    $response = $e->indices->get_upgrade(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<get_upgrade()> method returns information about which indices need to be
+upgraded, which can be done with the C<upgrade()> method.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<human>,
+    C<ignore_unavailable>
+
+See the L<upgrade docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-upgrade.html>
+for more information.
+
+=head2 C<upgrade()>
+
+    $response = $e->indices->upgrade(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<upgrade()> method upgrades all segments in the specified indices to the latest format.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<only_ancient_segments>,
+    C<wait_for_completion>
+
+See the L<upgrade docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-upgrade.html>
+for more information.
+
+=head1 MAPPING METHODS
+
+=head2 C<put_mapping()>
+
+    $response = $e->indices->put_mapping(
+        index => 'index' | \@indices    # optional,
+        type  => 'type',                # required
+
+        body  => { mapping }            # required
+    )
+
+The C<put_mapping()> method is used to create or update a type
+mapping on an existing index.  Mapping updates are allowed to add new
+fields, but not to overwrite or change existing fields.
+
+For instance:
+
+    $response = $e->indices->put_mapping(
+        index   => 'users',
+        type    => 'user',
+        body    => {
+            user => {
+                properties => {
+                    name => { type => 'string'  },
+                    age  => { type => 'integer' }
+                }
+            }
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<ignore_conflicts>,
+    C<master_timeout>,
+    C<timeout>
+
+See the L<put_mapping docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html>
+for more information.
+
+=head2 C<get_mapping()>
+
+    $result = $e->indices->get_mapping(
+        index => 'index' | \@indices    # optional,
+        type  => 'type'  | \@types      # optional
+    );
+
+The C<get_mapping()> method returns the type definitions for one, more or
+all types in one, more or all indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<get_mapping docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-mapping.html>
+for more information.
+
+=head2 C<get_field_mapping()>
+
+    $result = $e->indices->get_field_mapping(
+        index => 'index' | \@indices    # optional,
+        type  => 'type'  | \@types      # optional,
+        field => 'field' | \@fields     # required
+
+        include_defaults => 0 | 1
+    );
+
+The C<get_field_mapping()> method returns the field definitions for one, more or
+all fields in one, more or all types and indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<include_defaults>,
+    C<local>
+
+See the L<get_mapping docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html>
+for more information.
+
+=head2 C<exists_type()>
+
+    $bool = $e->indices->exists_type(
+        index => 'index' | \@indices    # required,
+        type  => 'type'  | \@types      # required
+    );
+
+The C<exists_type()> method checks for the existence of all specified types
+in all specified indices, and returns C<1> or the empty string.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<exists_type docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-types-exists.html>
+for more information.
+
+=head1 ALIAS METHODS
+
+=head2 C<update_aliases()>
+
+    $response = $e->indices->update_aliases(
+        body => { actions }             # required
+    );
+
+The C<update_aliases()> method changes (by adding or removing) multiple
+index aliases atomically. For instance:
+
+    $response = $e->indices->update_aliases(
+        body => {
+            actions => [
+                { add    => { alias => 'current', index => 'logs_2013_09' }},
+                { remove => { alias => 'current', index => 'logs_2013_08' }}
+            ]
+        }
+    );
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<update_aliases docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html>
+for more information.
+
+=head2 C<get_aliases()>
+
+    $result = $e->indices->get_aliases(
+        index   => 'index' | \@indices,     # optional
+        alias   => 'alias' | \@aliases      # optional
+    );
+
+The C<get_aliases()> method returns a list of aliases per index for all
+the specified indices.
+
+Query string parameters:
+    C<local>,
+    C<timeout>
+
+See the L<get_aliases docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html>
+for more information.
+
+=head2 C<put_alias()>
+
+    $response = $e->indices->put_alias(
+        index => 'index' | \@indices,       # required
+        name  => 'alias',                   # required
+
+        body  => { alias defn }             # optional
+    );
+
+The C<put_alias()> method creates an index alias. For instance:
+
+    $response = $e->indices->put_alias(
+        index => 'my_index',
+        name  => 'twitter',
+        body => {
+            filter => { term => { user_id => 'twitter' }}
+        }
+    );
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<put_alias docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html>
+for more information.
+
+=head2 C<get_alias()>
+
+    $result = $e->indices->get_alias(
+        index   => 'index' | \@indices,     # optional
+        name    => 'alias' | \@aliases      # optional
+    );
+
+The C<get_alias()> method returns the alias definitions for the specified
+aliases in the specified indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<get_alias docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html>
+for more information.
+
+=head2 C<exists_alias()>
+
+    $bool = $e->indices->exists_alias(
+        index   => 'index' | \@indices,     # optional
+        name    => 'alias' | \@aliases      # optional
+    );
+
+The C<exists_alias()> method returns C<1> or the empty string depending on
+whether the specified aliases exist in the specified indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<exists_alias docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html>
+for more information.
+
+=head2 C<delete_alias()>
+
+    $response = $e->indices->delete_alias(
+        index   => 'index' | \@indices        # required,
+        name    => 'alias' | \@aliases        # required
+    );
+
+The C<delete_alias()> method deletes one or more aliases from one or more
+indices.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<delete_alias docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html>
+for more information.
+
+=head1 SETTINGS METHODS
+
+=head2 C<put_settings()>
+
+    $response = $e->indices->put_settings(
+        index   => 'index' | \@indices      # optional
+
+        body    => { settings }
+    );
+
+The C<put_settings()> method sets the index settings for the specified
+indices or all indices. For instance:
+
+    $response = $e->indices->put_settings(
+        body => {
+            "index.refresh_interval" => -1
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<flat_settings>,
+    C<ignore_unavailable>,
+    C<master_timeout>
+
+See the L<put_settings docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html>
+for more information.
+
+=head2 C<get_settings()>
+
+    $result = $e->indices->get_settings(
+        index   => 'index' | \@indices      # optional
+        name    => 'name'  | \@names        # optional
+    );
+
+The C<get_settings()> method retrieves the index settings for the specified
+indices or all indices.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<flat_settings>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<get_settings docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-settings.html>
+for more information.
+
+=head1 TEMPLATE METHODS
+
+=head2 C<put_template()>
+
+    $response = $e->indices->put_template(
+        name => 'template'                  # required
+        body => { template defn }           # required
+    );
+
+The C<put_template()> method is used to create or update index templates.
+
+Query string parameters:
+    C<create>,
+    C<flat_settings>,
+    C<master_timeout>,
+    C<op_type>,
+    C<order>,
+    C<timeout>,
+    C<version>,
+    C<version_type>
+
+See the L<put_template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html>
+for more information.
+
+=head2 C<get_template()>
+
+    $result = $e->indices->get_template(
+        name  => 'template'                 # optional
+    );
+
+The C<get_template()> method is used to retrieve a named template.
+
+Query string parameters:
+    C<flat_settings>,
+    C<local>,
+    C<master_timeout>
+
+See the L<get_template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html>
+for more information.
+
+=head2 C<exists_template()>
+
+    $result = $e->indices->exists_template(
+        name  => 'template'                 # required
+    );
+
+The C<exists_template()> method is used to check whether the named template exists.
+
+Query string parameters:
+    C<local>,
+    C<master_timeout>
+
+See the L<get_template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html>
+for more information.
+
+=head2 C<delete_template()>
+
+    $response = $e->indices->delete_template(
+        name  => 'template'                 # required
+    );
+
+The C<delete_template()> method is used to delete a named template.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>,
+    C<version>,
+    C<version_type>
+
+See the L<delete_template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html>
+for more information.
+
+=head1 WARMER METHODS
+
+=head2 C<put_warmer()>
+
+    $response = $e->indices->put_warmer(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+        name    => 'warmer',                # required
+
+        body    => { warmer defn }          # required
+    );
+
+The C<put_warmer()> method is used to create or update named warmers which
+are used to I<warm up> new segments in the index before they are exposed
+to user searches.  For instance:
+
+    $response = $e->indices->put_warmer(
+        index   => 'my_index',
+        name    => 'date_field_warmer',
+        body    => {
+            sort => 'date'
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<master_timeout>
+
+See the L<put_warmer docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-warmers.html>
+for more information.
+
+=head2 C<get_warmer()>
+
+    $response = $e->indices->get_warmer(
+        index   => 'index'  | \@indices,    # optional
+        type    => 'type'   | \@types,      # optional
+        name    => 'warmer' | \@warmers,    # optional
+    );
+
+The C<get_warmer()> method is used to retrieve warmers by name.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
+See the L<get_warmer docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-warmers.html>
+for more information.
+
+=head2 C<delete_warmer()>
+
+    $response = $e->indices->get_warmer(
+        index   => 'index'  | \@indices,    # required
+        name    => 'warmer' | \@warmers,    # required
+    );
+
+The C<delete_warmer()> method is used to delete warmers by name.
+
+Query string parameters:
+    C<master_timeout>
+
+See the L<delete_warmer docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-warmers.html>
+for more information.
+
+=head1 STATS METHODS
+
+=head2 C<stats()>
+
+    $result = $e->indices->stats(
+        index   => 'index'  | \@indices      # optional
+        metric  => 'metric' | \@metrics      # optional
+    );
+
+The C<stats()> method returns statistical information about one, more or all
+indices. By default it returns all metrics, but you can limit which metrics
+are returned by specifying the C<metric>.
+
+Allowed metrics are:
+    C<_all>,
+    C<completion>
+    C<docs>,
+    C<fielddata>,
+    C<filter_cache>,
+    C<flush>,
+    C<get>,
+    C<id_cache>,
+    C<indexing>,
+    C<merge>,
+    C<percolate>,
+    C<query_cache>,
+    C<refresh>,
+    C<search>,
+    C<segments>,
+    C<store>,
+    C<warmer>
+
+Query string parameters:
+    C<completion_fields>,
+    C<fielddata_fields>,
+    C<fields>,
+    C<groups>,
+    C<human>,
+    C<level>,
+    C<types>
+
+See the L<stats docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-stats.html>
+for more information.
+
+=head2 C<recovery()>
+
+    $result = $e->indices->recovery(
+        index   => 'index' | \@indices      # optional
+    );
+
+Provides insight into on-going shard recoveries.
+
+Query string parameters:
+    C<active_only>,
+    C<detailed>,
+    C<human>
+
+See the L<recovery docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-recovery.html>
+for more information.
+
+=head2 C<segments()>
+
+    $result = $e->indices->segments(
+        index   => 'index' | \@indices      # optional
+    );
+
+The C<segments()> method is used to return information about the segments
+that an index contains.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<human>,
+    C<ignore_unavailable>
+
+See the L<segments docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-segments.html>
+for more information.
+
+=head1 QUERY AND ANALYSIS METHODS
+
+=head2 C<analyze()>
+
+    $result = $e->indices->analyze(
+        index   => 'index'                  # optional,
+        body    => 'text to analyze'
+    );
+
+The C<analyze()> method passes the text in the C<body> through the specified
+C<analyzer>, C<tokenizer> or token C<filter> - which may be global, or associated
+with a particular index or field - and returns the tokens.  Very useful
+for debugging analyzer configurations.
+
+Query string parameters:
+    C<analyzer>,
+    C<char_filters>,
+    C<field>,
+    C<filters>,
+    C<format>,
+    C<prefer_local>,
+    C<text>,
+    C<tokenizer>
+
+See the L<analyze docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-analyze.html>
+for more information.
+
+=head2 C<validate_query()>
+
+    $result = $e->indices->validate_query(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+
+        body    => { query }
+    );
+
+The C<validate_query()> method accepts a query in the C<body> and checks
+whether the query is valid or not.  Most useful when C<explain> is set
+to C<true>, in which case it includes an execution plan in the output.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<analyze_wildcard>,
+    C<analyzer>,
+    C<default_operator>,
+    C<df>,
+    C<explain>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<lenient>,
+    C<lowercase_expanded_terms>
+    C<q>
+
+See the L<validate_query docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/indices-validate.html>
+for more information.
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: A client for running index-level requests
+
@@ -0,0 +1,167 @@
+package Search::Elasticsearch::Client::2_0::Direct::Nodes;
+$Search::Elasticsearch::Client::2_0::Direct::Nodes::VERSION = '1.20';
+use Moo;
+with 'Search::Elasticsearch::Role::API::2_0';
+with 'Search::Elasticsearch::Role::Client::Direct';
+__PACKAGE__->_install_api('nodes');
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Client::2_0::Direct::Nodes - A client for running node-level requests
+
+=head1 VERSION
+
+version 1.20
+
+=head1 DESCRIPTION
+
+This module provides methods to make node-level requests, such as
+retrieving node info and stats.
+
+It does L<Search::Elasticsearch::Role::Client::Direct>.
+
+=head1 METHODS
+
+=head2 C<info()>
+
+    $response = $e->nodes->info(
+        node_id => $node_id | \@node_ids       # optional
+        metric  => $metric  | \@metrics        # optional
+    );
+
+The C<info()> method returns static information about the nodes in the
+cluster, such as the configured maximum number of file handles, the maximum
+configured heap size or the threadpool settings.
+
+Allowed metrics are:
+    C<http>,
+    C<jvm>,
+    C<network>,
+    C<os>,
+    C<plugin>,
+    C<process>,
+    C<settings>,
+    C<thread_pool>,
+    C<transport>
+
+Query string parameters:
+    C<flat_settings>,
+    C<human>
+
+See the L<node_info docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-nodes-info.html>
+for more information.
+
+=head2 C<stats()>
+
+    $response = $e->nodes->stats(
+        node_id      => $node_id    | \@node_ids       # optional
+        metric       => $metric     | \@metrics        # optional
+        index_metric => $ind_metric | \@ind_metrics    # optional
+    );
+
+The C<stats()> method returns statistics about the nodes in the
+cluster, such as the number of currently open file handles, the current
+heap memory usage or the current number of threads in use.
+
+Stats can be returned for all nodes, or limited to particular nodes
+with the C<node_id> parameter. By default all metrics are returned, but
+these can be limited to those specified in the C<metric> parameter.
+
+Allowed metrics are:
+    C<_all>,
+    C<breaker>,
+    C<fs>,
+    C<http>,
+    C<indices>,
+    C<jvm>,
+    C<network>,
+    C<os>,
+    C<process>,
+    C<thread_pool>,
+    C<transport>
+
+If the C<indices> metric (or C<_all>) is specified, then
+L<indices_stats|Search::Elasticsearch::Client::2_0::Direct::Indices/indices_stats()>
+information is returned on a per-node basis. Which indices stats are
+returned can be controlled with the C<index_metric> parameter:
+
+    $response = $e->cluster->node_stats(
+        node_id       => 'node_1',
+        metric        => ['indices','fs']
+        index_metric  => ['docs','fielddata']
+    );
+
+Allowed index metrics are:
+    C<_all>,
+    C<completion>
+    C<docs>,
+    C<fielddata>,
+    C<filter_cache>,
+    C<flush>,
+    C<get>,
+    C<id_cache>,
+    C<indexing>,
+    C<merge>,
+    C<percolate>,
+    C<query_cache>,
+    C<refresh>,
+    C<search>,
+    C<segments>,
+    C<store>,
+    C<warmer>
+
+Query string parameters:
+    C<completion_fields>,
+    C<fielddata_fields>,
+    C<fields>,
+    C<groups>,
+    C<human>,
+    C<level>,
+    C<types>
+
+See the L<node_stats docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-nodes-stats.html>
+for more information.
+
+=head2 C<hot_threads()>
+
+    $response = $e->nodes->hot_threads(
+        node_id => $node_id | \@node_ids       # optional
+    )
+
+The C<hot_threads()> method is a useful tool for diagnosing busy nodes. It
+takes a snapshot of which threads are consuming the most CPU.
+
+Query string parameters:
+    C<ignore_idle_threads>,
+    C<interval>,
+    C<snapshots>,
+    C<threads>,
+    C<type>
+
+See the L<hot_threads docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-nodes-hot-threads.html>
+for more information.
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: A client for running node-level requests
+
@@ -0,0 +1,190 @@
+package Search::Elasticsearch::Client::2_0::Direct::Snapshot;
+$Search::Elasticsearch::Client::2_0::Direct::Snapshot::VERSION = '1.20';
+use Moo;
+with 'Search::Elasticsearch::Role::API::2_0';
+with 'Search::Elasticsearch::Role::Client::Direct';
+__PACKAGE__->_install_api('snapshot');
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Client::2_0::Direct::Snapshot - A client for managing snapshot/restore
+
+=head1 VERSION
+
+version 1.20
+
+=head1 DESCRIPTION
+
+This module provides methods to manage snapshot/restore, or backups.
+It can create, get and delete configured backup repositories, and
+create, get, delete and restore snapshots of your cluster or indices.
+
+It does L<Search::Elasticsearch::Role::Client::Direct>.
+
+=head1 METHODS
+
+=head2 C<create_repository()>
+
+    $e->snapshot->create_repository(
+        repository  => 'repository',        # required
+        body        => { defn }             # required
+    );
+
+Create a repository for backups.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>,
+    C<verify>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<get_repository()>
+
+    $e->snapshot->get_repository(
+        repository  => 'repository' | \@repositories    # optional
+    );
+
+Retrieve existing repositories.
+
+Query string parameters:
+    C<local>,
+    C<master_timeout>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<verify_repository()>
+
+    $e->snapshot->verify_repository(
+        repository  => 'repository' # required
+    );
+
+Verify existing repository.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<delete_repository()>
+
+    $e->snapshot->delete_repository(
+        repository  => 'repository' | \@repositories    # required
+    );
+
+Delete repositories by name.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<create()>
+
+    $e->snapshot->create(
+        repository  => 'repository',     # required
+        snapshot    => 'snapshot',       # required,
+
+        body        => { snapshot defn } # optional
+    );
+
+Create a snapshot of the whole cluster or individual indices in the named
+repository.
+
+Query string parameters:
+    C<master_timeout>,
+    C<wait_for_completion>
+
+=head2 C<get()>
+
+    $e->snapshot->get(
+        repository  => 'repository'                   # required
+        snapshot    => 'snapshot'   | \@snapshots     # required
+    );
+
+Retrieve snapshots in the named repository.
+
+Query string parameters:
+    C<master_timeout>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<delete()>
+
+    $e->snapshot->delete(
+        repository  => 'repository',              # required
+        snapshot    => 'snapshot'                 # required
+    );
+
+Delete snapshot in the named repository.
+
+Query string parameters:
+    C<master_timeout>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<restore()>
+
+    $e->snapshot->restore(
+        repository  => 'repository',              # required
+        snapshot    => 'snapshot'                 # required
+
+        body        => { what to restore }        # optional
+    );
+
+Restore a named snapshot.
+
+Query string parameters:
+    C<master_timeout>,
+    C<wait_for_completion>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head2 C<status()>
+
+    $result = $e->snapshot->status(
+        repository  => 'repository',              # optional
+        snapshot    => 'snapshot' | \@snapshots   # optional
+    );
+
+Returns status information about the specified snapshots.
+
+Query string parameters:
+    C<master_timeout>
+
+See the L<"snapshot/restore docs"|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: A client for managing snapshot/restore
+
@@ -0,0 +1,1357 @@
+package Search::Elasticsearch::Client::2_0::Direct;
+$Search::Elasticsearch::Client::2_0::Direct::VERSION = '1.20';
+sub _namespace {__PACKAGE__}
+
+use Moo;
+with 'Search::Elasticsearch::Role::API::2_0';
+with 'Search::Elasticsearch::Role::Client::Direct';
+with 'Search::Elasticsearch::Role::Client::Direct::Main';
+
+__PACKAGE__->_install_api('');
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Client::2_0::Direct - Thin client with full support for Elasticsearch 2.x APIs
+
+=head1 VERSION
+
+version 1.20
+
+=head1 SYNOPSIS
+
+Create a client:
+
+    use Search::Elasticsearch;
+    my $e = Search::Elasticsearch->new(
+        client => '2_0::Direct'
+    );
+
+Index a doc:
+
+    $e->index(
+        index   => 'my_index',
+        type    => 'blog_post',
+        id      => 123,
+        body    => {
+            title   => "Elasticsearch clients",
+            content => "Interesting content...",
+            date    => "2013-09-23"
+        }
+    );
+
+Get a doc:
+
+    $e->get(
+        index   => 'my_index',
+        type    => 'my_type',
+        id      => 123
+    );
+
+Search for docs:
+
+    $results = $e->search(
+        index   => 'my_index',
+        body    => {
+            query => {
+                match => {
+                    title => "elasticsearch"
+                }
+            }
+        }
+    );
+
+Index-level requests:
+
+    $e->indices->create( index => 'my_index' );
+    $e->indices->delete( index => 'my_index' )
+
+Cluster-level requests:
+
+    $health = $e->cluster->health;
+
+Node-level requests:
+
+    $info  = $e->nodes->info;
+    $stats = $e->nodes->stats;
+
+Snapshot and restore:
+
+    $e->snapshot->create_repository(
+        repository => 'my_backups',
+        type       => 'fs',
+        settings   => {
+            location => '/mnt/backups'
+        }
+    );
+
+    $e->snapshot->create(
+        repository => 'my_backups',
+        snapshot   => 'backup_2014'
+    );
+
+`cat` debugging:
+
+    say $e->cat->allocation;
+    say $e->cat->health;
+
+=head1 DESCRIPTION
+
+The L<Search::Elasticsearch::Client::2_0::Direct> class provides a client
+compatible with the as-yet-unreleased version 2.x of Elasticsearch.
+
+    $e = Search::Elasticsearch->new(
+        client => "2_0::Direct"
+    );
+
+It is intended to be as close as possible to the native REST API that
+Elasticsearch uses, so that it is easy to translate the
+L<Elasticsearch reference documentation|http://www.elasticsearch/guide>
+for an API to the equivalent in this client.
+
+This class provides the methods for L<document CRUD|/DOCUMENT CRUD METHODS>,
+L<bulk document CRUD|/BULK DOCUMENT CRUD METHODS> and L<search|/SEARCH METHODS>.
+It also provides access to clients for managing L<indices|/indices()>
+and the L<cluster|/cluster()>.
+
+=head1 BACKWARDS COMPATIBILITY AND ELASTICSEARCH 1.x and 0.90.x
+
+This version of the client supports the Elasticsearch 2.0 branch,
+which is not backwards compatible with the 1.x and 0.90 branch.
+
+If you need to talk to a version of Elasticsearch before 2.0.0,
+please use L<Search::Elasticsearch::Client::1_0::Direct>
+or L<Search::Elasticsearch::Client::0_90::Direct> as follows:
+
+    $es = Search::Elasticsearch->new(
+        client => '1_0::Direct'  # or '0_90::Direct'
+    );
+
+=head1 CONVENTIONS
+
+=head2 Parameter passing
+
+Parameters can be passed to any request method as a list or as a hash
+reference. The following two statements are equivalent:
+
+    $e->search( size => 10 );
+    $e->search({size => 10});
+
+=head2 Path parameters
+
+Any values that should be included in the URL path, eg C</{index}/{type}>
+should be passed as top level parameters:
+
+    $e->search( index => 'my_index', type => 'my_type' );
+
+Alternatively, you can specify a C<path> parameter directly:
+
+    $e->search( path => '/my_index/my_type' );
+
+=head2 Query-string parameters
+
+Any values that should be included in the query string should be passed
+as top level parameters:
+
+    $e->search( size => 10 );
+
+If you pass in a C<\%params> hash, then it will be included in the
+query string parameters without any error checking. The following:
+
+    $e->search( size => 10, params => { from => 5, size => 5 })
+
+would result in this query string:
+
+    ?from=5&size=10
+
+=head2 Body parameter
+
+The request body should be passed in the C<body> key:
+
+    $e->search(
+        body => {
+            query => {...}
+        }
+    );
+
+The body can also be a UTF8-decoded string, which will be converted into
+UTF-8 bytes and passed as is:
+
+    $e->indices->analyze( body => "The quick brown fox");
+
+=head2 Ignore parameter
+
+Normally, any HTTP status code outside the 200-299 range will result in
+an error being thrown.  To suppress these errors, you can specify which
+status codes to ignore in the C<ignore> parameter.
+
+    $e->indices->delete(
+        index  => 'my_index',
+        ignore => 404
+    );
+
+This is most useful for
+L<Missing|Search::Elasticsearch::Error/Search::Elasticsearch::Error::Missing> errors, which
+are triggered by a C<404> status code when some requested resource does
+not exist.
+
+Multiple error codes can be specified with an array:
+
+    $e->indices->delete(
+        index  => 'my_index',
+        ignore => [404,409]
+    );
+
+=head1 CONFIGURATION
+
+=head2 C<bulk_helper_class>
+
+The class to use for the L</bulk_helper()> method. Defaults to
+L<Search::Elasticsearch::Bulk>.
+
+=head2 C<scroll_helper_class>
+
+The class to use for the L</scroll_helper()> method. Defaults to
+L<Search::Elasticsearch::Scroll>.
+
+=head1 GENERAL METHODS
+
+=head2 C<info()>
+
+    $info = $e->info
+
+Returns information about the version of Elasticsearch that the responding node
+is running.
+
+=head2 C<ping()>
+
+    $e->ping
+
+Pings a node in the cluster and returns C<1> if it receives a C<200>
+response, otherwise it throws an error.
+
+=head2 C<indices()>
+
+    $indices_client = $e->indices;
+
+Returns an L<Search::Elasticsearch::Client::2_0::Direct::Indices> object which can be used
+for managing indices, eg creating, deleting indices, managing mapping,
+index settings etc.
+
+=head2 C<cluster()>
+
+    $cluster_client = $e->cluster;
+
+Returns an L<Search::Elasticsearch::Client::2_0::Direct::Cluster> object which can be used
+for managing the cluster, eg cluster-wide settings and cluster health.
+
+=head2 C<nodes()>
+
+    $node_client = $e->nodes;
+
+Returns an L<Search::Elasticsearch::Client::2_0::Direct::Nodes> object which can be used
+to retrieve node info and stats.
+
+=head2 C<snapshot()>
+
+    $snapshot_client = $e->snapshot;
+
+Returns an L<Search::Elasticsearch::Client::2_0::Direct::Snapshot> object which
+is used for managing backup repositories and creating and restoring
+snapshots.
+
+=head2 C<cat()>
+
+    $cat_client = $e->cat;
+
+Returns an L<Search::Elasticsearch::Client::2_0::Direct::Cat> object which can be used
+to retrieve simple to read text info for debugging and monitoring an
+Elasticsearch cluster.
+
+=head1 DOCUMENT CRUD METHODS
+
+These methods allow you to perform create, index, update and delete requests
+for single documents:
+
+=head2 C<index()>
+
+    $response = $e->index(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # optional, otherwise auto-generated
+
+        body    => { document }         # required
+    );
+
+The C<index()> method is used to index a new document or to reindex
+an existing document.
+
+Query string parameters:
+    C<consistency>,
+    C<op_type>,
+    C<parent>,
+    C<refresh>,
+    C<routing>,
+    C<timeout>,
+    C<timestamp>,
+    C<ttl>,
+    C<version>,
+    C<version_type>
+
+See the L<index docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html>
+for more information.
+
+=head2 C<create()>
+
+    $response = $e->create(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # optional, otherwise auto-generated
+
+        body    => { document }         # required
+    );
+
+The C<create()> method works exactly like the L</index()> method, except
+that it will throw a C<Conflict> error if a document with the same
+C<index>, C<type> and C<id> already exists.
+
+Query string parameters:
+    C<consistency>,
+    C<op_type>,
+    C<parent>,
+    C<refresh>,
+    C<routing>,
+    C<timeout>,
+    C<timestamp>,
+    C<ttl>,
+    C<version>,
+    C<version_type>
+
+See the L<create docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-create.html>
+for more information.
+
+=head2 C<get()>
+
+    $response = $e->get(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # required
+    );
+
+The C<get()> method will retrieve the document with the specified
+C<index>, C<type> and C<id>, or will throw a C<Missing> error.
+
+Query string parameters:
+    C<_source>,
+    C<_source_exclude>,
+    C<_source_include>,
+    C<fields>,
+    C<parent>,
+    C<preference>,
+    C<realtime>,
+    C<refresh>,
+    C<routing>,
+    C<version>,
+    C<version_type>
+
+See the L<get docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-get.html>
+for more information.
+
+=head2 C<get_source()>
+
+    $response = $e->get_source(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # required
+    );
+
+The C<get_source()> method works just like the L</get()> method except that
+it returns just the C<_source> field (the value of the C<body> parameter
+in the L</index()> method) instead of returning the C<_source> field
+plus the document metadata, ie the C<_index>, C<_type> etc.
+
+Query string parameters:
+    C<_source>,
+    C<_source_exclude>,
+    C<_source_include>,
+    C<parent>,
+    C<preference>,
+    C<realtime>,
+    C<refresh>,
+    C<routing>,
+    C<version>,
+    C<version_type>
+
+See the L<get_source docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-get.html>
+for more information.
+
+=head2 C<exists()>
+
+    $response = $e->exists(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # required
+    );
+
+The C<exists()> method returns C<1> if a document with the specified
+C<index>, C<type> and C<id> exists, or an empty string if it doesn't.
+
+Query string parameters:
+    C<parent>,
+    C<preference>,
+    C<realtime>,
+    C<refresh>,
+    C<routing>
+
+See the L<exists docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-get.html>
+for more information.
+
+=head2 C<delete()>
+
+    $response = $e->delete(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # required
+    );
+
+The C<delete()> method will delete the document with the specified
+C<index>, C<type> and C<id>, or will throw a C<Missing> error.
+
+Query string parameters:
+    C<consistency>,
+    C<parent>,
+    C<refresh>,
+    C<routing>,
+    C<timeout>,
+    C<version>,
+    C<version_type>
+
+See the L<delete docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete.html>
+for more information.
+
+=head2 C<update()>
+
+    $response = $e->update(
+        index   => 'index_name',        # required
+        type    => 'type_name',         # required
+        id      => 'doc_id',            # required
+
+        body    => { update }           # required
+    );
+
+The C<update()> method updates a document with the corresponding
+C<index>, C<type> and C<id> if it exists. Updates can be performed either by:
+
+=over
+
+=item * providing a partial document to be merged in to the existing document:
+
+    $response = $e->update(
+        ...,
+        body => {
+            doc => { new_field => 'new_value'},
+        }
+    );
+
+=item * or with a script:
+
+    $response = $e->update(
+        ...,
+        body => {
+            script => "ctx._source.counter += incr",
+            params => { incr => 5 }
+        }
+    );
+
+=back
+
+Query string parameters:
+    C<consistency>,
+    C<fields>,
+    C<lang>,
+    C<parent>,
+    C<realtime>,
+    C<refresh>,
+    C<retry_on_conflict>,
+    C<routing>,
+    C<script>,
+    C<script_id>,
+    C<scripted_upsert>,
+    C<timeout>,
+    C<timestamp>,
+    C<ttl>,
+    C<version>,
+    C<version_type>
+
+See the L<update docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html>
+for more information.
+
+=head2 C<termvectors()>
+
+    $results = $e->termvectors(
+        index   => $index,          # required
+        type    => $type,           # required
+
+        id      => $id,             # optional
+        body    => {...}            # optional
+    )
+
+The C<termvectors()> method retrieves term and field statistics, positions,
+offsets and payloads for the specified document, assuming that termvectors
+have been enabled.
+
+Query string parameters:
+    C<dfs>,
+    C<field_statistics>,
+    C<fields>,
+    C<offsets>,
+    C<parent>,
+    C<payloads>,
+    C<positions>,
+    C<preference>,
+    C<realtime>,
+    C<routing>,
+    C<term_statistics>,
+    C<version>,
+    C<version_type>
+
+See the L<termvector docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-termvectors.html>
+for more information.
+
+=head1 BULK DOCUMENT CRUD METHODS
+
+The bulk document CRUD methods are used for running multiple CRUD actions
+within a single request.  By reducing the number of network requests
+that need to be made, bulk requests greatly improve performance.
+
+=head2 C<bulk()>
+
+    $response = $e->bulk(
+        index   => 'index_name',        # required if type specified
+        type    => 'type_name',         # optional
+
+        body    => [ actions ]          # required
+    );
+
+See L<Search::Elasticsearch::Bulk> and L</bulk_helper()> for a helper module that makes
+bulk indexing simpler to use.
+
+The C<bulk()> method can perform multiple L</index()>, L</create()>,
+L</delete()> or L</update()> actions with a single request. The C<body>
+parameter expects an array containing the list of actions to perform.
+
+An I<action> consists of an initial metadata hash ref containing the action
+type, plus the associated metadata, eg :
+
+    { delete => { _index => 'index', _type => 'type', _id => 123 }}
+
+The C<index> and C<create> actions then expect a hashref containing
+the document itself:
+
+    { create => { _index => 'index', _type => 'type', _id => 123 }},
+    { title => "A newly created document" }
+
+And the C<update> action expects a hashref containing the update commands,
+eg:
+
+    { update => { _index => 'index', _type => 'type', _id => 123 }},
+    { script => "ctx._source.counter+=1" }
+
+Each action can include the same parameters that you would pass to
+the equivalent L</index()>, L</create()>, L</delete()> or L</update()>
+request, except that C<_index>, C<_type> and C<_id> must be specified with
+the preceding underscore. All other parameters can be specified with or
+without the underscore.
+
+For instance:
+
+    $response = $e->bulk(
+        index   => 'index_name',        # default index name
+        type    => 'type_name',         # default type name
+        body    => [
+
+            # create action
+            { create => {
+                _index => 'not_the_default_index',
+                _type  => 'not_the_default_type',
+                _id    => 123
+            }},
+            { title => 'Foo' },
+
+            # index action
+            { index => { _id => 124 }},
+            { title => 'Foo' },
+
+            # delete action
+            { delete => { _id => 125 }},
+
+            # update action
+            { update => { _id => 126 }},
+            { script => "ctx._source.counter+1" }
+        ]
+    );
+
+Each action is performed separately. One failed action will not
+cause the others to fail as well.
+
+Query string parameters:
+    C<consistency>,
+    C<refresh>,
+    C<timeout>
+
+See the L<bulk docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html>
+for more information.
+
+=head2 C<bulk_helper()>
+
+    $bulk_helper = $e->bulk_helper( @args );
+
+Returns a new instance of the class specified in the L</bulk_helper_class>,
+which defaults to L<Search::Elasticsearch::Bulk>.
+
+=head2 C<mget()>
+
+    $results = $e->mget(
+        index   => 'default_index',     # optional, required when type specified
+        type    => 'default_type',      # optional
+
+        body    => { docs or ids }      # required
+    );
+
+The C<mget()> method will retrieve multiple documents with a single request.
+The C<body> consists of an array of documents to retrieve:
+
+    $results = $e->mget(
+        index   => 'default_index',
+        type    => 'default_type',
+        body    => {
+            docs => [
+                { _id => 1},
+                { _id => 2, _type => 'not_the_default_type' }
+            ]
+        }
+    );
+
+You can also pass any of the other parameters that the L</get()> request
+accepts.
+
+If you have specified an C<index> and C<type>, you can just include the
+C<ids> of the documents to retrieve:
+
+    $results = $e->mget(
+        index   => 'default_index',
+        type    => 'default_type',
+        body    => {
+            ids => [ 1, 2, 3]
+        }
+    );
+
+Query string parameters:
+    C<_source>,
+    C<_source_exclude>,
+    C<_source_include>,
+    C<fields>,
+    C<preference>,
+    C<realtime>,
+    C<refresh>
+
+See the L<mget docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-get.html>
+for more information.
+
+=head2 C<mtermvectors()>
+
+    $results = $e->mtermvectors(
+        index   => $index,          # required if type specified
+        type    => $type,           # optional
+
+        body    => { }              # optional
+    )
+
+Runs multiple L</termvector()> requests in a single request, eg:
+
+    $results = $e->mtermvectors(
+        index   => 'test',
+        body    => {
+            docs => [
+                { _type => 'test', _id => 1, fields => ['text'] },
+                { _type => 'test', _id => 2, payloads => 1 },
+            ]
+        }
+    );
+
+Query string parameters:
+    C<field_statistics>,
+    C<fields>,
+    C<ids>,
+    C<offsets>,
+    C<parent>,
+    C<payloads>,
+    C<positions>,
+    C<preference>,
+    C<realtime>,
+    C<routing>,
+    C<term_statistics>,
+    C<version>,
+    C<version_type>
+
+See the L<mtermvectors docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-termvectors.html>
+for more information.
+
+=head1 SEARCH METHODS
+
+The search methods are used for querying documents in one, more or all indices
+and of one, more or all types:
+
+=head2 C<search()>
+
+    $results = $e->search(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+
+        body    => { search params }        # optional
+    );
+
+The C<search()> method searches for matching documents in one or more
+indices.  It is just as easy to search a single index as it is to search
+all the indices in your cluster.  It can also return
+L<aggregations|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html>
+L<highlighted snippets|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-highlighting.html>
+and L<did-you-mean|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-phrase.html>
+or L<search-as-you-type|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html>
+suggestions.
+
+The I<lite> L<version of search|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html>
+allows you to specify a query string in the C<q> parameter, using the
+Lucene query string syntax:
+
+    $results = $e->search( q => 'title:(elasticsearch clients)');
+
+However, the preferred way to search is by using the
+L<Query DSL|http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html>
+to create a query, and passing that C<query> in the
+L<request body|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html>:
+
+    $results = $e->search(
+        body => {
+            query => {
+                match => { title => 'Elasticsearch clients'}
+            }
+        }
+    );
+
+Query string parameters:
+    C<_source>,
+    C<_source_exclude>,
+    C<_source_include>,
+    C<allow_no_indices>,
+    C<analyze_wildcard>,
+    C<analyzer>,
+    C<default_operator>,
+    C<df>,
+    C<expand_wildcards>,
+    C<explain>,
+    C<fielddata_fields>,
+    C<fields>,
+    C<from>,
+    C<ignore_unavailable>,
+    C<lenient>,
+    C<lowercase_expanded_terms>,
+    C<preference>,
+    C<q>,
+    C<query_cache>,
+    C<routing>,
+    C<scroll>,
+    C<search_type>,
+    C<size>,
+    C<sort>,
+    C<stats>,
+    C<suggest_field>,
+    C<suggest_mode>,
+    C<suggest_size>,
+    C<suggest_text>,
+    C<terminate_after>,
+    C<timeout>,
+    C<track_scores>,
+    C<version>
+
+See the L<search reference|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html>
+for more information.
+
+Also see L<Search::Elasticsearch::Transport/send_get_body_as>.
+
+=head2 C<search_exists()>
+
+The C<search_exists()> method is a quick version of search which can be
+used to find out whether there are matching search results or not.
+It doesn't return any results itself.
+
+    $results = $e->search_exists(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+
+        body    => { search params }        # optional
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<analyze_wildcard>,
+    C<analyzer>,
+    C<default_operator>,
+    C<df>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<lenient>,
+    C<lowercase_expanded_terms>
+    C<min_score>,
+    C<preference>,
+    C<q>,
+    C<routing>
+
+See the L<search exists reference|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-exists.html>
+for more information.
+
+=head2 C<count()>
+
+    $results = $e->count(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+
+        body    => { query }                # optional
+    )
+
+The C<count()> method returns the total count of all documents matching the
+query:
+
+    $results = $e->count(
+        body => {
+            query => {
+                match => { title => 'Elasticsearch clients' }
+            }
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<analyze_wildcard>,
+    C<analyzer>,
+    C<default_operator>,
+    C<df>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<lenient>,
+    C<lowercase_expanded_terms>
+    C<min_score>,
+    C<preference>,
+    C<q>,
+    C<routing>
+
+See the L<count docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-count.html>
+for more information.
+
+=head2 C<search_template()>
+
+    $results = $e->search_template(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+
+        body    => { search params }        # optional
+    );
+
+Perform a search by specifying a template (either predefined or defined
+within the C<body>) and parameters to use with the template, eg:
+
+    $results = $e->search_template(
+        template => {
+            query => {
+                match => {
+                    "{{my_field}}" => "{{my_value}}"
+                }
+            },
+            size => "{{my_size}}"
+        },
+        params => {
+            my_field => 'foo',
+            my_value => 'bar',
+            my_size  => 5
+        }
+    );
+
+See the L<search template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html>
+for more information.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<preference>,
+    C<scroll>,
+    C<search_type>
+
+=head2 C<scroll()>
+
+    $results = $e->scroll(
+        scroll      => '1m',
+        scroll_id   => $id
+    );
+
+When a L</search()> has been performed with the
+C<scroll> parameter, the C<scroll()>
+method allows you to keep pulling more results until the results
+are exhausted.
+
+B<NOTE:> you will almost always want to set the
+C<search_type> to C<scan> in your
+original C<search()> request.
+
+See L</scroll_helper()> and L<Search::Elasticsearch::Scroll> for a helper utility
+which makes managing scroll requests much easier.
+
+Query string parameters:
+    C<scroll>,
+    C<scroll_id>
+
+See the L<scroll docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-scroll.html>
+and the L<search_type docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search.html/search-request-search-type.html>
+for more information.
+
+=head2 C<clear_scroll()>
+
+    $response = $e->clear_scroll(
+        scroll_id => $id | \@ids    # required
+    );
+
+Or
+
+    $response = $e->clear_scroll(
+        body => $id
+    );
+
+The C<clear_scroll()> method can clear unfinished scroll requests, freeing
+up resources on the server.
+
+=head2 C<scroll_helper()>
+
+    $scroll_helper = $e->scroll_helper( @args );
+
+Returns a new instance of the class specified in the L</scroll_helper_class>,
+which defaults to L<Search::Elasticsearch::Scroll>.
+
+=head2 C<msearch()>
+
+    $results = $e->msearch(
+        index   => 'default_index' | \@indices,     # optional
+        type    => 'default_type'  | \@types,       # optional
+
+        body    => [ searches ]                     # required
+    );
+
+The C<msearch()> method allows you to perform multiple searches in a single
+request.  Similar to the L</bulk()> request, each search request in the
+C<body> consists of two hashes: the metadata hash then the search request
+hash (the same data that you'd specify in the C<body> of a L</search()>
+request).  For instance:
+
+    $results = $e->msearch(
+        index   => 'default_index',
+        type    => ['default_type_1', 'default_type_2'],
+        body => [
+            # uses defaults
+            {},
+            { query => { match_all => {} }},
+
+            # uses a custom index
+            { index => 'not_the_default_index' },
+            { query => { match_all => {} }}
+        ]
+    );
+
+Query string parameters:
+    C<search_type>
+
+See the L<msearch docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-multi-search.html>
+for more information.
+
+=head2 C<explain()>
+
+    $response = $e->explain(
+        index   => 'my_index',  # required
+        type    => 'my_type',   # required
+        id      => 123,         # required
+
+        body    => { search }   # required
+    );
+
+The C<explain()> method explains why the specified document did or
+did not match a query, and how the relevance score was calculated.
+For instance:
+
+    $response = $e->explain(
+        index   => 'my_index',
+        type    => 'my_type',
+        id      => 123,
+        body    => {
+            query => {
+                match => { title => 'Elasticsearch clients' }
+            }
+        }
+    );
+
+Query string parameters:
+    C<_source>,
+    C<_source_exclude>,
+    C<_source_include>,
+    C<analyze_wildcard>,
+    C<analyzer>,
+    C<default_operator>,
+    C<df>,
+    C<fields>,
+    C<lenient>,
+    C<lowercase_expanded_terms>,
+    C<parent>,
+    C<preference>,
+    C<q>,
+    C<routing>
+
+See the L<explain docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-explain.html>
+for more information.
+
+=head2 C<field_stats()>
+
+    $response = $e->field_stats(
+        index   => 'index'   | \@indices,   # optional
+        fields  => 'field'   | \@fields,    # optional
+        level   => 'cluster' | 'indices',   # optional
+    );
+
+The C<field-stats> API returns statistical properties of a field
+(such as min and max values) without executing a search.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<fields>,
+    C<ignore_unavailable>,
+    C<level>
+
+See the L<field-stats docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-field-stats.html>
+for more information.
+
+=head2 C<search_shards()>
+
+    $response = $e->search_shards(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+    )
+
+The C<search_shards()> method returns information about which shards on
+which nodes will execute a search request.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>,
+    C<preference>,
+    C<routing>
+
+See the L<search-shards docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-shards.html>
+for more information.
+
+=head1 PERCOLATION METHODS
+
+=head2 C<percolate()>
+
+    $results = $e->percolate(
+        index   => 'my_index',      # required
+        type    => 'my_type',       # required
+
+        body    => { percolation }  # required
+    );
+
+Percolation is search inverted: instead of finding docs which match a
+particular query, it finds queries which match a particular document, eg
+for I<alert-me-when> functionality.
+
+The C<percolate()> method runs a percolation request to find the
+queries matching a particular document. In the C<body> you should pass the
+C<_source> field of the document under the C<doc> key:
+
+    $results = $e->percolate(
+        index   => 'my_index',
+        type    => 'my_type',
+        body    => {
+            doc => {
+                title => 'Elasticsearch rocks'
+            }
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<percolate_format>,
+    C<percolate_index>,
+    C<percolate_preference>,
+    C<percolate_routing>,
+    C<percolate_type>,
+    C<preference>,
+    C<routing>,
+    C<version>,
+    C<version_type>
+
+See the L<percolate docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-percolate.html>
+for more information.
+
+=head2 C<count_percolate()>
+
+    $results = $e->count_percolate(
+        index   => 'my_index',      # required
+        type    => 'my_type',       # required
+
+        body    => { percolation }  # required
+    );
+
+The L</count_percolate()> request works just like the L</percolate()>
+request except that it returns a count of all matching queries, instead
+of the queries themselves.
+
+    $results = $e->count_percolate(
+        index   => 'my_index',
+        type    => 'my_type',
+        body    => {
+            doc => {
+                title => 'Elasticsearch rocks'
+            }
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<percolate_index>,
+    C<percolate_type>,
+    C<preference>,
+    C<routing>,
+    C<version>,
+    C<version_type>
+
+See the L<percolate docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-percolate.html>
+for more information.
+
+=head2 C<mpercolate()>
+
+    $results = $e->mpercolate(
+        index   => 'my_index',               # required if type
+        type    => 'my_type',                # optional
+
+        body    => [ percolation requests ]  # required
+    );
+
+Multi-percolation allows multiple L</percolate()> requests to be run
+in a single request.
+
+    $results = $e->mpercolate(
+        index   => 'my_index',
+        type    => 'my_type',
+        body    => [
+            # first request
+            { percolate => {
+                index => 'twitter',
+                type  => 'tweet'
+            }},
+            { doc => {message => 'some_text' }},
+
+            # second request
+            { percolate => {
+                index => 'twitter',
+                type  => 'tweet',
+                id    => 1
+            }},
+            {},
+        ]
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>
+
+See the L<mpercolate docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-percolate.html>
+for more information.
+
+=head2 C<suggest()>
+
+    $results = $e->suggest(
+        index   => 'index' | \@indices,     # optional
+
+        body    => { suggest request }      # required
+    );
+
+The C<suggest()> method is used to run
+L<did-you-mean|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesteres-phrase.html>
+or L<search-as-you-type|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html>
+suggestion requests, which can also be run as part of a L</search()> request.
+
+    $results = $e->suggest(
+        index   => 'my_index',
+        body    => {
+            my_suggestions => {
+                phrase  => {
+                    text    => 'johnny walker',
+                    field   => 'title'
+                }
+            }
+        }
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<preference>,
+    C<routing>
+
+=HEAD1 INDEXED SCRIPT METHODS
+
+If dynamic scripting is enabled, Elasticsearch allows you to store scripts in an internal index known as
+C<.scripts> and reference them by id. The methods to manage indexed scripts are as follows:
+
+=head2 C<put_script()>
+
+    $result  = $e->put_script(
+        lang => 'lang',     # required
+        id   => 'id',       # required
+        body => { script }  # required
+    );
+
+The C<put_script()> method is used to store a script in the C<.scripts> index. For instance:
+
+    $result  = $e->put_scripts(
+        lang => 'groovy',
+        id   => 'hello_world',
+        body => {
+          script => q(return "hello world");
+        }
+    );
+
+Query string parameters:
+    C<op_type>,
+    C<version>,
+    C<version_type>
+
+See the L<indexed scripts docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
+
+=head2 C<get_script()>
+
+    $script = $e->get_script(
+        lang => 'lang',     # required
+        id   => 'id',       # required
+    );
+
+Retrieve the indexed script from the C<.scripts> index.
+
+Query string parameters:
+    C<version>,
+    C<version_type>
+
+See the L<indexed scripts docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
+
+=head2 C<delete_script()>
+
+    $script = $e->delete_script(
+        lang => 'lang',     # required
+        id   => 'id',       # required
+    );
+
+Delete the indexed script from the C<.scripts> index.
+
+Query string parameters:
+    C<version>,
+    C<version_type>
+
+See the L<indexed scripts docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
+
+=HEAD1 INDEXED SEARCH TEMPLATE METHODS
+
+Mustache templates can be used to create search requests.  These templates can
+be stored in the C<.scripts> index and retrieved by ID. The methods to
+manage indexed scripts are as follows:
+
+=head2 C<put_template()>
+
+    $result  = $e->put_template(
+        id   => 'id',                       # required
+        body => { template } || "template"  # required
+    );
+
+The C<put_template()> method is used to store a template in the C<.scripts> index.
+For instance:
+
+    $result  = $e->put_template(
+        id   => 'hello_world',
+        body => {
+          template => {
+            query => {
+              match => {
+                title => "hello world"
+              }
+            }
+          }
+      }
+    );
+
+Query string parameters: None
+
+See the L<indexed search template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
+
+=head2 C<get_template()>
+
+    $script = $e->get_template(
+        id   => 'id',       # required
+    );
+
+Retrieve the indexed template from the C<.scripts> index.
+
+Query string parameters:
+    C<version>,
+    C<version_type>
+
+See the L<indexed search template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
+
+=head2 C<delete_template()>
+
+    $script = $e->delete_template(
+        id   => 'id',       # required
+    );
+
+Delete the indexed template from the C<.scripts> index.
+
+Query string parameters: None
+
+See the L<indexed search template docs|http://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: Thin client with full support for Elasticsearch 2.x APIs
+
@@ -1,354 +0,0 @@
-package Search::Elasticsearch::Client::Direct::Cat;
-$Search::Elasticsearch::Client::Direct::Cat::VERSION = '1.19';
-use Moo;
-with 'Search::Elasticsearch::Role::API';
-with 'Search::Elasticsearch::Role::Client::Direct';
-use Search::Elasticsearch::Util qw(parse_params);
-use namespace::clean;
-__PACKAGE__->_install_api('cat');
-
-#===================================
-sub help {
-#===================================
-    my ( $self, $params ) = parse_params(@_);
-    $params->{help} = 1;
-    my $defn = $self->api->{'cat.help'};
-    $self->perform_request( $defn, $params );
-}
-
-1;
-
-=pod
-
-=encoding UTF-8
-
-=head1 NAME
-
-Search::Elasticsearch::Client::Direct::Cat - A client for running cat debugging requests
-
-=head1 VERSION
-
-version 1.19
-
-=head1 DESCRIPTION
-
-The C<cat> API in Elasticsearch provides information about your
-cluster and indices in a simple, easy to read text format, intended
-for human consumption.
-
-These APIs have a number of parameters in common:
-
-=over
-
-=item * C<help>
-
-Returns help about the API, eg:
-
-    say $e->cat->allocation(help => 1);
-
-=item * C<v>
-
-Includes the column headers in the output:
-
-    say $e->cat->allocation(v => 1);
-
-=item * C<h>
-
-Accepts a list of column names to be output, eg:
-
-    say $e->cat->indices(h => ['health','index']);
-
-=item * C<bytes>
-
-Formats byte-based values as bytes (C<b>), kilobytes (C<k>), megabytes
-(C<m>) or gigabytes (C<g>)
-
-=back
-
-It does L<Search::Elasticsearch::Role::Client::Direct>.
-
-=head1 METHODS
-
-=head2 C<help()>
-
-    say $e->cat->help;
-
-Returns the list of supported C<cat> APIs
-
-=head2 C<aliases()>
-
-    say $e->cat->aliases(
-        name => 'name' | \@names    # optional
-    );
-
-Returns information about index aliases, optionally limited to the specified
-index/alias names.
-
-Query string parameters:
-    C<h>,
-    C<help>,
-    C<local>,
-    C<master_timeout>,
-    C<v>
-
-See the L<cat aliases docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-aliases.html>
-for more information.
-
-=head2 C<allocation()>
-
-    say $e->cat->allocation(
-        node_id => 'node' | \@nodes    # optional
-    );
-
-Provides a snapshot of how shards have located around the cluster and the
-state of disk usage.
-
-Query string parameters:
-    C<bytes>,
-    C<h>,
-    C<help>,
-    C<local>,
-    C<master_timeout>,
-    C<v>
-
-See the L<cat allocation docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-allocation.html>
-for more information.
-
-=head2 C<count()>
-
-    say $e->cat->count(
-        index => 'index' | \@indices    # optional
-    );
-
-Provides quick access to the document count of the entire cluster, or
-individual indices.
-
-Query string parameters:
-    C<h>,
-    C<help>,
-    C<local>,
-    C<master_timeout>,
-    C<v>
-
-See the L<cat count docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-count.html>
-for more information.
-
-=head2 C<fielddata()>
-
-    say $e->cat->fielddata(
-        fields => 'field' | \@fields    # optional
-    );
-
-Shows the amount of memory used by each of the specified `fields` (or all
-fields) loaded into fielddata.
-
-Query string parameters:
-    C<bytes>,
-    C<h>,
-    C<help>,
-    C<local>,
-    C<master_timeout>,
-    C<v>
-
-See the L<cat fielddata docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-fielddata.html>
-for more information.
-
-=head2 C<health()>
-
-    say $e->cat->health();
-
-Provides a snapshot of how shards have located around the cluster and the
-state of disk usage.
-
-Query string parameters:
-    C<bytes>,
-    C<h>,
-    C<help>,
-    C<local>,
-    C<master_timeout>,
-    C<ts>,
-    C<v>
-
-See the L<cat health docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-health.html>
-for more information.
-
-=head2 C<indices()>
-
-    say $e->cat->indices(
-        index => 'index' | \@indices    # optional
-    );
-
-Provides a summary of index size and health for the whole cluster
-or individual indices
-
-Query string parameters:
-    C<bytes>,
-    C<h>,
-    C<help>,
-    C<local>,
-    C<master_timeout>,
-    C<pri>,
-    C<v>
-
-See the L<cat indices docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-indices.html>
-for more information.
-
-=head2 C<master()>
-
-    say $e->cat->master();
-
-Displays the master’s node ID, bound IP address, and node name.
-
-Query string parameters:
-    C<h>,
-    C<help>,
-    C<local>,
-    C<master_timeout>,
-    C<v>
-
-See the L<cat master docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-master.html>
-for more information.
-
-=head2 C<nodes()>
-
-    say $e->cat->nodes();
-
-Provides a snapshot of all of the nodes in your cluster.
-
-Query string parameters:
-    C<h>,
-    C<help>,
-    C<local>,
-    C<master_timeout>,
-    C<v>
-
-See the L<cat nodes docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-nodes.html>
-for more information.
-
-=head2 C<pending_tasks()>
-
-    say $e->cat->pending_tasks();
-
-Returns any cluster-level tasks which are queued on the master.
-
-Query string parameters:
-    C<local>,
-    C<master_timeout>,
-    C<h>,
-    C<help>,
-    C<v>
-
-See the L<cat pending-tasks docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-pending-tasks.html>
-for more information.
-
-=head2 C<plugins()>
-
-    say $e->cat->plugins();
-
-Returns information about plugins installed on each node.
-
-Query string parameters:
-    C<local>,
-    C<master_timeout>,
-    C<h>,
-    C<help>,
-    C<v>
-
-See the L<cat plugins docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-plugins.html>
-for more information.
-
-=head2 C<recovery()>
-
-    say $e->cat->recovery(
-        index => 'index' | \@indices    # optional
-    );
-
-Provides a is a view of shard replication. It will show information
-anytime data from at least one shard is copying to a different node.
-It can also show up on cluster restarts. If your recovery process seems
-stuck, try it to see if there’s any movement using C<recovery()>.
-
-Query string parameters:
-    C<bytes>,
-    C<h>,
-    C<help>,
-    C<master_timeout>,
-    C<v>
-
-See the L<cat recovery docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-recovery.html>
-for more information.
-
-=head2 C<segments()>
-
-    say $e->cat->segments(
-        index => 'index' | \@indices    # optional
-    );
-
-Provides low level information about the segments in the shards of an index.
-
-Query string parameters:
-    C<h>,
-    C<help>,
-    C<v>
-
-See the L<cat shards docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-segments.html>
-for more information.
-
-=head2 C<shards()>
-
-    say $e->cat->shards(
-        index => 'index' | \@indices    # optional
-    );
-
-Provides a detailed view of what nodes contain which shards, the state and
-size of each shard.
-
-Query string parameters:
-    C<h>,
-    C<help>,
-    C<local>,
-    C<master_timeout>,
-    C<v>
-
-See the L<cat shards docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-shards.html>
-for more information.
-
-=head2 C<thread_pool()>
-
-    say $e->cat->thread_pool(
-        index => 'index' | \@indices    # optional
-    );
-
-Shows cluster wide thread pool statistics per node. By default the C<active>,
-C<queue> and C<rejected> statistics are returned for the C<bulk>, C<index> and
-C<search> thread pools.
-
-Query string parameters:
-    C<full_id>,
-    C<h>,
-    C<help>,
-    C<local>,
-    C<master_timeout>,
-    C<v>
-
-See the L<cat thread_pool docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-thread-pool.html>
-for more information.
-
-=head1 AUTHOR
-
-Clinton Gormley <drtech@cpan.org>
-
-=head1 COPYRIGHT AND LICENSE
-
-This software is Copyright (c) 2015 by Elasticsearch BV.
-
-This is free software, licensed under:
-
-  The Apache License, Version 2.0, January 2004
-
-=cut
-
-__END__
-
-# ABSTRACT: A client for running cat debugging requests
-
@@ -1,215 +0,0 @@
-package Search::Elasticsearch::Client::Direct::Cluster;
-$Search::Elasticsearch::Client::Direct::Cluster::VERSION = '1.19';
-use Moo;
-with 'Search::Elasticsearch::Role::API';
-with 'Search::Elasticsearch::Role::Client::Direct';
-__PACKAGE__->_install_api('cluster');
-
-sub node_info     { _deprecated( 'node_info',     'info' ) }
-sub node_stats    { _deprecated( 'node_stats',    'stats' ) }
-sub hot_threads   { _deprecated( 'hot_threads',   'hot_threads' ) }
-sub node_shutdown { _deprecated( 'node_shutdown', 'shutdown' ) }
-
-#===================================
-sub _deprecated {
-#===================================
-    my ( $old, $new ) = @_;
-    die "The method \$es->cluster->$old() has moved to \$es->nodes->$new()";
-}
-
-1;
-
-=pod
-
-=encoding UTF-8
-
-=head1 NAME
-
-Search::Elasticsearch::Client::Direct::Cluster - A client for running cluster-level requests
-
-=head1 VERSION
-
-version 1.19
-
-=head1 DESCRIPTION
-
-This module provides methods to make cluster-level requests, such as
-getting and setting cluster-level settings, manually rerouting shards,
-and retrieving for monitoring purposes.
-
-It does L<Search::Elasticsearch::Role::Client::Direct>.
-
-=head1 METHODS
-
-=head2 C<health()>
-
-    $response = $e->cluster->health(
-        index   => 'index' | \@indices  # optional
-    );
-
-The C<health()> method is used to retrieve information about the cluster
-health, returning C<red>, C<yellow> or C<green> to indicate the state
-of the cluster, indices or shards.
-
-Query string parameters:
-    C<level>,
-    C<local>,
-    C<master_timeout>,
-    C<timeout>,
-    C<wait_for_active_shards>,
-    C<wait_for_nodes>,
-    C<wait_for_relocating_shards>,
-    C<wait_for_status>
-
-See the L<cluster health docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-health.html>
-for more information.
-
-=head2 C<stats()>
-
-    $response = $e->cluster->stats(
-        node_id => 'node' | \@nodes     # optional
-    );
-
-Returns high-level cluster stats, optionally limited to the listed nodes.
-
-Query string parameters:
-    C<flat_settings>,
-    C<human>
-
-See the L<cluster stats docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-stats.html>
-for more information.
-
-=head2 C<get_settings()>
-
-    $response = $e->cluster->get_settings()
-
-The C<get_settings()> method is used to retrieve cluster-wide settings that
-have been set with the L</put_settings()> method.
-
-Query string parameters:
-    C<flat_settings>,
-    C<master_timeout>,
-    C<timeout>
-
-See the L<cluster settings docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-update-settings.html>
-for more information.
-
-=head2 C<put_settings()>
-
-    $response = $e->cluster->put_settings( %settings );
-
-The C<put_settings()> method is used to set cluster-wide settings, either
-transiently (which don't survive restarts) or permanently (which do survive
-restarts).
-
-For instance:
-
-    $response = $e->cluster->put_settings(
-        body => {
-            transient => { "discovery.zen.minimum_master_nodes" => 5 }
-        }
-    );
-
-Query string parameters:
-    C<flat_settings>
-
-See the L<cluster settings docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-update-settings.html>
- for more information.
-
-=head2 C<state()>
-
-    $response = $e->cluster->state(
-        metric => $metric | \@metrics   # optional
-        index  => $index  | \@indices   # optional
-    );
-
-The C<state()> method returns the current cluster state from the master node,
-or from the responding node if C<local> is set to C<true>.
-
-It returns all metrics by default, but these can be limited to any of:
-    C<_all>,
-    C<blocks>,
-    C<metadata>,
-    C<nodes>,
-    C<routing_table>
-
-Metrics for indices can be limited to particular indices with the C<index>
-parameter.
-
-Query string parameters:
-    C<flat_settings>,
-    C<local>,
-    C<master_timeout>
-
-See the L<cluster state docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-state.html>
-for more information.
-
-=head2 C<pending_tasks()>
-
-    $response = $e->cluster->pending_tasks();
-
-Returns a list of cluster-level tasks still pending on the master node.
-
-Query string parameters:
-    C<local>,
-    C<master_timeout>
-
-See the L<pending tasks docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-pending.html>
-for more information.
-
-=head2 C<reroute()>
-
-    $e->cluster->reroute(
-        body => { commands }
-    );
-
-The C<reroute()> method is used to manually reallocate shards from one
-node to another.  The C<body> should contain the C<commands> indicating
-which changes should be made. For instance:
-
-    $e->cluster->reroute(
-        body => {
-            commands => [
-                { move => {
-                    index     => 'test',
-                    shard     => 0,
-                    from_node => 'node_1',
-                    to_node   => 'node_2
-                }},
-                { allocate => {
-                    index     => 'test',
-                    shard     => 1,
-                    node      => 'node_3'
-                }}
-            ]
-        }
-    );
-
-Query string parameters:
-    C<dry_run>,
-    C<explain>,
-    C<master_timeout>,
-    C<metric>,
-    C<timeout>
-
-See the L<reroute docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-reroute.html>
-for more information.
-
-=head1 AUTHOR
-
-Clinton Gormley <drtech@cpan.org>
-
-=head1 COPYRIGHT AND LICENSE
-
-This software is Copyright (c) 2015 by Elasticsearch BV.
-
-This is free software, licensed under:
-
-  The Apache License, Version 2.0, January 2004
-
-=cut
-
-__END__
-
-# ABSTRACT: A client for running cluster-level requests
-
@@ -1,844 +0,0 @@
-package Search::Elasticsearch::Client::Direct::Indices;
-$Search::Elasticsearch::Client::Direct::Indices::VERSION = '1.19';
-use Moo;
-with 'Search::Elasticsearch::Role::API';
-with 'Search::Elasticsearch::Role::Client::Direct';
-__PACKAGE__->_install_api('indices');
-
-1;
-
-=pod
-
-=encoding UTF-8
-
-=head1 NAME
-
-Search::Elasticsearch::Client::Direct::Indices - A client for running index-level requests
-
-=head1 VERSION
-
-version 1.19
-
-=head1 DESCRIPTION
-
-This module provides methods to make index-level requests, such as
-creating and deleting indices, managing type mappings, index settings,
-warmers, index templates and aliases.
-
-It does L<Search::Elasticsearch::Role::Client::Direct>.
-
-=head1 INDEX METHODS
-
-=head2 C<create()>
-
-    $result = $e->indices->create(
-        index => 'my_index'             # required
-
-        body  => {                      # optional
-            index settings
-            mappings
-            warmers
-        }
-    );
-
-The C<create()> method is used to create an index. Optionally, index
-settings, type mappings and index warmers can be added at the same time.
-
-Query string parameters:
-    C<master_timeout>,
-    C<timeout>
-
-See the L<create index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-create-index.html>
-for more information.
-
-=head2 C<get()>
-
-    $response = $e->indices->get(
-        index   => 'index'   | \@indices    # optional
-        feature => 'feature' | \@features   # optional
-    );
-
-Returns the aliases, settings, mappings, and warmers for the specified indices.
-The C<feature> parameter can be set to none or more of: C<_settings>, C<_mappings>,
-C<_warmers> and C<_aliases>.
-
-See the L<get index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-get-index.html>.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<local>
-
-=head2 C<exists()>
-
-    $bool = $e->indices->exists(
-        index => 'index' | \@indices    # required
-    );
-
-The C<exists()> method returns C<1> or the empty string to indicate
-whether the specified index or indices exist.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<local>
-
-See the L<index exists docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-indices-exists.html>
-for more information.
-
-=head2 C<delete()>
-
-    $response = $e->indices->delete(
-        index => 'index' | \@indices    # required
-    );
-
-The C<delete()> method deletes the specified indices.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<master_timeout>,
-    C<timeout>
-
-See the L<delete index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-delete-index.html>
-for more information.
-
-=head2 C<close()>
-
-    $response = $e->indices->close(
-        index => 'index' | \@indices    # required
-    );
-
-The C<close()> method closes the specified indices, reducing resource usage
-but allowing them to be reopened later.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>
-    C<master_timeout>,
-    C<timeout>
-
-See the L<close index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-open-close.html>
-for more information.
-
-=head2 C<open()>
-
-    $response = $e->indices->open(
-        index => 'index' | \@indices    # required
-    );
-
-The C<open()> method opens closed indices.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>
-    C<master_timeout>,
-    C<timeout>
-
-See the L<open index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-open-close.html>
-for more information.
-
-=head2 C<clear_cache()>
-
-    $response = $e->indices->clear_cache(
-        index => 'index' | \@indices        # optional
-    );
-
-The C<clear_cache()> method is used to clear the in-memory filter, fielddata,
-or id cache for the specified indices.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<fielddata>,
-    C<fields>,
-    C<filter>,
-    C<filter_cache>,
-    C<filter_keys>,
-    C<id>,
-    C<id_cache>,
-    C<ignore_unavailable>,
-    C<query_cache>,
-    C<recycler>
-
-See the L<clear_cache docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-clearcache.html>
-for more information.
-
-=head2 C<refresh()>
-
-    $response = $e->indices->refresh(
-        index => 'index' | \@indices    # optional
-    );
-
-The C<refresh()> method refreshes the specified indices (or all indices),
-allowing recent changes to become visible to search. This process normally
-happens automatically once every second by default.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<force>,
-    C<ignore_unavailable>
-
-See the L<refresh index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-refresh.html>
-for more information.
-
-=head2 C<flush()>
-
-    $response = $e->indices->flush(
-        index => 'index' | \@indices    # optional
-    );
-
-The C<flush()> method causes the specified indices (or all indices) to be
-written to disk with an C<fsync>, and clears out the transaction log.
-This process normally happens automatically.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<force>,
-    C<full>,
-    C<ignore_unavailable>,
-    C<wait_if_ongoing>
-
-See the L<flush index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-flush.html>
-for more information.
-
-=head2 C<optimize()>
-
-    $response = $e->indices->optimize(
-        index => 'index' | \@indices    # optional
-    );
-
-The C<optimize()> method rewrites all the data in an index into at most
-C<max_num_segments>.  This is a very heavy operation and should only be run
-with care, and only on indices that are no longer being updated.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<flush>,
-    C<ignore_unavailable>,
-    C<max_num_segments>,
-    C<only_expunge_deletes>,
-    C<wait_for_merge>
-
-See the L<optimize index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-optimize.html>
-for more information.
-
-=head2 C<get_upgrade()>
-
-    $response = $e->indices->get_upgrade(
-        index => 'index' | \@indices    # optional
-    );
-
-The C<get_upgrade()> method returns information about which indices need to be
-upgraded, which can be done with the C<upgrade()> method.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<human>,
-    C<ignore_unavailable>
-
-See the L<upgrade docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-upgrade.html>
-for more information.
-
-=head2 C<upgrade()>
-
-    $response = $e->indices->upgrade(
-        index => 'index' | \@indices    # optional
-    );
-
-The C<upgrade()> method upgrades all segments in the specified indices to the latest format.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<wait_for_completion>
-
-See the L<upgrade docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-upgrade.html>
-for more information.
-
-=head1 MAPPING METHODS
-
-=head2 C<put_mapping()>
-
-    $response = $e->indices->put_mapping(
-        index => 'index' | \@indices    # optional,
-        type  => 'type',                # required
-
-        body  => { mapping }            # required
-    )
-
-The C<put_mapping()> method is used to create or update a type
-mapping on an existing index.  Mapping updates are allowed to add new
-fields, but not to overwrite or change existing fields.
-
-For instance:
-
-    $response = $e->indices->put_mapping(
-        index   => 'users',
-        type    => 'user',
-        body    => {
-            user => {
-                properties => {
-                    name => { type => 'string'  },
-                    age  => { type => 'integer' }
-                }
-            }
-        }
-    );
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<ignore_conflicts>,
-    C<master_timeout>,
-    C<timeout>
-
-See the L<put_mapping docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-put-mapping.html>
-for more information.
-
-=head2 C<get_mapping()>
-
-    $result = $e->indices->get_mapping(
-        index => 'index' | \@indices    # optional,
-        type  => 'type'  | \@types      # optional
-    );
-
-The C<get_mapping()> method returns the type definitions for one, more or
-all types in one, more or all indices.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<local>
-
-See the L<get_mapping docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-get-mapping.html>
-for more information.
-
-=head2 C<get_field_mapping()>
-
-    $result = $e->indices->get_field_mapping(
-        index => 'index' | \@indices    # optional,
-        type  => 'type'  | \@types      # optional,
-        field => 'field' | \@fields     # required
-
-        include_defaults => 0 | 1
-    );
-
-The C<get_field_mapping()> method returns the field definitions for one, more or
-all fields in one, more or all types and indices.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<include_defaults>,
-    C<local>
-
-See the L<get_mapping docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html>
-for more information.
-
-=head2 C<exists_type()>
-
-    $bool = $e->indices->exists_type(
-        index => 'index' | \@indices    # required,
-        type  => 'type'  | \@types      # required
-    );
-
-The C<exists_type()> method checks for the existence of all specified types
-in all specified indices, and returns C<1> or the empty string.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<local>
-
-See the L<exists_type docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-types-exists.html>
-for more information.
-
-=head2 C<delete_mapping()>
-
-    $response = $e->indices->delete_mapping(
-        index => 'index' | \@indices    # required,
-        type  => 'type'  | \@types      # required
-    );
-
-The C<delete_mapping()> method deletes the type mappings (and all documents of
-that type) in all specified indices.
-
-Query string parameters:
-    C<master_timeout>
-
-See the L<delete_mapping docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-delete-mapping.html>
-for more information.
-
-=head1 ALIAS METHODS
-
-=head2 C<update_aliases()>
-
-    $response = $e->indices->update_aliases(
-        body => { actions }             # required
-    );
-
-The C<update_aliases()> method changes (by adding or removing) multiple
-index aliases atomically. For instance:
-
-    $response = $e->indices->update_aliases(
-        body => {
-            actions => [
-                { add    => { alias => 'current', index => 'logs_2013_09' }},
-                { remove => { alias => 'current', index => 'logs_2013_08' }}
-            ]
-        }
-    );
-
-Query string parameters:
-    C<master_timeout>,
-    C<timeout>
-
-See the L<update_aliases docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html>
-for more information.
-
-=head2 C<get_aliases()>
-
-    $result = $e->indices->get_aliases(
-        index   => 'index' | \@indices,     # optional
-        alias   => 'alias' | \@aliases      # optional
-    );
-
-The C<get_aliases()> method returns a list of aliases per index for all
-the specified indices.
-
-Query string parameters:
-    C<local>,
-    C<timeout>
-
-See the L<get_aliases docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html>
-for more information.
-
-=head2 C<put_alias()>
-
-    $response = $e->indices->put_alias(
-        index => 'index' | \@indices,       # required
-        name  => 'alias',                   # required
-
-        body  => { alias defn }             # optional
-    );
-
-The C<put_alias()> method creates an index alias. For instance:
-
-    $response = $e->indices->put_alias(
-        index => 'my_index',
-        name  => 'twitter',
-        body => {
-            filter => { term => { user_id => 'twitter' }}
-        }
-    );
-
-Query string parameters:
-    C<master_timeout>,
-    C<timeout>
-
-See the L<put_alias docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html>
-for more information.
-
-=head2 C<get_alias()>
-
-    $result = $e->indices->get_alias(
-        index   => 'index' | \@indices,     # optional
-        name    => 'alias' | \@aliases      # optional
-    );
-
-The C<get_alias()> method returns the alias definitions for the specified
-aliases in the specified indices.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<local>
-
-See the L<get_alias docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html>
-for more information.
-
-=head2 C<exists_alias()>
-
-    $bool = $e->indices->exists_alias(
-        index   => 'index' | \@indices,     # optional
-        name    => 'alias' | \@aliases      # optional
-    );
-
-The C<exists_alias()> method returns C<1> or the empty string depending on
-whether the specified aliases exist in the specified indices.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<local>
-
-See the L<exists_alias docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html>
-for more information.
-
-=head2 C<delete_alias()>
-
-    $response = $e->indices->delete_alias(
-        index   => 'index' | \@indices        # required,
-        name    => 'alias' | \@aliases        # required
-    );
-
-The C<delete_alias()> method deletes one or more aliases from one or more
-indices.
-
-Query string parameters:
-    C<master_timeout>,
-    C<timeout>
-
-See the L<delete_alias docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html>
-for more information.
-
-=head1 SETTINGS METHODS
-
-=head2 C<put_settings()>
-
-    $response = $e->indices->put_settings(
-        index   => 'index' | \@indices      # optional
-
-        body    => { settings }
-    );
-
-The C<put_settings()> method sets the index settings for the specified
-indices or all indices. For instance:
-
-    $response = $e->indices->put_settings(
-        body => {
-            "index.refresh_interval" => -1
-        }
-    );
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<flat_settings>,
-    C<ignore_unavailable>,
-    C<master_timeout>
-
-See the L<put_settings docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-update-settings.html>
-for more information.
-
-=head2 C<get_settings()>
-
-    $result = $e->indices->get_settings(
-        index   => 'index' | \@indices      # optional
-        name    => 'name'  | \@names        # optional
-    );
-
-The C<get_settings()> method retrieves the index settings for the specified
-indices or all indices.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<flat_settings>,
-    C<ignore_unavailable>,
-    C<local>
-
-See the L<get_settings docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-get-settings.html>
-for more information.
-
-=head1 TEMPLATE METHODS
-
-=head2 C<put_template()>
-
-    $response = $e->indices->put_template(
-        name => 'template'                  # required
-        body => { template defn }           # required
-    );
-
-The C<put_template()> method is used to create or update index templates.
-
-Query string parameters:
-    C<create>,
-    C<flat_settings>,
-    C<master_timeout>,
-    C<op_type>,
-    C<order>,
-    C<timeout>,
-    C<version>,
-    C<version_type>
-
-See the L<put_template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html>
-for more information.
-
-=head2 C<get_template()>
-
-    $result = $e->indices->get_template(
-        name  => 'template'                 # optional
-    );
-
-The C<get_template()> method is used to retrieve a named template.
-
-Query string parameters:
-    C<flat_settings>,
-    C<local>
-
-See the L<get_template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html>
-for more information.
-
-=head2 C<exists_template()>
-
-    $result = $e->indices->exists_template(
-        name  => 'template'                 # required
-    );
-
-The C<exists_template()> method is used to check whether the named template exists.
-
-Query string parameters:
-    C<local>
-
-See the L<get_template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html>
-for more information.
-
-=head2 C<delete_template()>
-
-    $response = $e->indices->delete_template(
-        name  => 'template'                 # required
-    );
-
-The C<delete_template()> method is used to delete a named template.
-
-Query string parameters:
-    C<master_timeout>,
-    C<timeout>,
-    C<version>,
-    C<version_type>
-
-See the L<delete_template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html>
-for more information.
-
-=head1 WARMER METHODS
-
-=head2 C<put_warmer()>
-
-    $response = $e->indices->put_warmer(
-        index   => 'index' | \@indices,     # optional
-        type    => 'type'  | \@types,       # optional
-        name    => 'warmer',                # required
-
-        body    => { warmer defn }          # required
-    );
-
-The C<put_warmer()> method is used to create or update named warmers which
-are used to I<warm up> new segments in the index before they are exposed
-to user searches.  For instance:
-
-    $response = $e->indices->put_warmer(
-        index   => 'my_index',
-        name    => 'date_field_warmer',
-        body    => {
-            sort => 'date'
-        }
-    );
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<master_timeout>
-
-See the L<put_warmer docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html>
-for more information.
-
-=head2 C<get_warmer()>
-
-    $response = $e->indices->get_warmer(
-        index   => 'index'  | \@indices,    # optional
-        type    => 'type'   | \@types,      # optional
-        name    => 'warmer' | \@warmers,    # optional
-    );
-
-The C<get_warmer()> method is used to retrieve warmers by name.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<local>
-
-See the L<get_warmer docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html>
-for more information.
-
-=head2 C<delete_warmer()>
-
-    $response = $e->indices->get_warmer(
-        index   => 'index'  | \@indices,    # required
-        name    => 'warmer' | \@warmers,    # required
-    );
-
-The C<delete_warmer()> method is used to delete warmers by name.
-
-Query string parameters:
-    C<master_timeout>
-
-See the L<delete_warmer docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html>
-for more information.
-
-=head1 STATS METHODS
-
-=head2 C<stats()>
-
-    $result = $e->indices->stats(
-        index   => 'index'  | \@indices      # optional
-        metric  => 'metric' | \@metrics      # optional
-    );
-
-The C<stats()> method returns statistical information about one, more or all
-indices. By default it returns all metrics, but you can limit which metrics
-are returned by specifying the C<metric>.
-
-Allowed metrics are:
-    C<_all>,
-    C<completion>
-    C<docs>,
-    C<fielddata>,
-    C<filter_cache>,
-    C<flush>,
-    C<get>,
-    C<id_cache>,
-    C<indexing>,
-    C<merge>,
-    C<percolate>,
-    C<query_cache>,
-    C<refresh>,
-    C<search>,
-    C<segments>,
-    C<store>,
-    C<warmer>
-
-Query string parameters:
-    C<completion_fields>,
-    C<fielddata_fields>,
-    C<fields>,
-    C<groups>,
-    C<human>,
-    C<level>,
-    C<types>
-
-See the L<stats docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-stats.html>
-for more information.
-
-=head2 C<recovery()>
-
-    $result = $e->indices->recovery(
-        index   => 'index' | \@indices      # optional
-    );
-
-Provides insight into on-going shard recoveries.
-
-Query string parameters:
-    C<active_only>,
-    C<detailed>,
-    C<human>
-
-See the L<recovery docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-recovery.html>
-for more information.
-
-=head2 C<segments()>
-
-    $result = $e->indices->segments(
-        index   => 'index' | \@indices      # optional
-    );
-
-The C<segments()> method is used to return information about the segments
-that an index contains.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<human>,
-    C<ignore_unavailable>
-
-See the L<segments docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-segments.html>
-for more information.
-
-=head1 QUERY AND ANALYSIS METHODS
-
-=head2 C<analyze()>
-
-    $result = $e->indices->analyze(
-        index   => 'index'                  # optional,
-        body    => 'text to analyze'
-    );
-
-The C<analyze()> method passes the text in the C<body> through the specified
-C<analyzer>, C<tokenizer> or token C<filter> - which may be global, or associated
-with a particular index or field - and returns the tokens.  Very useful
-for debugging analyzer configurations.
-
-Query string parameters:
-    C<analyzer>,
-    C<char_filters>,
-    C<field>,
-    C<filters>,
-    C<format>,
-    C<prefer_local>,
-    C<text>,
-    C<tokenizer>
-
-See the L<analyze docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-analyze.html>
-for more information.
-
-=head2 C<validate_query()>
-
-    $result = $e->indices->validate_query(
-        index   => 'index' | \@indices,     # optional
-        type    => 'type'  | \@types,       # optional
-
-        body    => { query }
-    );
-
-The C<validate_query()> method accepts a query in the C<body> and checks
-whether the query is valid or not.  Most useful when C<explain> is set
-to C<true>, in which case it includes an execution plan in the output.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<explain>,
-    C<ignore_unavailable>,
-    C<q>,
-    C<source>
-
-See the L<validate_query docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-validate.html>
-for more information.
-
-=head1 AUTHOR
-
-Clinton Gormley <drtech@cpan.org>
-
-=head1 COPYRIGHT AND LICENSE
-
-This software is Copyright (c) 2015 by Elasticsearch BV.
-
-This is free software, licensed under:
-
-  The Apache License, Version 2.0, January 2004
-
-=cut
-
-__END__
-
-# ABSTRACT: A client for running index-level requests
-
@@ -1,183 +0,0 @@
-package Search::Elasticsearch::Client::Direct::Nodes;
-$Search::Elasticsearch::Client::Direct::Nodes::VERSION = '1.19';
-use Moo;
-with 'Search::Elasticsearch::Role::API';
-with 'Search::Elasticsearch::Role::Client::Direct';
-__PACKAGE__->_install_api('nodes');
-
-1;
-
-=pod
-
-=encoding UTF-8
-
-=head1 NAME
-
-Search::Elasticsearch::Client::Direct::Nodes - A client for running node-level requests
-
-=head1 VERSION
-
-version 1.19
-
-=head1 DESCRIPTION
-
-This module provides methods to make node-level requests, such as
-retrieving node info and stats.
-
-It does L<Search::Elasticsearch::Role::Client::Direct>.
-
-=head1 METHODS
-
-=head2 C<info()>
-
-    $response = $e->nodes->info(
-        node_id => $node_id | \@node_ids       # optional
-        metric  => $metric  | \@metrics        # optional
-    );
-
-The C<info()> method returns static information about the nodes in the
-cluster, such as the configured maximum number of file handles, the maximum
-configured heap size or the threadpool settings.
-
-Allowed metrics are:
-    C<http>,
-    C<jvm>,
-    C<network>,
-    C<os>,
-    C<plugin>,
-    C<process>,
-    C<settings>,
-    C<thread_pool>,
-    C<transport>
-
-Query string parameters:
-    C<flat_settings>,
-    C<human>
-
-See the L<node_info docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-nodes-info.html>
-for more information.
-
-=head2 C<stats()>
-
-    $response = $e->nodes->stats(
-        node_id      => $node_id    | \@node_ids       # optional
-        metric       => $metric     | \@metrics        # optional
-        index_metric => $ind_metric | \@ind_metrics    # optional
-    );
-
-The C<stats()> method returns statistics about the nodes in the
-cluster, such as the number of currently open file handles, the current
-heap memory usage or the current number of threads in use.
-
-Stats can be returned for all nodes, or limited to particular nodes
-with the C<node_id> parameter. By default all metrics are returned, but
-these can be limited to those specified in the C<metric> parameter.
-
-Allowed metrics are:
-    C<_all>,
-    C<breaker>,
-    C<fs>,
-    C<http>,
-    C<indices>,
-    C<jvm>,
-    C<network>,
-    C<os>,
-    C<process>,
-    C<thread_pool>,
-    C<transport>
-
-If the C<indices> metric (or C<_all>) is specified, then
-L<indices_stats|Search::Elasticsearch::Client::Direct::Indices/indices_stats()>
-information is returned on a per-node basis. Which indices stats are
-returned can be controlled with the C<index_metric> parameter:
-
-    $response = $e->cluster->node_stats(
-        node_id       => 'node_1',
-        metric        => ['indices','fs']
-        index_metric  => ['docs','fielddata']
-    );
-
-Allowed index metrics are:
-    C<_all>,
-    C<completion>
-    C<docs>,
-    C<fielddata>,
-    C<filter_cache>,
-    C<flush>,
-    C<get>,
-    C<id_cache>,
-    C<indexing>,
-    C<merge>,
-    C<percolate>,
-    C<query_cache>,
-    C<refresh>,
-    C<search>,
-    C<segments>,
-    C<store>,
-    C<warmer>
-
-Query string parameters:
-    C<completion_fields>,
-    C<fielddata_fields>,
-    C<fields>,
-    C<groups>,
-    C<human>,
-    C<level>,
-    C<types>
-
-See the L<node_stats docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-nodes-stats.html>
-for more information.
-
-=head2 C<hot_threads()>
-
-    $response = $e->nodes->hot_threads(
-        node_id => $node_id | \@node_ids       # optional
-    )
-
-The C<hot_threads()> method is a useful tool for diagnosing busy nodes. It
-takes a snapshot of which threads are consuming the most CPU.
-
-Query string parameters:
-    C<ignore_idle_threads>,
-    C<interval>,
-    C<snapshots>,
-    C<threads>,
-    C<type>
-
-See the L<hot_threads docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-nodes-hot-threads.html>
-for more information.
-
-=head2 C<shutdown()>
-
-    $e->nodes->shutdown(
-        node_id => $node_id | \@node_ids    # optional
-    );
-
-The C<shutdown()> method is used to shutdown one or more nodes, or the whole
-cluster.
-
-Query string parameters:
-    C<delay>,
-    C<exit>
-
-See the L<shutdown docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-nodes-shutdown.html>
-for more information.
-
-=head1 AUTHOR
-
-Clinton Gormley <drtech@cpan.org>
-
-=head1 COPYRIGHT AND LICENSE
-
-This software is Copyright (c) 2015 by Elasticsearch BV.
-
-This is free software, licensed under:
-
-  The Apache License, Version 2.0, January 2004
-
-=cut
-
-__END__
-
-# ABSTRACT: A client for running node-level requests
-
@@ -1,190 +0,0 @@
-package Search::Elasticsearch::Client::Direct::Snapshot;
-$Search::Elasticsearch::Client::Direct::Snapshot::VERSION = '1.19';
-use Moo;
-with 'Search::Elasticsearch::Role::API';
-with 'Search::Elasticsearch::Role::Client::Direct';
-__PACKAGE__->_install_api('snapshot');
-
-1;
-
-=pod
-
-=encoding UTF-8
-
-=head1 NAME
-
-Search::Elasticsearch::Client::Direct::Snapshot - A client for managing snapshot/restore
-
-=head1 VERSION
-
-version 1.19
-
-=head1 DESCRIPTION
-
-This module provides methods to manage snapshot/restore, or backups.
-It can create, get and delete configured backup repositories, and
-create, get, delete and restore snapshots of your cluster or indices.
-
-It does L<Search::Elasticsearch::Role::Client::Direct>.
-
-=head1 METHODS
-
-=head2 C<create_repository()>
-
-    $e->snapshot->create_repository(
-        repository  => 'repository',        # required
-        body        => { defn }             # required
-    );
-
-Create a repository for backups.
-
-Query string parameters:
-    C<master_timeout>,
-    C<timeout>,
-    C<verify>
-
-See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
-for more information.
-
-=head2 C<get_repository()>
-
-    $e->snapshot->get_repository(
-        repository  => 'repository' | \@repositories    # optional
-    );
-
-Retrieve existing repositories.
-
-Query string parameters:
-    C<local>,
-    C<master_timeout>
-
-See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
-for more information.
-
-=head2 C<verify_repository()>
-
-    $e->snapshot->verify_repository(
-        repository  => 'repository' # required
-    );
-
-Verify existing repository.
-
-Query string parameters:
-    C<master_timeout>,
-    C<timeout>
-
-See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
-for more information.
-
-=head2 C<delete_repository()>
-
-    $e->snapshot->delete_repository(
-        repository  => 'repository' | \@repositories    # required
-    );
-
-Delete repositories by name.
-
-Query string parameters:
-    C<master_timeout>,
-    C<timeout>
-
-See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
-for more information.
-
-=head2 C<create()>
-
-    $e->snapshot->create(
-        repository  => 'repository',     # required
-        snapshot    => 'snapshot',       # required,
-
-        body        => { snapshot defn } # optional
-    );
-
-Create a snapshot of the whole cluster or individual indices in the named
-repository.
-
-Query string parameters:
-    C<master_timeout>,
-    C<wait_for_completion>
-
-=head2 C<get()>
-
-    $e->snapshot->get(
-        repository  => 'repository'                   # required
-        snapshot    => 'snapshot'   | \@snapshots     # required
-    );
-
-Retrieve snapshots in the named repository.
-
-Query string parameters:
-    C<master_timeout>
-
-See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
-for more information.
-
-=head2 C<delete()>
-
-    $e->snapshot->delete(
-        repository  => 'repository',              # required
-        snapshot    => 'snapshot'                 # required
-    );
-
-Delete snapshot in the named repository.
-
-Query string parameters:
-    C<master_timeout>
-
-See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
-for more information.
-
-=head2 C<restore()>
-
-    $e->snapshot->restore(
-        repository  => 'repository',              # required
-        snapshot    => 'snapshot'                 # required
-
-        body        => { what to restore }        # optional
-    );
-
-Restore a named snapshot.
-
-Query string parameters:
-    C<master_timeout>,
-    C<wait_for_completion>
-
-See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
-for more information.
-
-=head2 C<status()>
-
-    $result = $e->snapshot->status(
-        repository  => 'repository',              # optional
-        snapshot    => 'snapshot' | \@snapshots   # optional
-    );
-
-Returns status information about the specified snapshots.
-
-Query string parameters:
-    C<master_timeout>
-
-See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
-for more information.
-
-=head1 AUTHOR
-
-Clinton Gormley <drtech@cpan.org>
-
-=head1 COPYRIGHT AND LICENSE
-
-This software is Copyright (c) 2015 by Elasticsearch BV.
-
-This is free software, licensed under:
-
-  The Apache License, Version 2.0, January 2004
-
-=cut
-
-__END__
-
-# ABSTRACT: A client for managing snapshot/restore
-
@@ -1,110 +1,16 @@
 package Search::Elasticsearch::Client::Direct;
-$Search::Elasticsearch::Client::Direct::VERSION = '1.19';
-use Moo;
-with 'Search::Elasticsearch::Role::API';
-with 'Search::Elasticsearch::Role::Client::Direct';
+$Search::Elasticsearch::Client::Direct::VERSION = '1.20';
+use parent 'Search::Elasticsearch::Client::1_0::Direct';
 
-use Search::Elasticsearch::Util qw(parse_params load_plugin is_compat);
-use namespace::clean;
+warn <<'END';
+The Search::Elasticsearch::Client::Direct class is deprecated.
+Please specify the version of the API that you would like to use, eg:
 
-has 'cluster'             => ( is => 'lazy', init_arg => undef );
-has 'nodes'               => ( is => 'lazy', init_arg => undef );
-has 'indices'             => ( is => 'lazy', init_arg => undef );
-has 'snapshot'            => ( is => 'lazy', init_arg => undef );
-has 'cat'                 => ( is => 'lazy', init_arg => undef );
-has 'bulk_helper_class'   => ( is => 'ro',   default  => 'Bulk' );
-has 'scroll_helper_class' => ( is => 'ro',   default  => 'Scroll' );
-has '_bulk_class'         => ( is => 'lazy' );
-has '_scroll_class'       => ( is => 'lazy' );
+     $e = Search::Elasticsearch->new(
+         client => '1_0::Direct'        # default
+     );
 
-__PACKAGE__->_install_api('');
-
-#===================================
-sub create {
-#===================================
-    my ( $self, $params ) = parse_params(@_);
-    $params->{op_type} = 'create';
-    $self->_index( 'create', $params );
-}
-
-#===================================
-sub index {
-#===================================
-    my ( $self, $params ) = parse_params(@_);
-    $self->_index( 'index', $params );
-}
-
-my $index_with_id = { %{ __PACKAGE__->api->{index} }, method => 'PUT' };
-
-#===================================
-sub _index {
-#===================================
-    my ( $self, $name, $params ) = @_;
-    my $defn = $self->api->{index};
-    if ( defined $params->{id} and length $params->{id} ) {
-        $defn = $index_with_id;
-    }
-    $self->perform_request( { %$defn, name => $name }, $params );
-}
-
-#===================================
-sub _build__bulk_class {
-#===================================
-    my $self = shift;
-    $self->_build_helper( 'bulk', $self->bulk_helper_class );
-}
-
-#===================================
-sub _build__scroll_class {
-#===================================
-    my $self = shift;
-    $self->_build_helper( 'scroll', $self->scroll_helper_class );
-}
-
-#===================================
-sub _build_helper {
-#===================================
-    my ( $self, $name, $sub_class ) = @_;
-    my $class = load_plugin( 'Search::Elasticsearch', $sub_class );
-    is_compat( $name . '_helper_class', $self->transport, $class );
-    return $class;
-}
-
-#===================================
-sub bulk_helper {
-#===================================
-    my ( $self, $params ) = parse_params(@_);
-    $params->{es} ||= $self;
-    $self->_bulk_class->new($params);
-}
-
-#===================================
-sub scroll_helper {
-#===================================
-    my ( $self, $params ) = parse_params(@_);
-    $params->{es} ||= $self;
-    $self->_scroll_class->new($params);
-}
-
-#===================================
-sub _build_cluster  { shift->_build_namespace('Cluster') }
-sub _build_nodes    { shift->_build_namespace('Nodes') }
-sub _build_indices  { shift->_build_namespace('Indices') }
-sub _build_snapshot { shift->_build_namespace('Snapshot') }
-sub _build_cat      { shift->_build_namespace('Cat') }
-#===================================
-
-#===================================
-sub _build_namespace {
-#===================================
-    my ( $self, $ns ) = @_;
-    my $class = load_plugin( __PACKAGE__, [$ns] );
-    return $class->new(
-        {   transport => $self->transport,
-            logger    => $self->logger
-        }
-    );
-}
+END
 
 1;
 
@@ -114,1438 +20,16 @@ sub _build_namespace {
 
 =head1 NAME
 
-Search::Elasticsearch::Client::Direct - Thin client with full support for Elasticsearch APIs
+Search::Elasticsearch::Client::Direct - Deprecated
 
 =head1 VERSION
 
-version 1.19
-
-=head1 SYNOPSIS
-
-Create a client:
-
-    use Search::Elasticsearch;
-    my $e = Search::Elasticsearch->new(
-        client => 'Direct'          # default
-    );
-
-Index a doc:
-
-    $e->index(
-        index   => 'my_index',
-        type    => 'blog_post',
-        id      => 123,
-        body    => {
-            title   => "Elasticsearch clients",
-            content => "Interesting content...",
-            date    => "2013-09-23"
-        }
-    );
-
-Get a doc:
-
-    $e->get(
-        index   => 'my_index',
-        type    => 'my_type',
-        id      => 123
-    );
-
-Search for docs:
-
-    $results = $e->search(
-        index   => 'my_index',
-        body    => {
-            query => {
-                match => {
-                    title => "elasticsearch"
-                }
-            }
-        }
-    );
-
-Index-level requests:
-
-    $e->indices->create( index => 'my_index' );
-    $e->indices->delete( index => 'my_index' )
-
-Cluster-level requests:
-
-    $health = $e->cluster->health;
-
-Node-level requests:
-
-    $info  = $e->nodes->info;
-    $stats = $e->nodes->stats;
-
-Snapshot and restore:
-
-    $e->snapshot->create_repository(
-        repository => 'my_backups',
-        type       => 'fs',
-        settings   => {
-            location => '/mnt/backups'
-        }
-    );
-
-    $e->snapshot->create(
-        repository => 'my_backups',
-        snapshot   => 'backup_2014'
-    );
-
-`cat` debugging:
-
-    say $e->cat->allocation;
-    say $e->cat->health;
+version 1.20
 
 =head1 DESCRIPTION
 
-The L<Search::Elasticsearch::Client::Direct> class provides the default
-client that is returned by:
-
-    $e = Search::Elasticsearch->new;
-
-It is intended to be as close as possible to the native REST API that
-Elasticsearch uses, so that it is easy to translate the
-L<Elasticsearch reference documentation|http://www.elasticsearch/guide>
-for an API to the equivalent in this client.
-
-This class provides the methods for L<document CRUD|/DOCUMENT CRUD METHODS>,
-L<bulk document CRUD|/BULK DOCUMENT CRUD METHODS> and L<search|/SEARCH METHODS>.
-It also provides access to clients for managing L<indices|/indices()>
-and the L<cluster|/cluster()>.
-
-=head1 BACKWARDS COMPATIBILITY AND ELASTICSEARCH 0.90.x
-
-This version of the client supports the Elasticsearch 1.0 branch by
-default, which is not backwards compatible with the 0.90 branch.
-
-If you need to talk to a version of Elasticsearch before 1.0.0,
-please use L<Search::Elasticsearch::Client::0_90::Direct> as follows:
-
-    $es = Search::Elasticsearch->new(
-        client => '0_90::Direct'
-    );
-
-=head1 CONVENTIONS
-
-=head2 Parameter passing
-
-Parameters can be passed to any request method as a list or as a hash
-reference. The following two statements are equivalent:
-
-    $e->search( size => 10 );
-    $e->search({size => 10});
-
-=head2 Path parameters
-
-Any values that should be included in the URL path, eg C</{index}/{type}>
-should be passed as top level parameters:
-
-    $e->search( index => 'my_index', type => 'my_type' );
-
-Alternatively, you can specify a C<path> parameter directly:
-
-    $e->search( path => '/my_index/my_type' );
-
-=head2 Query-string parameters
-
-Any values that should be included in the query string should be passed
-as top level parameters:
-
-    $e->search( size => 10 );
-
-If you pass in a C<\%params> hash, then it will be included in the
-query string parameters without any error checking. The following:
-
-    $e->search( size => 10, params => { from => 5, size => 5 })
-
-would result in this query string:
-
-    ?from=5&size=10
-
-=head2 Body parameter
-
-The request body should be passed in the C<body> key:
-
-    $e->search(
-        body => {
-            query => {...}
-        }
-    );
-
-The body can also be a UTF8-decoded string, which will be converted into
-UTF-8 bytes and passed as is:
-
-    $e->indices->analyze( body => "The quick brown fox");
-
-=head2 Ignore parameter
-
-Normally, any HTTP status code outside the 200-299 range will result in
-an error being thrown.  To suppress these errors, you can specify which
-status codes to ignore in the C<ignore> parameter.
-
-    $e->indices->delete(
-        index  => 'my_index',
-        ignore => 404
-    );
-
-This is most useful for
-L<Missing|Search::Elasticsearch::Error/Search::Elasticsearch::Error::Missing> errors, which
-are triggered by a C<404> status code when some requested resource does
-not exist.
-
-Multiple error codes can be specified with an array:
-
-    $e->indices->delete(
-        index  => 'my_index',
-        ignore => [404,409]
-    );
-
-=head1 CONFIGURATION
-
-=head2 C<bulk_helper_class>
-
-The class to use for the L</bulk_helper()> method. Defaults to
-L<Search::Elasticsearch::Bulk>.
-
-=head2 C<scroll_helper_class>
-
-The class to use for the L</scroll_helper()> method. Defaults to
-L<Search::Elasticsearch::Scroll>.
-
-=head1 GENERAL METHODS
-
-=head2 C<info()>
-
-    $info = $e->info
-
-Returns information about the version of Elasticsearch that the responding node
-is running.
-
-=head2 C<ping()>
-
-    $e->ping
-
-Pings a node in the cluster and returns C<1> if it receives a C<200>
-response, otherwise it throws an error.
-
-=head2 C<indices()>
-
-    $indices_client = $e->indices;
-
-Returns an L<Search::Elasticsearch::Client::Direct::Indices> object which can be used
-for managing indices, eg creating, deleting indices, managing mapping,
-index settings etc.
-
-=head2 C<cluster()>
-
-    $cluster_client = $e->cluster;
-
-Returns an L<Search::Elasticsearch::Client::Direct::Cluster> object which can be used
-for managing the cluster, eg cluster-wide settings and cluster health.
-
-=head2 C<nodes()>
-
-    $node_client = $e->nodes;
-
-Returns an L<Search::Elasticsearch::Client::Direct::Nodes> object which can be used
-to retrieve node info and stats.
-
-=head2 C<snapshot()>
-
-    $snapshot_client = $e->snapshot;
-
-Returns an L<Search::Elasticsearch::Client::Direct::Snapshot> object which
-is used for managing backup repositories and creating and restoring
-snapshots.
-
-=head2 C<cat()>
-
-    $cat_client = $e->cat;
-
-Returns an L<Search::Elasticsearch::Client::Direct::Cat> object which can be used
-to retrieve simple to read text info for debugging and monitoring an
-Elasticsearch cluster.
-
-=head1 DOCUMENT CRUD METHODS
-
-These methods allow you to perform create, index, update and delete requests
-for single documents:
-
-=head2 C<index()>
-
-    $response = $e->index(
-        index   => 'index_name',        # required
-        type    => 'type_name',         # required
-        id      => 'doc_id',            # optional, otherwise auto-generated
-
-        body    => { document }         # required
-    );
-
-The C<index()> method is used to index a new document or to reindex
-an existing document.
-
-Query string parameters:
-    C<consistency>,
-    C<op_type>,
-    C<parent>,
-    C<refresh>,
-    C<replication>,
-    C<routing>,
-    C<timeout>,
-    C<timestamp>,
-    C<ttl>,
-    C<version>,
-    C<version_type>
-
-See the L<index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-index_.html>
-for more information.
-
-=head2 C<create()>
-
-    $response = $e->create(
-        index   => 'index_name',        # required
-        type    => 'type_name',         # required
-        id      => 'doc_id',            # optional, otherwise auto-generated
-
-        body    => { document }         # required
-    );
-
-The C<create()> method works exactly like the L</index()> method, except
-that it will throw a C<Conflict> error if a document with the same
-C<index>, C<type> and C<id> already exists.
-
-Query string parameters:
-    C<consistency>,
-    C<op_type>,
-    C<parent>,
-    C<refresh>,
-    C<replication>,
-    C<routing>,
-    C<timeout>,
-    C<timestamp>,
-    C<ttl>,
-    C<version>,
-    C<version_type>
-
-See the L<create docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-create.html>
-for more information.
-
-=head2 C<get()>
-
-    $response = $e->get(
-        index   => 'index_name',        # required
-        type    => 'type_name',         # required
-        id      => 'doc_id',            # required
-    );
-
-The C<get()> method will retrieve the document with the specified
-C<index>, C<type> and C<id>, or will throw a C<Missing> error.
-
-Query string parameters:
-    C<_source>,
-    C<_source_exclude>,
-    C<_source_include>,
-    C<fields>,
-    C<parent>,
-    C<preference>,
-    C<realtime>,
-    C<refresh>,
-    C<routing>,
-    C<version>,
-    C<version_type>
-
-See the L<get docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-get.html>
-for more information.
-
-=head2 C<get_source()>
-
-    $response = $e->get_source(
-        index   => 'index_name',        # required
-        type    => 'type_name',         # required
-        id      => 'doc_id',            # required
-    );
-
-The C<get_source()> method works just like the L</get()> method except that
-it returns just the C<_source> field (the value of the C<body> parameter
-in the L</index()> method) instead of returning the C<_source> field
-plus the document metadata, ie the C<_index>, C<_type> etc.
-
-Query string parameters:
-    C<_source>,
-    C<_source_exclude>,
-    C<_source_include>,
-    C<parent>,
-    C<preference>,
-    C<realtime>,
-    C<refresh>,
-    C<routing>,
-    C<version>,
-    C<version_type>
-
-See the L<get_source docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-get.html>
-for more information.
-
-=head2 C<exists()>
-
-    $response = $e->exists(
-        index   => 'index_name',        # required
-        type    => 'type_name',         # required
-        id      => 'doc_id',            # required
-    );
-
-The C<exists()> method returns C<1> if a document with the specified
-C<index>, C<type> and C<id> exists, or an empty string if it doesn't.
-
-Query string parameters:
-    C<parent>,
-    C<preference>,
-    C<realtime>,
-    C<refresh>,
-    C<routing>
-
-See the L<exists docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-get.html>
-for more information.
-
-=head2 C<delete()>
-
-    $response = $e->delete(
-        index   => 'index_name',        # required
-        type    => 'type_name',         # required
-        id      => 'doc_id',            # required
-    );
-
-The C<delete()> method will delete the document with the specified
-C<index>, C<type> and C<id>, or will throw a C<Missing> error.
-
-Query string parameters:
-    C<consistency>,
-    C<parent>,
-    C<refresh>,
-    C<replication>,
-    C<routing>,
-    C<timeout>,
-    C<version>,
-    C<version_type>
-
-See the L<delete docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-delete.html>
-for more information.
-
-=head2 C<update()>
-
-    $response = $e->update(
-        index   => 'index_name',        # required
-        type    => 'type_name',         # required
-        id      => 'doc_id',            # required
-
-        body    => { update }           # required
-    );
-
-The C<update()> method updates a document with the corresponding
-C<index>, C<type> and C<id> if it exists. Updates can be performed either by:
-
-=over
-
-=item * providing a partial document to be merged in to the existing document:
-
-    $response = $e->update(
-        ...,
-        body => {
-            doc => { new_field => 'new_value'},
-        }
-    );
-
-=item * or with a script:
-
-    $response = $e->update(
-        ...,
-        body => {
-            script => "ctx._source.counter += incr",
-            params => { incr => 5 }
-        }
-    );
-
-=back
-
-Query string parameters:
-    C<consistency>,
-    C<fields>,
-    C<lang>,
-    C<parent>,
-    C<realtime>,
-    C<refresh>,
-    C<replication>,
-    C<retry_on_conflict>,
-    C<routing>,
-    C<script>,
-    C<script_id>,
-    C<scripted_upsert>,
-    C<timeout>,
-    C<timestamp>,
-    C<ttl>,
-    C<version>,
-    C<version_type>
-
-See the L<update docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-update.html>
-for more information.
-
-=head2 C<termvectors()>
-
-    $results = $e->termvectors(
-        index   => $index,          # required
-        type    => $type,           # required
-
-        id      => $id,             # optional
-        body    => {...}            # optional
-    )
-
-The C<termvectors()> method retrieves term and field statistics, positions,
-offsets and payloads for the specified document, assuming that termvectors
-have been enabled.
-
-Query string parameters:
-    C<dfs>,
-    C<field_statistics>,
-    C<fields>,
-    C<offsets>,
-    C<parent>,
-    C<payloads>,
-    C<positions>,
-    C<preference>,
-    C<realtime>,
-    C<routing>,
-    C<term_statistics>,
-    C<version>,
-    C<version_type>
-
-See the L<termvector docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-termvectors.html>
-for more information.
-
-=head1 BULK DOCUMENT CRUD METHODS
-
-The bulk document CRUD methods are used for running multiple CRUD actions
-within a single request.  By reducing the number of network requests
-that need to be made, bulk requests greatly improve performance.
-
-=head2 C<bulk()>
-
-    $response = $e->bulk(
-        index   => 'index_name',        # required if type specified
-        type    => 'type_name',         # optional
-
-        body    => [ actions ]          # required
-    );
-
-See L<Search::Elasticsearch::Bulk> and L</bulk_helper()> for a helper module that makes
-bulk indexing simpler to use.
-
-The C<bulk()> method can perform multiple L</index()>, L</create()>,
-L</delete()> or L</update()> actions with a single request. The C<body>
-parameter expects an array containing the list of actions to perform.
-
-An I<action> consists of an initial metadata hash ref containing the action
-type, plus the associated metadata, eg :
-
-    { delete => { _index => 'index', _type => 'type', _id => 123 }}
-
-The C<index> and C<create> actions then expect a hashref containing
-the document itself:
-
-    { create => { _index => 'index', _type => 'type', _id => 123 }},
-    { title => "A newly created document" }
-
-And the C<update> action expects a hashref containing the update commands,
-eg:
-
-    { update => { _index => 'index', _type => 'type', _id => 123 }},
-    { script => "ctx._source.counter+=1" }
-
-Each action can include the same parameters that you would pass to
-the equivalent L</index()>, L</create()>, L</delete()> or L</update()>
-request, except that C<_index>, C<_type> and C<_id> must be specified with
-the preceding underscore. All other parameters can be specified with or
-without the underscore.
-
-For instance:
-
-    $response = $e->bulk(
-        index   => 'index_name',        # default index name
-        type    => 'type_name',         # default type name
-        body    => [
-
-            # create action
-            { create => {
-                _index => 'not_the_default_index',
-                _type  => 'not_the_default_type',
-                _id    => 123
-            }},
-            { title => 'Foo' },
-
-            # index action
-            { index => { _id => 124 }},
-            { title => 'Foo' },
-
-            # delete action
-            { delete => { _id => 125 }},
-
-            # update action
-            { update => { _id => 126 }},
-            { script => "ctx._source.counter+1" }
-        ]
-    );
-
-Each action is performed separately. One failed action will not
-cause the others to fail as well.
-
-Query string parameters:
-    C<consistency>,
-    C<refresh>,
-    C<replication>,
-    C<timeout>
-
-See the L<bulk docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-bulk.html>
-for more information.
-
-=head2 C<bulk_helper()>
-
-    $bulk_helper = $e->bulk_helper( @args );
-
-Returns a new instance of the class specified in the L</bulk_helper_class>,
-which defaults to L<Search::Elasticsearch::Bulk>.
-
-=head2 C<mget()>
-
-    $results = $e->mget(
-        index   => 'default_index',     # optional, required when type specified
-        type    => 'default_type',      # optional
-
-        body    => { docs or ids }      # required
-    );
-
-The C<mget()> method will retrieve multiple documents with a single request.
-The C<body> consists of an array of documents to retrieve:
-
-    $results = $e->mget(
-        index   => 'default_index',
-        type    => 'default_type',
-        body    => {
-            docs => [
-                { _id => 1},
-                { _id => 2, _type => 'not_the_default_type' }
-            ]
-        }
-    );
-
-You can also pass any of the other parameters that the L</get()> request
-accepts.
-
-If you have specified an C<index> and C<type>, you can just include the
-C<ids> of the documents to retrieve:
-
-    $results = $e->mget(
-        index   => 'default_index',
-        type    => 'default_type',
-        body    => {
-            ids => [ 1, 2, 3]
-        }
-    );
-
-Query string parameters:
-    C<_source>,
-    C<_source_exclude>,
-    C<_source_include>,
-    C<fields>,
-    C<preference>,
-    C<realtime>,
-    C<refresh>
-
-See the L<mget docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-multi-get.html>
-for more information.
-
-=head2 C<delete_by_query()>
-
-    $result = $e->delete_by_query(
-        index => 'index' | \@indices,   # required
-        type  => 'type'  | \@types,     # optional
-
-        body  => { query }              # required
-
-    );
-
-The C<delete_by_query()> method deletes all documents which match the
-query.  For instance, to delete all documents from 2012:
-
-    $result = $e->delete_by_query(
-        body  => {
-            query => {
-                range => {
-                    date => {
-                        gte => '2012-01-01',
-                        lt  => '2013-01-01'
-                    }
-                }
-            }
-        }
-    );
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<analyzer>,
-    C<consistency>,
-    C<default_operator>,
-    C<df>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<q>,
-    C<replication>,
-    C<routing>,
-    C<source>,
-    C<timeout>
-
-See the L<delete_by_query docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-delete-by-query.html>
-for more information.
-
-=head2 C<mtermvectors()>
-
-    $results = $e->mtermvectors(
-        index   => $index,          # required if type specified
-        type    => $type,           # optional
-
-        body    => { }              # optional
-    )
-
-Runs multiple L</termvector()> requests in a single request, eg:
-
-    $results = $e->mtermvectors(
-        index   => 'test',
-        body    => {
-            docs => [
-                { _type => 'test', _id => 1, fields => ['text'] },
-                { _type => 'test', _id => 2, payloads => 1 },
-            ]
-        }
-    );
-
-Query string parameters:
-    C<field_statistics>,
-    C<fields>,
-    C<ids>,
-    C<offsets>,
-    C<parent>,
-    C<payloads>,
-    C<positions>,
-    C<preference>,
-    C<realtime>,
-    C<routing>,
-    C<term_statistics>,
-    C<version>,
-    C<version_type>
-
-See the L<mtermvectors docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-multi-termvectors.html>
-for more information.
-
-=head1 SEARCH METHODS
-
-The search methods are used for querying documents in one, more or all indices
-and of one, more or all types:
-
-=head2 C<search()>
-
-    $results = $e->search(
-        index   => 'index' | \@indices,     # optional
-        type    => 'type'  | \@types,       # optional
-
-        body    => { search params }        # optional
-    );
-
-The C<search()> method searches for matching documents in one or more
-indices.  It is just as easy to search a single index as it is to search
-all the indices in your cluster.  It can also return
-L<aggregations|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations.html>
-L<highlighted snippets|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-highlighting.html>
-and L<did-you-mean|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters-phrase.html>
-or L<search-as-you-type|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters-completion.html>
-suggestions.
-
-The I<lite> L<version of search|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-uri-request.html>
-allows you to specify a query string in the C<q> parameter, using the
-Lucene query string syntax:
-
-    $results = $e->search( q => 'title:(elasticsearch clients)');
-
-However, the preferred way to search is by using the
-L<Query DSL|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html>
-to create a query, and passing that C<query> in the
-L<request body|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-body.html>:
-
-    $results = $e->search(
-        body => {
-            query => {
-                match => { title => 'Elasticsearch clients'}
-            }
-        }
-    );
-
-Query string parameters:
-    C<_source>,
-    C<_source_exclude>,
-    C<_source_include>,
-    C<allow_no_indices>,
-    C<analyze_wildcard>,
-    C<analyzer>,
-    C<default_operator>,
-    C<df>,
-    C<expand_wildcards>,
-    C<explain>,
-    C<fields>,
-    C<from>,
-    C<ignore_unavailable>,
-    C<lenient>,
-    C<lowercase_expanded_terms>,
-    C<preference>,
-    C<q>,
-    C<query_cache>,
-    C<routing>,
-    C<scroll>,
-    C<search_type>,
-    C<size>,
-    C<sort>,
-    C<source>,
-    C<stats>,
-    C<suggest_field>,
-    C<suggest_mode>,
-    C<suggest_size>,
-    C<suggest_text>,
-    C<terminate_after>,
-    C<timeout>,
-    C<track_scores>,
-    C<version>
-
-See the L<search reference|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-body.html>
-for more information.
-
-Also see L<Search::Elasticsearch::Transport/send_get_body_as>.
-
-=head2 C<search_exists()>
-
-The C<search_exists()> method is a quick version of search which can be
-used to find out whether there are matching search results or not.
-It doesn't return any results itself.
-
-    $results = $e->search_exists(
-        index   => 'index' | \@indices,     # optional
-        type    => 'type'  | \@types,       # optional
-
-        body    => { search params }        # optional
-    );
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<min_score>,
-    C<preference>,
-    C<routing>,
-    C<source>
-
-See the L<search exists reference|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-exists.html>
-for more information.
-
-=head2 C<count()>
-
-    $results = $e->count(
-        index   => 'index' | \@indices,     # optional
-        type    => 'type'  | \@types,       # optional
-
-        body    => { query }                # optional
-    )
-
-The C<count()> method returns the total count of all documents matching the
-query:
-
-    $results = $e->count(
-        body => {
-            query => {
-                match => { title => 'Elasticsearch clients' }
-            }
-        }
-    );
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<min_score>,
-    C<preference>,
-    C<routing>,
-    C<source>
-
-See the L<count docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-count.html>
-for more information.
-
-=head2 C<search_template()>
-
-    $results = $e->search_template(
-        index   => 'index' | \@indices,     # optional
-        type    => 'type'  | \@types,       # optional
-
-        body    => { search params }        # optional
-    );
-
-Perform a search by specifying a template (either predefined or defined
-within the C<body>) and parameters to use with the template, eg:
-
-    $results = $e->search_template(
-        template => {
-            query => {
-                match => {
-                    "{{my_field}}" => "{{my_value}}"
-                }
-            },
-            size => "{{my_size}}"
-        },
-        params => {
-            my_field => 'foo',
-            my_value => 'bar',
-            my_size  => 5
-        }
-    );
-
-See the L<search template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-template.html>
-for more information.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<preference>,
-    C<scroll>,
-    C<search_type>
-
-=head2 C<scroll()>
-
-    $results = $e->scroll(
-        scroll      => '1m',
-        scroll_id   => $id
-    );
-
-When a L</search()> has been performed with the
-C<scroll> parameter, the C<scroll()>
-method allows you to keep pulling more results until the results
-are exhausted.
-
-B<NOTE:> you will almost always want to set the
-C<search_type> to C<scan> in your
-original C<search()> request.
-
-See L</scroll_helper()> and L<Search::Elasticsearch::Scroll> for a helper utility
-which makes managing scroll requests much easier.
-
-Query string parameters:
-    C<scroll>,
-    C<scroll_id>
-
-See the L<scroll docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-scroll.html>
-and the L<search_type docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search.html/search-request-search-type.html>
-for more information.
-
-=head2 C<clear_scroll()>
-
-    $response = $e->clear_scroll(
-        scroll_id => $id | \@ids    # required
-    );
-
-Or
-
-    $response = $e->clear_scroll(
-        body => $id
-    );
-
-The C<clear_scroll()> method can clear unfinished scroll requests, freeing
-up resources on the server.
-
-=head2 C<scroll_helper()>
-
-    $scroll_helper = $e->scroll_helper( @args );
-
-Returns a new instance of the class specified in the L</scroll_helper_class>,
-which defaults to L<Search::Elasticsearch::Scroll>.
-
-=head2 C<msearch()>
-
-    $results = $e->msearch(
-        index   => 'default_index' | \@indices,     # optional
-        type    => 'default_type'  | \@types,       # optional
-
-        body    => [ searches ]                     # required
-    );
-
-The C<msearch()> method allows you to perform multiple searches in a single
-request.  Similar to the L</bulk()> request, each search request in the
-C<body> consists of two hashes: the metadata hash then the search request
-hash (the same data that you'd specify in the C<body> of a L</search()>
-request).  For instance:
-
-    $results = $e->msearch(
-        index   => 'default_index',
-        type    => ['default_type_1', 'default_type_2'],
-        body => [
-            # uses defaults
-            {},
-            { query => { match_all => {} }},
-
-            # uses a custom index
-            { index => 'not_the_default_index' },
-            { query => { match_all => {} }}
-        ]
-    );
-
-Query string parameters:
-    C<search_type>
-
-See the L<msearch docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-multi-search.html>
-for more information.
-
-=head2 C<explain()>
-
-    $response = $e->explain(
-        index   => 'my_index',  # required
-        type    => 'my_type',   # required
-        id      => 123,         # required
-
-        body    => { search }   # required
-    );
-
-The C<explain()> method explains why the specified document did or
-did not match a query, and how the relevance score was calculated.
-For instance:
-
-    $response = $e->explain(
-        index   => 'my_index',
-        type    => 'my_type',
-        id      => 123,
-        body    => {
-            query => {
-                match => { title => 'Elasticsearch clients' }
-            }
-        }
-    );
-
-Query string parameters:
-    C<_source>,
-    C<_source_exclude>,
-    C<_source_include>,
-    C<analyze_wildcard>,
-    C<analyzer>,
-    C<default_operator>,
-    C<df>,
-    C<fields>,
-    C<lenient>,
-    C<lowercase_expanded_terms>,
-    C<parent>,
-    C<preference>,
-    C<q>,
-    C<routing>,
-    C<source>
-
-See the L<explain docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-explain.html>
-for more information.
-
-=head2 C<search_shards()>
-
-    $response = $e->search_shards(
-        index   => 'index' | \@indices,     # optional
-        type    => 'type'  | \@types,       # optional
-    )
-
-The C<search_shards()> method returns information about which shards on
-which nodes will execute a search request.
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<local>,
-    C<preference>,
-    C<routing>
-
-See the L<search-shards docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-shards.html>
-for more information.
-
-=head1 PERCOLATION METHODS
-
-=head2 C<percolate()>
-
-    $results = $e->percolate(
-        index   => 'my_index',      # required
-        type    => 'my_type',       # required
-
-        body    => { percolation }  # required
-    );
-
-Percolation is search inverted: instead of finding docs which match a
-particular query, it finds queries which match a particular document, eg
-for I<alert-me-when> functionality.
-
-The C<percolate()> method runs a percolation request to find the
-queries matching a particular document. In the C<body> you should pass the
-C<_source> field of the document under the C<doc> key:
-
-    $results = $e->percolate(
-        index   => 'my_index',
-        type    => 'my_type',
-        body    => {
-            doc => {
-                title => 'Elasticsearch rocks'
-            }
-        }
-    );
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<percolate_format>,
-    C<percolate_index>,
-    C<percolate_preference>,
-    C<percolate_routing>,
-    C<percolate_type>,
-    C<preference>,
-    C<routing>,
-    C<version>,
-    C<version_type>
-
-See the L<percolate docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-percolate.html>
-for more information.
-
-=head2 C<count_percolate()>
-
-    $results = $e->count_percolate(
-        index   => 'my_index',      # required
-        type    => 'my_type',       # required
-
-        body    => { percolation }  # required
-    );
-
-The L</count_percolate()> request works just like the L</percolate()>
-request except that it returns a count of all matching queries, instead
-of the queries themselves.
-
-    $results = $e->count_percolate(
-        index   => 'my_index',
-        type    => 'my_type',
-        body    => {
-            doc => {
-                title => 'Elasticsearch rocks'
-            }
-        }
-    );
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<percolate_index>,
-    C<percolate_type>,
-    C<preference>,
-    C<routing>,
-    C<version>,
-    C<version_type>
-
-See the L<percolate docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-percolate.html>
-for more information.
-
-=head2 C<mpercolate()>
-
-    $results = $e->mpercolate(
-        index   => 'my_index',               # required if type
-        type    => 'my_type',                # optional
-
-        body    => [ percolation requests ]  # required
-    );
-
-Multi-percolation allows multiple L</percolate()> requests to be run
-in a single request.
-
-    $results = $e->mpercolate(
-        index   => 'my_index',
-        type    => 'my_type',
-        body    => [
-            # first request
-            { percolate => {
-                index => 'twitter',
-                type  => 'tweet'
-            }},
-            { doc => {message => 'some_text' }},
-
-            # second request
-            { percolate => {
-                index => 'twitter',
-                type  => 'tweet',
-                id    => 1
-            }},
-            {},
-        ]
-    );
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>
-
-See the L<mpercolate docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-percolate.html>
-for more information.
-
-=head2 C<suggest()>
-
-    $results = $e->suggest(
-        index   => 'index' | \@indices,     # optional
-
-        body    => { suggest request }      # required
-    );
-
-The C<suggest()> method is used to run
-L<did-you-mean|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesteres-phrase.html>
-or L<search-as-you-type|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters-completion.html>
-suggestion requests, which can also be run as part of a L</search()> request.
-
-    $results = $e->suggest(
-        index   => 'my_index',
-        body    => {
-            my_suggestions => {
-                phrase  => {
-                    text    => 'johnny walker',
-                    field   => 'title'
-                }
-            }
-        }
-    );
-
-Query string parameters:
-    C<allow_no_indices>,
-    C<expand_wildcards>,
-    C<ignore_unavailable>,
-    C<preference>,
-    C<routing>,
-    C<source>
-
-=head2 C<mlt()>
-
-    $results = $e->mlt(
-        index   => 'my_index',  # required
-        type    => 'my_type',   # required
-        id      => 123,         # required
-
-        body    => { search }   # optional
-    );
-
-The C<mlt()> method runs a
-L<more-like-this query|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html>
-to find other documents which are similar to the specified document.
-
-Query string parameters:
-    C<boost_terms>,
-    C<max_doc_freq>,
-    C<max_query_terms>,
-    C<max_word_length>,
-    C<min_doc_freq>,
-    C<min_term_freq>,
-    C<min_word_length>,
-    C<mlt_fields>,
-    C<percent_terms_to_match>,
-    C<routing>,
-    C<search_from>,
-    C<search_indices>,
-    C<search_scroll>,
-    C<search_size>,
-    C<search_source>,
-    C<search_type>,
-    C<search_types>,
-    C<stop_words>
-
-See the L<mlt docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-more-like-this.html>
-for more information.
-
-=HEAD1 INDEXED SCRIPT METHODS
-
-If dynamic scripting is enabled, Elasticsearch allows you to store scripts in an internal index known as
-C<.scripts> and reference them by id. The methods to manage indexed scripts are as follows:
-
-=head2 C<put_script()>
-
-    $result  = $e->put_script(
-        lang => 'lang',     # required
-        id   => 'id',       # required
-        body => { script }  # required
-    );
-
-The C<put_script()> method is used to store a script in the C<.scripts> index. For instance:
-
-    $result  = $e->put_scripts(
-        lang => 'groovy',
-        id   => 'hello_world',
-        body => {
-          script => q(return "hello world");
-        }
-    );
-
-Query string parameters:
-    C<op_type>,
-    C<version>,
-    C<version_type>
-
-See the L<indexed scripts docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
-
-=head2 C<get_script()>
-
-    $script = $e->get_script(
-        lang => 'lang',     # required
-        id   => 'id',       # required
-    );
-
-Retrieve the indexed script from the C<.scripts> index.
-
-Query string parameters:
-    C<version>,
-    C<version_type>
-
-See the L<indexed scripts docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
-
-=head2 C<delete_script()>
-
-    $script = $e->delete_script(
-        lang => 'lang',     # required
-        id   => 'id',       # required
-    );
-
-Delete the indexed script from the C<.scripts> index.
-
-Query string parameters:
-    C<version>,
-    C<version_type>
-
-See the L<indexed scripts docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
-
-=HEAD1 INDEXED SEARCH TEMPLATE METHODS
-
-Mustache templates can be used to create search requests.  These templates can
-be stored in the C<.scripts> index and retrieved by ID. The methods to
-manage indexed scripts are as follows:
-
-=head2 C<put_template()>
-
-    $result  = $e->put_template(
-        id   => 'id',                       # required
-        body => { template } || "template"  # required
-    );
-
-The C<put_template()> method is used to store a template in the C<.scripts> index.
-For instance:
-
-    $result  = $e->put_template(
-        id   => 'hello_world',
-        body => {
-          template => {
-            query => {
-              match => {
-                title => "hello world"
-              }
-            }
-          }
-      }
-    );
-
-Query string parameters: None
-
-See the L<indexed search template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
-
-=head2 C<get_template()>
-
-    $script = $e->get_template(
-        id   => 'id',       # required
-    );
-
-Retrieve the indexed template from the C<.scripts> index.
-
-Query string parameters:
-    C<version>,
-    C<version_type>
-
-See the L<indexed search template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
-
-=head2 C<delete_template()>
-
-    $script = $e->delete_template(
-        id   => 'id',       # required
-    );
-
-Delete the indexed template from the C<.scripts> index.
-
-Query string parameters: None
-
-See the L<indexed search template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
-
-=head1 BENCHMARK METHODS
-
-=head2 C<benchmark()>
-
-    $results = $e->benchamrk(
-        index   => 'index' | \@indices,     # optional
-        type    => 'type'  | \@types,       # optional
-
-        body    => { search params }        # optional
-    );
-
-Run a search benchmark comparing query variations or the performance of
-different index settings, eg:
-
-    $results = $e->benchmark(
-        index => 'test_index',
-        type  => 'test_type',
-        body  => {
-            name        => 'test_query',
-            competitors => [
-                {
-                    name => 'term_query',
-                    requests =>[
-                        { query => { term => { my_field => 'bar' }}}
-                    ]
-                },
-                {
-                    name => 'match_query',
-                    requests =>[
-                        { query => { match => { my_field => 'bar' }}}
-                    ]
-                },
-            ]
-        }
-    );
-
-See the L<benchamrk docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-benchmark.html> for more.
-
-Query string parameters:
-    C<verbose>
-
-=head2 C<list_benchmarks()>
-
-    $results = $e->list_benchmarks(
-        index   => 'index' | \@indices,     # optional
-        type    => 'type'  | \@types,       # optional
-    )
-
-Lists any currently running benchmarks.
-
-See the L<benchamrk docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-benchmark.html> for more.
-
-=head2 L<abort_benchmark>
-
-    $response = $e->abort_benchmark(
-        name => $name                       # required
-    );
-
-Aborts the named benchmark
-
-See the L<benchamrk docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-benchmark.html> for more.
+This class has been deprecated.  Please see the
+L<Search::Elasticsearch::Client::1_0::Direct> class instead.
 
 =head1 AUTHOR
 
@@ -1563,5 +47,6 @@ This is free software, licensed under:
 
 __END__
 
-# ABSTRACT: Thin client with full support for Elasticsearch APIs
+# ABSTRACT: Deprecated
+
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Cxn::Factory;
-$Search::Elasticsearch::Cxn::Factory::VERSION = '1.19';
+$Search::Elasticsearch::Cxn::Factory::VERSION = '1.20';
 use Moo;
 use Search::Elasticsearch::Util qw(parse_params load_plugin);
 use namespace::clean;
@@ -48,7 +48,7 @@ Search::Elasticsearch::Cxn::Factory - Used by CxnPools to create new Cxn instanc
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Cxn::HTTPTiny;
-$Search::Elasticsearch::Cxn::HTTPTiny::VERSION = '1.19';
+$Search::Elasticsearch::Cxn::HTTPTiny::VERSION = '1.20';
 use Moo;
 with 'Search::Elasticsearch::Role::Cxn::HTTP',
     'Search::Elasticsearch::Role::Cxn',
@@ -85,7 +85,7 @@ Search::Elasticsearch::Cxn::HTTPTiny - A Cxn implementation which uses HTTP::Tin
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,11 +1,11 @@
 package Search::Elasticsearch::Cxn::Hijk;
-$Search::Elasticsearch::Cxn::Hijk::VERSION = '1.19';
+$Search::Elasticsearch::Cxn::Hijk::VERSION = '1.20';
 use Moo;
 with 'Search::Elasticsearch::Role::Cxn::HTTP',
     'Search::Elasticsearch::Role::Cxn',
     'Search::Elasticsearch::Role::Is_Sync';
 
-use Hijk 0.12;
+use Hijk 0.20;
 use Try::Tiny;
 use namespace::clean;
 
@@ -66,11 +66,11 @@ sub perform_request {
     my %head = map { lc($_) => $head->{$_} } keys %$head;
 
     return $self->process_response(
-        $params,                # request
-        $response->{status},    # code
-        $response->{error},     # msg
-        $response->{body},      # body
-        \%head                  # headers
+        $params,    # request
+        $response->{status} || 500,    # code
+        $response->{error},            # msg
+        $response->{body},             # body
+        \%head                         # headers
     );
 }
 
@@ -89,6 +89,8 @@ sub error_from_text {
     my $type
         = 0 + $_ & Hijk::Error::TIMEOUT        ? 'Timeout'
         : 0 + $_ & Hijk::Error::CANNOT_RESOLVE ? 'Cxn'
+        : 0 + $_ & Hijk::Error::REQUEST_ERROR  ? 'Cxn'
+        : 0 + $_ & Hijk::Error::RESPONSE_ERROR ? 'Cxn'
         : /Connection reset by peer/           ? 'ContentLength'
         : m/$Cxn_Error/                        ? 'Cxn'
         :                                        'Request';
@@ -115,7 +117,7 @@ Search::Elasticsearch::Cxn::Hijk - A Cxn implementation which uses Hijk
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Cxn::LWP;
-$Search::Elasticsearch::Cxn::LWP::VERSION = '1.19';
+$Search::Elasticsearch::Cxn::LWP::VERSION = '1.20';
 use Moo;
 with 'Search::Elasticsearch::Role::Cxn::HTTP',
     'Search::Elasticsearch::Role::Cxn',
@@ -94,7 +94,7 @@ Search::Elasticsearch::Cxn::LWP - A Cxn implementation which uses LWP
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::CxnPool::Sniff;
-$Search::Elasticsearch::CxnPool::Sniff::VERSION = '1.19';
+$Search::Elasticsearch::CxnPool::Sniff::VERSION = '1.20';
 use Moo;
 with 'Search::Elasticsearch::Role::CxnPool::Sniff',
     'Search::Elasticsearch::Role::Is_Sync';
@@ -81,7 +81,7 @@ Search::Elasticsearch::CxnPool::Sniff - A CxnPool for connecting to a local clus
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::CxnPool::Static::NoPing;
-$Search::Elasticsearch::CxnPool::Static::NoPing::VERSION = '1.19';
+$Search::Elasticsearch::CxnPool::Static::NoPing::VERSION = '1.20';
 use Moo;
 with 'Search::Elasticsearch::Role::CxnPool::Static::NoPing',
     'Search::Elasticsearch::Role::Is_Sync';
@@ -18,7 +18,7 @@ Search::Elasticsearch::CxnPool::Static::NoPing - A CxnPool for connecting to a r
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::CxnPool::Static;
-$Search::Elasticsearch::CxnPool::Static::VERSION = '1.19';
+$Search::Elasticsearch::CxnPool::Static::VERSION = '1.20';
 use Moo;
 with 'Search::Elasticsearch::Role::CxnPool::Static',
     'Search::Elasticsearch::Role::Is_Sync';
@@ -50,7 +50,7 @@ Search::Elasticsearch::CxnPool::Static - A CxnPool for connecting to a remote cl
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Error;
-$Search::Elasticsearch::Error::VERSION = '1.19';
+$Search::Elasticsearch::Error::VERSION = '1.20';
 use Moo;
 
 our $DEBUG = 0;
@@ -115,15 +115,18 @@ sub _stack {
 
     my @stack;
     while ( my @caller = caller( ++$caller ) ) {
-        if ( $caller[0] eq 'Try::Tiny' or $caller[0] eq 'main' ) {
-            next if $caller[3] eq '(eval)';
-            if ( $caller[3] =~ /^(.+)::__ANON__\[(.+):(\d+)\]$/ ) {
-                @caller = ( $1, $2, $3, '(ANON)' );
-            }
+        next if $caller[0] eq 'Try::Tiny';
+
+        if ( $caller[3] =~ /^(.+)::__ANON__\[(.+):(\d+)\]$/ ) {
+            @caller = ( $1, $2, $3, '(ANON)' );
+        }
+        elsif ( $caller[1] =~ /^\(eval \d+\)/ ) {
+            $caller[3] = "modified(" . $caller[3] . ")";
         }
+
         next
             if $caller[0] =~ /^Search::Elasticsearch/
-            and $DEBUG < 2 || $caller[3] eq 'Try::Tiny::try';
+            and ( $DEBUG < 2 or $caller[3] eq 'Try::Tiny::try' );
         push @stack, [ @caller[ 0, 1, 2, 3 ] ];
         last unless $DEBUG > 1;
     }
@@ -136,15 +139,15 @@ sub stacktrace {
     my $self = shift;
     my $stack = shift || $self->_stack();
 
-    my $o = sprintf "%s\n%-4s %-40s %-5s %s\n%s\n",
-        '-' x 60, '#', 'Package', 'Line', 'Sub-routine', '-' x 60;
+    my $o = sprintf "%s\n%-4s %-50s %-5s %s\n%s\n",
+        '-' x 80, '#', 'Package', 'Line', 'Sub-routine', '-' x 80;
 
     my $i = 1;
     for (@$stack) {
-        $o .= sprintf "%-4d %-40s %4d  %s\n", $i++, @{$_}[ 0, 2, 3 ];
+        $o .= sprintf "%-4d %-50s %4d  %s\n", $i++, @{$_}[ 0, 2, 3 ];
     }
 
-    return $o .= ( '-' x 60 ) . "\n";
+    return $o .= ( '-' x 80 ) . "\n";
 }
 1;
 
@@ -162,7 +165,7 @@ Search::Elasticsearch::Error - Errors thrown by Search::Elasticsearch
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Logger::LogAny;
-$Search::Elasticsearch::Logger::LogAny::VERSION = '1.19';
+$Search::Elasticsearch::Logger::LogAny::VERSION = '1.20';
 use Moo;
 with 'Search::Elasticsearch::Role::Logger';
 use Search::Elasticsearch::Util qw(parse_params to_list);
@@ -44,7 +44,7 @@ Search::Elasticsearch::Logger::LogAny - A Log::Any-based Logger implementation
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::API::0_90;
-$Search::Elasticsearch::Role::API::0_90::VERSION = '1.19';
+$Search::Elasticsearch::Role::API::0_90::VERSION = '1.20';
 use Moo::Role;
 
 use Search::Elasticsearch::Util qw(throw);
@@ -249,10 +249,9 @@ sub api {
             "min_word_len",           "mlt_fields",
             "percent_terms_to_match", "routing",
             "search_from",            "search_indices",
-            "search_scroll",
-            "search_size",            "search_source",
-            "search_type",            "search_types",
-            "stop_words",
+            "search_scroll",          "search_size",
+            "search_source",          "search_type",
+            "search_types",           "stop_words",
         ],
     },
 
@@ -952,12 +951,12 @@ Search::Elasticsearch::Role::API::0_90 - This class contains the spec for the El
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
 All of the Elasticsearch APIs are defined in this role. The example given below
-is the definition for the L<Search::Elasticsearch::Client::Direct/index()> method:
+is the definition for the L<Search::Elasticsearch::Client::0_90::Direct/index()> method:
 
     'index' => {
         body => {
@@ -1005,7 +1004,11 @@ L<Search::Elasticsearch::Util::API::QS>
 
 =item *
 
-L<Search::Elasticsearch::Client::Direct>
+L<Search::Elasticsearch::Client::1_0::Direct>
+
+=item *
+
+L<Search::Elasticsearch::Client::2_0::Direct>
 
 =back
 
@@ -0,0 +1,1683 @@
+package Search::Elasticsearch::Role::API::1_0;
+$Search::Elasticsearch::Role::API::1_0::VERSION = '1.20';
+use Moo::Role;
+
+use Search::Elasticsearch::Util qw(throw);
+use Search::Elasticsearch::Util::API::QS qw(qs_init);
+use namespace::clean;
+
+our %API;
+
+#===================================
+sub api {
+#===================================
+    my $name = $_[1] || return \%API;
+    return $API{$name}
+        || throw( 'Internal', "Unknown api name ($name)" );
+}
+
+#===================================
+%API = (
+#===================================
+
+#=== AUTOGEN - START ===
+
+    'bulk' => {
+        body            => { required => 1 },
+        doc             => "docs-bulk",
+        index_when_type => 1,
+        method          => "POST",
+        parts => { index => {}, type => {} },
+        paths => [
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_bulk" ],
+            [ { index => 0 }, "{index}", "_bulk" ],
+            [ {}, "_bulk" ],
+        ],
+        qs =>
+            [ "consistency", "refresh", "replication", "routing", "timeout" ],
+        serialize => "bulk",
+    },
+
+    'clear_scroll' => {
+        body   => {},
+        doc    => "search-request-scroll",
+        method => "DELETE",
+        parts  => { scroll_id => { multi => 1 } },
+        paths  => [
+            [ { scroll_id => 2 }, "_search", "scroll", "{scroll_id}" ],
+            [ {}, "_search", "scroll" ],
+        ],
+        qs => [],
+    },
+
+    'count' => {
+        body   => {},
+        doc    => "search-count",
+        method => "POST",
+        parts  => { index => { multi => 1 }, type => { multi => 1 } },
+        paths  => [
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_count" ],
+            [ { type => 1 }, "_all", "{type}", "_count" ],
+            [ { index => 0 }, "{index}", "_count" ],
+            [ {}, "_count" ],
+        ],
+        qs => [
+            "allow_no_indices",         "analyze_wildcard",
+            "analyzer",                 "default_operator",
+            "df",                       "expand_wildcards",
+            "ignore_unavailable",       "lenient",
+            "lowercase_expanded_terms", "min_score",
+            "preference",               "q",
+            "routing",
+        ],
+    },
+
+    'count_percolate' => {
+        body  => {},
+        doc   => "search-percolate",
+        parts => {
+            id    => {},
+            index => { required => 1 },
+            type  => { required => 1 }
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}",     "{id}",
+                "_percolate", "count",
+            ],
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_percolate",
+                "count",
+            ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "percolate_index",
+            "percolate_type",     "preference",
+            "routing",            "version",
+            "version_type",
+        ],
+    },
+
+    'delete' => {
+        doc    => "docs-delete",
+        method => "DELETE",
+        parts  => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}"
+            ],
+        ],
+        qs => [
+            "consistency", "parent",  "refresh", "replication",
+            "routing",     "timeout", "version", "version_type",
+        ],
+    },
+
+    'delete_by_query' => {
+        body   => {},
+        doc    => "docs-delete-by-query",
+        method => "DELETE",
+        parts  => {
+            index => { multi => 1, required => 1 },
+            type  => { multi => 1 }
+        },
+        paths => [
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_query" ],
+            [ { index => 0 }, "{index}", "_query" ],
+        ],
+        qs => [
+            "allow_no_indices",   "analyzer",
+            "consistency",        "default_operator",
+            "df",                 "expand_wildcards",
+            "ignore_unavailable", "q",
+            "replication",        "routing",
+            "timeout",
+        ],
+    },
+
+    'delete_script' => {
+        doc    => "modules-scripting",
+        method => "DELETE",
+        parts  => { id => { required => 1 }, lang => { required => 1 } },
+        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
+    'delete_template' => {
+        doc    => "search-template",
+        method => "DELETE",
+        parts  => { id => {} },
+        paths  => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
+    'exists' => {
+        doc    => "docs-get",
+        method => "HEAD",
+        parts  => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}"
+            ],
+        ],
+        qs => [ "parent", "preference", "realtime", "refresh", "routing" ],
+    },
+
+    'explain' => {
+        body  => {},
+        doc   => "search-explain",
+        parts => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}",
+                "_explain",
+            ],
+        ],
+        qs => [
+            "_source",         "_source_exclude",
+            "_source_include", "analyze_wildcard",
+            "analyzer",        "default_operator",
+            "df",              "fields",
+            "lenient",         "lowercase_expanded_terms",
+            "parent",          "preference",
+            "q",               "routing",
+        ],
+    },
+
+    'field_stats' => {
+        doc   => "search-field-stats",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 0 }, "{index}", "_field_stats" ],
+            [ {}, "_field_stats" ],
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "fields",           "ignore_unavailable",
+            "level",
+        ],
+    },
+
+    'get' => {
+        doc   => "docs-get",
+        parts => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}"
+            ],
+        ],
+        qs => [
+            "_source",         "_source_exclude",
+            "_source_include", "fields",
+            "parent",          "preference",
+            "realtime",        "refresh",
+            "routing",         "version",
+            "version_type",
+        ],
+    },
+
+    'get_script' => {
+        doc   => "modules-scripting",
+        parts => { id => { required => 1 }, lang => { required => 1 } },
+        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
+    'get_source' => {
+        doc   => "docs-get",
+        parts => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 },
+                "{index}", "{type}", "{id}", "_source",
+            ],
+        ],
+        qs => [
+            "_source",         "_source_exclude",
+            "_source_include", "parent",
+            "preference",      "realtime",
+            "refresh",         "routing",
+            "version",         "version_type",
+        ],
+    },
+
+    'get_template' => {
+        doc   => "search-template",
+        parts => { id => { required => 1 } },
+        paths => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
+    'index' => {
+        body   => { required => 1 },
+        doc    => "docs-index_",
+        method => "POST",
+        parts  => {
+            id    => {},
+            index => { required => 1 },
+            type  => { required => 1 }
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}"
+            ],
+            [ { index => 0, type => 1 }, "{index}", "{type}" ],
+        ],
+        qs => [
+            "consistency", "op_type", "parent",    "refresh",
+            "routing",     "timeout", "timestamp", "ttl",
+            "version",     "version_type",
+        ],
+    },
+
+    'info' => { doc => "", parts => {}, paths => [ [ {} ] ], qs => [] },
+
+    'mget' => {
+        body            => { required => 1 },
+        doc             => "docs-multi-get",
+        index_when_type => 1,
+        parts => { index => {}, type => {} },
+        paths => [
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_mget" ],
+            [ { index => 0 }, "{index}", "_mget" ],
+            [ {}, "_mget" ],
+        ],
+        qs => [
+            "_source",         "_source_exclude",
+            "_source_include", "fields",
+            "preference",      "realtime",
+            "refresh",
+        ],
+    },
+
+    'mlt' => {
+        body  => {},
+        doc   => "search-more-like-this",
+        parts => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 },
+                "{index}", "{type}", "{id}", "_mlt",
+            ],
+        ],
+        qs => [
+            "boost_terms",            "max_doc_freq",
+            "max_query_terms",        "max_word_length",
+            "min_doc_freq",           "min_term_freq",
+            "min_word_length",        "mlt_fields",
+            "percent_terms_to_match", "routing",
+            "search_from",            "search_indices",
+            "search_scroll",          "search_size",
+            "search_source",          "search_type",
+            "search_types",           "stop_words",
+        ],
+    },
+
+    'mpercolate' => {
+        body            => { required => 1 },
+        doc             => "search-percolate",
+        index_when_type => 1,
+        parts => { index => {}, type => {} },
+        paths => [
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_mpercolate" ],
+            [ { index => 0 }, "{index}", "_mpercolate" ],
+            [ {}, "_mpercolate" ],
+        ],
+        qs =>
+            [ "allow_no_indices", "expand_wildcards", "ignore_unavailable" ],
+        serialize => "bulk",
+    },
+
+    'msearch' => {
+        body => { required => 1 },
+        doc  => "search-multi-search",
+        parts => { index => { multi => 1 }, type => { multi => 1 } },
+        paths => [
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_msearch" ],
+            [ { type => 1 }, "_all", "{type}", "_msearch" ],
+            [ { index => 0 }, "{index}", "_msearch" ],
+            [ {}, "_msearch" ],
+        ],
+        qs        => ["search_type"],
+        serialize => "bulk",
+    },
+
+    'mtermvectors' => {
+        body            => {},
+        doc             => "docs-multi-termvectors",
+        index_when_type => 1,
+        parts           => { index => {}, type => {} },
+        paths           => [
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_mtermvectors"
+            ],
+            [ { index => 0 }, "{index}", "_mtermvectors" ],
+            [ {}, "_mtermvectors" ],
+        ],
+        qs => [
+            "field_statistics", "fields",
+            "ids",              "offsets",
+            "parent",           "payloads",
+            "positions",        "preference",
+            "realtime",         "routing",
+            "term_statistics",  "version",
+            "version_type",
+        ],
+    },
+
+    'percolate' => {
+        body  => {},
+        doc   => "search-percolate",
+        parts => {
+            id    => {},
+            index => { required => 1 },
+            type  => { required => 1 }
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}",
+                "_percolate",
+            ],
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_percolate" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "percolate_format",
+            "percolate_index",    "percolate_preference",
+            "percolate_routing",  "percolate_type",
+            "preference",         "routing",
+            "version",            "version_type",
+        ],
+    },
+
+    'ping' => {
+        doc    => "",
+        method => "HEAD",
+        parts  => {},
+        paths  => [ [ {} ] ],
+        qs     => []
+    },
+
+    'put_script' => {
+        body   => { required => 1 },
+        doc    => "modules-scripting",
+        method => "PUT",
+        parts => { id => { required => 1 }, lang => { required => 1 } },
+        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
+        qs => [ "op_type", "version", "version_type" ],
+    },
+
+    'put_template' => {
+        body   => { required => 1 },
+        doc    => "search-template",
+        method => "PUT",
+        parts => { id => { required => 1 } },
+        paths => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
+        qs => [ "op_type", "version", "version_type" ],
+    },
+
+    'scroll' => {
+        body  => {},
+        doc   => "search-request-scroll",
+        parts => { scroll_id => {} },
+        paths => [
+            [ { scroll_id => 2 }, "_search", "scroll", "{scroll_id}" ],
+            [ {}, "_search", "scroll" ],
+        ],
+        qs => ["scroll"],
+    },
+
+    'search' => {
+        body  => {},
+        doc   => "search-search",
+        parts => { index => { multi => 1 }, type => { multi => 1 } },
+        paths => [
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_search" ],
+            [ { type => 1 }, "_all", "{type}", "_search" ],
+            [ { index => 0 }, "{index}", "_search" ],
+            [ {}, "_search" ],
+        ],
+        qs => [
+            "_source",          "_source_exclude",
+            "_source_include",  "allow_no_indices",
+            "analyze_wildcard", "analyzer",
+            "default_operator", "df",
+            "expand_wildcards", "explain",
+            "fielddata_fields", "fields",
+            "from",             "ignore_unavailable",
+            "lenient",          "lowercase_expanded_terms",
+            "preference",       "q",
+            "query_cache",      "routing",
+            "scroll",           "search_type",
+            "size",             "sort",
+            "stats",            "suggest_field",
+            "suggest_mode",     "suggest_size",
+            "suggest_text",     "timeout",
+            "track_scores",     "version",
+        ],
+    },
+
+    'search_exists' => {
+        body   => {},
+        doc    => "search-exists",
+        method => "POST",
+        parts  => { index => { multi => 1 }, type => { multi => 1 } },
+        paths  => [
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_search",
+                "exists",
+            ],
+            [ { type => 1 }, "_all", "{type}", "_search", "exists" ],
+            [ { index => 0 }, "{index}", "_search", "exists" ],
+            [ {}, "_search", "exists" ],
+        ],
+        qs => [
+            "allow_no_indices",         "analyze_wildcard",
+            "analyzer",                 "default_operator",
+            "df",                       "expand_wildcards",
+            "ignore_unavailable",       "lenient",
+            "lowercase_expanded_terms", "min_score",
+            "preference",               "q",
+            "routing",
+        ],
+    },
+
+    'search_shards' => {
+        doc   => "search-shards",
+        parts => { index => {}, type => {} },
+        paths => [
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_search_shards",
+            ],
+            [ { type => 1 }, "_all", "{type}", "_search_shards" ],
+            [ { index => 0 }, "{index}", "_search_shards" ],
+            [ {}, "_search_shards" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+            "preference",         "routing",
+        ],
+    },
+
+    'search_template' => {
+        body  => {},
+        doc   => "search-template",
+        parts => { index => { multi => 1 }, type => { multi => 1 } },
+        paths => [
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_search",
+                "template",
+            ],
+            [ { type => 1 }, "_all", "{type}", "_search", "template" ],
+            [ { index => 0 }, "{index}", "_search", "template" ],
+            [ {}, "_search", "template" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "preference",
+            "routing",            "scroll",
+            "search_type",
+        ],
+    },
+
+    'suggest' => {
+        body   => { required => 1 },
+        doc    => "search-suggesters",
+        method => "POST",
+        parts => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_suggest" ], [ {}, "_suggest" ] ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "preference",
+            "routing",
+        ],
+    },
+
+    'termvector' => {
+        body  => {},
+        doc   => "docs-termvectors",
+        parts => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}",
+                "_termvector",
+            ],
+        ],
+        qs => [
+            "field_statistics", "fields",
+            "offsets",          "parent",
+            "payloads",         "positions",
+            "preference",       "realtime",
+            "routing",          "term_statistics",
+        ],
+    },
+
+    'termvectors' => {
+        body  => {},
+        doc   => "docs-termvectors",
+        parts => {
+            id    => {},
+            index => { required => 1 },
+            type  => { required => 1 }
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}",
+                "_termvectors",
+            ],
+            [   { index => 0, type => 1 }, "{index}", "{type}",
+                "_termvectors"
+            ],
+        ],
+        qs => [
+            "field_statistics", "fields",
+            "offsets",          "parent",
+            "payloads",         "positions",
+            "preference",       "realtime",
+            "routing",          "term_statistics",
+            "version",          "version_type",
+        ],
+    },
+
+    'update' => {
+        body   => {},
+        doc    => "docs-update",
+        method => "POST",
+        parts  => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 },
+                "{index}", "{type}", "{id}", "_update",
+            ],
+        ],
+        qs => [
+            "consistency",       "fields",
+            "lang",              "parent",
+            "refresh",           "replication",
+            "retry_on_conflict", "routing",
+            "script",            "script_id",
+            "scripted_upsert",   "timeout",
+            "timestamp",         "ttl",
+            "version",           "version_type",
+        ],
+    },
+
+    'cat.aliases' => {
+        doc   => "cat-alias",
+        parts => { name => { multi => 1 } },
+        paths => [
+            [ { name => 2 }, "_cat", "aliases", "{name}" ],
+            [ {}, "_cat", "aliases" ],
+        ],
+        qs => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.allocation' => {
+        doc   => "cat-allocation",
+        parts => { node_id => { multi => 1 } },
+        paths => [
+            [ { node_id => 2 }, "_cat", "allocation", "{node_id}" ],
+            [ {}, "_cat", "allocation" ],
+        ],
+        qs => [ "bytes", "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.count' => {
+        doc   => "cat-count",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 2 }, "_cat", "count", "{index}" ],
+            [ {}, "_cat", "count" ],
+        ],
+        qs => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.fielddata' => {
+        doc   => "cat-fielddata",
+        parts => { fields => { multi => 1 } },
+        paths => [
+            [ { fields => 2 }, "_cat", "fielddata", "{fields}" ],
+            [ {}, "_cat", "fielddata" ],
+        ],
+        qs => [ "bytes", "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.health' => {
+        doc   => "cat-health",
+        parts => {},
+        paths => [ [ {}, "_cat", "health" ] ],
+        qs    => [ "h", "help", "local", "master_timeout", "ts", "v" ],
+    },
+
+    'cat.help' => {
+        doc   => "cat",
+        parts => {},
+        paths => [ [ {}, "_cat" ] ],
+        qs    => ["help"]
+    },
+
+    'cat.indices' => {
+        doc   => "cat-indices",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 2 }, "_cat", "indices", "{index}" ],
+            [ {}, "_cat", "indices" ],
+        ],
+        qs => [ "bytes", "h", "help", "local", "master_timeout", "pri", "v" ],
+    },
+
+    'cat.master' => {
+        doc   => "cat-master",
+        parts => {},
+        paths => [ [ {}, "_cat", "master" ] ],
+        qs    => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.nodes' => {
+        doc   => "cat-nodes",
+        parts => {},
+        paths => [ [ {}, "_cat", "nodes" ] ],
+        qs    => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.pending_tasks' => {
+        doc   => "cat-pending-tasks",
+        parts => {},
+        paths => [ [ {}, "_cat", "pending_tasks" ] ],
+        qs    => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.plugins' => {
+        doc   => "cat-plugins",
+        parts => {},
+        paths => [ [ {}, "_cat", "plugins" ] ],
+        qs    => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.recovery' => {
+        doc   => "cat-recovery",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 2 }, "_cat", "recovery", "{index}" ],
+            [ {}, "_cat", "recovery" ],
+        ],
+        qs => [ "bytes", "h", "help", "master_timeout", "v" ],
+    },
+
+    'cat.segments' => {
+        doc   => "cat-segments",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 2 }, "_cat", "segments", "{index}" ],
+            [ {}, "_cat", "segments" ],
+        ],
+        qs => [ "h", "help", "v" ],
+    },
+
+    'cat.shards' => {
+        doc   => "cat-shards",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 2 }, "_cat", "shards", "{index}" ],
+            [ {}, "_cat", "shards" ],
+        ],
+        qs => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.thread_pool' => {
+        doc   => "cat-thread-pool",
+        parts => {},
+        paths => [ [ {}, "_cat", "thread_pool" ] ],
+        qs    => [ "full_id", "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cluster.get_settings' => {
+        doc   => "cluster-update-settings",
+        parts => {},
+        paths => [ [ {}, "_cluster", "settings" ] ],
+        qs => [ "flat_settings", "master_timeout", "timeout" ],
+    },
+
+    'cluster.health' => {
+        doc   => "cluster-health",
+        parts => { index => {} },
+        paths => [
+            [ { index => 2 }, "_cluster", "health", "{index}" ],
+            [ {}, "_cluster", "health" ],
+        ],
+        qs => [
+            "level",                      "local",
+            "master_timeout",             "timeout",
+            "wait_for_active_shards",     "wait_for_nodes",
+            "wait_for_relocating_shards", "wait_for_status",
+        ],
+    },
+
+    'cluster.pending_tasks' => {
+        doc   => "cluster-pending",
+        parts => {},
+        paths => [ [ {}, "_cluster", "pending_tasks" ] ],
+        qs => [ "local", "master_timeout" ],
+    },
+
+    'cluster.put_settings' => {
+        body   => {},
+        doc    => "cluster-update-settings",
+        method => "PUT",
+        parts  => {},
+        paths  => [ [ {}, "_cluster", "settings" ] ],
+        qs => [ "flat_settings", "master_timeout", "timeout" ],
+    },
+
+    'cluster.reroute' => {
+        body   => {},
+        doc    => "cluster-reroute",
+        method => "POST",
+        parts  => {},
+        paths  => [ [ {}, "_cluster", "reroute" ] ],
+        qs => [ "dry_run", "explain", "master_timeout", "metric", "timeout" ],
+    },
+
+    'cluster.state' => {
+        doc   => "cluster-state",
+        parts => { index => { multi => 1 }, metric => { multi => 1 } },
+        paths => [
+            [   { index => 3, metric => 2 }, "_cluster",
+                "state", "{metric}",
+                "{index}",
+            ],
+            [ { index => 3 }, "_cluster", "state", "_all", "{index}" ],
+            [ { metric => 2 }, "_cluster", "state", "{metric}" ],
+            [ {}, "_cluster", "state" ],
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "flat_settings",    "ignore_unavailable",
+            "local",            "master_timeout",
+        ],
+    },
+
+    'cluster.stats' => {
+        doc   => "cluster-stats",
+        parts => { node_id => { multi => 1 } },
+        paths => [
+            [ { node_id => 3 }, "_cluster", "stats", "nodes", "{node_id}" ],
+            [ {}, "_cluster", "stats" ],
+        ],
+        qs => [ "flat_settings", "human" ],
+    },
+
+    'indices.analyze' => {
+        body  => {},
+        doc   => "indices-analyze",
+        parts => { index => {} },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_analyze" ], [ {}, "_analyze" ] ],
+        qs => [
+            "analyzer", "char_filters", "field", "filters",
+            "format",   "prefer_local", "text",  "tokenizer",
+        ],
+    },
+
+    'indices.clear_cache' => {
+        doc    => "indices-clearcache",
+        method => "POST",
+        parts  => { index => { multi => 1 } },
+        paths  => [
+            [ { index => 0 }, "{index}", "_cache", "clear" ],
+            [ {}, "_cache", "clear" ],
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "fielddata",        "fields",
+            "filter",           "filter_cache",
+            "filter_keys",      "id",
+            "id_cache",         "ignore_unavailable",
+            "query_cache",      "recycler",
+        ],
+    },
+
+    'indices.close' => {
+        doc    => "indices-open-close",
+        method => "POST",
+        parts  => { index => { required => 1 } },
+        paths  => [ [ { index => 0 }, "{index}", "_close" ] ],
+        qs     => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "master_timeout",
+            "timeout",
+        ],
+    },
+
+    'indices.create' => {
+        body   => {},
+        doc    => "indices-create-index",
+        method => "PUT",
+        parts  => { index => { required => 1 } },
+        paths  => [ [ { index => 0 }, "{index}" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'indices.delete' => {
+        doc    => "indices-delete-index",
+        method => "DELETE",
+        parts  => { index => { multi => 1, required => 1 } },
+        paths => [ [ { index => 0 }, "{index}" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'indices.delete_alias' => {
+        doc    => "indices-aliases",
+        method => "DELETE",
+        parts  => {
+            index => { multi => 1, required => 1 },
+            name  => { multi => 1, required => 1 },
+        },
+        paths =>
+            [ [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'indices.delete_mapping' => {
+        doc    => "indices-delete-mapping",
+        method => "DELETE",
+        parts  => {
+            index => { multi => 1, required => 1 },
+            type  => { multi => 1, required => 1 },
+        },
+        paths => [
+            [ { index => 0, type => 2 }, "{index}", "_mapping", "{type}" ]
+        ],
+        qs => ["master_timeout"],
+    },
+
+    'indices.delete_template' => {
+        doc    => "indices-templates",
+        method => "DELETE",
+        parts  => { name => { required => 1 } },
+        paths  => [ [ { name => 1 }, "_template", "{name}" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'indices.delete_warmer' => {
+        doc    => "indices-warmers",
+        method => "DELETE",
+        parts  => {
+            index => { multi => 1, required => 1 },
+            name  => { multi => 1, required => 1 },
+        },
+        paths =>
+            [ [ { index => 0, name => 2 }, "{index}", "_warmer", "{name}" ] ],
+        qs => ["master_timeout"],
+    },
+
+    'indices.exists' => {
+        doc    => "indices-exists",
+        method => "HEAD",
+        parts  => { index => { multi => 1, required => 1 } },
+        paths => [ [ { index => 0 }, "{index}" ] ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.exists_alias' => {
+        doc    => "indices-aliases",
+        method => "HEAD",
+        parts  => { index => { multi => 1 }, name => { multi => 1 } },
+        paths  => [
+            [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ],
+            [ { index => 0 }, "{index}", "_alias" ],
+            [ { name  => 1 }, "_alias",  "{name}" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.exists_template' => {
+        doc    => "indices-templates",
+        method => "HEAD",
+        parts  => { name => { required => 1 } },
+        paths  => [ [ { name => 1 }, "_template", "{name}" ] ],
+        qs => [ "local", "master_timeout" ],
+    },
+
+    'indices.exists_type' => {
+        doc    => "indices-types-exists",
+        method => "HEAD",
+        parts  => {
+            index => { multi => 1, required => 1 },
+            type  => { multi => 1, required => 1 },
+        },
+        paths => [ [ { index => 0, type => 1 }, "{index}", "{type}" ] ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.flush' => {
+        doc    => "indices-flush",
+        method => "POST",
+        parts  => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_flush" ], [ {}, "_flush" ] ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "force",              "full",
+            "ignore_unavailable", "wait_if_ongoing",
+        ],
+    },
+
+    'indices.get' => {
+        doc   => "indices-get-index",
+        parts => {
+            feature => { multi => 1 },
+            index   => { multi => 1, required => 1 }
+        },
+        paths => [
+            [ { feature => 1, index => 0 }, "{index}", "{feature}" ],
+            [ { index => 0 }, "{index}" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.get_alias' => {
+        doc   => "indices-aliases",
+        parts => { index => { multi => 1 }, name => { multi => 1 } },
+        paths => [
+            [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ],
+            [ { index => 0 }, "{index}", "_alias" ],
+            [ { name  => 1 }, "_alias",  "{name}" ],
+            [ {}, "_alias" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.get_aliases' => {
+        doc   => "indices-aliases",
+        parts => { index => { multi => 1 }, name => { multi => 1 } },
+        paths => [
+            [ { index => 0, name => 2 }, "{index}", "_aliases", "{name}" ],
+            [ { index => 0 }, "{index}",  "_aliases" ],
+            [ { name  => 1 }, "_aliases", "{name}" ],
+            [ {}, "_aliases" ],
+        ],
+        qs => [ "local", "timeout" ],
+    },
+
+    'indices.get_field_mapping' => {
+        doc   => "indices-get-field-mapping",
+        parts => {
+            field => { multi => 1, required => 1 },
+            index => { multi => 1 },
+            type  => { multi => 1 },
+        },
+        paths => [
+            [   { field => 4, index => 0, type => 2 }, "{index}",
+                "_mapping", "{type}",
+                "field",    "{field}",
+            ],
+            [   { field => 3, index => 0 }, "{index}",
+                "_mapping", "field",
+                "{field}",
+            ],
+            [   { field => 3, type => 1 }, "_mapping",
+                "{type}", "field",
+                "{field}",
+            ],
+            [ { field => 2 }, "_mapping", "field", "{field}" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "include_defaults",
+            "local",
+        ],
+    },
+
+    'indices.get_mapping' => {
+        doc   => "indices-get-mapping",
+        parts => { index => { multi => 1 }, type => { multi => 1 } },
+        paths => [
+            [ { index => 0, type => 2 }, "{index}", "_mapping", "{type}" ],
+            [ { index => 0 }, "{index}",  "_mapping" ],
+            [ { type  => 1 }, "_mapping", "{type}" ],
+            [ {}, "_mapping" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.get_settings' => {
+        doc   => "indices-get-settings",
+        parts => { index => { multi => 1 }, name => { multi => 1 } },
+        paths => [
+            [ { index => 0, name => 2 }, "{index}", "_settings", "{name}" ],
+            [ { index => 0 }, "{index}",   "_settings" ],
+            [ { name  => 1 }, "_settings", "{name}" ],
+            [ {}, "_settings" ],
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "flat_settings",    "ignore_unavailable",
+            "local",
+        ],
+    },
+
+    'indices.get_template' => {
+        doc   => "indices-templates",
+        parts => { name => {} },
+        paths =>
+            [ [ { name => 1 }, "_template", "{name}" ], [ {}, "_template" ] ],
+        qs => [ "flat_settings", "local", "master_timeout" ],
+    },
+
+    'indices.get_upgrade' => {
+        doc   => "indices-upgrade",
+        parts => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_upgrade" ], [ {}, "_upgrade" ] ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "human",            "ignore_unavailable",
+        ],
+    },
+
+    'indices.get_warmer' => {
+        doc   => "indices-warmers",
+        parts => {
+            index => { multi => 1 },
+            name  => { multi => 1 },
+            type  => { multi => 1 }
+        },
+        paths => [
+            [   { index => 0, name => 3, type => 1 },
+                "{index}", "{type}", "_warmer", "{name}",
+            ],
+            [   { name => 3, type => 1 }, "_all",
+                "{type}", "_warmer",
+                "{name}"
+            ],
+            [ { index => 0, name => 2 }, "{index}", "_warmer", "{name}" ],
+            [ { index => 0 }, "{index}", "_warmer" ],
+            [ { name  => 1 }, "_warmer", "{name}" ],
+            [ {}, "_warmer" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.open' => {
+        doc    => "indices-open-close",
+        method => "POST",
+        parts  => { index => { required => 1 } },
+        paths  => [ [ { index => 0 }, "{index}", "_open" ] ],
+        qs     => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "master_timeout",
+            "timeout",
+        ],
+    },
+
+    'indices.optimize' => {
+        doc    => "indices-optimize",
+        method => "POST",
+        parts  => { index => { multi => 1 } },
+        paths  => [
+            [ { index => 0 }, "{index}", "_optimize" ],
+            [ {}, "_optimize" ]
+        ],
+        qs => [
+            "allow_no_indices",     "expand_wildcards",
+            "flush",                "force",
+            "ignore_unavailable",   "max_num_segments",
+            "only_expunge_deletes", "wait_for_merge",
+        ],
+    },
+
+    'indices.put_alias' => {
+        body   => {},
+        doc    => "indices-aliases",
+        method => "PUT",
+        parts  => {
+            index => { multi    => 1, required => 1 },
+            name  => { required => 1 }
+        },
+        paths =>
+            [ [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'indices.put_mapping' => {
+        body   => { required => 1 },
+        doc    => "indices-put-mapping",
+        method => "PUT",
+        parts => { index => { multi => 1 }, type => { required => 1 } },
+        paths => [
+            [ { index => 0, type => 2 }, "{index}", "_mapping", "{type}" ],
+            [ { type => 1 }, "_mapping", "{type}" ],
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "ignore_conflicts", "ignore_unavailable",
+            "master_timeout",   "timeout",
+        ],
+    },
+
+    'indices.put_settings' => {
+        body   => { required => 1 },
+        doc    => "indices-update-settings",
+        method => "PUT",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 0 }, "{index}", "_settings" ],
+            [ {}, "_settings" ]
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "flat_settings",    "ignore_unavailable",
+            "master_timeout",
+        ],
+    },
+
+    'indices.put_template' => {
+        body   => { required => 1 },
+        doc    => "indices-templates",
+        method => "PUT",
+        parts => { name => { required => 1 } },
+        paths => [ [ { name => 1 }, "_template", "{name}" ] ],
+        qs => [
+            "create",         "flat_settings",
+            "master_timeout", "order",
+            "timeout"
+        ],
+    },
+
+    'indices.put_warmer' => {
+        body   => { required => 1 },
+        doc    => "indices-warmers",
+        method => "PUT",
+        parts  => {
+            index => { multi    => 1 },
+            name  => { required => 1 },
+            type  => { multi    => 1 },
+        },
+        paths => [
+            [   { index => 0, name => 3, type => 1 },
+                "{index}", "{type}", "_warmer", "{name}",
+            ],
+            [   { name => 3, type => 1 }, "_all",
+                "{type}", "_warmer",
+                "{name}"
+            ],
+            [ { index => 0, name => 2 }, "{index}", "_warmer", "{name}" ],
+            [ { name => 1 }, "_warmer", "{name}" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "master_timeout",
+        ],
+    },
+
+    'indices.recovery' => {
+        doc   => "indices-recovery",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 0 }, "{index}", "_recovery" ],
+            [ {}, "_recovery" ]
+        ],
+        qs => [ "active_only", "detailed", "human" ],
+    },
+
+    'indices.refresh' => {
+        doc    => "indices-refresh",
+        method => "POST",
+        parts  => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_refresh" ], [ {}, "_refresh" ] ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "force",            "ignore_unavailable",
+        ],
+    },
+
+    'indices.segments' => {
+        doc   => "indices-segments",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 0 }, "{index}", "_segments" ],
+            [ {}, "_segments" ]
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "human",            "ignore_unavailable",
+        ],
+    },
+
+    'indices.snapshot_index' => {
+        doc    => "indices-gateway-snapshot",
+        method => "POST",
+        parts  => { index => { multi => 1 } },
+        paths  => [
+            [ { index => 0 }, "{index}", "_gateway", "snapshot" ],
+            [ {}, "_gateway", "snapshot" ],
+        ],
+        qs =>
+            [ "allow_no_indices", "expand_wildcards", "ignore_unavailable" ],
+    },
+
+    'indices.stats' => {
+        doc   => "indices-stats",
+        parts => { index => { multi => 1 }, metric => { multi => 1 } },
+        paths => [
+            [ { index => 0, metric => 2 }, "{index}", "_stats", "{metric}" ],
+            [ { index  => 0 }, "{index}", "_stats" ],
+            [ { metric => 1 }, "_stats",  "{metric}" ],
+            [ {}, "_stats" ],
+        ],
+        qs => [
+            "completion_fields", "fielddata_fields",
+            "fields",            "groups",
+            "human",             "level",
+            "types",
+        ],
+    },
+
+    'indices.status' => {
+        doc   => "indices-status",
+        parts => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_status" ], [ {}, "_status" ] ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "human",            "ignore_unavailable",
+            "recovery",         "snapshot",
+        ],
+    },
+
+    'indices.update_aliases' => {
+        body   => { required => 1 },
+        doc    => "indices-aliases",
+        method => "POST",
+        parts  => {},
+        paths => [ [ {}, "_aliases" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'indices.upgrade' => {
+        doc    => "indices-upgrade",
+        method => "POST",
+        parts  => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_upgrade" ], [ {}, "_upgrade" ] ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "only_ancient_segments",
+            "wait_for_completion",
+        ],
+    },
+
+    'indices.validate_query' => {
+        body  => {},
+        doc   => "search-validate",
+        parts => { index => { multi => 1 }, type => { multi => 1 } },
+        paths => [
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_validate",
+                "query",
+            ],
+            [ { type => 1 }, "_all", "{type}", "_validate", "query" ],
+            [ { index => 0 }, "{index}", "_validate", "query" ],
+            [ {}, "_validate", "query" ],
+        ],
+        qs => [
+            "allow_no_indices", "analyze_wildcard",
+            "analyzer",         "default_operator",
+            "df",               "expand_wildcards",
+            "explain",          "ignore_unavailable",
+            "lenient",          "lowercase_expanded_terms",
+            "q",
+        ],
+    },
+
+    'nodes.hot_threads' => {
+        doc   => "cluster-nodes-hot-threads",
+        parts => { node_id => { multi => 1 } },
+        paths => [
+            [ { node_id => 1 }, "_nodes", "{node_id}", "hot_threads" ],
+            [ {}, "_nodes", "hot_threads" ],
+        ],
+        qs => [
+            "ignore_idle_threads", "interval",
+            "snapshots",           "threads",
+            "type",
+        ],
+    },
+
+    'nodes.info' => {
+        doc   => "cluster-nodes-info",
+        parts => { metric => { multi => 1 }, node_id => { multi => 1 } },
+        paths => [
+            [   { metric => 2, node_id => 1 }, "_nodes",
+                "{node_id}", "{metric}",
+            ],
+            [ { metric => 2 }, "_nodes", "_all", "{metric}" ],
+            [ { node_id => 1 }, "_nodes", "{node_id}" ],
+            [ {}, "_nodes" ],
+        ],
+        qs => [ "flat_settings", "human" ],
+    },
+
+    'nodes.shutdown' => {
+        doc    => "cluster-nodes-shutdown",
+        method => "POST",
+        parts  => { node_id => { multi => 1 } },
+        paths  => [
+            [   { node_id => 2 }, "_cluster",
+                "nodes", "{node_id}",
+                "_shutdown"
+            ],
+            [ {}, "_shutdown" ],
+        ],
+        qs => [ "delay", "exit" ],
+    },
+
+    'nodes.stats' => {
+        doc   => "cluster-nodes-stats",
+        parts => {
+            index_metric => { multi => 1 },
+            metric       => { multi => 1 },
+            node_id      => { multi => 1 },
+        },
+        paths => [
+            [   { index_metric => 4, metric => 3, node_id => 1 },
+                "_nodes", "{node_id}", "stats", "{metric}", "{index_metric}",
+            ],
+            [   { index_metric => 4, node_id => 1 },
+                "_nodes", "{node_id}", "stats", "_all", "{index_metric}",
+            ],
+            [   { index_metric => 3, metric => 2 }, "_nodes",
+                "stats", "{metric}",
+                "{index_metric}",
+            ],
+            [   { index_metric => 3 }, "_nodes",
+                "stats", "_all",
+                "{index_metric}",
+            ],
+            [   { metric => 3, node_id => 1 }, "_nodes",
+                "{node_id}", "stats",
+                "{metric}",
+            ],
+            [ { metric  => 2 }, "_nodes", "stats",     "{metric}" ],
+            [ { node_id => 1 }, "_nodes", "{node_id}", "stats" ],
+            [ {}, "_nodes", "stats" ],
+        ],
+        qs => [
+            "completion_fields", "fielddata_fields",
+            "fields",            "groups",
+            "human",             "level",
+            "types",
+        ],
+    },
+
+    'snapshot.create' => {
+        body   => {},
+        doc    => "modules-snapshots",
+        method => "PUT",
+        parts  => {
+            repository => { required => 1 },
+            snapshot   => { required => 1 }
+        },
+        paths => [
+            [   { repository => 1, snapshot => 2 }, "_snapshot",
+                "{repository}", "{snapshot}",
+            ],
+        ],
+        qs => [ "master_timeout", "wait_for_completion" ],
+    },
+
+    'snapshot.create_repository' => {
+        body   => { required => 1 },
+        doc    => "modules-snapshots",
+        method => "PUT",
+        parts => { repository => { required => 1 } },
+        paths => [ [ { repository => 1 }, "_snapshot", "{repository}" ] ],
+        qs => [ "master_timeout", "timeout", "verify" ],
+    },
+
+    'snapshot.delete' => {
+        doc    => "modules-snapshots",
+        method => "DELETE",
+        parts  => {
+            repository => { required => 1 },
+            snapshot   => { required => 1 }
+        },
+        paths => [
+            [   { repository => 1, snapshot => 2 }, "_snapshot",
+                "{repository}", "{snapshot}",
+            ],
+        ],
+        qs => ["master_timeout"],
+    },
+
+    'snapshot.delete_repository' => {
+        doc    => "modules-snapshots",
+        method => "DELETE",
+        parts  => { repository => { multi => 1, required => 1 } },
+        paths  => [ [ { repository => 1 }, "_snapshot", "{repository}" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'snapshot.get' => {
+        doc   => "modules-snapshots",
+        parts => {
+            repository => { required => 1 },
+            snapshot   => { multi    => 1, required => 1 },
+        },
+        paths => [
+            [   { repository => 1, snapshot => 2 }, "_snapshot",
+                "{repository}", "{snapshot}",
+            ],
+        ],
+        qs => ["master_timeout"],
+    },
+
+    'snapshot.get_repository' => {
+        doc   => "modules-snapshots",
+        parts => { repository => { multi => 1 } },
+        paths => [
+            [ { repository => 1 }, "_snapshot", "{repository}" ],
+            [ {}, "_snapshot" ],
+        ],
+        qs => [ "local", "master_timeout" ],
+    },
+
+    'snapshot.restore' => {
+        body   => {},
+        doc    => "modules-snapshots",
+        method => "POST",
+        parts  => {
+            repository => { required => 1 },
+            snapshot   => { required => 1 }
+        },
+        paths => [
+            [   { repository => 1, snapshot => 2 }, "_snapshot",
+                "{repository}", "{snapshot}",
+                "_restore",
+            ],
+        ],
+        qs => [ "master_timeout", "wait_for_completion" ],
+    },
+
+    'snapshot.status' => {
+        doc   => "modules-snapshots",
+        parts => { repository => {}, snapshot => { multi => 1 } },
+        paths => [
+            [   { repository => 1, snapshot => 2 }, "_snapshot",
+                "{repository}", "{snapshot}",
+                "_status",
+            ],
+            [   { snapshot => 2 }, "_snapshot",
+                "_all", "{snapshot}",
+                "_status"
+            ],
+            [ { repository => 1 }, "_snapshot", "{repository}", "_status" ],
+            [ {}, "_snapshot", "_status" ],
+        ],
+        qs => ["master_timeout"],
+    },
+
+    'snapshot.verify_repository' => {
+        doc    => "modules-snapshots",
+        method => "POST",
+        parts  => { repository => { required => 1 } },
+        paths  => [
+            [ { repository => 1 }, "_snapshot", "{repository}", "_verify" ],
+        ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+#=== AUTOGEN - END ===
+
+);
+
+for ( values %API ) {
+    $_->{qs_handlers} = qs_init( @{ $_->{qs} } );
+}
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Role::API::1_0 - This class contains the spec for the Elasticsearch APIs
+
+=head1 VERSION
+
+version 1.20
+
+=head1 DESCRIPTION
+
+All of the Elasticsearch APIs are defined in this role. The example given below
+is the definition for the L<Search::Elasticsearch::Client::1_0::Direct/index()> method:
+
+    'index' => {
+        body => {
+            desc     => 'The document',
+            required => 1
+        },
+
+        doc    => '/api/index_/',
+        method => 'PUT',
+        path   => '{index}/{type}/{id|blank}',
+        qs     => [
+            'consistency', 'op_type',     'parent',  'percolate',
+            'refresh',     'replication', 'routing', 'timeout',
+            'timestamp',   'ttl',         'version', 'version_type'
+        ],
+    },
+
+These definitions can be used by different L<Search::Elasticsearch::Role::Client>
+implementations to provide distinct user interfaces.
+
+=head1 METHODS
+
+=head2 C<api()>
+
+    $defn = $api->api($name);
+
+The only method in this class is the C<api()> method which takes the name
+of the I<action> and returns its definition.  Actions in the
+C<indices> or C<cluster> namespace use the namespace as a prefix, eg:
+
+    $defn = $e->api('indices.create');
+    $defn = $e->api('cluster.node_stats');
+
+=head1 SEE ALSO
+
+=over
+
+=item *
+
+L<Search::Elasticsearch::Util::API::Path>
+
+=item *
+
+L<Search::Elasticsearch::Util::API::QS>
+
+=item *
+
+L<Search::Elasticsearch::Client::2_0::Direct>
+
+=item *
+
+L<Search::Elasticsearch::Client::0_90::Direct>
+
+=back
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: This class contains the spec for the Elasticsearch APIs
+
@@ -0,0 +1,1562 @@
+package Search::Elasticsearch::Role::API::2_0;
+$Search::Elasticsearch::Role::API::2_0::VERSION = '1.20';
+use Moo::Role;
+
+use Search::Elasticsearch::Util qw(throw);
+use Search::Elasticsearch::Util::API::QS qw(qs_init);
+use namespace::clean;
+
+our %API;
+
+#===================================
+sub api {
+#===================================
+    my $name = $_[1] || return \%API;
+    return $API{$name}
+        || throw( 'Internal', "Unknown api name ($name)" );
+}
+
+#===================================
+%API = (
+#===================================
+
+#=== AUTOGEN - START ===
+
+    'bulk' => {
+        body            => { required => 1 },
+        doc             => "docs-bulk",
+        index_when_type => 1,
+        method          => "POST",
+        parts => { index => {}, type => {} },
+        paths => [
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_bulk" ],
+            [ { index => 0 }, "{index}", "_bulk" ],
+            [ {}, "_bulk" ],
+        ],
+        qs        => [ "consistency", "refresh", "routing", "timeout" ],
+        serialize => "bulk",
+    },
+
+    'clear_scroll' => {
+        body   => {},
+        doc    => "search-request-scroll",
+        method => "DELETE",
+        parts  => { scroll_id => { multi => 1 } },
+        paths  => [
+            [ { scroll_id => 2 }, "_search", "scroll", "{scroll_id}" ],
+            [ {}, "_search", "scroll" ],
+        ],
+        qs => [],
+    },
+
+    'count' => {
+        body   => {},
+        doc    => "search-count",
+        method => "POST",
+        parts  => { index => { multi => 1 }, type => { multi => 1 } },
+        paths  => [
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_count" ],
+            [ { type => 1 }, "_all", "{type}", "_count" ],
+            [ { index => 0 }, "{index}", "_count" ],
+            [ {}, "_count" ],
+        ],
+        qs => [
+            "allow_no_indices",         "analyze_wildcard",
+            "analyzer",                 "default_operator",
+            "df",                       "expand_wildcards",
+            "ignore_unavailable",       "lenient",
+            "lowercase_expanded_terms", "min_score",
+            "preference",               "q",
+            "routing",
+        ],
+    },
+
+    'count_percolate' => {
+        body  => {},
+        doc   => "search-percolate",
+        parts => {
+            id    => {},
+            index => { required => 1 },
+            type  => { required => 1 }
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}",     "{id}",
+                "_percolate", "count",
+            ],
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_percolate",
+                "count",
+            ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "percolate_index",
+            "percolate_type",     "preference",
+            "routing",            "version",
+            "version_type",
+        ],
+    },
+
+    'delete' => {
+        doc    => "docs-delete",
+        method => "DELETE",
+        parts  => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}"
+            ],
+        ],
+        qs => [
+            "consistency", "parent",  "refresh", "routing",
+            "timeout",     "version", "version_type",
+        ],
+    },
+
+    'delete_script' => {
+        doc    => "modules-scripting",
+        method => "DELETE",
+        parts  => { id => { required => 1 }, lang => { required => 1 } },
+        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
+    'delete_template' => {
+        doc    => "search-template",
+        method => "DELETE",
+        parts  => { id => {} },
+        paths  => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
+    'exists' => {
+        doc    => "docs-get",
+        method => "HEAD",
+        parts  => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}"
+            ],
+        ],
+        qs => [ "parent", "preference", "realtime", "refresh", "routing" ],
+    },
+
+    'explain' => {
+        body  => {},
+        doc   => "search-explain",
+        parts => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}",
+                "_explain",
+            ],
+        ],
+        qs => [
+            "_source",         "_source_exclude",
+            "_source_include", "analyze_wildcard",
+            "analyzer",        "default_operator",
+            "df",              "fields",
+            "lenient",         "lowercase_expanded_terms",
+            "parent",          "preference",
+            "q",               "routing",
+        ],
+    },
+
+    'field_stats' => {
+        doc   => "search-field-stats",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 0 }, "{index}", "_field_stats" ],
+            [ {}, "_field_stats" ],
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "fields",           "ignore_unavailable",
+            "level",
+        ],
+    },
+
+    'get' => {
+        doc   => "docs-get",
+        parts => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}"
+            ],
+        ],
+        qs => [
+            "_source",         "_source_exclude",
+            "_source_include", "fields",
+            "parent",          "preference",
+            "realtime",        "refresh",
+            "routing",         "version",
+            "version_type",
+        ],
+    },
+
+    'get_script' => {
+        doc   => "modules-scripting",
+        parts => { id => { required => 1 }, lang => { required => 1 } },
+        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
+    'get_source' => {
+        doc   => "docs-get",
+        parts => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 },
+                "{index}", "{type}", "{id}", "_source",
+            ],
+        ],
+        qs => [
+            "_source",         "_source_exclude",
+            "_source_include", "parent",
+            "preference",      "realtime",
+            "refresh",         "routing",
+            "version",         "version_type",
+        ],
+    },
+
+    'get_template' => {
+        doc   => "search-template",
+        parts => { id => { required => 1 } },
+        paths => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
+    'index' => {
+        body   => { required => 1 },
+        doc    => "docs-index_",
+        method => "POST",
+        parts  => {
+            id    => {},
+            index => { required => 1 },
+            type  => { required => 1 }
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}"
+            ],
+            [ { index => 0, type => 1 }, "{index}", "{type}" ],
+        ],
+        qs => [
+            "consistency", "op_type", "parent",    "refresh",
+            "routing",     "timeout", "timestamp", "ttl",
+            "version",     "version_type",
+        ],
+    },
+
+    'info' => { doc => "", parts => {}, paths => [ [ {} ] ], qs => [] },
+
+    'mget' => {
+        body            => { required => 1 },
+        doc             => "docs-multi-get",
+        index_when_type => 1,
+        parts => { index => {}, type => {} },
+        paths => [
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_mget" ],
+            [ { index => 0 }, "{index}", "_mget" ],
+            [ {}, "_mget" ],
+        ],
+        qs => [
+            "_source",         "_source_exclude",
+            "_source_include", "fields",
+            "preference",      "realtime",
+            "refresh",
+        ],
+    },
+
+    'mpercolate' => {
+        body            => { required => 1 },
+        doc             => "search-percolate",
+        index_when_type => 1,
+        parts => { index => {}, type => {} },
+        paths => [
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_mpercolate" ],
+            [ { index => 0 }, "{index}", "_mpercolate" ],
+            [ {}, "_mpercolate" ],
+        ],
+        qs =>
+            [ "allow_no_indices", "expand_wildcards", "ignore_unavailable" ],
+        serialize => "bulk",
+    },
+
+    'msearch' => {
+        body => { required => 1 },
+        doc  => "search-multi-search",
+        parts => { index => { multi => 1 }, type => { multi => 1 } },
+        paths => [
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_msearch" ],
+            [ { type => 1 }, "_all", "{type}", "_msearch" ],
+            [ { index => 0 }, "{index}", "_msearch" ],
+            [ {}, "_msearch" ],
+        ],
+        qs        => ["search_type"],
+        serialize => "bulk",
+    },
+
+    'mtermvectors' => {
+        body            => {},
+        doc             => "docs-multi-termvectors",
+        index_when_type => 1,
+        parts           => { index => {}, type => {} },
+        paths           => [
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_mtermvectors"
+            ],
+            [ { index => 0 }, "{index}", "_mtermvectors" ],
+            [ {}, "_mtermvectors" ],
+        ],
+        qs => [
+            "field_statistics", "fields",
+            "ids",              "offsets",
+            "parent",           "payloads",
+            "positions",        "preference",
+            "realtime",         "routing",
+            "term_statistics",  "version",
+            "version_type",
+        ],
+    },
+
+    'percolate' => {
+        body  => {},
+        doc   => "search-percolate",
+        parts => {
+            id    => {},
+            index => { required => 1 },
+            type  => { required => 1 }
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}",
+                "_percolate",
+            ],
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_percolate" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "percolate_format",
+            "percolate_index",    "percolate_preference",
+            "percolate_routing",  "percolate_type",
+            "preference",         "routing",
+            "version",            "version_type",
+        ],
+    },
+
+    'ping' => {
+        doc    => "",
+        method => "HEAD",
+        parts  => {},
+        paths  => [ [ {} ] ],
+        qs     => []
+    },
+
+    'put_script' => {
+        body   => { required => 1 },
+        doc    => "modules-scripting",
+        method => "PUT",
+        parts => { id => { required => 1 }, lang => { required => 1 } },
+        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
+        qs => [ "op_type", "version", "version_type" ],
+    },
+
+    'put_template' => {
+        body   => { required => 1 },
+        doc    => "search-template",
+        method => "PUT",
+        parts => { id => { required => 1 } },
+        paths => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
+        qs => [ "op_type", "version", "version_type" ],
+    },
+
+    'scroll' => {
+        body  => {},
+        doc   => "search-request-scroll",
+        parts => { scroll_id => {} },
+        paths => [
+            [ { scroll_id => 2 }, "_search", "scroll", "{scroll_id}" ],
+            [ {}, "_search", "scroll" ],
+        ],
+        qs => ["scroll"],
+    },
+
+    'search' => {
+        body  => {},
+        doc   => "search-search",
+        parts => { index => { multi => 1 }, type => { multi => 1 } },
+        paths => [
+            [ { index => 0, type => 1 }, "{index}", "{type}", "_search" ],
+            [ { type => 1 }, "_all", "{type}", "_search" ],
+            [ { index => 0 }, "{index}", "_search" ],
+            [ {}, "_search" ],
+        ],
+        qs => [
+            "_source",          "_source_exclude",
+            "_source_include",  "allow_no_indices",
+            "analyze_wildcard", "analyzer",
+            "default_operator", "df",
+            "expand_wildcards", "explain",
+            "fielddata_fields", "fields",
+            "from",             "ignore_unavailable",
+            "lenient",          "lowercase_expanded_terms",
+            "preference",       "q",
+            "query_cache",      "routing",
+            "scroll",           "search_type",
+            "size",             "sort",
+            "stats",            "suggest_field",
+            "suggest_mode",     "suggest_size",
+            "suggest_text",     "terminate_after",
+            "timeout",          "track_scores",
+            "version",
+        ],
+    },
+
+    'search_exists' => {
+        body   => {},
+        doc    => "search-exists",
+        method => "POST",
+        parts  => { index => { multi => 1 }, type => { multi => 1 } },
+        paths  => [
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_search",
+                "exists",
+            ],
+            [ { type => 1 }, "_all", "{type}", "_search", "exists" ],
+            [ { index => 0 }, "{index}", "_search", "exists" ],
+            [ {}, "_search", "exists" ],
+        ],
+        qs => [
+            "allow_no_indices",         "analyze_wildcard",
+            "analyzer",                 "default_operator",
+            "df",                       "expand_wildcards",
+            "ignore_unavailable",       "lenient",
+            "lowercase_expanded_terms", "min_score",
+            "preference",               "q",
+            "routing",
+        ],
+    },
+
+    'search_shards' => {
+        doc   => "search-shards",
+        parts => { index => {}, type => {} },
+        paths => [
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_search_shards",
+            ],
+            [ { type => 1 }, "_all", "{type}", "_search_shards" ],
+            [ { index => 0 }, "{index}", "_search_shards" ],
+            [ {}, "_search_shards" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+            "preference",         "routing",
+        ],
+    },
+
+    'search_template' => {
+        body  => {},
+        doc   => "search-template",
+        parts => { index => { multi => 1 }, type => { multi => 1 } },
+        paths => [
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_search",
+                "template",
+            ],
+            [ { type => 1 }, "_all", "{type}", "_search", "template" ],
+            [ { index => 0 }, "{index}", "_search", "template" ],
+            [ {}, "_search", "template" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "preference",
+            "routing",            "scroll",
+            "search_type",
+        ],
+    },
+
+    'suggest' => {
+        body   => { required => 1 },
+        doc    => "search-suggesters",
+        method => "POST",
+        parts => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_suggest" ], [ {}, "_suggest" ] ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "preference",
+            "routing",
+        ],
+    },
+
+    'termvectors' => {
+        body  => {},
+        doc   => "docs-termvectors",
+        parts => {
+            id    => {},
+            index => { required => 1 },
+            type  => { required => 1 }
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 }, "{index}",
+                "{type}", "{id}",
+                "_termvectors",
+            ],
+            [   { index => 0, type => 1 }, "{index}", "{type}",
+                "_termvectors"
+            ],
+        ],
+        qs => [
+            "dfs",             "field_statistics",
+            "fields",          "offsets",
+            "parent",          "payloads",
+            "positions",       "preference",
+            "realtime",        "routing",
+            "term_statistics", "version",
+            "version_type",
+        ],
+    },
+
+    'update' => {
+        body   => {},
+        doc    => "docs-update",
+        method => "POST",
+        parts  => {
+            id    => { required => 1 },
+            index => { required => 1 },
+            type  => { required => 1 },
+        },
+        paths => [
+            [   { id => 2, index => 0, type => 1 },
+                "{index}", "{type}", "{id}", "_update",
+            ],
+        ],
+        qs => [
+            "consistency", "fields",
+            "lang",        "parent",
+            "refresh",     "retry_on_conflict",
+            "routing",     "script",
+            "script_id",   "scripted_upsert",
+            "timeout",     "timestamp",
+            "ttl",         "version",
+            "version_type",
+        ],
+    },
+
+    'cat.aliases' => {
+        doc   => "cat-alias",
+        parts => { name => { multi => 1 } },
+        paths => [
+            [ { name => 2 }, "_cat", "aliases", "{name}" ],
+            [ {}, "_cat", "aliases" ],
+        ],
+        qs => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.allocation' => {
+        doc   => "cat-allocation",
+        parts => { node_id => { multi => 1 } },
+        paths => [
+            [ { node_id => 2 }, "_cat", "allocation", "{node_id}" ],
+            [ {}, "_cat", "allocation" ],
+        ],
+        qs => [ "bytes", "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.count' => {
+        doc   => "cat-count",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 2 }, "_cat", "count", "{index}" ],
+            [ {}, "_cat", "count" ],
+        ],
+        qs => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.fielddata' => {
+        doc   => "cat-fielddata",
+        parts => { fields => { multi => 1 } },
+        paths => [
+            [ { fields => 2 }, "_cat", "fielddata", "{fields}" ],
+            [ {}, "_cat", "fielddata" ],
+        ],
+        qs => [ "bytes", "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.health' => {
+        doc   => "cat-health",
+        parts => {},
+        paths => [ [ {}, "_cat", "health" ] ],
+        qs    => [ "h", "help", "local", "master_timeout", "ts", "v" ],
+    },
+
+    'cat.help' => {
+        doc   => "cat",
+        parts => {},
+        paths => [ [ {}, "_cat" ] ],
+        qs    => ["help"]
+    },
+
+    'cat.indices' => {
+        doc   => "cat-indices",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 2 }, "_cat", "indices", "{index}" ],
+            [ {}, "_cat", "indices" ],
+        ],
+        qs => [ "bytes", "h", "help", "local", "master_timeout", "pri", "v" ],
+    },
+
+    'cat.master' => {
+        doc   => "cat-master",
+        parts => {},
+        paths => [ [ {}, "_cat", "master" ] ],
+        qs    => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.nodes' => {
+        doc   => "cat-nodes",
+        parts => {},
+        paths => [ [ {}, "_cat", "nodes" ] ],
+        qs    => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.pending_tasks' => {
+        doc   => "cat-pending-tasks",
+        parts => {},
+        paths => [ [ {}, "_cat", "pending_tasks" ] ],
+        qs    => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.plugins' => {
+        doc   => "cat-plugins",
+        parts => {},
+        paths => [ [ {}, "_cat", "plugins" ] ],
+        qs    => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.recovery' => {
+        doc   => "cat-recovery",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 2 }, "_cat", "recovery", "{index}" ],
+            [ {}, "_cat", "recovery" ],
+        ],
+        qs => [ "bytes", "h", "help", "master_timeout", "v" ],
+    },
+
+    'cat.segments' => {
+        doc   => "cat-segments",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 2 }, "_cat", "segments", "{index}" ],
+            [ {}, "_cat", "segments" ],
+        ],
+        qs => [ "h", "help", "v" ],
+    },
+
+    'cat.shards' => {
+        doc   => "cat-shards",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 2 }, "_cat", "shards", "{index}" ],
+            [ {}, "_cat", "shards" ],
+        ],
+        qs => [ "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cat.thread_pool' => {
+        doc   => "cat-thread-pool",
+        parts => {},
+        paths => [ [ {}, "_cat", "thread_pool" ] ],
+        qs    => [ "full_id", "h", "help", "local", "master_timeout", "v" ],
+    },
+
+    'cluster.get_settings' => {
+        doc   => "cluster-update-settings",
+        parts => {},
+        paths => [ [ {}, "_cluster", "settings" ] ],
+        qs => [ "flat_settings", "master_timeout", "timeout" ],
+    },
+
+    'cluster.health' => {
+        doc   => "cluster-health",
+        parts => { index => {} },
+        paths => [
+            [ { index => 2 }, "_cluster", "health", "{index}" ],
+            [ {}, "_cluster", "health" ],
+        ],
+        qs => [
+            "level",                      "local",
+            "master_timeout",             "timeout",
+            "wait_for_active_shards",     "wait_for_nodes",
+            "wait_for_relocating_shards", "wait_for_status",
+        ],
+    },
+
+    'cluster.pending_tasks' => {
+        doc   => "cluster-pending",
+        parts => {},
+        paths => [ [ {}, "_cluster", "pending_tasks" ] ],
+        qs => [ "local", "master_timeout" ],
+    },
+
+    'cluster.put_settings' => {
+        body   => {},
+        doc    => "cluster-update-settings",
+        method => "PUT",
+        parts  => {},
+        paths  => [ [ {}, "_cluster", "settings" ] ],
+        qs => [ "flat_settings", "master_timeout", "timeout" ],
+    },
+
+    'cluster.reroute' => {
+        body   => {},
+        doc    => "cluster-reroute",
+        method => "POST",
+        parts  => {},
+        paths  => [ [ {}, "_cluster", "reroute" ] ],
+        qs => [ "dry_run", "explain", "master_timeout", "metric", "timeout" ],
+    },
+
+    'cluster.state' => {
+        doc   => "cluster-state",
+        parts => { index => { multi => 1 }, metric => { multi => 1 } },
+        paths => [
+            [   { index => 3, metric => 2 }, "_cluster",
+                "state", "{metric}",
+                "{index}",
+            ],
+            [ { index => 3 }, "_cluster", "state", "_all", "{index}" ],
+            [ { metric => 2 }, "_cluster", "state", "{metric}" ],
+            [ {}, "_cluster", "state" ],
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "flat_settings",    "ignore_unavailable",
+            "local",            "master_timeout",
+        ],
+    },
+
+    'cluster.stats' => {
+        doc   => "cluster-stats",
+        parts => { node_id => { multi => 1 } },
+        paths => [
+            [ { node_id => 3 }, "_cluster", "stats", "nodes", "{node_id}" ],
+            [ {}, "_cluster", "stats" ],
+        ],
+        qs => [ "flat_settings", "human" ],
+    },
+
+    'indices.analyze' => {
+        body  => {},
+        doc   => "indices-analyze",
+        parts => { index => {} },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_analyze" ], [ {}, "_analyze" ] ],
+        qs => [
+            "analyzer", "char_filters", "field", "filters",
+            "format",   "prefer_local", "text",  "tokenizer",
+        ],
+    },
+
+    'indices.clear_cache' => {
+        doc    => "indices-clearcache",
+        method => "POST",
+        parts  => { index => { multi => 1 } },
+        paths  => [
+            [ { index => 0 }, "{index}", "_cache", "clear" ],
+            [ {}, "_cache", "clear" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "fielddata",          "fields",
+            "filter",             "filter_cache",
+            "id",                 "id_cache",
+            "ignore_unavailable", "query_cache",
+            "recycler",
+        ],
+    },
+
+    'indices.close' => {
+        doc    => "indices-open-close",
+        method => "POST",
+        parts  => { index => { required => 1 } },
+        paths  => [ [ { index => 0 }, "{index}", "_close" ] ],
+        qs     => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "master_timeout",
+            "timeout",
+        ],
+    },
+
+    'indices.create' => {
+        body   => {},
+        doc    => "indices-create-index",
+        method => "PUT",
+        parts  => { index => { required => 1 } },
+        paths  => [ [ { index => 0 }, "{index}" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'indices.delete' => {
+        doc    => "indices-delete-index",
+        method => "DELETE",
+        parts  => { index => { multi => 1, required => 1 } },
+        paths => [ [ { index => 0 }, "{index}" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'indices.delete_alias' => {
+        doc    => "indices-aliases",
+        method => "DELETE",
+        parts  => {
+            index => { multi => 1, required => 1 },
+            name  => { multi => 1, required => 1 },
+        },
+        paths =>
+            [ [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'indices.delete_template' => {
+        doc    => "indices-templates",
+        method => "DELETE",
+        parts  => { name => { required => 1 } },
+        paths  => [ [ { name => 1 }, "_template", "{name}" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'indices.delete_warmer' => {
+        doc    => "indices-warmers",
+        method => "DELETE",
+        parts  => {
+            index => { multi => 1, required => 1 },
+            name  => { multi => 1, required => 1 },
+        },
+        paths =>
+            [ [ { index => 0, name => 2 }, "{index}", "_warmer", "{name}" ] ],
+        qs => ["master_timeout"],
+    },
+
+    'indices.exists' => {
+        doc    => "indices-exists",
+        method => "HEAD",
+        parts  => { index => { multi => 1, required => 1 } },
+        paths => [ [ { index => 0 }, "{index}" ] ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.exists_alias' => {
+        doc    => "indices-aliases",
+        method => "HEAD",
+        parts  => { index => { multi => 1 }, name => { multi => 1 } },
+        paths  => [
+            [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ],
+            [ { index => 0 }, "{index}", "_alias" ],
+            [ { name  => 1 }, "_alias",  "{name}" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.exists_template' => {
+        doc    => "indices-templates",
+        method => "HEAD",
+        parts  => { name => { required => 1 } },
+        paths  => [ [ { name => 1 }, "_template", "{name}" ] ],
+        qs => [ "local", "master_timeout" ],
+    },
+
+    'indices.exists_type' => {
+        doc    => "indices-types-exists",
+        method => "HEAD",
+        parts  => {
+            index => { multi => 1, required => 1 },
+            type  => { multi => 1, required => 1 },
+        },
+        paths => [ [ { index => 0, type => 1 }, "{index}", "{type}" ] ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.flush' => {
+        doc    => "indices-flush",
+        method => "POST",
+        parts  => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_flush" ], [ {}, "_flush" ] ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "force",            "ignore_unavailable",
+            "wait_if_ongoing",
+        ],
+    },
+
+    'indices.get' => {
+        doc   => "indices-get-index",
+        parts => {
+            feature => { multi => 1 },
+            index   => { multi => 1, required => 1 }
+        },
+        paths => [
+            [ { feature => 1, index => 0 }, "{index}", "{feature}" ],
+            [ { index => 0 }, "{index}" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.get_alias' => {
+        doc   => "indices-aliases",
+        parts => { index => { multi => 1 }, name => { multi => 1 } },
+        paths => [
+            [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ],
+            [ { index => 0 }, "{index}", "_alias" ],
+            [ { name  => 1 }, "_alias",  "{name}" ],
+            [ {}, "_alias" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.get_aliases' => {
+        doc   => "indices-aliases",
+        parts => { index => { multi => 1 }, name => { multi => 1 } },
+        paths => [
+            [ { index => 0, name => 2 }, "{index}", "_aliases", "{name}" ],
+            [ { index => 0 }, "{index}",  "_aliases" ],
+            [ { name  => 1 }, "_aliases", "{name}" ],
+            [ {}, "_aliases" ],
+        ],
+        qs => [ "local", "timeout" ],
+    },
+
+    'indices.get_field_mapping' => {
+        doc   => "indices-get-field-mapping",
+        parts => {
+            field => { multi => 1, required => 1 },
+            index => { multi => 1 },
+            type  => { multi => 1 },
+        },
+        paths => [
+            [   { field => 4, index => 0, type => 2 }, "{index}",
+                "_mapping", "{type}",
+                "field",    "{field}",
+            ],
+            [   { field => 3, index => 0 }, "{index}",
+                "_mapping", "field",
+                "{field}",
+            ],
+            [   { field => 3, type => 1 }, "_mapping",
+                "{type}", "field",
+                "{field}",
+            ],
+            [ { field => 2 }, "_mapping", "field", "{field}" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "include_defaults",
+            "local",
+        ],
+    },
+
+    'indices.get_mapping' => {
+        doc   => "indices-get-mapping",
+        parts => { index => { multi => 1 }, type => { multi => 1 } },
+        paths => [
+            [ { index => 0, type => 2 }, "{index}", "_mapping", "{type}" ],
+            [ { index => 0 }, "{index}",  "_mapping" ],
+            [ { type  => 1 }, "_mapping", "{type}" ],
+            [ {}, "_mapping" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.get_settings' => {
+        doc   => "indices-get-settings",
+        parts => { index => { multi => 1 }, name => { multi => 1 } },
+        paths => [
+            [ { index => 0, name => 2 }, "{index}", "_settings", "{name}" ],
+            [ { index => 0 }, "{index}",   "_settings" ],
+            [ { name  => 1 }, "_settings", "{name}" ],
+            [ {}, "_settings" ],
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "flat_settings",    "ignore_unavailable",
+            "local",
+        ],
+    },
+
+    'indices.get_template' => {
+        doc   => "indices-templates",
+        parts => { name => {} },
+        paths =>
+            [ [ { name => 1 }, "_template", "{name}" ], [ {}, "_template" ] ],
+        qs => [ "flat_settings", "local", "master_timeout" ],
+    },
+
+    'indices.get_upgrade' => {
+        doc   => "indices-upgrade",
+        parts => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_upgrade" ], [ {}, "_upgrade" ] ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "human",            "ignore_unavailable",
+        ],
+    },
+
+    'indices.get_warmer' => {
+        doc   => "indices-warmers",
+        parts => {
+            index => { multi => 1 },
+            name  => { multi => 1 },
+            type  => { multi => 1 }
+        },
+        paths => [
+            [   { index => 0, name => 3, type => 1 },
+                "{index}", "{type}", "_warmer", "{name}",
+            ],
+            [   { name => 3, type => 1 }, "_all",
+                "{type}", "_warmer",
+                "{name}"
+            ],
+            [ { index => 0, name => 2 }, "{index}", "_warmer", "{name}" ],
+            [ { index => 0 }, "{index}", "_warmer" ],
+            [ { name  => 1 }, "_warmer", "{name}" ],
+            [ {}, "_warmer" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
+        ],
+    },
+
+    'indices.open' => {
+        doc    => "indices-open-close",
+        method => "POST",
+        parts  => { index => { required => 1 } },
+        paths  => [ [ { index => 0 }, "{index}", "_open" ] ],
+        qs     => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "master_timeout",
+            "timeout",
+        ],
+    },
+
+    'indices.optimize' => {
+        doc    => "indices-optimize",
+        method => "POST",
+        parts  => { index => { multi => 1 } },
+        paths  => [
+            [ { index => 0 }, "{index}", "_optimize" ],
+            [ {}, "_optimize" ]
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "flush",            "ignore_unavailable",
+            "max_num_segments", "only_expunge_deletes",
+            "wait_for_merge",
+        ],
+    },
+
+    'indices.put_alias' => {
+        body   => {},
+        doc    => "indices-aliases",
+        method => "PUT",
+        parts  => {
+            index => { multi    => 1, required => 1 },
+            name  => { required => 1 }
+        },
+        paths =>
+            [ [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'indices.put_mapping' => {
+        body   => { required => 1 },
+        doc    => "indices-put-mapping",
+        method => "PUT",
+        parts => { index => { multi => 1 }, type => { required => 1 } },
+        paths => [
+            [ { index => 0, type => 2 }, "{index}", "_mapping", "{type}" ],
+            [ { type => 1 }, "_mapping", "{type}" ],
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "ignore_conflicts", "ignore_unavailable",
+            "master_timeout",   "timeout",
+        ],
+    },
+
+    'indices.put_settings' => {
+        body   => { required => 1 },
+        doc    => "indices-update-settings",
+        method => "PUT",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 0 }, "{index}", "_settings" ],
+            [ {}, "_settings" ]
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "flat_settings",    "ignore_unavailable",
+            "master_timeout",
+        ],
+    },
+
+    'indices.put_template' => {
+        body   => { required => 1 },
+        doc    => "indices-templates",
+        method => "PUT",
+        parts => { name => { required => 1 } },
+        paths => [ [ { name => 1 }, "_template", "{name}" ] ],
+        qs => [
+            "create",         "flat_settings",
+            "master_timeout", "order",
+            "timeout"
+        ],
+    },
+
+    'indices.put_warmer' => {
+        body   => { required => 1 },
+        doc    => "indices-warmers",
+        method => "PUT",
+        parts  => {
+            index => { multi    => 1 },
+            name  => { required => 1 },
+            type  => { multi    => 1 },
+        },
+        paths => [
+            [   { index => 0, name => 3, type => 1 },
+                "{index}", "{type}", "_warmer", "{name}",
+            ],
+            [   { name => 3, type => 1 }, "_all",
+                "{type}", "_warmer",
+                "{name}"
+            ],
+            [ { index => 0, name => 2 }, "{index}", "_warmer", "{name}" ],
+            [ { name => 1 }, "_warmer", "{name}" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "master_timeout",
+        ],
+    },
+
+    'indices.recovery' => {
+        doc   => "indices-recovery",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 0 }, "{index}", "_recovery" ],
+            [ {}, "_recovery" ]
+        ],
+        qs => [ "active_only", "detailed", "human" ],
+    },
+
+    'indices.refresh' => {
+        doc    => "indices-refresh",
+        method => "POST",
+        parts  => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_refresh" ], [ {}, "_refresh" ] ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "force",            "ignore_unavailable",
+        ],
+    },
+
+    'indices.segments' => {
+        doc   => "indices-segments",
+        parts => { index => { multi => 1 } },
+        paths => [
+            [ { index => 0 }, "{index}", "_segments" ],
+            [ {}, "_segments" ]
+        ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "human",            "ignore_unavailable",
+        ],
+    },
+
+    'indices.stats' => {
+        doc   => "indices-stats",
+        parts => { index => { multi => 1 }, metric => { multi => 1 } },
+        paths => [
+            [ { index => 0, metric => 2 }, "{index}", "_stats", "{metric}" ],
+            [ { index  => 0 }, "{index}", "_stats" ],
+            [ { metric => 1 }, "_stats",  "{metric}" ],
+            [ {}, "_stats" ],
+        ],
+        qs => [
+            "completion_fields", "fielddata_fields",
+            "fields",            "groups",
+            "human",             "level",
+            "types",
+        ],
+    },
+
+    'indices.update_aliases' => {
+        body   => { required => 1 },
+        doc    => "indices-aliases",
+        method => "POST",
+        parts  => {},
+        paths => [ [ {}, "_aliases" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'indices.upgrade' => {
+        doc    => "indices-upgrade",
+        method => "POST",
+        parts  => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_upgrade" ], [ {}, "_upgrade" ] ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "only_ancient_segments",
+            "wait_for_completion",
+        ],
+    },
+
+    'indices.validate_query' => {
+        body  => {},
+        doc   => "search-validate",
+        parts => { index => { multi => 1 }, type => { multi => 1 } },
+        paths => [
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_validate",
+                "query",
+            ],
+            [ { type => 1 }, "_all", "{type}", "_validate", "query" ],
+            [ { index => 0 }, "{index}", "_validate", "query" ],
+            [ {}, "_validate", "query" ],
+        ],
+        qs => [
+            "allow_no_indices", "analyze_wildcard",
+            "analyzer",         "default_operator",
+            "df",               "expand_wildcards",
+            "explain",          "ignore_unavailable",
+            "lenient",          "lowercase_expanded_terms",
+            "q",
+        ],
+    },
+
+    'nodes.hot_threads' => {
+        doc   => "cluster-nodes-hot-threads",
+        parts => { node_id => { multi => 1 } },
+        paths => [
+            [ { node_id => 1 }, "_nodes", "{node_id}", "hot_threads" ],
+            [ {}, "_nodes", "hot_threads" ],
+        ],
+        qs => [
+            "ignore_idle_threads", "interval",
+            "snapshots",           "threads",
+            "type",
+        ],
+    },
+
+    'nodes.info' => {
+        doc   => "cluster-nodes-info",
+        parts => { metric => { multi => 1 }, node_id => { multi => 1 } },
+        paths => [
+            [   { metric => 2, node_id => 1 }, "_nodes",
+                "{node_id}", "{metric}",
+            ],
+            [ { metric => 2 }, "_nodes", "_all", "{metric}" ],
+            [ { node_id => 1 }, "_nodes", "{node_id}" ],
+            [ {}, "_nodes" ],
+        ],
+        qs => [ "flat_settings", "human" ],
+    },
+
+    'nodes.stats' => {
+        doc   => "cluster-nodes-stats",
+        parts => {
+            index_metric => { multi => 1 },
+            metric       => { multi => 1 },
+            node_id      => { multi => 1 },
+        },
+        paths => [
+            [   { index_metric => 4, metric => 3, node_id => 1 },
+                "_nodes", "{node_id}", "stats", "{metric}", "{index_metric}",
+            ],
+            [   { index_metric => 4, node_id => 1 },
+                "_nodes", "{node_id}", "stats", "_all", "{index_metric}",
+            ],
+            [   { index_metric => 3, metric => 2 }, "_nodes",
+                "stats", "{metric}",
+                "{index_metric}",
+            ],
+            [   { index_metric => 3 }, "_nodes",
+                "stats", "_all",
+                "{index_metric}",
+            ],
+            [   { metric => 3, node_id => 1 }, "_nodes",
+                "{node_id}", "stats",
+                "{metric}",
+            ],
+            [ { metric  => 2 }, "_nodes", "stats",     "{metric}" ],
+            [ { node_id => 1 }, "_nodes", "{node_id}", "stats" ],
+            [ {}, "_nodes", "stats" ],
+        ],
+        qs => [
+            "completion_fields", "fielddata_fields",
+            "fields",            "groups",
+            "human",             "level",
+            "types",
+        ],
+    },
+
+    'snapshot.create' => {
+        body   => {},
+        doc    => "modules-snapshots",
+        method => "PUT",
+        parts  => {
+            repository => { required => 1 },
+            snapshot   => { required => 1 }
+        },
+        paths => [
+            [   { repository => 1, snapshot => 2 }, "_snapshot",
+                "{repository}", "{snapshot}",
+            ],
+        ],
+        qs => [ "master_timeout", "wait_for_completion" ],
+    },
+
+    'snapshot.create_repository' => {
+        body   => { required => 1 },
+        doc    => "modules-snapshots",
+        method => "PUT",
+        parts => { repository => { required => 1 } },
+        paths => [ [ { repository => 1 }, "_snapshot", "{repository}" ] ],
+        qs => [ "master_timeout", "timeout", "verify" ],
+    },
+
+    'snapshot.delete' => {
+        doc    => "modules-snapshots",
+        method => "DELETE",
+        parts  => {
+            repository => { required => 1 },
+            snapshot   => { required => 1 }
+        },
+        paths => [
+            [   { repository => 1, snapshot => 2 }, "_snapshot",
+                "{repository}", "{snapshot}",
+            ],
+        ],
+        qs => ["master_timeout"],
+    },
+
+    'snapshot.delete_repository' => {
+        doc    => "modules-snapshots",
+        method => "DELETE",
+        parts  => { repository => { multi => 1, required => 1 } },
+        paths  => [ [ { repository => 1 }, "_snapshot", "{repository}" ] ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+    'snapshot.get' => {
+        doc   => "modules-snapshots",
+        parts => {
+            repository => { required => 1 },
+            snapshot   => { multi    => 1, required => 1 },
+        },
+        paths => [
+            [   { repository => 1, snapshot => 2 }, "_snapshot",
+                "{repository}", "{snapshot}",
+            ],
+        ],
+        qs => ["master_timeout"],
+    },
+
+    'snapshot.get_repository' => {
+        doc   => "modules-snapshots",
+        parts => { repository => { multi => 1 } },
+        paths => [
+            [ { repository => 1 }, "_snapshot", "{repository}" ],
+            [ {}, "_snapshot" ],
+        ],
+        qs => [ "local", "master_timeout" ],
+    },
+
+    'snapshot.restore' => {
+        body   => {},
+        doc    => "modules-snapshots",
+        method => "POST",
+        parts  => {
+            repository => { required => 1 },
+            snapshot   => { required => 1 }
+        },
+        paths => [
+            [   { repository => 1, snapshot => 2 }, "_snapshot",
+                "{repository}", "{snapshot}",
+                "_restore",
+            ],
+        ],
+        qs => [ "master_timeout", "wait_for_completion" ],
+    },
+
+    'snapshot.status' => {
+        doc   => "modules-snapshots",
+        parts => { repository => {}, snapshot => { multi => 1 } },
+        paths => [
+            [   { repository => 1, snapshot => 2 }, "_snapshot",
+                "{repository}", "{snapshot}",
+                "_status",
+            ],
+            [   { snapshot => 2 }, "_snapshot",
+                "_all", "{snapshot}",
+                "_status"
+            ],
+            [ { repository => 1 }, "_snapshot", "{repository}", "_status" ],
+            [ {}, "_snapshot", "_status" ],
+        ],
+        qs => ["master_timeout"],
+    },
+
+    'snapshot.verify_repository' => {
+        doc    => "modules-snapshots",
+        method => "POST",
+        parts  => { repository => { required => 1 } },
+        paths  => [
+            [ { repository => 1 }, "_snapshot", "{repository}", "_verify" ],
+        ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
+#=== AUTOGEN - END ===
+
+);
+
+for ( values %API ) {
+    $_->{qs_handlers} = qs_init( @{ $_->{qs} } );
+}
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Role::API::2_0 - This class contains the spec for the Elasticsearch APIs
+
+=head1 VERSION
+
+version 1.20
+
+=head1 DESCRIPTION
+
+All of the Elasticsearch APIs are defined in this role. The example given below
+is the definition for the L<Search::Elasticsearch::Client::2_0::Direct/index()> method:
+
+    'index' => {
+        body => {
+            desc     => 'The document',
+            required => 1
+        },
+
+        doc    => '/api/index_/',
+        method => 'PUT',
+        path   => '{index}/{type}/{id|blank}',
+        qs     => [
+            'consistency', 'op_type',     'parent',  'percolate',
+            'refresh',     'routing',     'timeout',
+            'timestamp',   'ttl',         'version', 'version_type'
+        ],
+    },
+
+These definitions can be used by different L<Search::Elasticsearch::Role::Client>
+implementations to provide distinct user interfaces.
+
+=head1 METHODS
+
+=head2 C<api()>
+
+    $defn = $api->api($name);
+
+The only method in this class is the C<api()> method which takes the name
+of the I<action> and returns its definition.  Actions in the
+C<indices> or C<cluster> namespace use the namespace as a prefix, eg:
+
+    $defn = $e->api('indices.create');
+    $defn = $e->api('cluster.node_stats');
+
+=head1 SEE ALSO
+
+=over
+
+=item *
+
+L<Search::Elasticsearch::Util::API::Path>
+
+=item *
+
+L<Search::Elasticsearch::Util::API::QS>
+
+=item *
+
+L<Search::Elasticsearch::Client::1_0::Direct>
+
+=item *
+
+L<Search::Elasticsearch::Client::0_90::Direct>
+
+=back
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: This class contains the spec for the Elasticsearch APIs
+
@@ -1,1689 +0,0 @@
-package Search::Elasticsearch::Role::API;
-$Search::Elasticsearch::Role::API::VERSION = '1.19';
-use Moo::Role;
-
-use Search::Elasticsearch::Util qw(throw);
-use Search::Elasticsearch::Util::API::QS qw(qs_init);
-use namespace::clean;
-
-our %API;
-
-#===================================
-sub api {
-#===================================
-    my $name = $_[1] || return \%API;
-    return $API{$name}
-        || throw( 'Internal', "Unknown api name ($name)" );
-}
-
-#===================================
-%API = (
-#===================================
-
-#=== AUTOGEN - START ===
-
-    'abort_benchmark' => {
-        doc    => "search-benchmark",
-        method => "POST",
-        parts  => { name => {} },
-        paths  => [ [ { name => 2 }, "_bench", "abort", "{name}" ] ],
-        qs     => [],
-    },
-
-    'benchmark' => {
-        body   => {},
-        doc    => "search-benchmark",
-        method => "PUT",
-        parts  => { index => { multi => 1 }, type => {} },
-        paths  => [
-            [ { index => 0, type => 1 }, "{index}", "{type}", "_bench" ],
-            [ { type => 1 }, "_all", "{type}", "_bench" ],
-            [ { index => 0 }, "{index}", "_bench" ],
-            [ {}, "_bench" ],
-        ],
-        qs => ["verbose"],
-    },
-
-    'bulk' => {
-        body            => { required => 1 },
-        doc             => "docs-bulk",
-        index_when_type => 1,
-        method          => "POST",
-        parts => { index => {}, type => {} },
-        paths => [
-            [ { index => 0, type => 1 }, "{index}", "{type}", "_bulk" ],
-            [ { index => 0 }, "{index}", "_bulk" ],
-            [ {}, "_bulk" ],
-        ],
-        qs =>
-            [ "consistency", "refresh", "replication", "routing", "timeout" ],
-        serialize => "bulk",
-    },
-
-    'clear_scroll' => {
-        body   => {},
-        doc    => "search-request-scroll",
-        method => "DELETE",
-        parts  => { scroll_id => { multi => 1 } },
-        paths  => [
-            [ { scroll_id => 2 }, "_search", "scroll", "{scroll_id}" ],
-            [ {}, "_search", "scroll" ],
-        ],
-        qs => [],
-    },
-
-    'count' => {
-        body   => {},
-        doc    => "search-count",
-        method => "POST",
-        parts  => { index => { multi => 1 }, type => { multi => 1 } },
-        paths  => [
-            [ { index => 0, type => 1 }, "{index}", "{type}", "_count" ],
-            [ { type => 1 }, "_all", "{type}", "_count" ],
-            [ { index => 0 }, "{index}", "_count" ],
-            [ {}, "_count" ],
-        ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "min_score",
-            "preference",         "routing",
-            "source",
-        ],
-    },
-
-    'count_percolate' => {
-        body  => {},
-        doc   => "search-percolate",
-        parts => {
-            id    => {},
-            index => { required => 1 },
-            type  => { required => 1 }
-        },
-        paths => [
-            [   { id => 2, index => 0, type => 1 }, "{index}",
-                "{type}",     "{id}",
-                "_percolate", "count",
-            ],
-            [   { index => 0, type => 1 }, "{index}",
-                "{type}", "_percolate",
-                "count",
-            ],
-        ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "percolate_index",
-            "percolate_type",     "preference",
-            "routing",            "version",
-            "version_type",
-        ],
-    },
-
-    'delete' => {
-        doc    => "docs-delete",
-        method => "DELETE",
-        parts  => {
-            id    => { required => 1 },
-            index => { required => 1 },
-            type  => { required => 1 },
-        },
-        paths => [
-            [   { id => 2, index => 0, type => 1 }, "{index}",
-                "{type}", "{id}"
-            ],
-        ],
-        qs => [
-            "consistency", "parent",  "refresh", "replication",
-            "routing",     "timeout", "version", "version_type",
-        ],
-    },
-
-    'delete_by_query' => {
-        body   => {},
-        doc    => "docs-delete-by-query",
-        method => "DELETE",
-        parts  => {
-            index => { multi => 1, required => 1 },
-            type  => { multi => 1 }
-        },
-        paths => [
-            [ { index => 0, type => 1 }, "{index}", "{type}", "_query" ],
-            [ { index => 0 }, "{index}", "_query" ],
-        ],
-        qs => [
-            "allow_no_indices",   "analyzer",
-            "consistency",        "default_operator",
-            "df",                 "expand_wildcards",
-            "ignore_unavailable", "q",
-            "replication",        "routing",
-            "source",             "timeout",
-        ],
-    },
-
-    'delete_script' => {
-        doc    => "modules-scripting",
-        method => "DELETE",
-        parts  => { id => { required => 1 }, lang => { required => 1 } },
-        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
-        qs => [ "version", "version_type" ],
-    },
-
-    'delete_template' => {
-        doc    => "search-template",
-        method => "DELETE",
-        parts  => { id => {} },
-        paths  => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
-        qs => [ "version", "version_type" ],
-    },
-
-    'exists' => {
-        doc    => "docs-get",
-        method => "HEAD",
-        parts  => {
-            id    => { required => 1 },
-            index => { required => 1 },
-            type  => { required => 1 },
-        },
-        paths => [
-            [   { id => 2, index => 0, type => 1 }, "{index}",
-                "{type}", "{id}"
-            ],
-        ],
-        qs => [ "parent", "preference", "realtime", "refresh", "routing" ],
-    },
-
-    'explain' => {
-        body  => {},
-        doc   => "search-explain",
-        parts => {
-            id    => { required => 1 },
-            index => { required => 1 },
-            type  => { required => 1 },
-        },
-        paths => [
-            [   { id => 2, index => 0, type => 1 }, "{index}",
-                "{type}", "{id}",
-                "_explain",
-            ],
-        ],
-        qs => [
-            "_source",         "_source_exclude",
-            "_source_include", "analyze_wildcard",
-            "analyzer",        "default_operator",
-            "df",              "fields",
-            "lenient",         "lowercase_expanded_terms",
-            "parent",          "preference",
-            "q",               "routing",
-            "source",
-        ],
-    },
-
-    'get' => {
-        doc   => "docs-get",
-        parts => {
-            id    => { required => 1 },
-            index => { required => 1 },
-            type  => { required => 1 },
-        },
-        paths => [
-            [   { id => 2, index => 0, type => 1 }, "{index}",
-                "{type}", "{id}"
-            ],
-        ],
-        qs => [
-            "_source",         "_source_exclude",
-            "_source_include", "fields",
-            "parent",          "preference",
-            "realtime",        "refresh",
-            "routing",         "version",
-            "version_type",
-        ],
-    },
-
-    'get_script' => {
-        doc   => "modules-scripting",
-        parts => { id => { required => 1 }, lang => { required => 1 } },
-        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
-        qs => [ "version", "version_type" ],
-    },
-
-    'get_source' => {
-        doc   => "docs-get",
-        parts => {
-            id    => { required => 1 },
-            index => { required => 1 },
-            type  => { required => 1 },
-        },
-        paths => [
-            [   { id => 2, index => 0, type => 1 },
-                "{index}", "{type}", "{id}", "_source",
-            ],
-        ],
-        qs => [
-            "_source",         "_source_exclude",
-            "_source_include", "parent",
-            "preference",      "realtime",
-            "refresh",         "routing",
-            "version",         "version_type",
-        ],
-    },
-
-    'get_template' => {
-        doc   => "search-template",
-        parts => { id => { required => 1 } },
-        paths => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
-        qs => [ "version", "version_type" ],
-    },
-
-    'index' => {
-        body   => { required => 1 },
-        doc    => "docs-index_",
-        method => "POST",
-        parts  => {
-            id    => {},
-            index => { required => 1 },
-            type  => { required => 1 }
-        },
-        paths => [
-            [   { id => 2, index => 0, type => 1 }, "{index}",
-                "{type}", "{id}"
-            ],
-            [ { index => 0, type => 1 }, "{index}", "{type}" ],
-        ],
-        qs => [
-            "consistency", "op_type", "parent",  "refresh",
-            "replication", "routing", "timeout", "timestamp",
-            "ttl",         "version", "version_type",
-        ],
-    },
-
-    'info' => { doc => "", parts => {}, paths => [ [ {} ] ], qs => [] },
-
-    'list_benchmarks' => {
-        doc   => "search-benchmark",
-        parts => { index => { multi => 1 }, type => {} },
-        paths => [
-            [ { index => 0, type => 1 }, "{index}", "{type}", "_bench" ],
-            [ { type => 1 }, "_all", "{type}", "_bench" ],
-            [ { index => 0 }, "{index}", "_bench" ],
-            [ {}, "_bench" ],
-        ],
-        qs => [],
-    },
-
-    'mget' => {
-        body            => { required => 1 },
-        doc             => "docs-multi-get",
-        index_when_type => 1,
-        parts => { index => {}, type => {} },
-        paths => [
-            [ { index => 0, type => 1 }, "{index}", "{type}", "_mget" ],
-            [ { index => 0 }, "{index}", "_mget" ],
-            [ {}, "_mget" ],
-        ],
-        qs => [
-            "_source",         "_source_exclude",
-            "_source_include", "fields",
-            "preference",      "realtime",
-            "refresh",
-        ],
-    },
-
-    'mlt' => {
-        body  => {},
-        doc   => "search-more-like-this",
-        parts => {
-            id    => { required => 1 },
-            index => { required => 1 },
-            type  => { required => 1 },
-        },
-        paths => [
-            [   { id => 2, index => 0, type => 1 },
-                "{index}", "{type}", "{id}", "_mlt",
-            ],
-        ],
-        qs => [
-            "boost_terms",            "max_doc_freq",
-            "max_query_terms",        "max_word_length",
-            "min_doc_freq",           "min_term_freq",
-            "min_word_length",        "mlt_fields",
-            "percent_terms_to_match", "routing",
-            "search_from",            "search_indices",
-            "search_scroll",          "search_size",
-            "search_source",          "search_type",
-            "search_types",           "stop_words",
-        ],
-    },
-
-    'mpercolate' => {
-        body            => { required => 1 },
-        doc             => "search-percolate",
-        index_when_type => 1,
-        parts => { index => {}, type => {} },
-        paths => [
-            [ { index => 0, type => 1 }, "{index}", "{type}", "_mpercolate" ],
-            [ { index => 0 }, "{index}", "_mpercolate" ],
-            [ {}, "_mpercolate" ],
-        ],
-        qs =>
-            [ "allow_no_indices", "expand_wildcards", "ignore_unavailable" ],
-        serialize => "bulk",
-    },
-
-    'msearch' => {
-        body => { required => 1 },
-        doc  => "search-multi-search",
-        parts => { index => { multi => 1 }, type => { multi => 1 } },
-        paths => [
-            [ { index => 0, type => 1 }, "{index}", "{type}", "_msearch" ],
-            [ { type => 1 }, "_all", "{type}", "_msearch" ],
-            [ { index => 0 }, "{index}", "_msearch" ],
-            [ {}, "_msearch" ],
-        ],
-        qs        => ["search_type"],
-        serialize => "bulk",
-    },
-
-    'mtermvectors' => {
-        body            => {},
-        doc             => "docs-multi-termvectors",
-        index_when_type => 1,
-        parts           => { index => {}, type => {} },
-        paths           => [
-            [   { index => 0, type => 1 }, "{index}",
-                "{type}", "_mtermvectors"
-            ],
-            [ { index => 0 }, "{index}", "_mtermvectors" ],
-            [ {}, "_mtermvectors" ],
-        ],
-        qs => [
-            "field_statistics", "fields",
-            "ids",              "offsets",
-            "parent",           "payloads",
-            "positions",        "preference",
-            "realtime",         "routing",
-            "term_statistics",  "version",
-            "version_type",
-        ],
-    },
-
-    'percolate' => {
-        body  => {},
-        doc   => "search-percolate",
-        parts => {
-            id    => {},
-            index => { required => 1 },
-            type  => { required => 1 }
-        },
-        paths => [
-            [   { id => 2, index => 0, type => 1 }, "{index}",
-                "{type}", "{id}",
-                "_percolate",
-            ],
-            [ { index => 0, type => 1 }, "{index}", "{type}", "_percolate" ],
-        ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "percolate_format",
-            "percolate_index",    "percolate_preference",
-            "percolate_routing",  "percolate_type",
-            "preference",         "routing",
-            "version",            "version_type",
-        ],
-    },
-
-    'ping' => {
-        doc    => "",
-        method => "HEAD",
-        parts  => {},
-        paths  => [ [ {} ] ],
-        qs     => []
-    },
-
-    'put_script' => {
-        body   => { required => 1 },
-        doc    => "modules-scripting",
-        method => "PUT",
-        parts => { id => { required => 1 }, lang => { required => 1 } },
-        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
-        qs => [ "op_type", "version", "version_type" ],
-    },
-
-    'put_template' => {
-        body   => { required => 1 },
-        doc    => "search-template",
-        method => "PUT",
-        parts => { id => { required => 1 } },
-        paths => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
-        qs => [ "op_type", "version", "version_type" ],
-    },
-
-    'scroll' => {
-        body  => {},
-        doc   => "search-request-scroll",
-        parts => { scroll_id => {} },
-        paths => [
-            [ { scroll_id => 2 }, "_search", "scroll", "{scroll_id}" ],
-            [ {}, "_search", "scroll" ],
-        ],
-        qs => ["scroll"],
-    },
-
-    'search' => {
-        body  => {},
-        doc   => "search-search",
-        parts => { index => { multi => 1 }, type => { multi => 1 } },
-        paths => [
-            [ { index => 0, type => 1 }, "{index}", "{type}", "_search" ],
-            [ { type => 1 }, "_all", "{type}", "_search" ],
-            [ { index => 0 }, "{index}", "_search" ],
-            [ {}, "_search" ],
-        ],
-        qs => [
-            "_source",                  "_source_exclude",
-            "_source_include",          "allow_no_indices",
-            "analyze_wildcard",         "analyzer",
-            "default_operator",         "df",
-            "expand_wildcards",         "explain",
-            "fields",                   "from",
-            "ignore_unavailable",       "lenient",
-            "lowercase_expanded_terms", "preference",
-            "q",                        "query_cache",
-            "routing",                  "scroll",
-            "search_type",              "size",
-            "sort",                     "source",
-            "stats",                    "suggest_field",
-            "suggest_mode",             "suggest_size",
-            "suggest_text",             "terminate_after",
-            "timeout",                  "track_scores",
-            "version",
-        ],
-    },
-
-    'search_exists' => {
-        body   => {},
-        doc    => "search-exists",
-        method => "POST",
-        parts  => { index => { multi => 1 }, type => { multi => 1 } },
-        paths  => [
-            [   { index => 0, type => 1 }, "{index}",
-                "{type}", "_search",
-                "exists",
-            ],
-            [ { type => 1 }, "_all", "{type}", "_search", "exists" ],
-            [ { index => 0 }, "{index}", "_search", "exists" ],
-            [ {}, "_search", "exists" ],
-        ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "min_score",
-            "preference",         "routing",
-            "source",
-        ],
-    },
-
-    'search_shards' => {
-        doc   => "search-shards",
-        parts => { index => {}, type => {} },
-        paths => [
-            [   { index => 0, type => 1 }, "{index}",
-                "{type}", "_search_shards",
-            ],
-            [ { type => 1 }, "_all", "{type}", "_search_shards" ],
-            [ { index => 0 }, "{index}", "_search_shards" ],
-            [ {}, "_search_shards" ],
-        ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "local",
-            "preference",         "routing",
-        ],
-    },
-
-    'search_template' => {
-        body  => {},
-        doc   => "search-template",
-        parts => { index => { multi => 1 }, type => { multi => 1 } },
-        paths => [
-            [   { index => 0, type => 1 }, "{index}",
-                "{type}", "_search",
-                "template",
-            ],
-            [ { type => 1 }, "_all", "{type}", "_search", "template" ],
-            [ { index => 0 }, "{index}", "_search", "template" ],
-            [ {}, "_search", "template" ],
-        ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "preference",
-            "routing",            "scroll",
-            "search_type",
-        ],
-    },
-
-    'suggest' => {
-        body   => { required => 1 },
-        doc    => "search-suggesters",
-        method => "POST",
-        parts => { index => { multi => 1 } },
-        paths =>
-            [ [ { index => 0 }, "{index}", "_suggest" ], [ {}, "_suggest" ] ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "preference",
-            "routing",            "source",
-        ],
-    },
-
-    'termvector' => {
-        body  => {},
-        doc   => "docs-termvectors",
-        parts => {
-            id    => { required => 1 },
-            index => { required => 1 },
-            type  => { required => 1 },
-        },
-        paths => [
-            [   { id => 2, index => 0, type => 1 }, "{index}",
-                "{type}", "{id}",
-                "_termvector",
-            ],
-        ],
-        qs => [
-            "dfs",       "field_statistics",
-            "fields",    "offsets",
-            "parent",    "payloads",
-            "positions", "preference",
-            "realtime",  "routing",
-            "term_statistics",
-        ],
-    },
-
-    'termvectors' => {
-        body  => {},
-        doc   => "docs-termvectors",
-        parts => {
-            id    => {},
-            index => { required => 1 },
-            type  => { required => 1 }
-        },
-        paths => [
-            [   { id => 2, index => 0, type => 1 }, "{index}",
-                "{type}", "{id}",
-                "_termvectors",
-            ],
-            [   { index => 0, type => 1 }, "{index}", "{type}",
-                "_termvectors"
-            ],
-        ],
-        qs => [
-            "dfs",             "field_statistics",
-            "fields",          "offsets",
-            "parent",          "payloads",
-            "positions",       "preference",
-            "realtime",        "routing",
-            "term_statistics", "version",
-            "version_type",
-        ],
-    },
-
-    'update' => {
-        body   => {},
-        doc    => "docs-update",
-        method => "POST",
-        parts  => {
-            id    => { required => 1 },
-            index => { required => 1 },
-            type  => { required => 1 },
-        },
-        paths => [
-            [   { id => 2, index => 0, type => 1 },
-                "{index}", "{type}", "{id}", "_update",
-            ],
-        ],
-        qs => [
-            "consistency",       "fields",
-            "lang",              "parent",
-            "refresh",           "replication",
-            "retry_on_conflict", "routing",
-            "script",            "script_id",
-            "scripted_upsert",   "timeout",
-            "timestamp",         "ttl",
-            "version",           "version_type",
-        ],
-    },
-
-    'cat.aliases' => {
-        doc   => "cat-alias",
-        parts => { name => { multi => 1 } },
-        paths => [
-            [ { name => 2 }, "_cat", "aliases", "{name}" ],
-            [ {}, "_cat", "aliases" ],
-        ],
-        qs => [ "h", "help", "local", "master_timeout", "v" ],
-    },
-
-    'cat.allocation' => {
-        doc   => "cat-allocation",
-        parts => { node_id => { multi => 1 } },
-        paths => [
-            [ { node_id => 2 }, "_cat", "allocation", "{node_id}" ],
-            [ {}, "_cat", "allocation" ],
-        ],
-        qs => [ "bytes", "h", "help", "local", "master_timeout", "v" ],
-    },
-
-    'cat.count' => {
-        doc   => "cat-count",
-        parts => { index => { multi => 1 } },
-        paths => [
-            [ { index => 2 }, "_cat", "count", "{index}" ],
-            [ {}, "_cat", "count" ],
-        ],
-        qs => [ "h", "help", "local", "master_timeout", "v" ],
-    },
-
-    'cat.fielddata' => {
-        doc   => "cat-fielddata",
-        parts => { fields => { multi => 1 } },
-        paths => [
-            [ { fields => 2 }, "_cat", "fielddata", "{fields}" ],
-            [ {}, "_cat", "fielddata" ],
-        ],
-        qs => [ "bytes", "h", "help", "local", "master_timeout", "v" ],
-    },
-
-    'cat.health' => {
-        doc   => "cat-health",
-        parts => {},
-        paths => [ [ {}, "_cat", "health" ] ],
-        qs    => [ "h", "help", "local", "master_timeout", "ts", "v" ],
-    },
-
-    'cat.help' => {
-        doc   => "cat",
-        parts => {},
-        paths => [ [ {}, "_cat" ] ],
-        qs    => ["help"]
-    },
-
-    'cat.indices' => {
-        doc   => "cat-indices",
-        parts => { index => { multi => 1 } },
-        paths => [
-            [ { index => 2 }, "_cat", "indices", "{index}" ],
-            [ {}, "_cat", "indices" ],
-        ],
-        qs => [ "bytes", "h", "help", "local", "master_timeout", "pri", "v" ],
-    },
-
-    'cat.master' => {
-        doc   => "cat-master",
-        parts => {},
-        paths => [ [ {}, "_cat", "master" ] ],
-        qs    => [ "h", "help", "local", "master_timeout", "v" ],
-    },
-
-    'cat.nodes' => {
-        doc   => "cat-nodes",
-        parts => {},
-        paths => [ [ {}, "_cat", "nodes" ] ],
-        qs    => [ "h", "help", "local", "master_timeout", "v" ],
-    },
-
-    'cat.pending_tasks' => {
-        doc   => "cat-pending-tasks",
-        parts => {},
-        paths => [ [ {}, "_cat", "pending_tasks" ] ],
-        qs    => [ "h", "help", "local", "master_timeout", "v" ],
-    },
-
-    'cat.plugins' => {
-        doc   => "cat-plugins",
-        parts => {},
-        paths => [ [ {}, "_cat", "plugins" ] ],
-        qs    => [ "h", "help", "local", "master_timeout", "v" ],
-    },
-
-    'cat.recovery' => {
-        doc   => "cat-recovery",
-        parts => { index => { multi => 1 } },
-        paths => [
-            [ { index => 2 }, "_cat", "recovery", "{index}" ],
-            [ {}, "_cat", "recovery" ],
-        ],
-        qs => [ "bytes", "h", "help", "master_timeout", "v" ],
-    },
-
-    'cat.segments' => {
-        doc   => "cat-segments",
-        parts => { index => { multi => 1 } },
-        paths => [
-            [ { index => 2 }, "_cat", "segments", "{index}" ],
-            [ {}, "_cat", "segments" ],
-        ],
-        qs => [ "h", "help", "v" ],
-    },
-
-    'cat.shards' => {
-        doc   => "cat-shards",
-        parts => { index => { multi => 1 } },
-        paths => [
-            [ { index => 2 }, "_cat", "shards", "{index}" ],
-            [ {}, "_cat", "shards" ],
-        ],
-        qs => [ "h", "help", "local", "master_timeout", "v" ],
-    },
-
-    'cat.thread_pool' => {
-        doc   => "cat-thread-pool",
-        parts => {},
-        paths => [ [ {}, "_cat", "thread_pool" ] ],
-        qs    => [ "full_id", "h", "help", "local", "master_timeout", "v" ],
-    },
-
-    'cluster.get_settings' => {
-        doc   => "cluster-update-settings",
-        parts => {},
-        paths => [ [ {}, "_cluster", "settings" ] ],
-        qs => [ "flat_settings", "master_timeout", "timeout" ],
-    },
-
-    'cluster.health' => {
-        doc   => "cluster-health",
-        parts => { index => {} },
-        paths => [
-            [ { index => 2 }, "_cluster", "health", "{index}" ],
-            [ {}, "_cluster", "health" ],
-        ],
-        qs => [
-            "level",                      "local",
-            "master_timeout",             "timeout",
-            "wait_for_active_shards",     "wait_for_nodes",
-            "wait_for_relocating_shards", "wait_for_status",
-        ],
-    },
-
-    'cluster.pending_tasks' => {
-        doc   => "cluster-pending",
-        parts => {},
-        paths => [ [ {}, "_cluster", "pending_tasks" ] ],
-        qs => [ "local", "master_timeout" ],
-    },
-
-    'cluster.put_settings' => {
-        body   => {},
-        doc    => "cluster-update-settings",
-        method => "PUT",
-        parts  => {},
-        paths  => [ [ {}, "_cluster", "settings" ] ],
-        qs => [ "flat_settings", "master_timeout", "timeout" ],
-    },
-
-    'cluster.reroute' => {
-        body   => {},
-        doc    => "cluster-reroute",
-        method => "POST",
-        parts  => {},
-        paths  => [ [ {}, "_cluster", "reroute" ] ],
-        qs => [ "dry_run", "explain", "master_timeout", "metric", "timeout" ],
-    },
-
-    'cluster.state' => {
-        doc   => "cluster-state",
-        parts => { index => { multi => 1 }, metric => { multi => 1 } },
-        paths => [
-            [   { index => 3, metric => 2 }, "_cluster",
-                "state", "{metric}",
-                "{index}",
-            ],
-            [ { index => 3 }, "_cluster", "state", "_all", "{index}" ],
-            [ { metric => 2 }, "_cluster", "state", "{metric}" ],
-            [ {}, "_cluster", "state" ],
-        ],
-        qs => [ "flat_settings", "local", "master_timeout" ],
-    },
-
-    'cluster.stats' => {
-        doc   => "cluster-stats",
-        parts => { node_id => { multi => 1 } },
-        paths => [
-            [ { node_id => 3 }, "_cluster", "stats", "nodes", "{node_id}" ],
-            [ {}, "_cluster", "stats" ],
-        ],
-        qs => [ "flat_settings", "human" ],
-    },
-
-    'indices.analyze' => {
-        body  => {},
-        doc   => "indices-analyze",
-        parts => { index => {} },
-        paths =>
-            [ [ { index => 0 }, "{index}", "_analyze" ], [ {}, "_analyze" ] ],
-        qs => [
-            "analyzer", "char_filters", "field", "filters",
-            "format",   "prefer_local", "text",  "tokenizer",
-        ],
-    },
-
-    'indices.clear_cache' => {
-        doc    => "indices-clearcache",
-        method => "POST",
-        parts  => { index => { multi => 1 } },
-        paths  => [
-            [ { index => 0 }, "{index}", "_cache", "clear" ],
-            [ {}, "_cache", "clear" ],
-        ],
-        qs => [
-            "allow_no_indices", "expand_wildcards",
-            "fielddata",        "fields",
-            "filter",           "filter_cache",
-            "filter_keys",      "id",
-            "id_cache",         "ignore_unavailable",
-            "query_cache",      "recycler",
-        ],
-    },
-
-    'indices.close' => {
-        doc    => "indices-open-close",
-        method => "POST",
-        parts  => { index => { required => 1 } },
-        paths  => [ [ { index => 0 }, "{index}", "_close" ] ],
-        qs     => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "master_timeout",
-            "timeout",
-        ],
-    },
-
-    'indices.create' => {
-        body   => {},
-        doc    => "indices-create-index",
-        method => "PUT",
-        parts  => { index => { required => 1 } },
-        paths  => [ [ { index => 0 }, "{index}" ] ],
-        qs => [ "master_timeout", "timeout" ],
-    },
-
-    'indices.delete' => {
-        doc    => "indices-delete-index",
-        method => "DELETE",
-        parts  => { index => { multi => 1, required => 1 } },
-        paths => [ [ { index => 0 }, "{index}" ] ],
-        qs => [ "master_timeout", "timeout" ],
-    },
-
-    'indices.delete_alias' => {
-        doc    => "indices-aliases",
-        method => "DELETE",
-        parts  => {
-            index => { multi => 1, required => 1 },
-            name  => { multi => 1, required => 1 },
-        },
-        paths =>
-            [ [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ] ],
-        qs => [ "master_timeout", "timeout" ],
-    },
-
-    'indices.delete_mapping' => {
-        doc    => "indices-delete-mapping",
-        method => "DELETE",
-        parts  => {
-            index => { multi => 1, required => 1 },
-            type  => { multi => 1, required => 1 },
-        },
-        paths => [
-            [ { index => 0, type => 2 }, "{index}", "_mapping", "{type}" ]
-        ],
-        qs => ["master_timeout"],
-    },
-
-    'indices.delete_template' => {
-        doc    => "indices-templates",
-        method => "DELETE",
-        parts  => { name => { required => 1 } },
-        paths  => [ [ { name => 1 }, "_template", "{name}" ] ],
-        qs => [ "master_timeout", "timeout" ],
-    },
-
-    'indices.delete_warmer' => {
-        doc    => "indices-warmers",
-        method => "DELETE",
-        parts  => {
-            index => { multi => 1, required => 1 },
-            name  => { multi => 1, required => 1 },
-        },
-        paths =>
-            [ [ { index => 0, name => 2 }, "{index}", "_warmer", "{name}" ] ],
-        qs => ["master_timeout"],
-    },
-
-    'indices.exists' => {
-        doc    => "indices-exists",
-        method => "HEAD",
-        parts  => { index => { multi => 1, required => 1 } },
-        paths => [ [ { index => 0 }, "{index}" ] ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "local",
-        ],
-    },
-
-    'indices.exists_alias' => {
-        doc    => "indices-aliases",
-        method => "HEAD",
-        parts  => { index => { multi => 1 }, name => { multi => 1 } },
-        paths  => [
-            [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ],
-            [ { index => 0 }, "{index}", "_alias" ],
-            [ { name  => 1 }, "_alias",  "{name}" ],
-        ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "local",
-        ],
-    },
-
-    'indices.exists_template' => {
-        doc    => "indices-templates",
-        method => "HEAD",
-        parts  => { name => { required => 1 } },
-        paths  => [ [ { name => 1 }, "_template", "{name}" ] ],
-        qs     => ["local"],
-    },
-
-    'indices.exists_type' => {
-        doc    => "indices-types-exists",
-        method => "HEAD",
-        parts  => {
-            index => { multi => 1, required => 1 },
-            type  => { multi => 1, required => 1 },
-        },
-        paths => [ [ { index => 0, type => 1 }, "{index}", "{type}" ] ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "local",
-        ],
-    },
-
-    'indices.flush' => {
-        doc    => "indices-flush",
-        method => "POST",
-        parts  => { index => { multi => 1 } },
-        paths =>
-            [ [ { index => 0 }, "{index}", "_flush" ], [ {}, "_flush" ] ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "force",              "full",
-            "ignore_unavailable", "wait_if_ongoing",
-        ],
-    },
-
-    'indices.get' => {
-        doc   => "indices-get-index",
-        parts => {
-            feature => { multi => 1 },
-            index   => { multi => 1, required => 1 }
-        },
-        paths => [
-            [ { feature => 1, index => 0 }, "{index}", "{feature}" ],
-            [ { index => 0 }, "{index}" ],
-        ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "local",
-        ],
-    },
-
-    'indices.get_alias' => {
-        doc   => "indices-aliases",
-        parts => { index => { multi => 1 }, name => { multi => 1 } },
-        paths => [
-            [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ],
-            [ { index => 0 }, "{index}", "_alias" ],
-            [ { name  => 1 }, "_alias",  "{name}" ],
-            [ {}, "_alias" ],
-        ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "local",
-        ],
-    },
-
-    'indices.get_aliases' => {
-        doc   => "indices-aliases",
-        parts => { index => { multi => 1 }, name => { multi => 1 } },
-        paths => [
-            [ { index => 0, name => 2 }, "{index}", "_aliases", "{name}" ],
-            [ { index => 0 }, "{index}",  "_aliases" ],
-            [ { name  => 1 }, "_aliases", "{name}" ],
-            [ {}, "_aliases" ],
-        ],
-        qs => [ "local", "timeout" ],
-    },
-
-    'indices.get_field_mapping' => {
-        doc   => "indices-get-field-mapping",
-        parts => {
-            field => { multi => 1, required => 1 },
-            index => { multi => 1 },
-            type  => { multi => 1 },
-        },
-        paths => [
-            [   { field => 4, index => 0, type => 2 }, "{index}",
-                "_mapping", "{type}",
-                "field",    "{field}",
-            ],
-            [   { field => 3, index => 0 }, "{index}",
-                "_mapping", "field",
-                "{field}",
-            ],
-            [   { field => 3, type => 1 }, "_mapping",
-                "{type}", "field",
-                "{field}",
-            ],
-            [ { field => 2 }, "_mapping", "field", "{field}" ],
-        ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "include_defaults",
-            "local",
-        ],
-    },
-
-    'indices.get_mapping' => {
-        doc   => "indices-get-mapping",
-        parts => { index => { multi => 1 }, type => { multi => 1 } },
-        paths => [
-            [ { index => 0, type => 2 }, "{index}", "_mapping", "{type}" ],
-            [ { index => 0 }, "{index}",  "_mapping" ],
-            [ { type  => 1 }, "_mapping", "{type}" ],
-            [ {}, "_mapping" ],
-        ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "local",
-        ],
-    },
-
-    'indices.get_settings' => {
-        doc   => "indices-get-settings",
-        parts => { index => { multi => 1 }, name => { multi => 1 } },
-        paths => [
-            [ { index => 0, name => 2 }, "{index}", "_settings", "{name}" ],
-            [ { index => 0 }, "{index}",   "_settings" ],
-            [ { name  => 1 }, "_settings", "{name}" ],
-            [ {}, "_settings" ],
-        ],
-        qs => [
-            "allow_no_indices", "expand_wildcards",
-            "flat_settings",    "ignore_unavailable",
-            "local",
-        ],
-    },
-
-    'indices.get_template' => {
-        doc   => "indices-templates",
-        parts => { name => {} },
-        paths =>
-            [ [ { name => 1 }, "_template", "{name}" ], [ {}, "_template" ] ],
-        qs => [ "flat_settings", "local" ],
-    },
-
-    'indices.get_upgrade' => {
-        doc   => "indices-upgrade",
-        parts => { index => { multi => 1 } },
-        paths =>
-            [ [ { index => 0 }, "{index}", "_upgrade" ], [ {}, "_upgrade" ] ],
-        qs => [
-            "allow_no_indices", "expand_wildcards",
-            "human",            "ignore_unavailable",
-        ],
-    },
-
-    'indices.get_warmer' => {
-        doc   => "indices-warmers",
-        parts => {
-            index => { multi => 1 },
-            name  => { multi => 1 },
-            type  => { multi => 1 }
-        },
-        paths => [
-            [   { index => 0, name => 3, type => 1 },
-                "{index}", "{type}", "_warmer", "{name}",
-            ],
-            [   { name => 3, type => 1 }, "_all",
-                "{type}", "_warmer",
-                "{name}"
-            ],
-            [ { index => 0, name => 2 }, "{index}", "_warmer", "{name}" ],
-            [ { index => 0 }, "{index}", "_warmer" ],
-            [ { name  => 1 }, "_warmer", "{name}" ],
-            [ {}, "_warmer" ],
-        ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "local",
-        ],
-    },
-
-    'indices.open' => {
-        doc    => "indices-open-close",
-        method => "POST",
-        parts  => { index => { required => 1 } },
-        paths  => [ [ { index => 0 }, "{index}", "_open" ] ],
-        qs     => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "master_timeout",
-            "timeout",
-        ],
-    },
-
-    'indices.optimize' => {
-        doc    => "indices-optimize",
-        method => "POST",
-        parts  => { index => { multi => 1 } },
-        paths  => [
-            [ { index => 0 }, "{index}", "_optimize" ],
-            [ {}, "_optimize" ]
-        ],
-        qs => [
-            "allow_no_indices",     "expand_wildcards",
-            "flush",                "force",
-            "ignore_unavailable",   "max_num_segments",
-            "only_expunge_deletes", "wait_for_merge",
-        ],
-    },
-
-    'indices.put_alias' => {
-        body   => {},
-        doc    => "indices-aliases",
-        method => "PUT",
-        parts  => {
-            index => { multi    => 1, required => 1 },
-            name  => { required => 1 }
-        },
-        paths =>
-            [ [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ] ],
-        qs => [ "master_timeout", "timeout" ],
-    },
-
-    'indices.put_mapping' => {
-        body   => { required => 1 },
-        doc    => "indices-put-mapping",
-        method => "PUT",
-        parts => { index => { multi => 1 }, type => { required => 1 } },
-        paths => [
-            [ { index => 0, type => 2 }, "{index}", "_mapping", "{type}" ],
-            [ { type => 1 }, "_mapping", "{type}" ],
-        ],
-        qs => [
-            "allow_no_indices", "expand_wildcards",
-            "ignore_conflicts", "ignore_unavailable",
-            "master_timeout",   "timeout",
-        ],
-    },
-
-    'indices.put_settings' => {
-        body   => { required => 1 },
-        doc    => "indices-update-settings",
-        method => "PUT",
-        parts => { index => { multi => 1 } },
-        paths => [
-            [ { index => 0 }, "{index}", "_settings" ],
-            [ {}, "_settings" ]
-        ],
-        qs => [
-            "allow_no_indices", "expand_wildcards",
-            "flat_settings",    "ignore_unavailable",
-            "master_timeout",
-        ],
-    },
-
-    'indices.put_template' => {
-        body   => { required => 1 },
-        doc    => "indices-templates",
-        method => "PUT",
-        parts => { name => { required => 1 } },
-        paths => [ [ { name => 1 }, "_template", "{name}" ] ],
-        qs => [
-            "create",         "flat_settings",
-            "master_timeout", "order",
-            "timeout"
-        ],
-    },
-
-    'indices.put_warmer' => {
-        body   => { required => 1 },
-        doc    => "indices-warmers",
-        method => "PUT",
-        parts  => {
-            index => { multi    => 1 },
-            name  => { required => 1 },
-            type  => { multi    => 1 },
-        },
-        paths => [
-            [   { index => 0, name => 3, type => 1 },
-                "{index}", "{type}", "_warmer", "{name}",
-            ],
-            [   { name => 3, type => 1 }, "_all",
-                "{type}", "_warmer",
-                "{name}"
-            ],
-            [ { index => 0, name => 2 }, "{index}", "_warmer", "{name}" ],
-            [ { name => 1 }, "_warmer", "{name}" ],
-        ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "master_timeout",
-        ],
-    },
-
-    'indices.recovery' => {
-        doc   => "indices-recovery",
-        parts => { index => { multi => 1 } },
-        paths => [
-            [ { index => 0 }, "{index}", "_recovery" ],
-            [ {}, "_recovery" ]
-        ],
-        qs => [ "active_only", "detailed", "human" ],
-    },
-
-    'indices.refresh' => {
-        doc    => "indices-refresh",
-        method => "POST",
-        parts  => { index => { multi => 1 } },
-        paths =>
-            [ [ { index => 0 }, "{index}", "_refresh" ], [ {}, "_refresh" ] ],
-        qs => [
-            "allow_no_indices", "expand_wildcards",
-            "force",            "ignore_unavailable",
-        ],
-    },
-
-    'indices.segments' => {
-        doc   => "indices-segments",
-        parts => { index => { multi => 1 } },
-        paths => [
-            [ { index => 0 }, "{index}", "_segments" ],
-            [ {}, "_segments" ]
-        ],
-        qs => [
-            "allow_no_indices", "expand_wildcards",
-            "human",            "ignore_unavailable",
-        ],
-    },
-
-    'indices.snapshot_index' => {
-        doc    => "indices-gateway-snapshot",
-        method => "POST",
-        parts  => { index => { multi => 1 } },
-        paths  => [
-            [ { index => 0 }, "{index}", "_gateway", "snapshot" ],
-            [ {}, "_gateway", "snapshot" ],
-        ],
-        qs =>
-            [ "allow_no_indices", "expand_wildcards", "ignore_unavailable" ],
-    },
-
-    'indices.stats' => {
-        doc   => "indices-stats",
-        parts => { index => { multi => 1 }, metric => { multi => 1 } },
-        paths => [
-            [ { index => 0, metric => 2 }, "{index}", "_stats", "{metric}" ],
-            [ { index  => 0 }, "{index}", "_stats" ],
-            [ { metric => 1 }, "_stats",  "{metric}" ],
-            [ {}, "_stats" ],
-        ],
-        qs => [
-            "completion_fields", "fielddata_fields",
-            "fields",            "groups",
-            "human",             "level",
-            "types",
-        ],
-    },
-
-    'indices.status' => {
-        doc   => "indices-status",
-        parts => { index => { multi => 1 } },
-        paths =>
-            [ [ { index => 0 }, "{index}", "_status" ], [ {}, "_status" ] ],
-        qs => [
-            "allow_no_indices", "expand_wildcards",
-            "human",            "ignore_unavailable",
-            "recovery",         "snapshot",
-        ],
-    },
-
-    'indices.update_aliases' => {
-        body   => { required => 1 },
-        doc    => "indices-aliases",
-        method => "POST",
-        parts  => {},
-        paths => [ [ {}, "_aliases" ] ],
-        qs => [ "master_timeout", "timeout" ],
-    },
-
-    'indices.upgrade' => {
-        doc    => "indices-upgrade",
-        method => "POST",
-        parts  => { index => { multi => 1 } },
-        paths =>
-            [ [ { index => 0 }, "{index}", "_upgrade" ], [ {}, "_upgrade" ] ],
-        qs => [
-            "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "wait_for_completion",
-        ],
-    },
-
-    'indices.validate_query' => {
-        body  => {},
-        doc   => "search-validate",
-        parts => { index => { multi => 1 }, type => { multi => 1 } },
-        paths => [
-            [   { index => 0, type => 1 }, "{index}",
-                "{type}", "_validate",
-                "query",
-            ],
-            [ { type => 1 }, "_all", "{type}", "_validate", "query" ],
-            [ { index => 0 }, "{index}", "_validate", "query" ],
-            [ {}, "_validate", "query" ],
-        ],
-        qs => [
-            "allow_no_indices", "expand_wildcards",
-            "explain",          "ignore_unavailable",
-            "q",                "source",
-        ],
-    },
-
-    'nodes.hot_threads' => {
-        doc   => "cluster-nodes-hot-threads",
-        parts => { node_id => { multi => 1 } },
-        paths => [
-            [ { node_id => 1 }, "_nodes", "{node_id}", "hot_threads" ],
-            [ {}, "_nodes", "hot_threads" ],
-        ],
-        qs => [
-            "ignore_idle_threads", "interval",
-            "snapshots",           "threads",
-            "type",
-        ],
-    },
-
-    'nodes.info' => {
-        doc   => "cluster-nodes-info",
-        parts => { metric => { multi => 1 }, node_id => { multi => 1 } },
-        paths => [
-            [   { metric => 2, node_id => 1 }, "_nodes",
-                "{node_id}", "{metric}",
-            ],
-            [ { metric => 2 }, "_nodes", "_all", "{metric}" ],
-            [ { node_id => 1 }, "_nodes", "{node_id}" ],
-            [ {}, "_nodes" ],
-        ],
-        qs => [ "flat_settings", "human" ],
-    },
-
-    'nodes.shutdown' => {
-        doc    => "cluster-nodes-shutdown",
-        method => "POST",
-        parts  => { node_id => { multi => 1 } },
-        paths  => [
-            [   { node_id => 2 }, "_cluster",
-                "nodes", "{node_id}",
-                "_shutdown"
-            ],
-            [ {}, "_shutdown" ],
-        ],
-        qs => [ "delay", "exit" ],
-    },
-
-    'nodes.stats' => {
-        doc   => "cluster-nodes-stats",
-        parts => {
-            index_metric => { multi => 1 },
-            metric       => { multi => 1 },
-            node_id      => { multi => 1 },
-        },
-        paths => [
-            [   { index_metric => 4, metric => 3, node_id => 1 },
-                "_nodes", "{node_id}", "stats", "{metric}", "{index_metric}",
-            ],
-            [   { index_metric => 4, node_id => 1 },
-                "_nodes", "{node_id}", "stats", "_all", "{index_metric}",
-            ],
-            [   { index_metric => 3, metric => 2 }, "_nodes",
-                "stats", "{metric}",
-                "{index_metric}",
-            ],
-            [   { index_metric => 3 }, "_nodes",
-                "stats", "_all",
-                "{index_metric}",
-            ],
-            [   { metric => 3, node_id => 1 }, "_nodes",
-                "{node_id}", "stats",
-                "{metric}",
-            ],
-            [ { metric  => 2 }, "_nodes", "stats",     "{metric}" ],
-            [ { node_id => 1 }, "_nodes", "{node_id}", "stats" ],
-            [ {}, "_nodes", "stats" ],
-        ],
-        qs => [
-            "completion_fields", "fielddata_fields",
-            "fields",            "groups",
-            "human",             "level",
-            "types",
-        ],
-    },
-
-    'snapshot.create' => {
-        body   => {},
-        doc    => "modules-snapshots",
-        method => "PUT",
-        parts  => {
-            repository => { required => 1 },
-            snapshot   => { required => 1 }
-        },
-        paths => [
-            [   { repository => 1, snapshot => 2 }, "_snapshot",
-                "{repository}", "{snapshot}",
-            ],
-        ],
-        qs => [ "master_timeout", "wait_for_completion" ],
-    },
-
-    'snapshot.create_repository' => {
-        body   => { required => 1 },
-        doc    => "modules-snapshots",
-        method => "PUT",
-        parts => { repository => { required => 1 } },
-        paths => [ [ { repository => 1 }, "_snapshot", "{repository}" ] ],
-        qs => [ "master_timeout", "timeout", "verify" ],
-    },
-
-    'snapshot.delete' => {
-        doc    => "modules-snapshots",
-        method => "DELETE",
-        parts  => {
-            repository => { required => 1 },
-            snapshot   => { required => 1 }
-        },
-        paths => [
-            [   { repository => 1, snapshot => 2 }, "_snapshot",
-                "{repository}", "{snapshot}",
-            ],
-        ],
-        qs => ["master_timeout"],
-    },
-
-    'snapshot.delete_repository' => {
-        doc    => "modules-snapshots",
-        method => "DELETE",
-        parts  => { repository => { multi => 1, required => 1 } },
-        paths  => [ [ { repository => 1 }, "_snapshot", "{repository}" ] ],
-        qs => [ "master_timeout", "timeout" ],
-    },
-
-    'snapshot.get' => {
-        doc   => "modules-snapshots",
-        parts => {
-            repository => { required => 1 },
-            snapshot   => { multi    => 1, required => 1 },
-        },
-        paths => [
-            [   { repository => 1, snapshot => 2 }, "_snapshot",
-                "{repository}", "{snapshot}",
-            ],
-        ],
-        qs => ["master_timeout"],
-    },
-
-    'snapshot.get_repository' => {
-        doc   => "modules-snapshots",
-        parts => { repository => { multi => 1 } },
-        paths => [
-            [ { repository => 1 }, "_snapshot", "{repository}" ],
-            [ {}, "_snapshot" ],
-        ],
-        qs => [ "local", "master_timeout" ],
-    },
-
-    'snapshot.restore' => {
-        body   => {},
-        doc    => "modules-snapshots",
-        method => "POST",
-        parts  => {
-            repository => { required => 1 },
-            snapshot   => { required => 1 }
-        },
-        paths => [
-            [   { repository => 1, snapshot => 2 }, "_snapshot",
-                "{repository}", "{snapshot}",
-                "_restore",
-            ],
-        ],
-        qs => [ "master_timeout", "wait_for_completion" ],
-    },
-
-    'snapshot.status' => {
-        doc   => "modules-snapshots",
-        parts => { repository => {}, snapshot => { multi => 1 } },
-        paths => [
-            [   { repository => 1, snapshot => 2 }, "_snapshot",
-                "{repository}", "{snapshot}",
-                "_status",
-            ],
-            [   { snapshot => 2 }, "_snapshot",
-                "_all", "{snapshot}",
-                "_status"
-            ],
-            [ { repository => 1 }, "_snapshot", "{repository}", "_status" ],
-            [ {}, "_snapshot", "_status" ],
-        ],
-        qs => ["master_timeout"],
-    },
-
-    'snapshot.verify_repository' => {
-        doc    => "modules-snapshots",
-        method => "POST",
-        parts  => { repository => { required => 1 } },
-        paths  => [
-            [ { repository => 1 }, "_snapshot", "{repository}", "_verify" ],
-        ],
-        qs => [ "master_timeout", "timeout" ],
-    },
-
-#=== AUTOGEN - END ===
-
-);
-
-for ( values %API ) {
-    $_->{qs_handlers} = qs_init( @{ $_->{qs} } );
-}
-
-1;
-
-=pod
-
-=encoding UTF-8
-
-=head1 NAME
-
-Search::Elasticsearch::Role::API - This class contains the spec for the Elasticsearch APIs
-
-=head1 VERSION
-
-version 1.19
-
-=head1 DESCRIPTION
-
-All of the Elasticsearch APIs are defined in this role. The example given below
-is the definition for the L<Search::Elasticsearch::Client::Direct/index()> method:
-
-    'index' => {
-        body => {
-            desc     => 'The document',
-            required => 1
-        },
-
-        doc    => '/api/index_/',
-        method => 'PUT',
-        path   => '{index}/{type}/{id|blank}',
-        qs     => [
-            'consistency', 'op_type',     'parent',  'percolate',
-            'refresh',     'replication', 'routing', 'timeout',
-            'timestamp',   'ttl',         'version', 'version_type'
-        ],
-    },
-
-These definitions can be used by different L<Search::Elasticsearch::Role::Client>
-implementations to provide distinct user interfaces.
-
-=head1 METHODS
-
-=head2 C<api()>
-
-    $defn = $api->api($name);
-
-The only method in this class is the C<api()> method which takes the name
-of the I<action> and returns its definition.  Actions in the
-C<indices> or C<cluster> namespace use the namespace as a prefix, eg:
-
-    $defn = $e->api('indices.create');
-    $defn = $e->api('cluster.node_stats');
-
-=head1 SEE ALSO
-
-=over
-
-=item *
-
-L<Search::Elasticsearch::Util::API::Path>
-
-=item *
-
-L<Search::Elasticsearch::Util::API::QS>
-
-=item *
-
-L<Search::Elasticsearch::Client::Direct>
-
-=back
-
-=head1 AUTHOR
-
-Clinton Gormley <drtech@cpan.org>
-
-=head1 COPYRIGHT AND LICENSE
-
-This software is Copyright (c) 2015 by Elasticsearch BV.
-
-This is free software, licensed under:
-
-  The Apache License, Version 2.0, January 2004
-
-=cut
-
-__END__
-
-# ABSTRACT: This class contains the spec for the Elasticsearch APIs
-
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Bulk;
-$Search::Elasticsearch::Role::Bulk::VERSION = '1.19';
+$Search::Elasticsearch::Role::Bulk::VERSION = '1.20';
 use Moo::Role;
 requires 'add_action', 'flush';
 
@@ -104,6 +104,12 @@ sub delete_ids {
     $self->add_action( map { ( 'delete' => { _id => $_ } ) } @_ );
 }
 
+our @Update_Params = qw(
+    doc upsert doc_as_upsert scripted_upsert
+    script script_id script_file
+    params lang detect_noop
+);
+
 #===================================
 sub _encode_action {
 #===================================
@@ -136,7 +142,7 @@ sub _encode_action {
 
     my $source;
     if ( $action eq 'update' ) {
-        for (qw(doc upsert doc_as_upsert script params lang)) {
+        for (@Update_Params) {
             $source->{$_} = delete $params->{$_}
                 if exists $params->{$_};
         }
@@ -255,7 +261,7 @@ Search::Elasticsearch::Role::Bulk - Provides common functionality to L<Elasticse
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 AUTHOR
 
@@ -0,0 +1,123 @@
+package Search::Elasticsearch::Role::Client::Direct::Main;
+$Search::Elasticsearch::Role::Client::Direct::Main::VERSION = '1.20';
+use Moo::Role;
+requires '_namespace';
+
+use Search::Elasticsearch::Util qw(parse_params load_plugin is_compat);
+
+has 'cluster'             => ( is => 'lazy', init_arg => undef );
+has 'nodes'               => ( is => 'lazy', init_arg => undef );
+has 'indices'             => ( is => 'lazy', init_arg => undef );
+has 'snapshot'            => ( is => 'lazy', init_arg => undef );
+has 'cat'                 => ( is => 'lazy', init_arg => undef );
+has 'bulk_helper_class'   => ( is => 'ro',   default  => 'Bulk' );
+has 'scroll_helper_class' => ( is => 'ro',   default  => 'Scroll' );
+has '_bulk_class'         => ( is => 'lazy' );
+has '_scroll_class'       => ( is => 'lazy' );
+
+#===================================
+sub create {
+#===================================
+    my ( $self, $params ) = parse_params(@_);
+    my $defn = $self->api->{index};
+    $params->{op_type} = 'create';
+    $self->perform_request( { %$defn, name => 'create' }, $params );
+}
+
+#===================================
+sub _build__bulk_class {
+#===================================
+    my $self = shift;
+    $self->_build_helper( 'bulk', $self->bulk_helper_class );
+}
+
+#===================================
+sub _build__scroll_class {
+#===================================
+    my $self = shift;
+    $self->_build_helper( 'scroll', $self->scroll_helper_class );
+}
+
+#===================================
+sub _build_helper {
+#===================================
+    my ( $self, $name, $sub_class ) = @_;
+    my $class = load_plugin( 'Search::Elasticsearch', $sub_class );
+    is_compat( $name . '_helper_class', $self->transport, $class );
+    return $class;
+}
+
+#===================================
+sub bulk_helper {
+#===================================
+    my ( $self, $params ) = parse_params(@_);
+    $params->{es} ||= $self;
+    $self->_bulk_class->new($params);
+}
+
+#===================================
+sub scroll_helper {
+#===================================
+    my ( $self, $params ) = parse_params(@_);
+    $params->{es} ||= $self;
+    $self->_scroll_class->new($params);
+}
+
+#===================================
+sub _build_cluster  { shift->_build_namespace('Cluster') }
+sub _build_nodes    { shift->_build_namespace('Nodes') }
+sub _build_indices  { shift->_build_namespace('Indices') }
+sub _build_snapshot { shift->_build_namespace('Snapshot') }
+sub _build_cat      { shift->_build_namespace('Cat') }
+#===================================
+
+#===================================
+sub _build_namespace {
+#===================================
+    my ( $self, $ns ) = @_;
+    my $class = load_plugin( $self->_namespace, [$ns] );
+    return $class->new(
+        {   transport => $self->transport,
+            logger    => $self->logger
+        }
+    );
+}
+
+1;
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Search::Elasticsearch::Role::Client::Direct::Main - Attributes and methods used by the top-level Direct::Client
+
+=head1 VERSION
+
+version 1.20
+
+=head1 DESCRIPTION
+
+Contains attributes and builders used to load client namespaces and helpers
+such as C<cluster()>, C<nodes()>, C<bulk_helper()> etc used by the
+top-level Direct::Client classes.
+
+=head1 AUTHOR
+
+Clinton Gormley <drtech@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2015 by Elasticsearch BV.
+
+This is free software, licensed under:
+
+  The Apache License, Version 2.0, January 2004
+
+=cut
+
+__END__
+
+# ABSTRACT: Attributes and methods used by the top-level Direct::Client
+
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Client::Direct;
-$Search::Elasticsearch::Role::Client::Direct::VERSION = '1.19';
+$Search::Elasticsearch::Role::Client::Direct::VERSION = '1.20';
 use Moo::Role;
 with 'Search::Elasticsearch::Role::Client';
 use Search::Elasticsearch::Util::API::Path qw(path_handler);
@@ -30,7 +30,7 @@ sub parse_request {
         my $name = $defn->{name} || '<unknown method>';
         $self->logger->throw_error( 'Param',
                   "$_ in ($name) request. "
-                . "See docs at: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/"
+                . "See docs at: http://www.elastic.co/guide/en/elasticsearch/reference/current/"
                 . $defn->{doc}
                 . '.html' );
     };
@@ -120,7 +120,7 @@ Search::Elasticsearch::Role::Client::Direct - Request parsing for Direct clients
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Client;
-$Search::Elasticsearch::Role::Client::VERSION = '1.19';
+$Search::Elasticsearch::Role::Client::VERSION = '1.20';
 use Moo::Role;
 use namespace::clean;
 
@@ -28,7 +28,7 @@ Search::Elasticsearch::Role::Client - Provides common functionality for Client i
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Cxn::HTTP;
-$Search::Elasticsearch::Role::Cxn::HTTP::VERSION = '1.19';
+$Search::Elasticsearch::Role::Cxn::HTTP::VERSION = '1.20';
 use Moo::Role;
 
 use URI();
@@ -167,7 +167,7 @@ Search::Elasticsearch::Role::Cxn::HTTP - Provides common functionality to HTTP C
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -252,7 +252,7 @@ unless you specify a custom C<max_content_length>:
 
 This client can request compressed responses from Elasticsearch by
 enabling the C<http.compression> config setting in
-L<Elasticsearch|http://www.elasticsearch.org/guide/reference/modules/http/>
+L<Elasticsearch|http://www.elastic.co/guide/reference/modules/http/>
 and setting C<deflate> to C<true>:
 
     $e = Search::Elasticsearch->new(
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Cxn;
-$Search::Elasticsearch::Role::Cxn::VERSION = '1.19';
+$Search::Elasticsearch::Role::Cxn::VERSION = '1.20';
 use Moo::Role;
 use Search::Elasticsearch::Util qw(throw);
 use List::Util qw(min);
@@ -122,6 +122,8 @@ sub process_response {
 
     my $is_encoded = $mime_type && $mime_type ne 'text/plain';
 
+    # Request is successful
+
     if ( $code >= 200 and $code <= 209 ) {
         if ( defined $body and length $body ) {
             $body = $self->serializer->decode($body)
@@ -132,10 +134,12 @@ sub process_response {
         return ( $code, '' );
     }
 
+    # Check if the error should be ignored
     my @ignore = to_list( $params->{ignore} );
     push @ignore, 404 if $params->{method} eq 'HEAD';
     return ($code) if grep { $_ eq $code } @ignore;
 
+    # Determine error type
     my $error_type = $Code_To_Error{$code};
     unless ($error_type) {
         if ( defined $body and length $body ) {
@@ -148,14 +152,11 @@ sub process_response {
     delete $params->{data} if $params->{body};
     my %error_args = ( status_code => $code, request => $params );
 
+    # Extract error message from the body, if present
+
     if ( $body = $self->serializer->decode($body) ) {
         $error_args{body} = $body;
-        if ( ref $body ) {
-            $msg = $body->{error} || $msg;
-        }
-        else {
-            $msg = $body;
-        }
+        $msg = $self->_munge_elasticsearch_exception($body) || $msg;
 
         $error_args{current_version} = $1
             if $error_type eq 'Conflict'
@@ -168,6 +169,37 @@ sub process_response {
         \%error_args );
 }
 
+#===================================
+sub _munge_elasticsearch_exception {
+#===================================
+    my ( $self, $body ) = @_;
+    return $body unless ref $body eq 'HASH';
+    my $error = $body->{error} || return;
+    return $error unless ref $error eq 'HASH';
+
+    my $root_causes = $error->{root_cause} || [];
+    unless (@$root_causes) {
+        my $msg = "[" . $error->{type} . "] " if $error->{type};
+        $msg .= $error->{reason} if $error->{reason};
+        return $msg;
+    }
+
+    my $json = $self->serializer;
+    my @msgs;
+    for (@$root_causes) {
+        my %cause = (%$_);
+        my $msg
+            = "["
+            . ( delete $cause{type} ) . "] "
+            . ( delete $cause{reason} );
+        if ( keys %cause ) {
+            $msg .= ", with: " . $json->encode( \%cause );
+        }
+        push @msgs, $msg;
+    }
+    return ( join ", ", @msgs );
+}
+
 1;
 
 # ABSTRACT: Provides common functionality to Cxn implementations
@@ -184,7 +216,7 @@ Search::Elasticsearch::Role::Cxn - Provides common functionality to Cxn implemen
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -211,9 +243,10 @@ The configuration parameters are as follows:
 How long a normal request (ie not a ping or sniff request) should wait
 before throwing a C<Timeout> error.  Defaults to C<30> seconds.
 
-B<Note:> In production, no request should take 30 seconds to run, other
-than an L<optimize()/Search::Elasticsearch::Client::Direct/optimize()> request.
-A more reasonable value for production would be C<10> seconds or lower.
+B<Note:> In production, no CRUD or search request should take 30 seconds to run,
+although admin tasks like C<upgrade()>, C<optimize()>, or snapshot C<create()>
+may take much longer. A more reasonable value for production would be
+C<10> seconds or lower.
 
 =head2 C<ping_timeout>
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::CxnPool::Sniff;
-$Search::Elasticsearch::Role::CxnPool::Sniff::VERSION = '1.19';
+$Search::Elasticsearch::Role::CxnPool::Sniff::VERSION = '1.20';
 use Moo::Role;
 with 'Search::Elasticsearch::Role::CxnPool';
 requires 'next_cxn', 'sniff';
@@ -88,7 +88,7 @@ Search::Elasticsearch::Role::CxnPool::Sniff - A CxnPool role for connecting to a
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 CONFIGURATION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::CxnPool::Static::NoPing;
-$Search::Elasticsearch::Role::CxnPool::Static::NoPing::VERSION = '1.19';
+$Search::Elasticsearch::Role::CxnPool::Static::NoPing::VERSION = '1.20';
 use Moo::Role;
 with 'Search::Elasticsearch::Role::CxnPool';
 
@@ -79,7 +79,7 @@ Search::Elasticsearch::Role::CxnPool::Static::NoPing - A CxnPool for connecting
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 AUTHOR
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::CxnPool::Static;
-$Search::Elasticsearch::Role::CxnPool::Static::VERSION = '1.19';
+$Search::Elasticsearch::Role::CxnPool::Static::VERSION = '1.20';
 use Moo::Role;
 with 'Search::Elasticsearch::Role::CxnPool';
 requires 'next_cxn';
@@ -39,7 +39,7 @@ Search::Elasticsearch::Role::CxnPool::Static - A CxnPool role for connecting to
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 METHODS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::CxnPool;
-$Search::Elasticsearch::Role::CxnPool::VERSION = '1.19';
+$Search::Elasticsearch::Role::CxnPool::VERSION = '1.20';
 use Moo::Role;
 use Search::Elasticsearch::Util qw(parse_params);
 use List::Util qw(shuffle);
@@ -134,7 +134,7 @@ Search::Elasticsearch::Role::CxnPool - Provides common functionality to the CxnP
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Is_Sync;
-$Search::Elasticsearch::Role::Is_Sync::VERSION = '1.19';
+$Search::Elasticsearch::Role::Is_Sync::VERSION = '1.20';
 use Moo::Role;
 use namespace::clean;
 
@@ -19,7 +19,7 @@ Search::Elasticsearch::Role::Is_Sync - A role to mark classes which should be us
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 AUTHOR
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Logger;
-$Search::Elasticsearch::Role::Logger::VERSION = '1.19';
+$Search::Elasticsearch::Role::Logger::VERSION = '1.20';
 use Moo::Role;
 
 use URI();
@@ -139,7 +139,7 @@ Search::Elasticsearch::Role::Logger - Provides common functionality to Logger im
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Scroll;
-$Search::Elasticsearch::Role::Scroll::VERSION = '1.19';
+$Search::Elasticsearch::Role::Scroll::VERSION = '1.20';
 use Moo::Role;
 requires '_clear_scroll';
 use Search::Elasticsearch::Util qw(parse_params throw);
@@ -66,7 +66,7 @@ Search::Elasticsearch::Role::Scroll - Provides common functionality to L<Elastic
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 AUTHOR
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Serializer::JSON;
-$Search::Elasticsearch::Role::Serializer::JSON::VERSION = '1.19';
+$Search::Elasticsearch::Role::Serializer::JSON::VERSION = '1.20';
 use Moo::Role;
 requires 'JSON';
 
@@ -103,7 +103,7 @@ Search::Elasticsearch::Role::Serializer::JSON - A Serializer role for JSON modul
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Serializer;
-$Search::Elasticsearch::Role::Serializer::VERSION = '1.19';
+$Search::Elasticsearch::Role::Serializer::VERSION = '1.20';
 use Moo::Role;
 
 requires qw(encode decode encode_pretty encode_bulk mime_type);
@@ -20,7 +20,7 @@ Search::Elasticsearch::Role::Serializer - An interface for Serializer modules
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Transport;
-$Search::Elasticsearch::Role::Transport::VERSION = '1.19';
+$Search::Elasticsearch::Role::Transport::VERSION = '1.20';
 use Moo::Role;
 
 requires qw(perform_request);
@@ -72,7 +72,7 @@ Search::Elasticsearch::Role::Transport - Transport role providing interface betw
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 AUTHOR
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Scroll;
-$Search::Elasticsearch::Scroll::VERSION = '1.19';
+$Search::Elasticsearch::Scroll::VERSION = '1.20';
 use Moo;
 use Search::Elasticsearch::Util qw(parse_params throw);
 use namespace::clean;
@@ -129,7 +129,7 @@ Search::Elasticsearch::Scroll - A helper module for scrolled searches
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 SYNOPSIS
 
@@ -156,14 +156,14 @@ until there are no more matching results, much like a cursor in an SQL
 database.
 
 Unlike paginating through results (with the C<from> parameter in
-L<search()|Search::Elasticsearch::Client::Direct/search()>),
+L<search()|Search::Elasticsearch::Client::1_0::Direct/search()>),
 scrolled searches take a snapshot of the current state of the index. Even
 if you keep adding new documents to the index or updating existing documents,
 a scrolled search will only see the index as it was when the search began.
 
 This module is a helper utility that wraps the functionality of the
-L<search()|Search::Elasticsearch::Client::Direct/search()> and
-L<scroll()|Search::Elasticsearch::Client::Direct/scroll()> methods to make
+L<search()|Search::Elasticsearch::Client::1_0::Direct/search()> and
+L<scroll()|Search::Elasticsearch::Client::1_0::Direct/scroll()> methods to make
 them easier to use.
 
 B<IMPORTANT>: Deep scrolling can be expensive.  See L</DEEP SCROLLING>
@@ -284,13 +284,13 @@ are memory constrained, you will need to take this into account.
         %search_params
     );
 
-The L<Search::Elasticsearch::Client::Direct/scroll_helper()> method loads
+The L<Search::Elasticsearch::Client::1_0::Direct/scroll_helper()> method loads
 L<Search::Elasticsearch::Scroll> class and calls L</new()>,
 passing in any arguments.
 
 You can specify a C<scroll> duration (which defaults to C<"1m">) and
 C<scroll_in_qs> (which defaults to C<false>). Any other parameters are
-passed directly to L<Search::Elasticsearch::Client::Direct/search()>.
+passed directly to L<Search::Elasticsearch::Client::1_0::Direct/search()>.
 
 The C<scroll> duration tells Elasticearch how long it should keep the scroll
 alive.  B<Note>: this duration doesn't need to be long enough to process
@@ -299,7 +299,7 @@ The expiry gets renewed for another C<scroll> period every time new
 a new batch of results is retrieved from the cluster.
 
 By default, the C<scroll_id> is passed as the C<body> to the
-L<scroll|Search::Elasticsearch::Client::Direct/scroll()> request.
+L<scroll|Search::Elasticsearch::Client::1_0::Direct/scroll()> request.
 To send it in the query string instead, set C<scroll_in_qs> to a true value,
 but be aware: when querying very many indices, the scroll ID can become
 too long for intervening proxies.
@@ -398,9 +398,9 @@ How long the original search plus all subsequent batches took, in milliseconds.
 
 =item * L<Search::Elasticsearch::Bulk/reindex()>
 
-=item * L<Search::Elasticsearch::Client::Direct/search()>
+=item * L<Search::Elasticsearch::Client::1_0::Direct/search()>
 
-=item * L<Search::Elasticsearch::Client::Direct/scroll()>
+=item * L<Search::Elasticsearch::Client::1_0::Direct/scroll()>
 
 =back
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Serializer::JSON::Cpanel;
-$Search::Elasticsearch::Serializer::JSON::Cpanel::VERSION = '1.19';
+$Search::Elasticsearch::Serializer::JSON::Cpanel::VERSION = '1.20';
 use Cpanel::JSON::XS;
 use Moo;
 
@@ -20,7 +20,7 @@ Search::Elasticsearch::Serializer::JSON::Cpanel - A JSON Serializer using Cpanel
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Serializer::JSON::PP;
-$Search::Elasticsearch::Serializer::JSON::PP::VERSION = '1.19';
+$Search::Elasticsearch::Serializer::JSON::PP::VERSION = '1.20';
 use Moo;
 use JSON::PP;
 
@@ -23,7 +23,7 @@ Search::Elasticsearch::Serializer::JSON::PP - A JSON Serializer using JSON::PP
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Serializer::JSON::XS;
-$Search::Elasticsearch::Serializer::JSON::XS::VERSION = '1.19';
+$Search::Elasticsearch::Serializer::JSON::XS::VERSION = '1.20';
 use Moo;
 use JSON::XS 2.26;
 
@@ -19,7 +19,7 @@ Search::Elasticsearch::Serializer::JSON::XS - A JSON Serializer using JSON::XS
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Serializer::JSON;
-$Search::Elasticsearch::Serializer::JSON::VERSION = '1.19';
+$Search::Elasticsearch::Serializer::JSON::VERSION = '1.20';
 use Moo;
 use JSON::MaybeXS 1.002002 ();
 
@@ -24,7 +24,7 @@ Search::Elasticsearch::Serializer::JSON - The default JSON Serializer, using JSO
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::TestServer;
-$Search::Elasticsearch::TestServer::VERSION = '1.19';
+$Search::Elasticsearch::TestServer::VERSION = '1.20';
 use Moo;
 use Search::Elasticsearch();
 use POSIX 'setsid';
@@ -174,7 +174,7 @@ Search::Elasticsearch::TestServer - A helper class to launch Elasticsearch nodes
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 SYNOPSIS
 
@@ -205,7 +205,7 @@ be shutdown automatically.
         instances => 1,
         http_port => 9600,
         es_port   => 9700,
-        conf      => ['node.bench=true','script.disable_dynamic=false'],
+        conf      => ['script.disable_dynamic=false'],
     );
 
 Params:
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Transport;
-$Search::Elasticsearch::Transport::VERSION = '1.19';
+$Search::Elasticsearch::Transport::VERSION = '1.20';
 use Moo;
 
 use URI();
@@ -48,7 +48,6 @@ sub perform_request {
         }
 
         $logger->trace_error( $cxn, $error );
-        delete $error->{vars}{body};
         $error->is('NoNodes')
             ? $logger->throw_critical($error)
             : $logger->throw_error($error);
@@ -73,7 +72,7 @@ Search::Elasticsearch::Transport - Provides interface between the client class a
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -92,7 +91,7 @@ L<Search::Elasticsearch::Role::Is_Sync>.
         send_get_body_as => 'POST'
     );
 
-Certain endpoints like L<Search::Elasticsearch::Client::Direct/search()>
+Certain endpoints like L<Search::Elasticsearch::Client::1_0::Direct/search()>
 default to using a C<GET> method, even when they include a request body.
 Some proxy servers do not support C<GET> requests with a body.  To work
 around this, the C<send_get_body_as>  parameter accepts the following:
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Util::API::Path;
-$Search::Elasticsearch::Util::API::Path::VERSION = '1.19';
+$Search::Elasticsearch::Util::API::Path::VERSION = '1.20';
 use strict;
 use warnings;
 use Any::URI::Escape qw(uri_escape);
@@ -66,7 +66,7 @@ Search::Elasticsearch::Util::API::Path - A utility class for converting path tem
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Util::API::QS;
-$Search::Elasticsearch::Util::API::QS::VERSION = '1.19';
+$Search::Elasticsearch::Util::API::QS::VERSION = '1.20';
 use strict;
 use warnings;
 
@@ -13,25 +13,29 @@ our %Handler = (
             : shift();
     },
     bool => sub { $_[0] ? 1 : 0 },
-    enum => sub {"$_[0]"},
+    enum => sub {
+        ref $_[0] eq 'ARRAY'
+            ? join( ',', @{ shift() } )
+            : shift();
+    },
     number   => sub { 0 + $_[0] },
     datetime => sub {"$_[0]"},
     duration => sub {"$_[0]"},
 );
 
 our %Params = (
-    active_only       => { type => 'bool' },
-    all               => { type => 'bool' },
-    allow_no_indices  => { type => 'bool' },
-    analyze_wildcard  => { type => 'bool' },
-    analyzer          => { type => 'string' },
-    boost_terms       => { type => 'number' },
-    bytes             => { type => 'enum', options => [ 'b', 'k', 'm', 'g' ] },
-    char_filters      => { type => 'list' },
-    clear             => { type => 'bool' },
-    completion        => { type => 'bool' },
+    active_only      => { type => 'bool' },
+    all              => { type => 'bool' },
+    allow_no_indices => { type => 'bool' },
+    analyze_wildcard => { type => 'bool' },
+    analyzer         => { type => 'string' },
+    boost_terms      => { type => 'number' },
+    bytes            => { type => 'enum', options => [ 'b', 'k', 'm', 'g' ] },
+    char_filters     => { type => 'list' },
+    clear            => { type => 'bool' },
+    completion       => { type => 'bool' },
     completion_fields => { type => 'list' },
-    consistency => {
+    consistency       => {
         options => [ 'one', 'quorum', 'all' ],
         type    => 'enum'
     },
@@ -48,16 +52,19 @@ our %Params = (
     docs             => { type => 'bool' },
     dry_run          => { type => 'bool' },
     exit             => { type => 'bool' },
-    expand_wildcards => { type => 'enum', options => [ 'open', 'closed' ] },
-    explain          => { type => 'bool' },
-    field            => { type => 'string' },
-    field_statistics => { type => 'bool' },
-    fielddata        => { type => 'bool' },
-    fielddata_fields => { type => 'list' },
-    fields           => { type => 'list' },
-    filter           => { type => 'bool' },
-    filter_blocks    => { type => 'bool' },
-    filter_cache     => { type => 'bool' },
+    expand_wildcards => {
+        type    => 'enum',
+        options => [ 'open', 'closed', 'none', 'all' ]
+    },
+    explain                => { type => 'bool' },
+    field                  => { type => 'string' },
+    field_statistics       => { type => 'bool' },
+    fielddata              => { type => 'bool' },
+    fielddata_fields       => { type => 'list' },
+    fields                 => { type => 'list' },
+    filter                 => { type => 'bool' },
+    filter_blocks          => { type => 'bool' },
+    filter_cache           => { type => 'bool' },
     filter_index_templates => { type => 'bool' },
     filter_indices         => { type => 'list' },
     filter_keys            => { type => 'bool' },
@@ -123,18 +130,19 @@ our %Params = (
             "routing_table", "master_node", "version"
         ]
     },
-    merge                => { type => 'bool' },
-    min_doc_freq         => { type => 'number' },
-    min_score            => { type => 'number' },
-    min_term_freq        => { type => 'number' },
-    min_word_len         => { type => 'number' },    # depr 0.90
-    min_word_length      => { type => 'number' },
-    mlt_fields           => { type => 'list' },
-    name                 => { type => 'list' },
-    network              => { type => 'bool' },
-    offsets              => { type => 'bool' },
-    only_expunge_deletes => { type => 'bool' },
-    op_type              => {
+    merge                 => { type => 'bool' },
+    min_doc_freq          => { type => 'number' },
+    min_score             => { type => 'number' },
+    min_term_freq         => { type => 'number' },
+    min_word_len          => { type => 'number' },    # depr 0.90
+    min_word_length       => { type => 'number' },
+    mlt_fields            => { type => 'list' },
+    name                  => { type => 'list' },
+    network               => { type => 'bool' },
+    offsets               => { type => 'bool' },
+    only_ancient_segments => { type => 'bool' },
+    only_expunge_deletes  => { type => 'bool' },
+    op_type               => {
         default => 'index',
         options => [ 'index', 'create' ],
         type    => 'enum'
@@ -271,7 +279,7 @@ Search::Elasticsearch::Util::API::QS - A utility class for query string paramete
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Util;
-$Search::Elasticsearch::Util::VERSION = '1.19';
+$Search::Elasticsearch::Util::VERSION = '1.20';
 use Moo;
 use Search::Elasticsearch::Error();
 use Scalar::Util qw(blessed);
@@ -119,7 +119,7 @@ Search::Elasticsearch::Util - A utility class for internal use by Search::Elasti
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 AUTHOR
 
@@ -1,14 +1,14 @@
 package Search::Elasticsearch;
 
-use Moo 1.003;
+use Moo 1.003 ();
 
 use Search::Elasticsearch::Util qw(parse_params load_plugin);
 use namespace::clean;
 
-our $VERSION = '1.19';
+our $VERSION = '1.20';
 
 my %Default_Plugins = (
-    client      => [ 'Search::Elasticsearch::Client',       'Direct' ],
+    client      => [ 'Search::Elasticsearch::Client',       '1_0::Direct' ],
     cxn_factory => [ 'Search::Elasticsearch::Cxn::Factory', '' ],
     cxn_pool    => [ 'Search::Elasticsearch::CxnPool',      'Static' ],
     logger      => [ 'Search::Elasticsearch::Logger',       'LogAny' ],
@@ -31,6 +31,7 @@ sub new {
     my ( $class, $params ) = parse_params(@_);
 
     $params->{cxn} ||= 'HTTPTiny';
+    my $plugins = delete $params->{plugins} || [];
 
     for my $name (@Load_Order) {
         my ( $base, $default ) = @{ $Default_Plugins{$name} };
@@ -38,6 +39,13 @@ sub new {
         my $plugin_class = load_plugin( $base, $sub_class );
         $params->{$name} = $plugin_class->new($params);
     }
+
+    for my $name (@$plugins) {
+        my $plugin_class
+            = load_plugin( 'Search::Elasticsearch::Plugin', $name );
+        $plugin_class->_init_plugin($params);
+    }
+
     return $params->{client};
 }
 
@@ -53,7 +61,7 @@ Search::Elasticsearch - The official client for Elasticsearch
 
 =head1 VERSION
 
-version 1.19
+version 1.20
 
 =head1 SYNOPSIS
 
@@ -128,7 +136,7 @@ L<Search::Elasticsearch> is the official Perl client for Elasticsearch,
 supported by L<elasticsearch.com|http://www.elasticsearch.com>.  Elasticsearch
 itself is a flexible and powerful open source, distributed real-time
 search and analytics engine for the cloud.  You can read more about it
-on L<elasticsearch.org|http://www.elasticsearch.org>.
+on L<elastic.co|http://www.elastic.co>.
 
 =head1 BACKWARDS COMPATIBILITY AND ELASTICSEARCH 0.90.x
 
@@ -155,7 +163,7 @@ Unfortunately, the opinions of programmers seldom coincide. The intention of
 this client, and of the officially supported clients available for other
 languages, is to provide robust support for the full native Elasticsearch API
 with as few opinions as possible:  you should be able to read the
-L<Elasticsearch reference documentation|http://www.elasticsearch.org/guide>
+L<Elasticsearch reference documentation|http://www.elastic.co/guide>
 and understand how to use this client, or any of the other official clients.
 
 Should you decide that you want to customize the API, then this client
@@ -210,14 +218,14 @@ Easy extensibility
 =head1 INSTALLING ELASTICSEARCH
 
 You can download the latest version of Elasticsearch from
-L<http://www.elasticsearch.org/download>. See the
-L<installation instructions|http://www.elasticsearch.org/guide/reference/setup/installation/>
+L<http://www.elastic.co/download>. See the
+L<installation instructions|http://www.elastic.co/guide/reference/setup/installation/>
 for details. You will need to have a recent version of Java installed,
 preferably the Java v7 from Sun.
 
 =head1 CREATING A NEW INSTANCE
 
-The L</new()> method returns a new L<client|Search::Elasticsearch::Client::Direct>
+The L</new()> method returns a new L<client|Search::Elasticsearch::Client::1_0::Direct>
 which can be used to run requests against the Elasticsearch cluster.
 
     use Search::Elasticsearch;
@@ -337,7 +345,7 @@ Other arguments are explained in the respective L<module docs|/MODULES>.
 =head1 RUNNING REQUESTS
 
 When you create a new instance of Search::Elasticsearch, it returns a
-L<client|Search::Elasticsearch::Client::Direct> object, which can be used for
+L<client|Search::Elasticsearch::Client::1_0::Direct> object, which can be used for
 running requests.
 
     use Search::Elasticsearch;
@@ -358,7 +366,7 @@ running requests.
         }
     );
 
-See L<Search::Elasticsearch::Client::Direct> for more details about the requests that
+See L<Search::Elasticsearch::Client::1_0::Direct> for more details about the requests that
 can be run.
 
 =head1 MODULES
@@ -389,11 +397,21 @@ The class to use for the client functionality, which provides
 methods that can be called to execute requests, such as
 C<search()>, C<index()> or C<delete()>. The client parses the user's
 requests and passes them to the L</transport> class to be executed.
+
+The default version of the client is C<1_0::Direct>, which can
+be explicitly specified as follows:
+
+    $e = Search::Elasticsearch->new(
+        client => '1_0::Direct'
+    );
+
 See :
 
 =over
 
-=item * L<Search::Elasticsearch::Client::Direct> (default, for 1.0 branch)
+=item * L<Search::Elasticsearch::Client::1_0::Direct> (default, for 1.0 branch)
+
+=item * L<Search::Elasticsearch::Client::2_0::Direct> (for 2.0 branch)
 
 =item * L<Search::Elasticsearch::Client::0_90::Direct> (for 0.90 branch)
 
@@ -611,7 +629,7 @@ C<irc.freenode.net>.
 
 =item * Mailing list
 
-The main L<Elasticsearch mailing list|http://www.elasticsearch.org/community/forum/>.
+The main L<Elasticsearch mailing list|http://www.elastic.co/community>.
 
 =back
 
@@ -4,8 +4,9 @@ BEGIN { use_ok('Search::Elasticsearch') }
 
 my ( $e, $p, $t );
 
-isa_ok $e = Search::Elasticsearch->new(),
-    'Search::Elasticsearch::Client::Direct', "client";
+ok $e = Search::Elasticsearch->new(), "new client";
+ok $e->does('Search::Elasticsearch::Role::Client::Direct'),
+    "client does Search::Elasticsearch::Role::Client::Direct";
 isa_ok $t = $e->transport, 'Search::Elasticsearch::Transport', "transport";
 isa_ok $p = $t->cxn_pool, 'Search::Elasticsearch::CxnPool::Static',
     "cxn_pool";
@@ -37,7 +37,8 @@ isa_ok $l = Search::Elasticsearch->new(
     )->logger, 'Search::Elasticsearch::Logger::LogAny',
     'File Logger';
 
-isa_ok $l->log_handle->adapter, 'Log::Any::Adapter::File', 'File - Log to file';
+isa_ok $l->log_handle->adapter, 'Log::Any::Adapter::File',
+    'File - Log to file';
 isa_ok $l->trace_handle->adapter, 'Log::Any::Adapter::File',
     'File - Trace to file';
 
@@ -12,7 +12,8 @@ isa_ok my $l = Search::Elasticsearch->new->logger,
     'Search::Elasticsearch::Logger::LogAny',
     'Default Logger';
 
-isa_ok $l->log_handle->adapter, 'Log::Any::Adapter::Stdout', 'Default - Log to Stdout';
+isa_ok $l->log_handle->adapter, 'Log::Any::Adapter::Stdout',
+    'Default - Log to Stdout';
 isa_ok $l->trace_handle->adapter, 'Log::Any::Adapter::Stderr',
     'Default - Trace to Stderr';
 
@@ -4,9 +4,8 @@ use Search::Elasticsearch;
 use lib 't/lib';
 do 'LogCallback.pl';
 
-isa_ok my $e
+ok my $e
     = Search::Elasticsearch->new( nodes => 'https://foo.bar:444/some/path' ),
-    'Search::Elasticsearch::Client::Direct',
     'Client';
 
 isa_ok my $l = $e->logger, 'Search::Elasticsearch::Logger::LogAny', 'Logger';
@@ -4,9 +4,8 @@ use Search::Elasticsearch;
 use lib 't/lib';
 do 'LogCallback.pl';
 
-isa_ok my $e
+ok my $e
     = Search::Elasticsearch->new( nodes => 'https://foo.bar:444/some/path' ),
-    'Search::Elasticsearch::Client::Direct',
     'Client';
 
 isa_ok my $l = $e->logger, 'Search::Elasticsearch::Logger::LogAny', 'Logger';
@@ -4,9 +4,8 @@ use Search::Elasticsearch;
 use lib 't/lib';
 do 'LogCallback.pl';
 
-isa_ok my $e
+ok my $e
     = Search::Elasticsearch->new( nodes => 'https://foo.bar:444/some/path' ),
-    'Search::Elasticsearch::Client::Direct',
     'Client';
 
 isa_ok my $l = $e->logger, 'Search::Elasticsearch::Logger::LogAny', 'Logger';
@@ -5,9 +5,8 @@ use lib 't/lib';
 do 'LogCallback.pl';
 our $format;
 
-isa_ok my $e
+ok my $e
     = Search::Elasticsearch->new( nodes => 'https://foo.bar:444/some/path' ),
-    'Search::Elasticsearch::Client::Direct',
     'Client';
 
 isa_ok my $l = $e->logger, 'Search::Elasticsearch::Logger::LogAny', 'Logger';
@@ -80,7 +80,7 @@ throws_ok {
 }
 qr/\[400\] error in body/, "Request error";
 
-### Conflict error
+### Conflict error pre v2
 throws_ok {
     $c->process_response(
         { method => 'GET', ignore => [] },
@@ -90,8 +90,21 @@ throws_ok {
         { 'content-type' => 'application/json' }
     );
 }
-qr/\[409\] VersionConflictEngineException/, "Conflict error";
-is $@->{vars}{current_version}, 1, "Error has current version";
+qr/\[409\] VersionConflictEngineException/, "Conflict error v1";
+is $@->{vars}{current_version}, 1, "Error has current version v1";
+
+### Conflict error >= v2
+throws_ok {
+    $c->process_response(
+        { method => 'GET', ignore => [] },
+        409,
+        "Conflict",
+        '{"error":{"type":"version_conflict_engine_exception","index":"test","root_cause":[{"shard":2,"reason":"[t][1]: version conflict, current [1], provided [2]","type":"version_conflict_engine_exception","index":"test"}],"shard":3,"reason":"[t][1]: version conflict, current [1], provided [2]"},"status":409}',
+        { 'content-type' => 'application/json' }
+    );
+}
+qr/\[409\] \[version_conflict_engine_exception\]/, "Conflict error v2";
+is $@->{vars}{current_version}, 1, "Error has current version v2";
 
 ### Timeout error
 throws_ok {
@@ -206,6 +206,36 @@ ok $b->add_action(
         lang          => 'mvel',
         params        => { incr => 1 },
     },
+    update => {
+        _index        => 'foo',
+        _type         => 'bar',
+        _id           => 1,
+        _routing      => 1,
+        _parent       => 1,
+        _timestamp    => 1380019061000,
+        _ttl          => '10m',
+        _version      => 1,
+        _version_type => 'external',
+        doc           => { foo => 'bar' },
+        doc_as_upsert => 1,
+        detect_noop   => 1,
+    },
+    update => {
+        _index        => 'foo',
+        _type         => 'bar',
+        _id           => 1,
+        _routing      => 1,
+        _parent       => 1,
+        _timestamp    => 1380019061000,
+        _ttl          => '10m',
+        _version      => 1,
+        _version_type => 'external',
+        upsert        => { counter => 0 },
+        script        => '_ctx.source.counter+=incr',
+        lang          => 'mvel',
+        params        => { incr => 1 },
+        detect_noop   => 1,
+    },
     ),
     'Add update actions';
 
@@ -219,11 +249,15 @@ cmp_deeply $b->_buffer,
     q({"doc":{"foo":"bar"},"doc_as_upsert":1}),
     q({"update":{"_id":1,"_index":"foo","_parent":1,"_routing":1,"_timestamp":1380019061000,"_ttl":"10m","_type":"bar","_version":1,"_version_type":"external"}}),
     q({"lang":"mvel","params":{"incr":1},"script":"_ctx.source.counter+=incr","upsert":{"counter":0}}),
+    q({"update":{"_id":1,"_index":"foo","_parent":1,"_routing":1,"_timestamp":1380019061000,"_ttl":"10m","_type":"bar","_version":1,"_version_type":"external"}}),
+    q({"detect_noop":1,"doc":{"foo":"bar"},"doc_as_upsert":1}),
+    q({"update":{"_id":1,"_index":"foo","_parent":1,"_routing":1,"_timestamp":1380019061000,"_ttl":"10m","_type":"bar","_version":1,"_version_type":"external"}}),
+    q({"detect_noop":1,"lang":"mvel","params":{"incr":1},"script":"_ctx.source.counter+=incr","upsert":{"counter":0}}),
     ],
     "Update actions in buffer";
 
-is $b->_buffer_size,  892, "Update actions buffer size";
-is $b->_buffer_count, 4,   "Update actions buffer count";
+is $b->_buffer_size,  1370, "Update actions buffer size";
+is $b->_buffer_count, 6,    "Update actions buffer count";
 
 $b->clear_buffer;
 
@@ -227,6 +227,34 @@ ok $b->update(
         lang          => 'mvel',
         params        => { incr => 1 },
     },
+    {   _index        => 'foo',
+        _type         => 'bar',
+        _id           => 1,
+        _routing      => 1,
+        _parent       => 1,
+        _timestamp    => 1380019061000,
+        _ttl          => '10m',
+        _version      => 1,
+        _version_type => 'external',
+        doc           => { foo => 'bar' },
+        doc_as_upsert => 1,
+        detect_noop   => 1,
+    },
+    {   _index        => 'foo',
+        _type         => 'bar',
+        _id           => 1,
+        _routing      => 1,
+        _parent       => 1,
+        _timestamp    => 1380019061000,
+        _ttl          => '10m',
+        _version      => 1,
+        _version_type => 'external',
+        upsert        => { counter => 0 },
+        script        => '_ctx.source.counter+=incr',
+        lang          => 'mvel',
+        params        => { incr => 1 },
+        detect_noop   => 1,
+    },
     ),
     'Update';
 
@@ -240,11 +268,15 @@ cmp_deeply $b->_buffer,
     q({"doc":{"foo":"bar"},"doc_as_upsert":1}),
     q({"update":{"_id":1,"_index":"foo","_parent":1,"_routing":1,"_timestamp":1380019061000,"_ttl":"10m","_type":"bar","_version":1,"_version_type":"external"}}),
     q({"lang":"mvel","params":{"incr":1},"script":"_ctx.source.counter+=incr","upsert":{"counter":0}}),
+    q({"update":{"_id":1,"_index":"foo","_parent":1,"_routing":1,"_timestamp":1380019061000,"_ttl":"10m","_type":"bar","_version":1,"_version_type":"external"}}),
+    q({"detect_noop":1,"doc":{"foo":"bar"},"doc_as_upsert":1}),
+    q({"update":{"_id":1,"_index":"foo","_parent":1,"_routing":1,"_timestamp":1380019061000,"_ttl":"10m","_type":"bar","_version":1,"_version_type":"external"}}),
+    q({"detect_noop":1,"lang":"mvel","params":{"incr":1},"script":"_ctx.source.counter+=incr","upsert":{"counter":0}}),
     ],
     "Update in buffer";
 
-is $b->_buffer_size,  892, "Update buffer size";
-is $b->_buffer_count, 4,   "Update buffer count";
+is $b->_buffer_size,  1370, "Update buffer size";
+is $b->_buffer_count, 6,    "Update buffer count";
 
 $b->clear_buffer;
 
@@ -25,8 +25,6 @@ my @Std = (
 
 my ( $b, $success_count, $error_count, $custom_count, $conflict_count );
 
-# Cxn error - to not clear buffers
-
 ## Default error handling
 $b = bulk( { index => 'test', type => 'test' }, @Std );
 test_flush( "Default", 0, 2, 0, 0 );
@@ -128,7 +126,7 @@ $b = bulk(
             {   _index => 'test',
                 _type  => 'test',
                 _id    => 1,
-                error  => re('VersionConflictEngineException'),
+                error  => re('version conflict'),
                 status => 409,
             },
             2, 1
@@ -0,0 +1,36 @@
+use Test::More;
+use Test::Deep;
+use Test::Exception;
+
+use strict;
+use warnings;
+use lib 't/lib';
+use Search::Elasticsearch::Bulk;
+use Log::Any::Adapter;
+
+$ENV{ES}           = '127.0.0.2:9200';
+$ENV{ES_SKIP_PING} = 1;
+$ENV{ES_CXN_POOL}  = 'Static';
+$ENV{ES_TIMEOUT}   = 1;
+
+my $es = do "es_sync.pl";
+SKIP: {
+    skip
+        "IO::Socket::IP doesn't respect timeout: https://rt.cpan.org/Ticket/Display.html?id=103878",
+        3
+        if $es->transport->cxn_pool->cxn_factory->cxn_class eq
+        'Search::Elasticsearch::Cxn::HTTPTiny'
+        && $^V =~ /^v5.2\d/;
+
+    # Check that the buffer is not cleared on a NoNodes exception
+
+    my $b = $es->bulk_helper( index => 'foo', type => 'bar' );
+    $b->create_docs( { foo => 'bar' } );
+
+    is $b->_buffer_count, 1, "Buffer count pre-flush";
+    throws_ok { $b->flush } 'Search::Elasticsearch::Error::NoNodes';
+    is $b->_buffer_count, 1, "Buffer count post-flush";
+
+}
+
+done_testing;
@@ -20,12 +20,19 @@ my @files = (
     'lib/Search/Elasticsearch/Client/0_90/Direct.pm',
     'lib/Search/Elasticsearch/Client/0_90/Direct/Cluster.pm',
     'lib/Search/Elasticsearch/Client/0_90/Direct/Indices.pm',
+    'lib/Search/Elasticsearch/Client/1_0/Direct.pm',
+    'lib/Search/Elasticsearch/Client/1_0/Direct/Cat.pm',
+    'lib/Search/Elasticsearch/Client/1_0/Direct/Cluster.pm',
+    'lib/Search/Elasticsearch/Client/1_0/Direct/Indices.pm',
+    'lib/Search/Elasticsearch/Client/1_0/Direct/Nodes.pm',
+    'lib/Search/Elasticsearch/Client/1_0/Direct/Snapshot.pm',
+    'lib/Search/Elasticsearch/Client/2_0/Direct.pm',
+    'lib/Search/Elasticsearch/Client/2_0/Direct/Cat.pm',
+    'lib/Search/Elasticsearch/Client/2_0/Direct/Cluster.pm',
+    'lib/Search/Elasticsearch/Client/2_0/Direct/Indices.pm',
+    'lib/Search/Elasticsearch/Client/2_0/Direct/Nodes.pm',
+    'lib/Search/Elasticsearch/Client/2_0/Direct/Snapshot.pm',
     'lib/Search/Elasticsearch/Client/Direct.pm',
-    'lib/Search/Elasticsearch/Client/Direct/Cat.pm',
-    'lib/Search/Elasticsearch/Client/Direct/Cluster.pm',
-    'lib/Search/Elasticsearch/Client/Direct/Indices.pm',
-    'lib/Search/Elasticsearch/Client/Direct/Nodes.pm',
-    'lib/Search/Elasticsearch/Client/Direct/Snapshot.pm',
     'lib/Search/Elasticsearch/Cxn/Factory.pm',
     'lib/Search/Elasticsearch/Cxn/HTTPTiny.pm',
     'lib/Search/Elasticsearch/Cxn/Hijk.pm',
@@ -35,11 +42,13 @@ my @files = (
     'lib/Search/Elasticsearch/CxnPool/Static/NoPing.pm',
     'lib/Search/Elasticsearch/Error.pm',
     'lib/Search/Elasticsearch/Logger/LogAny.pm',
-    'lib/Search/Elasticsearch/Role/API.pm',
     'lib/Search/Elasticsearch/Role/API/0_90.pm',
+    'lib/Search/Elasticsearch/Role/API/1_0.pm',
+    'lib/Search/Elasticsearch/Role/API/2_0.pm',
     'lib/Search/Elasticsearch/Role/Bulk.pm',
     'lib/Search/Elasticsearch/Role/Client.pm',
     'lib/Search/Elasticsearch/Role/Client/Direct.pm',
+    'lib/Search/Elasticsearch/Role/Client/Direct/Main.pm',
     'lib/Search/Elasticsearch/Role/Cxn.pm',
     'lib/Search/Elasticsearch/Role/Cxn/HTTP.pm',
     'lib/Search/Elasticsearch/Role/CxnPool.pm',
@@ -128,6 +137,7 @@ my @files = (
     't/70_Helper/20_bulk_helpers.t',
     't/70_Helper/30_bulk_flush.t',
     't/70_Helper/40_bulk_errors.t',
+    't/70_Helper/45_bulk_cxn_errors.t',
     't/70_Helper/50_scroll.t',
     't/70_Helper/60_reindex.t',
     't/90_Client_Spec/00_print_version.t',
@@ -135,7 +145,7 @@ my @files = (
     't/author-no-tabs.t',
     't/lib/LogCallback.pl',
     't/lib/MockCxn.pm',
-    't/lib/bad_cacert.pm',
+    't/lib/bad_cacert.pem',
     't/lib/default_cxn.pl',
     't/lib/es_sync.pl',
     't/lib/es_sync_auth.pl',
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDijCCAvOgAwIBAgIJAIFQM5672YHcMA0GCSqGSIb3DQEBBQUAMIGLMRcwFQYD
+sQQKEw5LZXZpbiBUZXN0IE9yZzEbMBkGCSqGSIb3DQEJARYMa2V2aW5AZXMub3Jn
+MRIwEAYDVQQHEwlBbXN0ZXJkYW0xEjAQBgNVBAgTCUFtc3RlcmRhbTELMAkGA1UE
+BhMCTkwxHjAcBgNVBAMTFUtldmlucyBob3VzZSBvZiBjZXJ0czAeFw0xNDEwMTcy
+MzIyMjlaFw0xNTEwMTcyMzIyMjlaMIGLMRcwFQYDVQQKEw5LZXZpbiBUZXN0IE9y
+ZzEbMBkGCSqGSIb3DQEJARYMa2V2aW5AZXMub3JnMRIwEAYDVQQHEwlBbXN0ZXJk
+YW0xEjAQBgNVBAgTCUFtc3RlcmRhbTELMAkGA1UEBhMCTkwxHjAcBgNVBAMTFUtl
+dmlucyBob3VzZSBvZiBjZXJ0czCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
+9xG5d4JaJ2vFuyKGbzvAlHpAeIiOFuCOum9UXsUIeCCQn/q/BNlIaF+UQ+Y/yNJr
+3zraL9oboVSJZph8CIN7dKmLSnnAe83cjlQQNosS1heUTSyVWC7dWCj3djO3xeT9
+qTfhAj4a2OfvLHk2yT5Mp2cZYUnEKqCwhC98R7jKGtsCAwEAAaOB8zCB8DAMBgNV
+HRMEBTADAQH/MB0GA1UdDgQWBBQUtCQRtRzPojRpZ/3hanfZN3nxwjCBwAYDVR0j
+BIG4MIG1gBQUtCQRtRzPojRpZ/3hanfZN3nxwqGBkaSBjjCBizEXMBUGA1UEChMO
+S2V2aW4gVGVzdCBPcmcxGzAZBgkqhkiG9w0BCQEWDGtldmluQGVzLm9yZzESMBAG
+A1UEBxMJQW1zdGVyZGFtMRIwEAYDVQQIEwlBbXN0ZXJkYW0xCzAJBgNVBAYTAk5M
+MR4wHAYDVQQDExVLZXZpbnMgaG91c2Ugb2YgY2VydHOCCQCBUDOeu9mB3DANBgkq
+hkiG9w0BAQUFAAOBgQDF2nfTTrM7cviLiExF6iQP/HwigXiHhotcBtyjfPvXhRe0
+k96MwEWS+87XsLERF1FPkEzW4TjF6f4pRxAYbTA3frWZ4vFwM7CflI/9ca9HlRux
+WTG7ZMdyKE1Z2Vip2W1kVtVb/Gd/qWzxEoCwuHWo5dRZ8nrZ27U+Ij3CAFWEhQ==
+-----END CERTIFICATE-----
@@ -1,21 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDijCCAvOgAwIBAgIJAIFQM5672YHcMA0GCSqGSIb3DQEBBQUAMIGLMRcwFQYD
-sQQKEw5LZXZpbiBUZXN0IE9yZzEbMBkGCSqGSIb3DQEJARYMa2V2aW5AZXMub3Jn
-MRIwEAYDVQQHEwlBbXN0ZXJkYW0xEjAQBgNVBAgTCUFtc3RlcmRhbTELMAkGA1UE
-BhMCTkwxHjAcBgNVBAMTFUtldmlucyBob3VzZSBvZiBjZXJ0czAeFw0xNDEwMTcy
-MzIyMjlaFw0xNTEwMTcyMzIyMjlaMIGLMRcwFQYDVQQKEw5LZXZpbiBUZXN0IE9y
-ZzEbMBkGCSqGSIb3DQEJARYMa2V2aW5AZXMub3JnMRIwEAYDVQQHEwlBbXN0ZXJk
-YW0xEjAQBgNVBAgTCUFtc3RlcmRhbTELMAkGA1UEBhMCTkwxHjAcBgNVBAMTFUtl
-dmlucyBob3VzZSBvZiBjZXJ0czCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
-9xG5d4JaJ2vFuyKGbzvAlHpAeIiOFuCOum9UXsUIeCCQn/q/BNlIaF+UQ+Y/yNJr
-3zraL9oboVSJZph8CIN7dKmLSnnAe83cjlQQNosS1heUTSyVWC7dWCj3djO3xeT9
-qTfhAj4a2OfvLHk2yT5Mp2cZYUnEKqCwhC98R7jKGtsCAwEAAaOB8zCB8DAMBgNV
-HRMEBTADAQH/MB0GA1UdDgQWBBQUtCQRtRzPojRpZ/3hanfZN3nxwjCBwAYDVR0j
-BIG4MIG1gBQUtCQRtRzPojRpZ/3hanfZN3nxwqGBkaSBjjCBizEXMBUGA1UEChMO
-S2V2aW4gVGVzdCBPcmcxGzAZBgkqhkiG9w0BCQEWDGtldmluQGVzLm9yZzESMBAG
-A1UEBxMJQW1zdGVyZGFtMRIwEAYDVQQIEwlBbXN0ZXJkYW0xCzAJBgNVBAYTAk5M
-MR4wHAYDVQQDExVLZXZpbnMgaG91c2Ugb2YgY2VydHOCCQCBUDOeu9mB3DANBgkq
-hkiG9w0BAQUFAAOBgQDF2nfTTrM7cviLiExF6iQP/HwigXiHhotcBtyjfPvXhRe0
-k96MwEWS+87XsLERF1FPkEzW4TjF6f4pRxAYbTA3frWZ4vFwM7CflI/9ca9HlRux
-WTG7ZMdyKE1Z2Vip2W1kVtVb/Gd/qWzxEoCwuHWo5dRZ8nrZ27U+Ij3CAFWEhQ==
------END CERTIFICATE-----
@@ -9,11 +9,16 @@ my $trace
     :                      [ 'File', $ENV{TRACE} ];
 
 my $version = $ENV{ES_VERSION} || '';
-my $api = $version =~ /^0.90/ ? '0_90::Direct' : 'Direct';
+my $api
+    = $version =~ /^0.90/   ? '0_90::Direct'
+    : $version =~ /^2\./    ? '2_0::Direct'
+    : $version =~ /^master/ ? '2_0::Direct'
+    :                         '1_0::Direct';
 my $body     = $ENV{ES_BODY}     || 'GET';
 my $cxn      = $ENV{ES_CXN}      || do "default_cxn.pl" || die $!;
 my $cxn_pool = $ENV{ES_CXN_POOL} || 'Static';
 my $timeout  = $ENV{ES_TIMEOUT}  || 30;
+my @plugins = split /,/, ( $ENV{ES_PLUGINS} || '' );
 our %Auth;
 
 my $es;
@@ -27,6 +32,7 @@ if ( $ENV{ES} ) {
             client           => $api,
             send_get_body_as => $body,
             request_timeout  => $timeout,
+            plugins          => \@plugins,
             %Auth
         );
         $es->ping unless $ENV{ES_SKIP_PING};
@@ -33,7 +33,8 @@ our %Auth = ( use_https => 1, userinfo => $ENV{ES_USERINFO} );
 $ENV{ES_CXN_POOL} = 'Static';
 my $es = do "es_sync.pl";
 
-ok $es->cluster->health, "$ENV{ES_CXN} - Non-cert HTTPS with auth, cxn static";
+ok $es->cluster->health,
+    "$ENV{ES_CXN} - Non-cert HTTPS with auth, cxn static";
 
 $ENV{ES_CXN_POOL} = 'Sniff';
 $es = do "es_sync.pl";
@@ -41,7 +42,8 @@ ok $es->cluster->health, "$ENV{ES_CXN} - Non-cert HTTPS with auth, cxn sniff";
 
 $ENV{ES_CXN_POOL} = 'Static::NoPing';
 $es = do "es_sync.pl";
-ok $es->cluster->health, "$ENV{ES_CXN} - Non-cert HTTPS with auth, cxn noping";
+ok $es->cluster->health,
+    "$ENV{ES_CXN} - Non-cert HTTPS with auth, cxn noping";
 
 # Test forbidden action
 throws_ok { $es->nodes->shutdown }
@@ -63,8 +65,8 @@ throws_ok { $es->cluster->health }
     "$ENV{ES_CXN} - Bad userinfo";
 
 # Test https connection with correct auth, with invalid cacert
-$Auth{ssl_options} = ssl_options('t/lib/bad_cacert.pm');
-$ENV{ES}="https://www.google.com";
+$Auth{ssl_options} = ssl_options('t/lib/bad_cacert.pem');
+$ENV{ES}           = "https://www.google.com";
 
 $es = do "es_sync.pl";