Using Relevanssi outside search pages

There’s a method to get Relevanssi results outside regular search pages. Relevanssi needs to know two things: the search term and the number of search results you want.

$query->query_vars['s'] = 'search term';
$query->query_vars['posts_per_page'] = 10;
relevanssi_do_query($query);

After this bit of code, you’ll have up to 10 search results for the search term “search term” in $query->posts.

You can use all the usual restrictions and filters, just add query_vars. If you want to restrict the search to category 3, just add

$query->query_vars['cats'] = '3';

and so on.

Remember that Relevanssi searches can be quite slow, so if you want to add, for example, a similar posts feature to the end of your every post, caching is a must. Using Relevanssi cache is not recommended, but it’s fairly easy to do a simple cache using WP transients. Something like this:

$similar = get_transient('relevanssi_similar_' . $post->ID);
if (empty($similar)) {
	$query->query_vars['s'] = $post->post_title;
	$query->query_vars['posts_per_page'] = 5;
	$query->query_vars['operator'] = 'or';
	relevanssi_do_query($query);
	$similar = "<ul>";
	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);
		$similar .= "<li><a href='$link'>$title</a></li>";
	}
	$similar .= "</ul>";
	set_transient('relevanssi_similar_' . $post->ID, $similar, 60 * 60 * 24 * 4);
}
echo $similar;

70 comments Using Relevanssi outside search pages

  1. 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);

    1. 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.

      1. 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!

        1. 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.

  2. 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.

    1. 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

  3. 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 🙂

      1. 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!

        1. 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.

          1. 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.

          2. 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.

      1. 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?

          1. 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?

          2. 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.

          3. 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?

          4. 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?

  4. 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?

  5. 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?

    1. 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”).

      1. 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;

          1. 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.

          2. 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.””;

      1. 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

  6. 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

        1. 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”.

          1. 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 );

            }

          2. 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;
            }

          3. 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))

          4. 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))

          5. 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.

          6. yes indeed, its the users who appears mixed with all searches.. does disabling it from options solve the issue?

          7. 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.

          8. 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!

  7. 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?

      1. 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!

      2. 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

  8. 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

    1. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.