Posted on

Using Relevanssi without a search term

Deprecated: Relevanssi has long supported searching without a search term. These instructions are not necessary.

Version 1.7.3 introduces the possibility to use Relevanssi without a search term. This is useful when you have extra query arguments that can be used to narrow the search, but which would be useful without a search term present.

This was originally implemented for a restaurant search, where the users can search for restaurants based on search terms, opening hours and price category. The client wished to be able to use the opening hours and price category with and without a search term.

The problem is, Relevanssi doesn’t trigger without a search term. To fix that, you need to use a new filter hook relevanssi_search_ok. Add this code to your site:

add_filter( 'relevanssi_search_ok', 'search_trigger' );
function search_trigger( $search_ok ) {
	global $wp_query;
	if ( ! empty( $wp_query->query_vars[ 'price' ] ) ) {
		$search_ok = true;
	}
	return $search_ok;
}

This function will trigger Relevanssi, when the query var price appears in the query.

Of course, without a search term, Relevanssi will find nothing. So, you need another function attached to relevanssi_hits_filter.

It needs to have something like this:

add_filter( 'relevanssi_hits_filter', 'rlv_hits_filter' );
function rlv_hits_filter( $hits ) {
  if ( empty( $hits[0] ) ) {
    // no search hits, so must create new
    $args    = array(...some arguments to fetch posts by...);
    $hits[0] = get_posts( $args );
  } else {
    // posts available, take only those that match the conditions
    $ok = array();
	foreach ( $hits[0] as $hit ) {
      if (...post matches conditions...) {
        array_push( $ok, $hit );
      }
    }
    $hits[0] = $ok;
  }
  return $hits;
}

Make this a proper function and hook it to relevanssi_hits_filter and it’ll work.

Joel Stransky contributed the following:

I have what I feel is a pretty common situation. In the absence of a search term, I’m ok with missing out on Relevanssi’s benefits and just need native WP behavior (which matches on the sub queries even if no search phrase exists). In my current project I’m only modifying meta_query and tax_query so that’s all I check for to ensure I want to do this.

Add this code to your site:

// approve the search when there are active filters
// but no search term
add_filter( 'relevanssi_search_ok', 'search_trigger' );
function search_trigger( $search_ok ) {
	global $wp_query;
	if ( ! isset( $wp_query->query['s'] ) && isset( $wp_query-&>query_vars['tax_query'] ) || isset( $wp_query->query_vars['meta_query'] ) ) {
		$search_ok = true;
	}
	return $search_ok;
}

Then in the hits filter, run a similar check, turn nopaging on and return the results of get_posts() with my modified query_vars. Add this to your site:

add_filter( 'relevanssi_hits_filter', 'rlv_hits_filter' );
/**
 * return results when there are active filters but no search term
 * @param  array $hits $hits[0] is a list of matched WP_Post objects
 *                     $hits[1] is the search term if any
 * @return array       $hits
 */
function rlv_hits_filter( $hits ) {
	global $wp_query;
	if ( ! $hits[1] && isset( $wp_query->query_vars['tax_query'] ) || isset( $wp_query->query_vars['meta_query'] ) ) {
		$wp_query->set( 'nopaging', true );
		$hits[0] = get_posts( $wp_query->query_vars );
	}
	return $hits;
}

