Drupal 8 Custom Site Search with Search APIJanuary 10, 2018
Setting up a robust Drupal internal site search that searches all of the content that you add to a complex site can be a bit like finding your way through a maze.
Drupal 8 core Search has been revamped and is much more powerful and accurate than in D7, but it still concentrates on text in nodes and not other entities those nodes might contain—like Paragraphs, Views, or custom blocks. Core Search also does not allow you to choose which fields you want to index, how important those fields are, or use any preprocessors to tailor your search. Search API gives you all this and more.
Search API is a Drupal contributed module that allows you create searches on any entity known to Drupal. You can use Views to create a custom search results page with specific filters. You can create different indexes tied to specific sections or content on your site. You can do just about anything to architect your search experience other than use the core Search block—which is really the only thing that makes core Search worth using. This post however, will show you how to take advantage of the power of Search API, and keep your site search box.
Benefits of Search API in Drupal 8
As noted above, for smaller sites and less complex search needs, core Search is completely fine. If you think you need something with a little more power under the hood, here some of the benefits of Search API:
Choose Your Entities and Fields to be Indexed
You can create different indexes for different types of entities for custom searches on specific areas of your site or combine them all into one site-wide search. You can choose to index nodes, but exclude certain content types. You can index the title and body field, but not your banner image field. You can customize your search indexes to be pretty much anything you need.
Assign Relevance Weights and Different Processors
Besides customizing what Search API will index, you can define how important the items it is indexing are. You can set the title field to be the most important thing to index. This would show nodes with the keyword in their title before those that only have it in the body.
You can use preprocessors in the Search API UI to exclude unpublished entities, ignore text case, define words to be ignored in searches, split text into individual word tokens for searching, add boosts to datasource types and specific HTML tags, check for node content access, highlight results in an excerpt, and stem results to their English root words (jumping would be indexed as jump).
Index the Site Whenever You Want
Drupal core Search indexes the site only on cron runs. You can define the interval and batch size, but that’s about it. Search API lets you choose to index on cron runs and set the batch size as well, but you can also index new items automatically and index the site anytime you want from the UI—which is handy when migrating content.
Allows for a Custom Search Page with Little to no Coding
One of the things we most enjoy about Drupal 8 is the switch to Twig templating. You can use Twig to customize the core Search results pretty much however you want, but we understand that not everyone knows and loves Twig the way we do. Thankfully, with Search API you can build a custom Views search page, and create your results list and filters based on your needs—all through the UI if that's how you want to do it.
Enabling Search API
Next, we’ll want to add the Search API contrib module. From your site’s root folder in the command line, run: composer require drupal/search_api (if you’re using a Composer-based D8 build) to download the module and its dependencies and then install it. If you’re not using Composer, manually download the module and install or use the /admin/modules/install UI.
You’ll also want to install the Database Search submodule at this time. This will allow Search API to search the site’s database just like core Search does.
Create a Search Index
In order for Search API to work, it needs to know what content to look at and catalogue. This means we need to configure a search index. Unlike Drupal core Search which concentrates on node entities, Search API allows you to choose to include any entity recognizable to Drupal. You can configure one index that will keep track of all entities or you can create different indexes for different entities and use different views to allow specific searches for certain content. A prime example would be a university with custom searches set up per department.
Go to /admin/config/search/search-api and follow these steps:
Name it something descriptive based on what it will be used for (i.e. Content).
Select the datasources (we’ll just use Content for the sake of simplicity).
Configure the datasources how you want them. You can choose to include and exclude different types for each datasource entity.
Choose the server you just created.
Enable the server.
Index options allows you to choose to Index items immediately. New nodes and entities will be added to the search index immediately instead of waiting for cron to run.
Index options also lets you set the number of entities to index per cron run. We keep the cron batch size to the default of 50 since we are adding new entities when they are created.
If you’re bulk adding a bunch of content through a migration, wait until after the migration to use the Index immediately setting—or if you have a site with dozens of important pages being added daily, don’t use that setting at all because it will be a performance hit trying to keep up.
Enable Processors to Tailor Search API
Search API processors work in much the same way as CKEditor's text format filters. You can change data before its indexed to create keyword tokens, ignore case, or filter out certain HTML. You can use a processor to ignore unpublished nodes or take into account Drupal’s node permissions when showing results. You can highlight keywords in the search results (only works if showing a search excerpt in your search results). You can also bring keywords to their English stem, exclude certain words from being indexed and use transliteration for non-English text.
We like to use Entity status to index only published entities, HTML filter to strip tags and decode content that might be in the body field, Ignore case to give the broadest results, Tokenizer so that test strings can be split into single keywords for searching, and Stemmer to trim keywords to their root.
Once you decide which processors make sense for you to use, you’ll have to set their order. Some processors only act at certain times in the indexing/query process and some act at multiple times. Thankfully, Search API does a nice job of letting you know which processors work at which times and even lets you know if a certain processor needs be at certain point in the order to get the best results.
If using the same processors as us, you’ll want to have Tokenizer be first, then Ignore case, HTML filter and Stemmer.
Lastly, you’ll need to configure some of the preprocessors that you chose. Most of them offer options to enable the processor on all supported fields, or just on some. You can define the excerpt and highlighting tag if using Highlight. You can also set the minimum word length for Tokenizer.
We enabled our Tokenizer, HTML filter, Ignore case, and Stemmer processors on all supported fields. Our HTML filter boosts tags with h1 as the most important and each subsequent tag as a lesser value. Tokenizer should be set to the same minimum word length that your Index database configuration is set to—3 for us.
Now that we have the search server and index all setup, the site is ready to start indexing nodes. You'll want to click on the View tab for the index, then click the Index Now button at the bottom to index the site.
Recreate the Core Search Block
Go to the Block Layout UI (/admin/structure/block) and click Place block on the region you want the block to be assigned to. We’re going to assign ours to the header.
In the list of available blocks, you will see one called Exposed form: my_view_name-my_view_display_name.
Once you choose your filter block, you can configure it like you would any block. For now, let’s leave the configuration as default.
Since we are replacing the core search block, it's helpful to create a twig template for this block and to assign the same ‘block-search-form-block’ class to the block to preserve some of the theming that was in place from the core block. For more information on creating custom twig template, see our Twig for Drupal 8 Development: Twig Templating Part 1 of 2 post.
If you’re creating a custom template for your exposed filter block to add the core class, its very easy to create a search toggle button to show/hide your global search box. Just add your button tag before the block content and use a bit of CSS and JS to show/hide the search input based on a user clicking the toggle icon.