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?
I think you can use
Relevanssi
without any problem but need to use afilter
hook, check relevanssi_modify_wp_query for more details, check following codeI’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 ifphp 5.3+
is installedAlso, 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 yourfunctions.php
file.Scree shot given below
Ok so I ended up using Relevanssi after all. But with quite a few modifications.
First of all, filtering on taxonomies was quite easy as this is built into Relevanssi, all I needed to do was change the names of my
<select>
elements to the taxonomy names + change the values to the slugs:Second, to allow sorting by a custom field, I had to use the
relevanssi_hits_filter
filter. Unlikepre_get_posts
orrelevanssi_modify_wp_query
(which Sheikh Heera kindly suggested), this filter gets passed the array of posts and not a WP_Query object. When I tried to use the WP_Query object the order simply refused to change. Here’s basically how to do your own sort withrelevanssi_hits_filter
:This also helped with a previous problem I had in that posts that lacked the “price” key didn’t show up in searches. Now they do, and the reason I give them a price of “10000000” is so that they show up after the ones that do have a price.
Finally, I also needed empty searches to work. According to the Relevanssi dev this is only supported in the Premium version, but I think I managed to work around it. First I forced WP to display the search page even if ?s was empty:
Second, I told Relevanssi to fetch all posts if ?s was empty, by default it won’t fetch any posts at all. Unfortunately, in doing this the default behaviour with custom taxonomies stopped working (my code over wrote it) so I had to manually check for taxonomies in this code as well:
And that’s it. Everything seems to work and hopefully this will help someone who has similar requests in the future.
I really hope WP improves its ridiculous search in the future. Sorting by relevance should be something that’s available in the world’s most popular CMS imo.
Thanks @Sheikh Heera for pointing me in the right direction. I’m not sure who to give the right answer to though seeing as I really couldn’t use the stuff you suggested.
Just found out that WP already has this in core.
In https://developer.wordpress.org/reference/classes/wp_query/, look at the “orderby” => “relevance” parameter.