Tuesday, January 14, 2014

ElasticSearch from AngularJS (fun w/ elasticsearch-js!)


We've recently switched over to AngularJS (from ExtJS).  And if you've been following along at home, you know that we are *HUGE* ElasticSearch fans.  So today, I set out to answer the question, "How easy would it be to hit Elastic Search directly from javascript?"  The answer lies below. =)

First off, I should say that we recently hired a rock-star UI architect (@ddubya) that has brought with him Javascript Voodoo the likes of which few have seen.  We have wormsign... and we now have grunt paired with bower for package management.  Wicked cool.

So, when I set out to connect our Angular App to Elastic Search, I was pleased to see that Elastic Search Inc recently announced a javascript client that they will officially support.  I quickly raced over to bower.io and found a rep listed in their registry...

I then spent the next two hours banging my head against a wall.

Do NOT pull the git repo via bower even though it is listed in the bower registry!  There is an open issue on the project to add support for bower.  Until that closes, the use of Node's require() within the angular wrapper prevents it from running inside a browser.  Using browserify, the ES guys kindly generate a browser compatible version for us.   So *use* the browser download (zip or tar ball) instead!

Once you have the download, just unzip it in your app.  Load the library with a script tag:
<script src="third_party_components/elasticsearch-js/elasticsearch.angular.js"></script>
That code registers the elastic search module and creates a factory that you can use:
angular.module('elasticsearch', [])
  .factory('esFactory', ['$http', '$q', function ($http, $q) {

    var factory = function (config) {
      config = config || {};
      config.connectionClass = AngularConnector;
      config.$http = $http;
      config.defer = function () {
        return $q.defer();
      };
      return new Client(config);
    };
You can then create a service that uses that factory, creating an instance of a client that you can use from your controller, etc:
angular.module('hms.complete.control.components.search')
  .service('es', function (esFactory) {
  return esFactory({
    host: 'search01:9200'
  });
});
Then, assuming you have a controller defined similar to:
angular.module('my.components.search')
  .controller('searchController', ['$window', '$scope', 'es', function ($window, $scope, es) {
The following code, translated from their example, works like a champ!
es.ping({
  requestTimeout: 1000,
  hello: "elasticsearch!"
}, function (error) {
  if (error) {
    console.error('elasticsearch cluster is down!');
  } else {
    console.log('All is well');
  }
});
From there, you can extend things to do much more... like search! =)

Kudos to the Elastic Search Inc crew for making this available.


No comments: