-
Notifications
You must be signed in to change notification settings - Fork 12
Customizing Relevance
Elasticsearch does a fantastic job at analyzing your content and delivering mathematically relevant results. However, this doesn't take into account the nuances of your site, your content, and the way users need to interact with your content. Say you're searching a news website, new content is considerably more important than old content. If somebody is searching for articles about weather, it's more likely they want to read about recent weather and not weather from last year -- even if the article last year is technically a better match for their exact search terms. That's not to say we want to disregard relevance entirely, but we may want to use the publication date to (significantly) influence relevance. There are limitless ways you can influence relevance in your site's search.
As mentioned in Searchable Fields, SearchPress boosts the relevance of the post title by a factor of 3, and the relevance of the post excerpt by a factor of 2. If you want to flatten these and make the title, excerpt, and content all equally important, you can do that using the sp_search_wp_query_args
filter:
add_filter( 'sp_search_wp_query_args', function( $wp_args ) {
$fields =& $wp_args['query_fields'];
$fields[ array_search( 'post_title^3', $fields ) ] = 'post_title';
$fields[ array_search( 'post_excerpt^2', $fields ) ] = 'post_excerpt';
return $wp_args;
} );
If you have a meta field containing search keywords and you want that to be extremely important for relevance, you could add that and give it a very high boost value:
add_filter( 'sp_search_wp_query_args', function( $wp_args ) {
$wp_args['query_fields'][] = 'post_meta.keywords.value^10';
return $wp_args;
} );
Search relevance is complex and can be very frustrating at times when you're trying to get things just right. When adjusting relevance, you'll likely have a lot of trial-and-error until you strike the exact right balance. Don't expect to implement an example from this page verbatim and have it work exactly the way you want on the first go. Make your change, test it out, tweak it, test it, etc.
This example touches on a fairly advanced topic, decay functions. See the official documentation on the subject for more information.
/**
* Decay score by age of article.
*
* @param array $es_args Elasticsearch DSL.
* @return array
*/
add_filter( 'sp_search_query_args', function( $es_args ) {
if ( ! empty( $es_args['query'] ) && empty( $es_args['query']['function_score'] ) ) {
$es_args['query'] = [
'function_score' => [
// The initial query is moved to `query.function_score.query`.
'query' => $es_args['query'],
'functions' => [
[
'exp' => [
'post_date.date' => [
// The half life of an article will be 365 days.
'decay' => 0.5,
'scale' => '365d',
],
],
],
],
],
];
}
return $es_args;
} );
This example has very powerful implications, since the meta field could be populated by any number of sources: manually by a field in the admin, from an analytics API to boost relevance based on popularity, by some revenue-based resource, etc.
/**
* Influence score by meta field.
*
* @param array $es_args Elasticsearch DSL.
* @return array
*/
add_filter( 'sp_search_query_args', function( $es_args ) {
if ( ! empty( $es_args['query'] ) && empty( $es_args['query']['function_score'] ) ) {
$es_args['query'] = [
'function_score' => [
// The initial query is moved to `query.function_score.query`.
'query' => $es_args['query'],
'functions' => [
[
'field_value_factor' => [
'field' => 'post_meta.boost.double',
'missing' => 1,
],
],
],
],
];
}
return $es_args;
} );
When going a route like this, be mindful of the values in your post meta. It doesn't take much for the boost to completely override relevance instead of influencing it -- even a value of 2.0
could boost a relatively irrelevant result to the top of the results (similarly, a value of 0.5
can drop a result to the bottom of the results). Elasticsearch can apply a modifier to the value, or you can normalize your data prior to indexing. We recommend keeping your values between 0.75 - 1.5
to start, and adjust from there.