42 comments Using Relevanssi without a search term

  1. I would love to try this but don’t understand what I need to do be able to search without a query string, could you please add som example code?

    /Jens

    1. The first function in the post is used to make Relevanssi active, when a certain query variable is present. This is the query variable you want to use to control what is shown if there is no search term present. So, in this case, if the query variable “price” appears in the URL, Relevanssi is activated, whether there’s search term (“s”) or not.

      Then you’ll also have another function that uses the query variable to restrict the searches. This is hooked to “relevanssi_hits_filter” and in this case it would go through all the search hits and discard those that don’t match the value of the “price” query variable.

      So far pretty simple, right? However, if this is all you do, you’ll end up with no results when you don’t use the search term, because there are no search results to process. You need to find something to process yourself. This is where the second code snippet comes into play. This code goes to the function hooked to “relevanssi_hits_filter”. It checks the $hits[0] array. If it’s empty, there are no posts to process, so we need to get some. The easiest solution is to use get_posts to fetch every post in the database and then process like you would with search results.

      However, that’s perhaps a bit ineffecient, as the get_posts() is a fairly powerful function in itself and you can probably use it to limit the posts.

      So, these two snippets of code are all you need. The first is a full function in itself, the second needs to go to a function that is then hooked to “relevanssi_hits_filter”.

  2. So, if I understand this correctly, if we have a variable named “price” in the URL, we could use a meta-search like so:
    $query = new WP_Query( array( ‘meta_key’ => ‘price’, ‘meta_value’ => $searchvalue ) );
    $hits[0]=$query->posts
    where $searchvalue is the value of the price-parameter in the URL, and use that in the second function above (the one attached to the relevanssi_hits_filter). Would that work?

  3. hello, using relevanssi and works fine. i’m not an expert in coding and need to know what code/function to put and where to make relevanssi work without any term inside. please help

    1. I’m sorry, but it’s a complicated thing and requires programming knowledge. If you don’t understand the instructions in this post, it’s too complicated to explain in a comment here. You also need to have a Premium license.

  4. Hi Mikko,
    Great plugin! I just have a small question how do I turn off the search without term in the latest version. I wan’t to show a “No results were found, you must enter a keyword” when the user doesn’t type anything. I don’t want to display a list of everything in my site.

    Thanks!

    1. Looks like there’s a small bug somewhere. It’s not supposed to work like that. I’ll fix it for the next version.

      Actually, looking at this, a search without a search term passes right through Relevanssi without Relevanssi being activated. Relevanssi doesn’t touch the posts WordPress finds. So, this is actually the WordPress default behaviour and has nothing to do with Relevanssi.

      You can probably fix that on your search results template though, just check what’s in the query and display whatever you want instead of the posts if the query is empty.

  5. Hi,

    I just found your plugin in google and I wondered if it could be adapted to what I need. Right now I’m working on a project for a friend’s car shop. Using Types and Views I set up front-end filters to search cars by brand, model or year, or a combination thereof. These parameters are set in every car using select box custom fields. I chose select boxes so I could previously set those values instead of letting the client fill them in. The front-end filters work but they don’t auto populate according to a user’s selection. Say, a wants to filter car by Ford brand. I expect the other 2 controls would update (via ajax) to only show car models and years that are set to that brand.
    Could your plugin be customized to this behavior with or without the View plugin’s filters I’m currently using?
    thanks
    Roberto

      1. Hi, I had to hire a php developer to build some custom code that interacts with the search fields.

        I think the developers of View could build this functionality into their code but it’s not in their list of priorities.

  6. Is there a way to use this filter to turn off relevanssi? I have a custom post type, where the user can perform a search on the archive page. Doing the below returns 0 results.

    add_action( ‘relevanssi_search_ok’, ‘mcfta_turn_off_relevanssi’ );
    function mcfta_turn_off_relevanssi($search_ok) {

    if (is_post_type_archive( ‘event’ )) {
    $search_ok = false;
    }

    return $search_ok;
    }

      1. K great, thanks for the quick response. I just asked because the nav menu has “Buy Premium” highlighted green as current category.

  7. Thank you for the wonderful plug-in.

    Since there is a place which usage does not understand, please let me ask a question.

    Now, it is multisite and is using Relevanssi.

    relevanssi_hits_filter is specified so that it can search, even if two or more custom taxonomy to searchterm cannot be found, but searchblogs cannot make it function well.

    If it becomes as it is used, inputting search term, the searchblogs will operate normally.

    Aren’t any hints got?

    Since the translation engine is used, I think that a text is strange.

    I’m sorry.

      1. Thank you for the instant reply.

        I am allowed to purchase to the beginning of this year, and am using the present premium version.

        1. Ok. You should note that relevanssi_hits_filter is not available in multisite searches (when search_blogs is used). You can’t use taxonomy filtering, either. Multisite searching only supports post type filtering.

  8. Thank you for your reply. I am sorry for the delay in it and the replying here.

    An understanding was completed for a while, seeing the function of Relevanssi, since Mikko taught. Moreover, if it may not understand in the middle of work, please let me ask a question.

    Thank you.

  9. Need your Help. I am using a Custom Post Type “Listing” and I have a Taxonomy “Location”. In the Taxonomy “Location” I have multiple Categories for different locations. How do I search only “Richmond” Category posts when the Input Search form is Empty? I am trying to use the above example, but I’m not having any luck in getting this to work. Much help is appreciated.

    1. In the bottom example, replace this line:

      $args = array(…some arguments to fetch posts by…);

      with arguments that fetch posts in the “Richmond” category. See WordPress Codex documentation on get_posts() to see how that is done.

      1. I did do that but it didn’t work. On the Top part, where it says “Price”, What do I replace that with.

          1. Do I put all this code (above) in the themes Function.php file?

            Sorry for all the questions.

            Shawn

          2. Hi Mikko, Again… Thanks for all the help. Here is a complete of what I am doing:

            url from search result: .com/listing/?s=

            What I have in my Functions.php file:

            add_filter(‘relevanssi_search_ok’, ‘search_trigger’);
            function search_trigger($search_ok) {
            global $wp_query;
            if (!empty($wp_query->query_vars[‘richmond’])) {
            $search_ok = true;
            }
            return $search_ok;
            }

            // Second Part

            if ($hits[0] == null) {
            // no search hits, so must create new
            $args = array(‘post_type’ => ‘listing’,’location’ => ‘richmond’, ‘posts_per_page’=>3);
            $hits[0] = get_posts($args);
            }
            else {
            // posts available, take only those that match the conditions
            $ok = array();
            foreach ($hits[0] as $hit) {
            if ($args)
            array_push($ok, $hit);
            }
            $hits[0] = $ok;
            }

            What my Search Form Looks Like:

            My Post Type is: Listing
            My Taxonomy is: Location
            My Category in Location is: Richmond

            Relevance is Indexing only: Listing (Post Type) and Location (Taxonomy)

          3. In the first function, “richmond” should be “location”. The second part is missing the actual function. I’ve changed the example a bit so that it includes the complete function, so it’s easier to understand.

  10. Hi Mikko!
    I’m wondering if relevanssi_search_ok is mandatory. Because relevanssi_hits_filter is triggered for my search anyway and there’s no difference in search results (and in SQL queries too) when I remove relevanssi_search_ok.

    1. If there’s no need for it, then drop it. It’s only necessary when there’s no search term ($wp_query->query_vars[“s”]), because in those cases the search isn’t triggered at all.

  11. I have what I feel is a pretty common situation. In the absence of a search term, I’m ok with missing out on Relevanssi’s benefits and just need native WP behavior (which matches on the sub queries even if no search phrase exists)
    In my current project I’m only modifying meta_query and tax_query so that’s all I check for to ensure I want to do this.


    // approve the search when there are active filters
    // but no search term
    add_filter('relevanssi_search_ok', 'search_trigger');
    function search_trigger($search_ok) {
    global $wp_query;
    if ( !isset($wp_query->query['s']) && isset( $wp_query->query_vars['tax_query']) || isset( $wp_query->query_vars['meta_query']) ) {
    $search_ok = true;
    }
    return $search_ok;
    }

    Then in the hits filter, run a similar check, turn ‘nopaging’ on and return the results of get_posts() with my modified query_vars

    add_filter('relevanssi_hits_filter', 'rlv_hits_filter');
    /**
    * return results when there are active filters but no search term
    * @param array $hits $hits[0] is a list of matched WP_Post objects
    * $hits[1] is the search term if any
    * @return array $hits
    */
    function rlv_hits_filter($hits) {
    global $wp_query;
    if ( !$hits[1] && isset( $wp_query->query_vars['tax_query']) || isset( $wp_query->query_vars['meta_query']) ) {
    $wp_query->set('nopaging', true);
    $hits[0] = get_posts( $wp_query->query_vars );
    }
    return $hits;
    }

    Unless I’m overlooking something, this appears to work great.

Leave a Reply

Are you a Relevanssi Premium customer looking for support? Please use the Premium support form.

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