5

I'm using WP Query and the results coming back when using the search term aren't working as I wish. For example searching for 'art' returns also results for words containing 'art' such as 'part'. How can I avoid this? and just return results for 'art' containing the exact word 'art'.

1

2 Answers 2

11

This is actually a tricky question, as by stating exact there are two ways in which one can interprit your question -

  1. Only find posts where the whole title or the whole content match exactly. For example, if you search My post is super you would not have returned a post with the title My post is super awesome.
  2. Fine posts where the exact phrase exists, not just part of a phrase. For example, if you search his house you would not have returned a post with the title I love this house, but you would a post with the title I'm going to his house (rubish examples, but hopefully you get the point).

Luckily you can do either, but method 1 is by far the simpler. Add either of these examples to your functions.php file -


Method 1

add_action('pre_get_posts', 'my_make_search_exact', 10);
function my_make_search_exact($query){

    if(!is_admin() && $query->is_main_query() && $query->is_search) :
        $query->set('exact', true);
    endif;

}

The my_make_search_exact() function will be called everytime a query is made, using the pre_get_posts action hook.

To ensure we don't mess with the query when we don't need to, within the function we check that we are NOT viewing the admin area, that we ARE constructing the main query and that we ARE making a search.


Method 2

add_filter('posts_search', 'my_search_is_exact', 20, 2);
function my_search_is_exact($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 ';

    endforeach;

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

    return $search;

}

Credit to tinyGod for this answer - http://tinygod.pt/make-wordpress-search-exact/

2
  • thanks we ended up working this out ourselves but you've done a nice description. Commented Feb 5, 2015 at 23:36
  • @David Gard Thank you so much. I'm getting the exact result which I want. :)
    – Ravi
    Commented May 9, 2019 at 15:24
12

I think someone else has answered this before: Check this answer, from @Sunyatasattva

But apparently WP_Query supports some extra search parameters:

's' => $s, //(string) - Passes along the query string variable from a search.

'exact' => true, //(bool) - flag to make it only match whole titles/posts - Default value is false.

'sentence' => true, //(bool) - flag to make it do a phrase search - Default value is false.

More at: https://gist.github.com/luetkemj/2023628

Hope it helps,

1
  • Sadly the sentence => true parameter doesn't do what the user wants. Rather it means the WP will only return posts where the sentence part of a sentence exists, where usually it would return matches for part OR of OR a OR sentence. In both cases the results would not be what is required if a search for art was made.
    – David Gard
    Commented Feb 5, 2015 at 15:20

Not the answer you're looking for? Browse other questions tagged or ask your own question.