A common question about the WordPress search is how to make it exact, or in other words, directly from the geeSearch support forum:

if I search for a term, all kinds of words are shown which contain the term, for example if I search “round” I also get results for “background” – but I want only results with the word “round”. Is that possible in any way?

— It is possible, but…

The Exact parameter

One of my favourite classes in WordPress is WP_Query. It makes so easy to query the WordPress database that I almost forget SQL select statements are in the bottom of everything.

Although it is not documented in the codex, this class contains a parameter called exact which allows to set whether the search query should return results containing exactly the searched terms or, as set by default, a more relaxed set of results, where search terms could be part of other words or sentences.

So, if you set your Search to work in exact mode, placing the following example code in your theme’s functions.php:

add_action( 'pre_get_posts', 'my_search_is_exact', 10 );

function my_search_is_exact( $query ) {
    if ( !is_admin() && $query->is_main_query() && $query->is_search ) {
        $query->set( 'exact', true );
    }
}

…you’ll probably take it back again, as this exact mode only returns results if the post title or the post content match exactly the searched terms. As an example, if you have a post title like “Alice in the wonderland” a search by “alice” won’t return results in the exact mode.

If are still reading this post, you’re probably a little bit frustrated as I am not presenting any solution to this issue – yes, “I can feel your anger”.

The Solution

Turns out that the initial question is not so simple…

After some investigation, I found a sweet solution here. Hereby the code to be placed in the functions.php:

add_filter( 'posts_search', 'my_search_is_perfect', 20, 2 );
function my_search_is_perfect( $search, $wp_query ) {
    global $wpdb;

    if ( empty( $search ) )
        return $search;

    $q = $wp_query->query_vars;
    $n = !empty( $q['exact'] ) ? '' : '%';

    $search = $searchand = '';

    foreach ( (array) $q['search_terms'] as $term ) {
        $term = esc_sql( like_escape( $term ) );

        $search .= "{$searchand}($wpdb->posts.post_title REGEXP '[[:<:]]{$term}[[:>:]]') OR ($wpdb->posts.post_content REGEXP '[[:<:]]{$term}[[:>:]]')";

        $searchand = ' AND ';
    }

    if ( ! empty( $search ) ) {
        $search = " AND ({$search}) ";
        if ( ! is_user_logged_in() )
            $search .= " AND ($wpdb->posts.post_password = '') ";
    }

    return $search;
}

This is another itch that needs attention and might be integrated in a future release of geeSearch Plus plugin.