Trifork Blog

Searching with the elasticshell

March 7th, 2013 by
| Reply

elasticshell
So as promised here is a sequel to my previous post Introducing the elasticshell. Let's start exactly where we left off...

What about search?
We of course need to search against the created index. We can provide queries as either json documents or Java QueryBuilders provided with the elasticsearch Java API, which are exposed to the shell as they are.

Here is an example using the basic search method; we can either search on all indexes or on a specific index (and type too). When no query is specified, the match_all query is used. Since we are lazy by nature, and we don't want to write a whole query by ourselves, let's say we want to execute a multi match query, thus we start just copy pasting the example taken from the query DSL documentation.

> var query = {
...   "multi_match" : {
...     "query" : "this is a test",
...     "fields" : [ "subject", "message" ]
...   }
... }

Now we can customize our example as we prefer.

> query.multi_match.query="elasticshell"
elasticshell
> query.multi_match.fields=["title^2","content"]
[title^2, content]
> query
{
  "multi_match": {
    "query": "elasticshell",
    "fields": [
      "title^2",
      "content"
    ]
  }
}

The basic search method accepts the whole search source as parameter, which might contain facets, sort and many more fragments. Thus we need to wrap our query in a new json object, let's call it searchSource.

> var searchSource={}
> searchSource.query=query
{
  "multi_match": {
    "query": "elasticshell",
    "fields": [
      "title^2",
      "content"
    ]
  }
}
> searchSource
{
  "query": {
    "multi_match": {
      "query": "elasticshell",
      "fields": [
        "title^2",
        "content"
      ]
    }
  }
}

We are now ready to execute our search:

> es.search(searchSource);
{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.19178301,
    "hits": [
      {
        "_index": "blog",
        "_type": "trifork",
        "_id": "1",
        "_score": 0.19178301,
        "_source": {
          "title": "Introducing the elasticshell",
          "author": "Luca Cavanna",
          "content": "A few days ago I released the first beta version of the elasticshell, a shell for elasticsearch."
        }
      }
    ]
  }
}

Here is how we can achieve the same result using the more flexible searchBuilder method, which allows to specify all the options that elasticsearch supports. The difference is that we don't need to specify the whole search source but only the needed parts, like only the query in the example below. We can just use a fragment of the searchSource json object, since it's native in the shell.

> es.searchBuilder().query(searchSource.query).execute();
{
  "took": 5,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.19178301,
    "hits": [
      {
        "_index": "blog",
        "_type": "trifork",
        "_id": "1",
        "_score": 0.19178301,
        "_source": {
          "title": "Introducing the elasticshell",
          "author": "Luca Cavanna",
          "content": "A few days ago I released the first beta version of the elasticshell, a shell for elasticsearch."
        }
      }
    ]
  }
}

Let's say we now want to search for something else, it's really easy to modify again our existing query object and execute a new search.

The following is another example, using this time the QueryBuilders provided with the Java API. The QueryBuilders class exposes some static methods that allow to create the different queries supported by the query DSL. All the queries are created through builder objects, which all implement the QueryBuilder interface. You can use auto-suggestions here too to know what methods you can use. When you're done you just have to provide your own QueryBuilder as argument to the queryBuilder method and execute your search like this:

> var queryBuilder = QueryBuilders.multiMatchQuery("elasticshell", "title^2", "content");
> es.searchBuilder().queryBuilder(queryBuilder).execute();
{
  "took": 8,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.19178301,
    "hits": [
      {
        "_index": "blog",
        "_type": "trifork",
        "_id": "1",
        "_score": 0.19178301,
        "_source": {
          "title": "Introducing the elasticshell",
          "author": "Luca Cavanna",
          "content": "A few days ago I released the first beta version of the elasticshell, a shell for elasticsearch."
        }
      }
    ]
  }
}

The limitation of this last approach is that it's not trivial to combine it with native json within the shell. The QueryBuilder is the elasticsearch (Java) internal representation of the queries, thus we would need to convert it back to the string format and parse it as json in order to play around with the related json objects. I'll explain this better in the next post, together with another solution I've been working on, which would allow you to use the nice elastic.js api within the shell.

Stay tuned!
Now that you know how you can execute a search using the elasticshell you have one more good reason to download it and give it a try! More articles and examples will follow too.
Feedback is more than welcome, and again, the released version is still a BETA; should you find any problem, I'd kindly ask you to open an issue here on github.

Leave a Reply