Posted on

Search results breakdown by type

Do you want to have a breakdown of search results by post type? This could be used for example to show a list of post types like books, movies, albums on a review site, and make them links to limit the search results to that post type.

This is fairly easy to do with the relevanssi_hits_filter hook. Here’s a function that can be attached to the hook. It will fill a global variable with the post type breakdown:

1
2
3
4
5
6
7
8
9
10
11
12
add_filter('relevanssi_hits_filter', 'search_result_types');
function search_result_types( $hits ) {
    global $hns_search_result_type_counts;
    $types = array();
    if ( ! empty( $hits ) ) {
        foreach ( $hits[0] as $hit ) {
            $types[$hit->post_type]++;
        }
    }
    $hns_search_result_type_counts = $types;
    return $hits;
}

Add the function to your theme functions.php. This function was written by Simon from Lumpy Lemon. Thanks to Simon for sharing the code!

An extended version

The code above has one problem. If the search is restricted to just one post type, the code won’t count the other post types: only those that are present in the search. If you want all post types counted, you can use this version of the function:

add_filter('relevanssi_hits_filter', 'search_result_types');
function search_result_types( $hits ) {
    global $hns_search_result_type_counts, $wp_query, $rlv_doing_this_already;
 
    if (!$rlv_doing_this_already && $wp_query->query_vars['post_type'] != 'any') {
    	$copy_query = $wp_query;
    	$copy_query->query_vars['post_type'] = "any";
    	$rlv_doing_this_already = true;
    	relevanssi_do_query($copy_query);
    	return $hits;
    }
 
    $types = array();
    if ( ! empty( $hits ) ) {
        foreach ( $hits[0] as $hit ) {
            $types[$hit->post_type]++;
        }
    }
 
    $hns_search_result_type_counts = $types;
    return $hits;
}

This version counts all post types.

22 comments Search results breakdown by type

  1. Great plugin!
    A question: How do i use this function with the relevanssi_hits_filter hook in order to separate results by type? I’m at a loss.

    Is there also an easy way to style the post types?

  2. The code was missing an add_filter() call. I’ve added that.

    Styling post types… Well, the post type is stored in $post->post_type, so you can find it there and use that to style it, for example using it to add a post type dependent class to a div that contains the post.

  3. Thank you for your prompt reply!

    I’ve pasted the code in functions.php, but I’m maybe supposed to do more steps – cause nothing changes?

    My usual approach would be to add multiple loops and style each loop separatly, but iguess that will not work. I’d like some post-types only show as links.

  4. Ah, sorry, misread your questions. This does not separate posts by post type, just creates an array that has the counts of posts per type.

    If you want to separate by type, you need to go through the $hits array, check each post and file it in the correct array by post type, then reconstruct the $hits array from the post type arrays in the order you desire.

    In your loop, check $post->post_type and style the post according to the type. So instead of multiple loops, you’ll have a single loop and a switch clause or something like that.

    1. Hi Mikko,

      can you please go in more detail here? I would like to show my custom post type “products” first, then pages and last posts.

        1. This function doesn’t do anything visible, that’s why.

          It just puts the data in the global variable $hns_search_result_type_counts. You need to write some code to do something with that data in order to see visible results.

          1. Hi Mikko. Can you guide me on how to access the data from that variable? I tried but failed.

          2. Add this to your search results template:

            global $hns_search_result_type_counts;
            var_dump($hns_search_result_type_counts);

            It’ll show you what’s inside the variable.

  5. Thank you so much for this information! I was able to get it to work. However, I do have a question. Let’s say I have results from 3 post types: posts, media, and products. On the search landing page, it shows “# posts, # media, and # products”. However, when you click on products, let’s say, the hits in the function change, and instead of showing “# products” only. Any way of keeping the original counts for the entirety of the search on the filtered results pages?

    ETA: I’m using Emily Johnson’s pastebin code below, along with the function above.

    Thank you!

  6. Hey Mikko, thanks for the code. I’m on the latest version of WordPress and I get the error “Undefined index” from the line where it adds to the count. Any ideas why?

    1. Of course I figure it out right after I post this. I had to add the following to get the code above to work:

      $types[‘product’] = ”;

      $types[‘lookbook’] = ”;

      $types[‘post’] = ”;

  7. It looks like the extended version needs to be changed from query_vars[‘post_type’] to query_vars[‘post_types’] in order to work.

Leave a Reply

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