Elasticshell
Elasticsearch is a wonderful database for performing full-text on rich documents at terabyte-scale.
It’s already pretty easy to talk to Elasticsearch. You can
-
use the HTTP-based, REST API via commmand-line tools like curl, your favorite HTTP library, or even your browser’s URL bar
-
use the interface built on Apache Thrift
-
use the native Java classes
What’s missing was a command-line shell that let you directly inspect Elasticsearch’s “filesystem” or “database schema”, run queries, and in general muck about. I got sick of writing things like
$ curl -s -X GET "http://localhost:9200/_status" | ruby -rjson -e 'puts JSON.parse($stdin.read)["indices"]["my_index"]["docs"]["num_docs"]'
How about
$ es /_status --only=indices.my_index.docs.num_docs
Installation
Installing Elasticshell should be as simple as installing the gem:
$ sudo gem install elasticshell
This should install a binary program ‘es’ that you can run from the command line to start Elasticshell. Try
$ es --help
right now to see that everything is properly installed. You’ll also see a brief survey of Elasticshell’s startup options.
Usage
To start an Elasticshell session, just run
$ es
Elasticshell will automatically try to connect to a local Elasticsearch database running on the default port. You can modify this with the startup options. Type help
at any time to get some contextual help from Elasticshell.
Within Elasticshell, there are three variables whose values affect behavior. These variables are reflected in the default prompt, for example:
GET /my_index/my_type >
This prompt tells us three things:
-
The default HTTP verb we’re using for requests is
GET
. -
The default API “scope” we’re in is
/my_index/my_type
. -
Elasticshell will print raw responses from the database – this is the
>
at the end of the prompt. If we were in pretty-print mode, this would become a$
.
Changing Scope
Use the cd
built-in to move between scopes:
GET /my_index/my_type > cd /other_index/other_type
GET /other_index/other_type > cd ..
GET /other_index > cd
GET / >
Tab-complete within a scope after typing cd
to see what other scopes live under this one.
Changing HTTP Verb
You can change Elasticsearch’s default HTTP verb by giving it one. Here’s the same thing in two steps:
GET / > PUT
PUT / > /my_new_index
Non-ambiguous shortcuts for HTTP verbs will also work, e.g. - pu
in this case for PUT
.
Changing Prettiness
Typing pretty
at any time will toggle Elasticsearch’s pretty-printing format on or off.
GET / > pretty
GET / $
The $
-sign means it’s pretty…
Running Commands
There are a lot of different ways of telling Elasticsearch what you want done.
Named commands
Each scope has different commands, as per the Elasticsearch API documentation. Within a scope, tab-complete on the first word to see a list of possible commands. Hit enter after a command to see output from Elasticsearch.
Here’s a command to get the status for the cluster:
GET / > _status
Here’s a command to get the health of the cluster:
GET / > cd _cluster
GET /_cluster > health
Commands with query strings
Commands will also accept a query string, as in this example of a search through my_index
:
GET /my_index > _search?q=foo+AND+bar
Commands with query bodies
In this example the query foo AND bar
was passed via the query string part of a URL. Passing a more complex query requires we put the query in the body of the request. If you’re willing to forego using spaces you can do this right on the same line:
GET /my_index > _search {"query":{"query_string":{"query":"foo"}}}
But if you want more expressiveness you can either name a file (with tab-completion) that contains the body you want:
# in /tmp/query.json
{
"query": {
"query_string: {
"query": "foo AND bar"
}
}
}
followed by
GET /my_index > _search /tmp/query.json
Or you can do cat
-style, pasting the query into the shell, by using the -
character:
GET /my_index > _search -
{
"query": {
"query_string: {
"query": "foo AND bar"
}
}
}
Don’t forget to use Ctrl-D
to send an EOF
to flush the input of the query.
Arbitrary commands
You can send an arbitrary HTTP request to Elasticsearch, just spell the command with a leading slash:
GET / > /my_index/_search?q=foo+AND+bar
You can specify a different HTTP verb by prefixing it before the path you send the request to. Here’s how to create an index using a PUT
request:
GET / > PUT /my_new_index
You can also change Elasticsearch’s default HTTP verb by giving it one. Here’s the same thing in two steps:
GET / > PUT
PUT / > /my_new_index
Non-ambiguous shortcuts for HTTP verbs will also work, e.g. - pu
in this case for PUT
.
Running just a single command
Instead of running Elasticshell interactively, you can exit after running only a single command by using the --only
option on startup. For example,
$ es --only /_cluster/health
will output the cluster health and exit immediately. This can be combined with the --pretty
option for readability.
The --only
option can also be passed a .
-separated hierarchical list of keys to slice into the resulting object. This is useful when trying to drill into a large amount of data returned by Elasticsearch. The example from the start of this file is relevant again here:
$ es /_status --only=indices.my_index.docs.num_docs