If you want to use Relevanssi outside search results templates, you can use the relevanssi_do_query()
function to run Relevanssi queries. It needs a WP_Query object as a parameter:
$args = array( 's' => 'search terms', ); $query = new WP_Query(); $query->parse_query( $args ); relevanssi_do_query( $query );
After you do this, you’ll find the search results for “search terms” in $query->posts
. You can use most of the WP_Query parameters, Relevanssi will understand most that make sense within searching context.
Notice that the code doesn’t do $query = new WP_Query( $args );
, because that runs the query. If you create the object without parameters and use parse_query()
instead, the query won’t be run, which is a small performance advantage.
You can also set the parameter relevanssi
to true
in the query to make sure Relevanssi processes the query. This is the same as the code above:
$args = array( 's' => 'search terms', 'relevanssi' => true, ); $query = new WP_Query( $args );
Hi, I’m using my custom search with relevanssi_do_query but query result contains not only published posts but draft, trash, etc. What is the problem, how can I query just published posts? My code snippet:
$query = new WP_Query(‘post_status=publish’);
$query->query_vars[‘s’] = $q;
$query->query_vars[‘posts_per_page’] = 10;
$query->query_vars[‘post_status’] = array( ‘post_status’ => ‘publish’);
relevanssi_do_query($query);
Relevanssi doesn’t care about ‘post_status’, but it should never include posts in trash, either. Drafts are indexed, but will not be shown in front end searches.
You could add a filter on ‘relevanssi_hits_filter’ filter hook to filter out the unwanted posts.
You are right trash isn’t there but draft is. How should relevanssi_do_query know is he called from front or admin? I think actualy it can’t figure out. I use it inside my frontend plugin and call it with admin-ajax.php maybe this is the problem.
The strange thing is that I use this method since WP 3.3 but now I upgraded my WP and relevanssi setup to 3.6 and 3.1.8. Before this upgrade everything works fine.
Actually my solution is filter Relevannsi output and don’t display draft posts:
while ($query->have_posts()) : $query->the_post();
if (get_post_status() != ‘publish’) continue;
…
I will check relevanssi_hits_filter. Thanks for your quick answer!
Relevanssi checks $wp_query->is_admin and should play nice with admin-ajax.php, but that may be part of the problem, yes. Filtering out the results like that is a good idea, relevanssi_hits_filter gives you another way to filter.
I am facing same problem.
Did you find any solution on this?
Hello, how can i avoid logging this searches? There isn´t any hook around the logging method.
There’s no method for it now. I should probably add something in the future, yes.
Can I help you? Give me some guideline and i will fork it for you.
Analizing the code it seems easy to solve.
Well, do it the way you’d want to use it; that’s the best approach, since it’s you who will be using the feature, not me.
Hi, I really can’t believe that nobody is asking this question, but how can I do pagination without having the total number of pages (or posts) returned? I can’t find any documentation about using this plugin with pagination.
nevermind. I was using it like this:
$query = relevanssi_do_query($this->query_object);
and the query details are written into the
$this->query_object
It works nicely, but I’m presented with the same problem that I ran into with Search Everything. The search filtering works perfectly upon page load, but when I run my search through AJAX, it returns to the basic “title and content” search that comes with WordPress. Is there a way to initialise the plugin before my AJAX search function?
Thanks 🙂
Relevanssi attaches itself to the_posts hook. How does the AJAX search work? Is there a hook I could attach Relevanssi to?
Basically, I have my PHP identical to the examples above, and it works fine on page load. Then I hit that same PHP again, but with an AJAX request (passing the search query as $_POST instead of $_GET), and Relevanssi seems to be bypassed.
My JS is like:
$.ajax({ type: “POST”, url:”/wp-admin/admin-ajax.php”,
data: “action=getpagecontentfunction&pageid=”+pageID+”&query=”+searchQuery,
cache: true, success: function(results){
// append results
});
Is there a function or something that I could run at the start of my getpagecontent() in my PHP?
Thanks for the speedy reply!
That’s probably not a proper search query, hence Relevanssi is not triggered. You can use the relevanssi_do_query() function to run Relevanssi anywhere, perhaps you should use that.
I think it’s because both Search Everything and Relevanssi do a check for admin-ajax.php, and stop what they’re doing if true. In Search Everything, I managed to just comment out this check, and everything is working as expected. Will this be the same deal with Relevanssi? A simple check for is_admin() or if admin-ajax.php that needs to be removed? Leaving this here just incase anyone runs up against the same problem.
Have you enabled Relevanssi in admin? If not, then yes, that’s going to stop it. Relevanssi is checking for $wp_query->is_admin instead of is_admin() so it should work with admin AJAX, at least for that part.
Does query_vars accept meta_key and orderby=meta_value arguments?
meta_key works, orderby=meta_value doesn’t. If you want to order by meta_value, you can do that with a relevanssi_hits_filter filter.
Okay I’ve seen some examples on how to do a relevanssi_hits_filter, one more question: can I apply this filter only to the search query outside the search page?
What exactly do you mean by that?
I have a page that works like this:
The user clicks on a span element which has a “slug” attribute.
Clicking on the span element triggers an AJAX script that sends the “slug” attribute to a separate page that contains a PHP script with the relevanssi_do_query function passing the attribute as the “s” query variable and returns the query results.
In this query I also need to sort the results by a numeric custom field.
Adding the hits_filter will also affect the regular search queries done on the default search form? If so, is there any way I can avoid it?
Yeah, the hits_filter will hit all searches – unless you restrict it somehow. Can you set a global variable you could check in the filter function? Or maybe there’s something in $wp_query you can use to recognise whether you’re in AJAX script or regular search query? There’s got to be something different.
Well, taking a look at some hits_filter examples I can tell if it’s AJAX script thanks to this line
if ($wp_query->query_vars[‘orderby’] == ‘meta_value_num’)
because the main search doesn’t have the orderby argument set to ‘meta_value_num’.
Since the filter currently works with the global variable $wp_query, how can I edit it to work with the variable $query as in the examples above?
Well, relevanssi_hits_filter can use $wp_query, because it’s globally available. The above examples don’t have anything to do with relevanssi_hits_filter and thus don’t really apply here. So the answer is – I don’t know. Can you make your query variable global earlier in the process?
I’ll try using query_posts on the WP_query passing the query_vars I need
Hello Mikko! Let me tell you that you’ve done an amazing work on this plugin. I have a little question:
Let’s say I have two custom fields “dealer_order” and “dealer_city”, results should first be ordered by the “dealer_order” value first and then after by “dealer_city” values, both ascending.
Using query_vars and relevanssi_hits_filter can I order the query’s results by two meta_values?
With relevanssi_hits_filter, you can do anything you want with the query results. There’s no limits – you can order the results any way you want.
Hello Mikko
Congrats for this great plugin!
Hope you can help me with the following:
I want to display products for a certain keyword within a page. I use woocomerce and only index type products and taxonomie category, product_cat and product_tag with relevanssi. Would it be possible to display within a text a certain number of products using relevanssi_do_query?
Yes, you could do that, though it’s probably faster to do with direct database query (“SELECT * FROM wp_posts WHERE post_content LIKE ‘%keyword%’ AND the rest of the parameters here”).
How can I get the excerpt from the above function?
It’s in $post->post_excerpt, if you’ve enabled custom excerpts in Relevanssi settings.
I have excerpts in Relevanssi on and in all search results, excerpts have the same content for each post.
This is the code I use:
$query->query_vars[‘s’] = ‘printer’;
$query->query_vars[‘posts_per_page’] = 10;
$query->query_vars[‘paged’] = 1;
relevanssi_do_query($query);
$similar = “”;
foreach ($query->posts as $r_post) {
if ($r_post->ID == $post->ID) continue;
$link = get_permalink($r_post->ID);
$title = get_the_title($r_post->ID);
$excerpt = $post->post_excerpt;
$similar .= “$title“;
$similar .= “”.$excerpt.””;
$similar .= “”.$r_post->ID.””;
}
$similar .= “”;
echo $similar;
You’re reading the excerpt from $post instead of $r_post.
Oppsss! Now it works! Thanks.
Two more questions:
1.- I have included a filter by category_id but when I insert the following sentence, it search among all posts.
$query->query_vars[‘cat’] = 3;
2.- How can I get the total number of items founds in a search? It’s for pagination purposes.
Try using “cats” instead of “cat”. That’s more reliable in Relevanssi.
Total number of items is in $wp_query->found_posts.
Hi, thanks. yes, did not realized the that it was ‘cats’ instead of ‘cat’.
With respect the total number of search results, it return 0.
$query->query_vars[‘s’] = urldecode($_GET[‘search’]);
$query->query_vars[‘posts_per_page’] = 20;
$query->query_vars[‘paged’] = isset($_GET[‘page’])?$_GET[‘page’]:1;
$query->query_vars[‘cats’] = 3;
relevanssi_do_query($query);
echo “Total: “.$wp_query->found_posts.””;
If your query is in the variable $query and not $wp_query, then the found posts are also in $query->found_posts.
Hi,
is it possible to use relevanssi_didyoumean(…) with this (outside search pages)?
Thank you
Yes, you can use that anywhere, as it’s not at all related to the search query – you can give it any text to correct, really.
wow.. thanks for the amazing speed in response..
This is a code that I am writing now for testing purposes to allow search through a thirdparty app..
function ao_api_search(){
//return 1;
$s = sanitize_text_field( $_REQUEST[‘k’] );
$lang = sanitize_text_field( $_REQUEST[‘lang’] );
$per_page = (isset($_REQUEST[‘posts_per_page’]) && is_numeric($_REQUEST[‘posts_per_page’])) ? $_REQUEST[‘posts_per_page’] : ’10’ ;
$page = (isset($_REQUEST[‘page’]) && is_numeric($_REQUEST[‘page’])) ? $_REQUEST[‘page’] : ‘1’ ;
$ao_query->query_vars[‘s’] = $s;
$ao_query->query_vars[‘posts_per_page’] = $per_page;
$ao_query->query_vars[‘paged’] = $page;
relevanssi_do_query($ao_query);
return array(relevanssi_didyoumean($ao_query, ”, ”, $n = 5), $ao_query);
}
but I cant get any suggestions when I write a misspelled word
thanks
You’ve got the relevanssi_didyoumean() parameter wrong – it takes the search terms as a string, not a query object.
Oh.. Thanks million times
Hello Mikko,
When I put
$query->query_vars[‘posts_type’] = ‘something’;
it returns all post types, how can I restrict it to one post_type?
thanks
The correct parameter is “post_type” or “post_types”, not “posts_type”.
Sorry for the typos.. Its written as you mentioned, but though.. Returning all post types..
If “post_types” parameter has no effect, the search is not actually powered by Relevanssi. Also, do note that in most cases, trying to set “post_type” to “page” causes WP to actually set it to “any”. That doesn’t happen with “post_types”.
I set it to product, where I use woocommerce but it returns everything including users and posts.
$query->query_vars[‘s’] = $s;
$query->query_vars[‘posts_per_page’] = $per_page;
$query->query_vars[‘paged’] = $page;
$query->query_vars[‘post_type’] = ‘product’;
relevanssi_do_query($query);
foreach ($query->posts as $post) {
$image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), ‘single-post-thumbnail’);
$res = array(
“ID” => $post->ID,
“Post_Title” => $post->post_title,
“Image” => $image[‘0’],
‘description’ => substr($post->original_excerpt, 0, 50).’…’,
‘type’ => $post->post_type,
);
array_push( $response, $res );
}
What if you use “post_types” instead of “post_type”, is the result same?
Yes, I tried this, and tried using both togather, but no luck 🙁
Strange. The code seems correct to me. Can you show me what this function prints out:
add_filter(‘relevanssi_query_filter’, ‘rlv_qf_test’);
function rlv_qf_test($q) {
var_dump($q);
return $q;
}
Can you please tell me where to but this within my original code ^ .. because I get results via postman
In that case change the var_dump() to something you can see, for example mail(“your@address”, “test”, $q);
okay thanks, but where to but this code? any where outside original my function ? or within?
Anywhere that is run, theme functions.php is a good place.
SELECT relevanssi.*, relevanssi.title * 5 +
relevanssi.content + relevanssi.comment * 0.75 +
relevanssi.tag * 1 + relevanssi.link * 0.75 +
relevanssi.author + relevanssi.category * 2 + relevanssi.excerpt +
relevanssi.taxonomy + relevanssi.customfield + relevanssi.mysqlcolumn AS tf
FROM lp_relevanssi AS relevanssi WHERE (term LIKE ‘%moh’ OR term LIKE ‘moh%’) AND ((relevanssi.doc IN (SELECT DISTINCT(posts.ID) FROM lp_posts AS posts
WHERE posts.post_type IN (‘product’))) OR (doc = -1))
Ok, there’s the post type restriction. Relevanssi shouldn’t return anything but products. Are you 100% sure the results are produced by Relevanssi?
yes I’m sure. I checked by returning the result object, it has all the properties added by relevanssi, like the highlights and everything.
I am not an expert with MySQL stuff… but this part looks weird -> OR (doc = -1))
That’s necessary to include things that don’t have a post ID. I can see how users can creep in the results but it doesn’t explain why you’re seeing posts.
yes indeed, its the users who appears mixed with all searches.. does disabling it from options solve the issue?
Yes, that’s the easiest solution. If you want users in some other searches, you can filter the results with relevanssi_hits_filter to weed out the users.
I disabled:
Index and search user profiles:
and
Index subscriber profiles..
That works for me, and for users I switched to use wp_users_query, its quiet powerful.
Thank you for your outstanding support!
Hello Mikko,
the plugin is great and the function relevanssi_do_query was just what I was looking for… BUT I’m not able to make it work properly
I’m trying to use it on a template page, where I have a custom search box and search results inside the same page. I get this error:
Object of class WP_User could not be converted to int in …essentials.php on line 120
And I tried by this simple code:
if( isset( $_REQUEST[‘cerca’] ) ) {
$query = new WP_Query( array( ‘s’ => $_GET[‘cerca’],’posts_per_page’ => 10 ) );
relevanssi_do_query($query);
}
When I run it without relevanssi_do_query AND disabling relevanssi plugin (to avoid wp_query overriding), I don’t get errors and – adding a wp loop to the code – I can see the results.
Could you kindly help me?
Put the code in a Pastebin and share the link, I can’t see the whole code here.
thank you for your rapid reply ! this is the pastebin of the entire template page:
http://pastebin.com/ctWEKi90
I’m not a coder, I hope I didn’t mess too much 🙂
SOLVED. It’s some other plugin conflicting with relevanssi. I’m using plugin organizer to discover which one 🙂
I’ll leave a message to tell you who’s the guilty when I discover it, hope this helps!
So: the problem was “wp private” plugin, and (I didn’t notice it) the error appeared only when logged in wordpress, I mean when I loaded the page as admin. Now it seems to work perfectly
update just for the sake of precision: it wasn’t an error, it’s a notice and appears only in php debug mode
Hi,
I need to use relevanssi_do_query() function without a search term. I already have my main site search working without a search term thanks to relevanssi_hits_filter. I would want to do the same in an ajax search query I’m executing with relevanssi_do_query(). For the moment, I couldn’t manage to execute this query without a search term. Can I apply the same filters relevanssi_hits_filter and relevanssi_search_ok of main search in a relevanssi_do_query?
Thanks
Andreu, I’m almost certain that you shouldn’t be calling relevanssi_do_query() at all, but instead directly interacting with WP_Query. If you don’t have a search term, Relevanssi is doing nothing there but slowing down things. Without a search term, WP_Query is doing all the work, so you’re better off calling it directly.
This snippet allows to return the Relevanssi results into Flatsome theme’s ajax live-search
// Integrate Flatsome's live search with Relevanssi - gna@r-us.hu 2020
function my_flatsome_relevanssi_integration( $search_query, $args, $defaults ) {
if ( ! function_exists('relevanssi_do_query') ) {
return $function;
}
$rlv_args = array(
's' => $defaults['s'],
);
$rlv_query = new WP_Query();
$rlv_query->parse_query( $rlv_args );
relevanssi_do_query( $rlv_query );
return $rlv_query->posts;
}
add_filter('flatsome_ajax_search_function', function() {
return 'my_flatsome_relevanssi_integration';
}, 10, 2 );
I am wanting to do a search and then display results in a highly customized template not in the normal WP hierarchy, eg mycooltemplate.php. No matter what I try, I get a 404, if the search form specifies anything other than action=”/” (“/” works ok). Can relevanssi do this?
No, not really, because Relevanssi has no opinion on the templates. That’s all left to the theme to handle.
See How to customize multiple search results pages in WordPress for one solution on how to make a custom template for search results.
First thank you for your plugin. It’s the best of all. Because of that, I’m trying to modify my template to make the theme search works with Relevanssi because the default search is consuming a lot of CPU. I’d appreciate any help very much.
I found that function in my template’s live search:
static function &get_wp_query_search($search_string) {
$args = array(
‘s’ => $search_string,
);
$td_query = new WP_Query($args);
return $td_query;
}
I tried to adapt to something like this, but didn’t work (I’m getting empty results and I have no idea how to debug something that comes from the template):
static function &get_wp_query_search($search_string) {
$args = array(
‘s’ => $search_string,
);
$td_query = new WP_Query();
$td_query->parse_query( $args );
relevanssi_do_query( $td_query );
return $td_query;
}
This way nothing works at all. If I remove “return $td_query”; it works but I get empty results.
I also tried “$td_query = $td_query->posts” but it didn’t work either.
Any idea what I’m missing?
Henrique, the default WP search is most certainly more CPU-friendly than Relevanssi. If your site is so big that the way the default search uses the MySQL database gets heavy, Relevanssi won’t help much, but Relevanssi Light may be useful.
The code looks fine to me. It should work. Does the Relevanssi admin search (Dashboard > Admin search) return results for the same search query?
You can debug this by using error_log(). It can only print out strings, but you can use
wp_json_encode()
to convert anything into a string.issue 1: relevanssi is not used in the search REST API (so frontend searches differ from REST API search)
issue 2: after solving for issue 1, pagination is broken, likely due to how relevanssi does not account for other code in WP_Query
The following attempts to solve for both issues above:
/**
* Enable relevanssi for REST API search requests.
*/
add_filter( ‘posts_pre_query’, function( $check, $query ) {
if ( $query->is_search() && defined( ‘REST_REQUEST’ ) && REST_REQUEST ) {
$posts = relevanssi_do_query( $query );
$query->relevanssi_found_posts = $query->found_posts;
return $posts;
}
return $check;
}, 10, 2 );
/**
* Because “relevanssi” does not properly account for code run in WP_Query, like
* the wordpress filter “found_posts_query”, which undoes “found_posts”, it must
* be reset. This is primarily evident with code that fully use WP_Query, such
* as the REST API.
*/
add_filter( ‘found_posts’, function( $found_posts, $query ){
return $query->relevanssi_found_posts;
}, 20, 2 );
Dimas, Relevanssi is blocked in REST API on purpose, as you’ve noticed it does not work very well. I would recommend creating and using a proper REST API endpoint for Relevanssi. Here’s a starting point for that.
Is relevanssi processing the query sent to wp-json/wp/v2/search? Do we need to add relevanssi = true to the query_args in the rest_post_search_query filter?
add_filter( ‘rest_post_search_query’, ‘rest_search_add_custom_field_cb’, 10, 2 );
function rest_search_add_custom_field_cb( $query_args, $request ) {
$query_args[‘relevanssi’] = true;
return $query_args;
}
If it is running, how can we verify it is?
Jason, Relevanssi is by default disabled in the REST API. You can use
remove_filter( 'rest_api_init', 'relevanssi_rest_api_disable' );
to enable it, and setting therelevanssi
query argument should also work.You can verify by searching something only Relevanssi can find, like custom field content.
Hi,
I have a few issues:
1) How can i exclude the password protected pages from the results?
$args[‘has_password’] = false; // Only get non password protected pages
$wp_query = new WP_Query($args);
$wp_query->parse_query($args);
relevanssi_do_query($wp_query);
This does not work.
2) For a custom post type my_posttype, i have the content data in custom meta fields. But relevanssi does not search those. It seems to only search the title. How can i address this?
3) This is more minor, but I have noticed that my previous code
$args = array(
‘s’ => $search,
);
$wp_query = new WP_Query($args);
if executed in a shortcode does not work any more after I installed relevanssi.
It only works, if i do:
$args = array(
‘s’ => $search,
);
$wp_query = new WP_Query($args);
$wp_query->parse_query($args);
relevanssi_do_query($wp_query);
Would yo know why it would affect existing WP_Query?
Edd,
1) Relevanssi doesn’t support the
has_password
parameter. I’ve never thought about it, and you’re the first one to ask in 15 years. You can do this:add_filter( 'relevanssi_post_ok', function( $ok, $post_id ) {
if ( post_password_required( $post_id ) ) {
$ok = false;
}
return $ok;
}, 10, 2 );
2) You can control which custom fields are indexed from the Relevanssi indexing settings. This setting applies to all post types.
3) For starters, using
new WP_Query()
in a shortcode is wrong. WP_Query should only be used in templates, and it’s better to useget_posts()
instead. It gets you the posts, without wreaking havoc on global variables.The WP_Query doesn’t work, because Relevanssi disables the default search in WP_Query (because WP_Query is meant to be only used in the templates, so a search using WP_Query should be the search template). The easy solution is to make the WP_Query use Relevanssi, and the easiest way to do that is this:
$args = array(
's' => $search,
'relevanssi' => true,
);
$wp_query = new WP_Query($args);
You can control Relevanssi behaviour with relevanssi_prevent_default_request hook if you don’t want Relevanssi to mess with a particular query.
But in a shortcode, you really should be using
get_posts()
.