The Search Experience for the Harte Research Institute

We recently launched a new site for the Harte Research Institute for Gulf of Mexico Studies (hereinafter HRI). You can find out more about HRI and its launch in a previous blog post. Search was an integral part of the site design and we were able to accomplish all our goals with Drupal 8 and Search API.

The Goal

Most of the main pages share the same pattern: A collection of content, usually a grid, searchable by the user. A good example of that pattern is the Our Work page, where the user can search by the type of research, the type of project, and a fulltext search. We’ll call these directory pages.

Screenshot of the Our Work directory page on HRI website

We also wanted the user to search everything, so we provide a site search page as well. This allows users to do fulltext search over all content and optionally filter by content type.

Screenshot of the site search page on HRI website

The Plan™

First, we created a Search API Server with an Apache Solr backend by installing and configuring the Solr Search module. This was very easy since includes Solr and it’s correct Drupal configuration as part of the local development environment and hosting stack.

Next we created a new Search API index for each directory page. The important step here is to add the fields that will be used for the dropdown filters and each field that you want to be fulltext searchable. We also created an index for the site search, and added almost all the fields for each content type. This works fine, but next time we may consider using the “General > Rendered HTML output” field to avoid adding everything one at a time.

The next step is to create the pages that will show our search results. We use Page Manager for layout and Views to return search results. Views gives us the flexibility to configure filters, sorting, pagination, AJAX, returning rendered entities, etc., but also has the power of Search API and Solr behind it. When creating the view, just pick the index you want to return results from and the rest should be familiar. Our setup is fairly straightforward. Here’s the configuration of the Our Work directory view. You’ll notice this is where we’ve added the fulltext filter.

Screenshot of the views configuration for a directory page

We also want the user to search by taxonomy terms and content type. In the first screenshot those are shown as dropdowns. You can do this with Views exposed filters but we are using the Facets module. This is to prevent showing the user search options that may not return content. After installing the module, each index becomes a facet source which can have one or more facets. It’s a simple process to add a facet by selecting the source, the field, and a name. Set the widget to be dropdown and check the setting “Make sure only one result can be shown” and you’re good to go. Head back to page manager, add your new facets as blocks and rejoice! You can also optionally improve the experience by using a fancy dropdown javascript library, like Chosen.

The last thing needed to complete the page is to tell the user about their current search query. We tell them what facets they’ve selected, as well as the fulltext search query. This shows up only after the user has searched for something.

Screensot of the Our Work directory page with search form filled out

For this we’re using a custom module which lets us add a new block for each facet that prints out the current facet selection. It also provides a block that prints the current fulltext search query, and a block that provides a search reset link. There is an active issue in the Facets module to provide this built-in, please have a look and help with testing: Introducing the current search/summary block.

We needed the ability to exclude certain pages (like custom 404/503 pages) from the search index. You can configure Search API to exclude whole content types from the index, but how do you exclude a few nodes from the index? As is Drupal tradition, there’s a module for that! The Search API Exclude Entity module lets you add an exclude field to any entity bundle so you can make sure certain entities don’t get indexed.

The Issues

Did everything work perfectly? Unfortunately, no, but we were able to work around them or work with the wonderful Search API and Facets folks to get them fixed. One minor issue is finding the right versions of Search API, Solr Search, and Facets that all play nice together. This took a little trial and error, but we found that generally a non-dev release of Search API and a dev release of Facets work. Checking the issue queue was also helpful to pick what works together.

When you combine a views exposed filter and facets, the former will remove any facet filters the user had selected. So if a user first picks a content type, then does a fulltext search for “Oil spill,” the final results will include all content types because that facet was removed. Doing the search in the other direction works properly. There is an open issue to “allow exposed form to preserver URL query parameters,” but we used the following JavaScript to fix it instead.

The Contributions

The major linchpin in our plan is the combination of Search API, Facets, Views and Page Manager. When we started this project, everything worked well on their own, but there was no way to combine them all in one page. Our friend Alex Tkachev from the Zürich team was able to add views block display support to Facets which is included in the latest release.

Another important design feature was using <select> elements in the search form, including the ability to auto-submit when the user selects a new option. At the time Facets only supported lists of links for the display widget, but now there are many options including checkboxes and dropdown. This was accomplished as part of the Widget dropdown - select issue.

We ran into a small problem with multiple indexes and fields with matching machine names. We found content from one index was being included in the results from another index. In order to fix it we had to directly edit our config files to make index field machine names globally unique and re-import. This was much easier to do using configuration management than it would have been in Drupal 7, but it was still difficult enough that we decided to help fix the “Make field names and IDs editable” issue. As long as you’re using 8.x-1.0-beta1 or later, you can easily avoid this problem.

The Conclusion

Overall we’re pleased with the status of the Search API and similar modules. We’re not using any hacked or patched versions thanks to the responsiveness of the maintainers and Drupal community. We were able to build everything we designed and delivered a fully functional search system. Our client is happy with the end product and we’re excited to build with the latest Drupal technologies.

November 21, 2016

Get our Newsletter


What is Amazee Labs?