Custom Fields and Weighted Search with ElasticPress

by

One of the most powerful features of ElasticPress is the ability to add more fields to your website search. By default, WordPress only searches for titles, excerpts, and content but with ElasticPress you can search in any field, from taxonomy terms to your plugin custom field. Since ElasticPress 3.1, you can also weight your fields, adjusting their prominence in the queried search results. In this post, we will see how you can add your fields taking advantage of the weighting engine.

Why can’t I just use the search_fields parameter?

As per the ElasticPress documentation, the plugin accepts some WP_Query special parameters, supported only by ElasticPress. With them, you can add aggregation results, which sites you want to search on a multisite installation, and also add new search fields.

The snippet below will add category and tags taxonomies to the searched fields:

new WP_Query( array(
    's' => 'term search phrase',
    'search_fields' => array(
        'post_title',
        'post_content',
        'post_excerpt',
        'taxonomies' => array( 'category', 'post_tag' ),
    ),
) );

But with that in place, the weighting engine won’t be used.

How can I have custom fields AND the weighted search?

If you need to change the fields used in the search and keep the weighted search working, the ep_weighting_configuration_for_search filter is what you’re looking for. Functions hooked to the filter will receive two parameters:

  • $weight_config: The current weight configuration. The one you can manage through the Dashboard
  • $args: the arguments passed to the WP_Query.

Without any manipulation, the $weight_config variable will be an array looking like this:

Array (
    [post] => Array (
            [post_title] => Array (
                    [weight] => 1
                    [enabled] => 1
                )
            [post_content] => Array (
                    [weight] => 2
                    [enabled] => 1
                )
            ...
            [terms.category.name] => Array (
                    [weight] => 1
                    [enabled] => 1
                )
        )
    [page] => Array
           ...
        )
)

It is a multidimensional array, indexed by the post type with an array of fields inside of it. Each field has a weight value and boolean for the enabled key.

On the ElasticSearch side of the query, we’ll have something like this:

...
"bool": {
	"must": [
		{
			"bool": {
				"should": [
					{
						"multi_match": {
							"query": "test",
							"type": "phrase",
							"fields": [
								"post_title^1",
								"post_content^2",
								"terms.category.name^1",
								"terms.ep_custom_result.name^9999"
							],
							"boost": 4
						}
					},
					...
				]
			}
		}
	],
	"filter": [
		{
			"match": {
				"post_type.raw": "post"
			}
		}
	]
}

Did you note the field_name^weight pattern there? That is what makes ElasticSearch properly weight the fields.

Let’s say you need to remove, for the “post” post type, the post title, and add the post excerpt with 20 as the weight. You have to hook a function to the ep_weighting_configuration_for_search filter, remove the $weight_config['post']['post_title'] index and add a $weight_config['post']['post_excerpt'] with what you need as weight. Don’t forget to also add the enabled key.

Your code will be similar to this:

function my_ep_weighting_configuration_for_search( $weight_config, $args ) {
	$post_type = (array) $args['post_type'];
	if ( in_array( 'post', $post_type, true ) ) {
		if ( isset( $weight_config['post']['post_title'] ) ) {
			unset( $weight_config['post']['post_title'] );
		}
		$weight_config['post']['post_excerpt'] = array(
			'weight'  => 20,
			'enabled' => 1,
		);
	}
	return $weight_config;
}
add_filter( 'ep_weighting_configuration_for_search', 'my_ep_weighting_configuration_for_search', 10, 2 );

Conclusion

ElasticPress goes beyond being the glue between your WordPress website and an ElasticSearch server. It solves all the usual scenarios but also is extensible enough to solve problems specific to your needs. Adding the search_fields parameter to your query, you can use any field you want but using the ‘ep_weighting_configuration_for_search’ filter you can add those fields while taking advantage of weighted searches.

Happy searching!

Is there another search case you would like us to address? Reach out to us in the GitHub repository: https://github.com/10up/ElasticPress/issues or send us a Tweet.

Looking for professionals who know ElasticPress? Reach out to one of our specialists and we’ll be in touch right away!