relevanssi_didyoumean()

relevanssi_didyoumean( string $query, string $pre, string $post, int $n = 5, boolean $echo = true )

Generates the Did you mean suggestions.

Source: /lib/didyoumean.php, /lib/common.php before 4.9.2 / 2.11.2.

Parameters

$query
(string) (required) The query string. If you don’t have it at hand, get_search_query( false ) is a good source.

$pre
(string) (required) This string is printed before the suggestion link.

$post
(string) (required) This string is printed after the suggestion link.

$n
(int) (optional) Maximum number of search results found for the suggestions to show up. If there are more results than this, the suggestions are not displayed.
Default value: 5

$echo
(boolean) (optional) If true, the suggestion is echoed out; otherwise it is only returned.
Default value: true

Returns

(string|null) The HTML code for the suggestion element, or null if no element was created.

Usage

This is a wrapper for the actual logic, which depends on the version of Relevanssi used. In Relevanssi Premium, the actual work is done in relevanssi_premium_didyoumean() and in the free version in relevanssi_simple_didyoumean().

The typical way to use this is to add this to your theme search results template:

if ( function_exists( 'relevanssi_didyoumean' ) ) {
    relevanssi_didyoumean(
    	get_search_query( false ),
        '<p>Did you mean: ',
        '</p>',
        5
    );
}

This will print out the suggestion if there’s less than five results found.

Pro tip: If you place this code inside the if ( have_posts() ) conditional in your template, it’ll only run when there’s a typo, but some posts are still found. Most of the time that is not exactly what you want, so make sure the function is also called when have_posts() returns false.

Free version

In the free version, the suggestions are generated in the function relevanssi_simple_generate_suggestion() and they are based on the logged searches. Relevanssi looks for searches that have found something and will use those as the material for suggestions. Thus, using the “Did you mean” feature requires the use of search logs and it takes some time before there are enough searches in the log so that the suggestions work properly.

There’s caching involved: the results of the query are stored in a transient relevanssi_didyoumean_query for a month, because it’s a bit slow query. This means that the suggestions are refreshed only once per month. If you’re debugging things, simply remove the transient to get fresh results.

The matching is based on the Levenshtein distance between the words.

Premium version

In Relevanssi Premium, the algorithm doesn’t use the search logs except as a backup. Premium looks for the words in your database, so whatever is used on your site is what it suggests. Relevanssi uses a spelling correction method that tries different removals, insertions and replacements with letters, and sees what works.

The source material comes from your database. This can be a really heavy query, so it too is cached for a month. This cache is stored in the wp_options database in the option relevanssi_words. If you want to purge the cache, just remove that option.

Relevanssi only includes words that appear at least twice in the database. On big sites, that’s too much, and it’s better to reduce the number of words included. You can adjust the minimum to 3 with this little snippet:

add_filter( 'relevanssi_get_words_having', function() { return 3; } );

This should be enough in most cases, but on very large sites it may be helpful to lift the bar even higher.

Genesis

Here’s how you can use the Did you mean feature in Genesis themes. Add this to your child theme functions.php:

add_action( 'genesis_before_loop', 'genesis_add_didyoumean' );
function genesis_add_didyoumean() {
    if ( function_exists( 'relevanssi_didyoumean' ) ) {
        relevanssi_didyoumean( get_search_query( false ), '<p>Did you mean: ', '</p>', 5 );
    }
}	

Automatic search for “Did you mean” corrections

If you want to make Relevanssi automatically search for corrected search terms if there are no results found for the original search term, you can do this using the relevanssi_fallback filter hook (this only works in Relevanssi Premium):

add_filter( 'relevanssi_fallback', 'rlv_didyoumean_fallback' );
function rlv_didyoumean_fallback( $args ) {
    global $relevanssi_dym_fallback;
    $query  = $args['args']['q'];
    $query  = htmlspecialchars_decode( $query );
    $tokens = relevanssi_tokenize( $query );

    $sc = new Relevanssi_SpellCorrector();

    $correct   = array();
    $new_query = $query;
    foreach ( array_keys( $tokens ) as $token ) {
        $token = trim( $token );
        $c     = $sc->correct( $token );
        if ( ! empty( $c ) && $c !== strval( $token ) ) {
            array_push( $correct, $c );
            $new_query = str_ireplace( $token, $c, $query );
        }
    }

    if ( $new_query !== $query ) {
        $relevanssi_dym_fallback = $new_query;
    
    	$args['args']['q'] = $new_query;
        remove_filter( 'relevanssi_fallback', 'rlv_didyoumean_fallback' );
        $return = relevanssi_search( $args['args'] );
        add_filter( 'relevanssi_fallback', 'rlv_didyoumean_fallback' );
        $args['return'] = $return;
    }
    return $args;
}

If the search term doesn’t find any results, this function gets triggered, runs the spelling corrector for the search query and does a new search with the corrected query, hopefully returning useful results.

If you add this code to your theme functions.php, it will work automatically, but the change is invisible: your search results page will still show the original search term. That may be confusing. In order to fix that, this function sets the global variable $relevanssi_dym_fallback and stores the corrected query in it.

You can use that global function on your search results template to figure out if the query has been corrected and then print out the corrected search result:

<?php
	global $relevanssi_dym_fallback;
	if ( ! empty( $relevanssi_dym_fallback ) && $relevanssi_dym_fallback !== get_search_query() ) {
      	echo "<h2 class='page-title'>Actually searched for: $relevanssi_dym_fallback</h2>";
    }
?>

Filter hooks