Sort Wordpress Search by Relevance

powerbuoy picture powerbuoy · Jul 18, 2013 · Viewed 10.3k times · Source

I've created a pretty advanced search for a Wordpress site I'm working on atm. Allowing visitors to filter results by different taxonomies, sort them by date or custom fields as well as the normal free text search (which WP offers by default).

I've accomplished this using the pre_get_posts filter and by simply adding my stuff to the query, something like this: (note that I've left out some sanity checks and other code)

<?php
add_filter('pre_get_posts', 'my_search');

function my_search ($qry) {
    # Include more post types
    $qry->set('post_type', array('foo', 'bar'));

    if ($_GET['myorder'] == 'price') {
        $qry->set('orderby', 'meta_value_num');
        $qry->set('meta_key', 'price');
        $qry->set('order', 'ASC');
    }
    else {
        $qry->set('orderby', 'date');
        $qry->set('order', 'DESC');
    }
}

Now I would like to add another way to sort the posts, namely by relevance. I understand this is a really common request and most solutions to the problem I've seen include using the Relevanssi plugin. Seeing as I've already written my own "plugin" (well, code at least) and have all my search forms and listings set up to use that, switching to Relevanssi won't be too easy at this point.

Sooo, I'd like to know if anyone knows of some (preferably) easy way to add this with the code I've already got?

As far as I understand, WP does its search using LIKE instead of MATCH() and that's why it doesn't even have a relevance score to sort on. If this is correct I assume I would have to write my own query altogether? How can I do this without messing up WP's pagination etc? Or could I add something like $qry->set('WHERE', "MATCH(post_content) AGAINST('$q' IN BOOLEAN MODE) AS relevance"); $qry->set('sortby', 'relevance') do you reckon?

Answer

The Alpha picture The Alpha · Jul 20, 2013

I think you can use Relevanssi without any problem but need to use a filter hook, check relevanssi_modify_wp_query for more details, check following code

function func_reli($qry){
    $qry->set( 'post_type', array( 'post', 'page', 'restaurant', 'products' ) );

    if ($_GET['myorder'] == 'price') {
        $qry->set('orderby', 'meta_value_num');
        $qry->set('meta_key', 'price');
        $qry->set('order', 'ASC');
    }
    else {
        $qry->set('orderby', 'date');
        $qry->set('order', 'DESC'); // <-- set (in your code 'add' is used)
    }
    return $qry; // <-- must return, in your code you didn't
}
add_filter('relevanssi_modify_wp_query', 'func_reli');

I've tested this code and just works fine. In this example I've used 'restaurant' and 'products' custom post types and search works really fine, just the relevant results. You can also use if php 5.3+ is installed

add_filter('relevanssi_modify_wp_query', function($qry){
    // Same code
});

Also, if you use Relevanssi plugin, you can use it's setup page to set post_type instead of using this ($qry->set( 'post_type', array(...) )) in your functions.php file.

Scree shot given below

enter image description here