Node-Elastical: Implement stats function

Recently, I had to find the size of an index in Elasticsearch. I could have just built my query using request like this:

var request = require('request');
request.get('http://localhost:9200/' + myIndex + '/_stats'
  , function (err, res, body) {
    console.log(res._all.primaries.store.size_in_bytes);
});

Fast and easy. Since it’s not available yet in node-elastical, I found it better to add this functionality so that other people can use it. Implementing the stats function wasn’t difficult. It just require parsing options to create the right url and then making the request (with request) to Elasticsearch. I used the Indices Stats API documentation to create the function.

In file client.js

stats: function (options, callback) {
  var query = [],
  url = '',
  hasOptions;

  if (typeof options === 'function') {
    callback = options;
    options = {};
  }
  //Create a copy of options so we can modify it.
  options = util.merge(options || {});

  if (options.index) {
    url = '/' + encode(Array.isArray(options.index) ?
      options.index.join(',') : options.index);
    delete options.index;
    //Look for types only if there is an index
    if (options.types) {
      query.push(encode('types') + '=' + encode(
        Array.isArray(options.types) ?
        options.types.join(',') : options.types));
    }
    delete options.types;
  }

  url += '/_stats';

  util.each(options, function (value, name) {
    if (value === true || value === false) {
      value = value ? '1' : '0';
    }

    query.push(encode(name) + '=' + encode(value));
  });

  if (query.length) {
    url += '?' + query.join('&');
  }

  this._request(url, {
    method: 'GET'
  }, function (err, res) {
    if(err) { return callback(err, null, res), undefined; }
    callback(null, res);
  });
},
In file index.js
stats: function (options, callback) {
  if (typeof options === 'function') {
    callback = options;
    options = {};
  }
  this.client.stats(util.merge(options,{index: this.name}), callback);
},

Node-Elastical: Delete by query option

What is Elastical?

Elastical is a Node.js client library for the ElasticSearch REST API.

That’s it for the presentation.

Until a few weeks ago, it wasn’t possible to delete data by query without using a hack. The hack was the following:

client.delete('twitter', 'tweet', '', {q: 'user:Shay'} );

Here, we set id to an empty string and we use the options parameter to perform a search on user with value Shay. Not so practical at all.

Using curl to interact with ElasticSearch, it is possible to delete by query:

curl -XDELETE 'http://localhost:9200/twitter/tweet/_query' -d ' 
  { "term" : { "user" : "kimchy" } 
}
'

This handy way of deleting things in ElasticSearch was not possible with Elastical (unless, you managed to use the hack above).

So I’ve added a new parameter options.query which allow us to perform such a query more easily.

client.delete('twitter', 'tweet', '', {query:
  { "term" : { "user" : "kimchy" } } 
});

When using the query parameter, id and all other options except ignoreMissing will be ignored.

Let’s take a quick look at the code involved:

if(params.query) {
  url = '/' + encode(this.name) + '/' + encode(type) + '/_query';

  this.client._request(url, {method: 'DELETE', json: params.query}
  , function (err, res) {
    if (err) {
      if (ignoreMissing && res && res.found === false) {
        return callback(null, res), undefined;
      } else {
        return callback(err, res), undefined;
      }
    }
    callback(null, res);
  });
} else {

It’s pretty simple. First, we need to build the url, then we’re requesting ElasticSearch on the given url, passing the query in the json parameter. If options.query doesn’t exist, then the original code is used.

As a conclusion, delete by query is now available in Elastical and you should use it!

 

ElasticSearch: Delete By Query API