Using Elasticsearch for Drupal 7 Search
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.