We're big fans of Elasticsearch. It is significantly easier to deploy, manage, and scale than SOLR in our experience. Since we've already been using Elasticsearch for indexing and storing system logs, it makes since for use to use Elasticsearch as the search backend for our clients' websites.

While currently not as feature-complete as the present SOLR integration for Search API, our Elasticsearch integration handles many of the most commonly used search features, and we're adding new capabilities as time and demand permits.

Getting started with Elasticsearch is easy. 

Install and configure Elasticsearch

Elasticsearch is very easy to install. If you're just getting started, the default settings are likely adequate for your needs. You just need to download and install the appropriate package from Elasticsearch.org.

If you're just running a single Elasticsearch node, that's all you will need. However, if you want to take advantage of it's superb clustering abilities, you'll want to set your cluster name. Elasticsearch tries to find other Elasticsearch nodes on the same network via multicast. As long as the nodes have the same cluster name, they will auto-join together. Alternatively, you can specify the IP addresses of the nodes that should be together. It is strongly recommended to use an odd number of nodes to prevent split-brain.

Install the Search API Elasticsearch module

After you have Elasticsearch running, you will need to download and install the Search API Elasticsearch module as well as the Search API module. Search API Elasticsearch requires the third-party Elastica library, but you have a choice as to whether you want that handled via Libraries API or Composer Manager. We strongly recommend Composer Manager as it will handle any additional library dependencies for you should they be introduced later.

By the way, a question we often get asked since the release of the official elasticsearch-php library pertains to why we continue to use the third-party Elastica library. There are several reasons we have chosen to stick with Elastica. First, elasticsearch-php didn't come out until after we had started actively developing this module. Second, Elastica is very widely used and there seem to currently be no plans to deprecate it. Performance is also a factor, as is the issue of possible Dependency Hell. However, we are currently exploring the possibility of supporting both libraries due to client demands.

Configure Search API and index your content

After you've installed the Search API Elasticsearch module, you'll need to go to admin/config/search/search_api. The first thing you will need to do is add your Elasticsearch server. If you're running just one node or running a loadbalancer in front of your nodes (such as HAProxy), then that's all you need. However, you can enter in the information for each individual node and the module will pick one for each query.

After you've told Search API about your Elasticsearch service, you'll need to tell an index to use it. Search API comes with a default_node_index, so we'll just use that one for now. If you're back on admin/config/search/search_api, click the drop-down menu for "default node index" and click "Edit". Enable the index and tell it to use the Elasticsearch service that you just created.

Next, you'll want to configure the fields that you want indexed at admin/config/search/search_api/index/default_node_index/fields. Under the Workflow tab, feel free to configure your data alterations, but you should disable all of the processors because Elasticsearch handles most of it. (The only one that we'd recommend that you consider enabling at this time is the HTML filter.)

After you've done this, go to admin/config/search/search_api/index/default_node_index and tell Drupal to index your content.

Search your content

What good is indexing your content in Elasticsearch if you can't search it? The best way to do this is to use the Search API Views module (included with Search API). Because Views configuration is a lot easier to just show, we've exported the view from a fresh installation. Feel free to import it to your site.

$view = new view();
$view->name = 'es_search';
$view->description = '';
$view->tag = 'default';
$view->base_table = 'search_api_index_default_node_index';
$view->human_name = 'ES Search';
$view->core = 7;
$view->api_version = '3.0';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */

/* Display: Master */
$handler = $view->new_display('default', 'Master', 'default');
$handler->display->display_options['title'] = 'Search';
$handler->display->display_options['use_more_always'] = FALSE;
$handler->display->display_options['access']['type'] = 'none';
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['exposed_form']['options']['submit_button'] = 'Search';
$handler->display->display_options['exposed_form']['options']['expose_sort_order'] = FALSE;
$handler->display->display_options['pager']['type'] = 'full';
$handler->display->display_options['pager']['options']['items_per_page'] = '10';
$handler->display->display_options['style_plugin'] = 'default';
$handler->display->display_options['row_plugin'] = 'entity';
$handler->display->display_options['row_options']['view_mode'] = 'teaser';
/* No results behavior: Global: Text area */
$handler->display->display_options['empty']['area']['id'] = 'area';
$handler->display->display_options['empty']['area']['table'] = 'views';
$handler->display->display_options['empty']['area']['field'] = 'area';
$handler->display->display_options['empty']['area']['label'] = 'No results';
$handler->display->display_options['empty']['area']['empty'] = TRUE;
$handler->display->display_options['empty']['area']['content'] = 'No results matched your search.';
$handler->display->display_options['empty']['area']['format'] = 'filtered_html';
/* Field: Indexed Node: Node ID */
$handler->display->display_options['fields']['nid']['id'] = 'nid';
$handler->display->display_options['fields']['nid']['table'] = 'search_api_index_default_node_index';
$handler->display->display_options['fields']['nid']['field'] = 'nid';
/* Sort criterion: Search: Relevance */
$handler->display->display_options['sorts']['search_api_relevance']['id'] = 'search_api_relevance';
$handler->display->display_options['sorts']['search_api_relevance']['table'] = 'search_api_index_default_node_index';
$handler->display->display_options['sorts']['search_api_relevance']['field'] = 'search_api_relevance';
$handler->display->display_options['sorts']['search_api_relevance']['order'] = 'DESC';
/* Filter criterion: Search: Fulltext search */
$handler->display->display_options['filters']['search_api_views_fulltext']['id'] = 'search_api_views_fulltext';
$handler->display->display_options['filters']['search_api_views_fulltext']['table'] = 'search_api_index_default_node_index';
$handler->display->display_options['filters']['search_api_views_fulltext']['field'] = 'search_api_views_fulltext';
$handler->display->display_options['filters']['search_api_views_fulltext']['exposed'] = TRUE;
$handler->display->display_options['filters']['search_api_views_fulltext']['expose']['operator_id'] = 'search_api_views_fulltext_op';
$handler->display->display_options['filters']['search_api_views_fulltext']['expose']['label'] = 'Search';
$handler->display->display_options['filters']['search_api_views_fulltext']['expose']['operator'] = 'search_api_views_fulltext_op';
$handler->display->display_options['filters']['search_api_views_fulltext']['expose']['identifier'] = 'search_api_views_fulltext';
$handler->display->display_options['filters']['search_api_views_fulltext']['expose']['required'] = TRUE;
$handler->display->display_options['filters']['search_api_views_fulltext']['expose']['remember'] = TRUE;
$handler->display->display_options['filters']['search_api_views_fulltext']['expose']['remember_roles'] = array(
  2 => '2',
  1 => 0,
  3 => 0,
);

/* Display: Page */
$handler = $view->new_display('page', 'Page', 'page');
$handler->display->display_options['exposed_block'] = TRUE;
$handler->display->display_options['path'] = 'search';

Now, to actually have a search field that your users can use, you'll need to display the exposed form block for your Search API index view. Assuming you're using Drupal's block system, it's as easy as going to admin/structure/blocks and placing the "Export form: es_search-page" block in your desired region.

How stable is the Search API Elasticsearch module?

It's relatively stable. At this point, as we implement more features we are being very careful not to break previously implemented features. We're also adding tests along the way. Once a few more of the more popular features are implemented, we'll begin tagging alpha releases. We're doing our testing on Travis-CI, so feel free to submit pull requests in our Github repository.

To give an idea of how long this has been used in production without any major issues, Sooner State Pawn has been using Search API Elasticsearch for about a year now. We've also assisted a few other clients with deployments for several hundred sites during the past six months.

By the way, we are absolutely committed to having a Drupal 8 release as soon as Search API has their Drupal 8 release.

If you liked this post, you should share it...

StumbleUpon icon
LinkedIn icon
Google icon
Reddit icon

Comments

I'm looking forward for D8 version because I will need it soon :)

How does Elastic Search support Arabic? Does it handle diacritics efficiently?

What if you have content that needs to be indexed, but isn't in Drupal?

What kind of search stats can you get?

Can you customize results? As in, place a specific page at the top of every search for a specific search term?

Any search autocorrection like what google does with misspelled words?

External content is possible, though not currently implemented in the module. Support is planned. What kind of stats are you looking for? Featured results are a possibility with Elasticsearch, though we haven't done it ourselves. Elasticsearch does support autocomplete and suggestions. Both are currently implemented in the module.

We're currently using a Google Mini at my work. Unfortunately, Google stopped supporting the mini's in favor of the more expensive GSA, so eventually we'll have to find another solution. We do make pretty heavy use of stats, though, I'm not the one doing that. My co-worker is.

He said:
"for arbitrary dates, it'll give us a list of keywords searched and their count, a list of search phrases and their count, and a complete log of searches with assocaited ips.
also useful is the stats about number of pages and number of errors found under each domain, an easy way to list links to a given url, as well as an indicator about the pagerank of a page"

Do you have any sites with this set up in production? Can I visit and see how they work?

One of the more extensive sites that we have that uses Elasticsearch on the backend (at least that we can publicly discuss at this time) is Sooner State Pawn. Nearly all of the product listings you see on the site are pulled in via Search API Views, and we're using the Search API Elasticsearch module to integrate the site with Elasticsearch.

Wonderfully written! It's such a rarity to be able to follow a tutorial all the way through and not get lost for too long between the finer points. Thank you sir.

Add comment

Stay updated!