Separating posts by post type

Using the relevanssi_hits_filter, it’s easy to separate the search results by post type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
add_filter('relevanssi_hits_filter', 'separate_result_types');
function separate_result_types($hits) {
    $types = array();
 
    // Split the post types in array $types
    if (!empty($hits)) {
        foreach ($hits[0] as $hit) {
            if (!is_array($types[$hit->post_type])) $types[$hit->post_type] = array();                        
            array_push($types[$hit->post_type], $hit);
        }
    }
 
    // Merge back to $hits in the desired order
    $hits[0] = array_merge($types['mycustomtypethatgoesfirst'], $types['thesecondmostimportanttype'], $types['post'], $types['pages']);
    return $hits;
}

The basic idea is: first split the search results in separate arrays by post type, then merge then back to $hits[0] in the correct order. The order of search results within the types remains untouched in the process.

More relevanssi_hits_filter examples in the user manual.

  • http://www.fddb.org Carloalberto Fornea

    Hi there, first I’d like to thank you for your great work!

    Finally with Relevannsi I can search through custom post types and even custom post taxonomy… like I never do before!

    My new challenge is to separate search result by post page… and here you come again with a great help!

    Unfortunately I’m not able to make it work!

    I add your code to my function.php file and change “mycustomtypethatgoesfirst” and “thesecondmostimportanttype” with my custom post type slugs but when I try searching something I get this error

    Warning: array_merge() [function.array-merge]: Argument #2 is not an array in /web/htdocs/www.fddb.org/home/wp-content/themes/thematic-fddb/functions.php

    Any suggestion?
    Maybe I had to use custom post type IDs ?

    thanks again
    regards

    Carloalberto

    • http://www.mikkosaari.fi/ Mikko Saari

      The problem is caused when there are no posts of the second custom type in the results.

      Before the array_merge() line, add line like this for each post type:

      if (!is_array($types[‘mycustomtypethatgoesfirst’])) $types[‘mycustomtypethatgoesfirst’] = array();

      That should fix it.

  • http://www.fddb.org Carloalberto Fornea

    Hi Mikko,

    I’m sorry, I don’t like to bother you but I’m not able to make it work…

    Here is my code in my function.php

    add_filter(‘relevanssi_hits_filter’, ‘separate_result_types’);
    function separate_result_types($hits) {
    $types = array();

    // Split the post types in array $types
    if (!empty($hits)) {
    foreach ($hits[0] as $hit) {
    if (!is_array($types[$hit->post_type])) $types[$hit->post_type] = array();
    array_push($types[$hit->post_type], $hit);
    }
    }

    // Merge back to $hits in the desired order
    if (!is_array($types[‘show’])) $types[‘event’] = array();
    $hits[0] = array_merge($types[‘show’], $types[‘event’], $types[‘post’], $types[‘pages’]);
    return $hits;
    }

    And here is the error I got

    Warning: array_merge() [function.array-merge]: Argument #2 is not an array in …/functions.php on line 1548

    Warning: array_merge() [function.array-merge]: Argument #3 is not an array in …/functions.php on line 1548

    Warning: array_merge() [function.array-merge]: Argument #4 is not an array in …/functions.php on line 1548

    sometimes it change Argument number if there aren’t post of that type to show… but anyway it’s not working.

    Thanks again.
    Carloalberto

  • http://www.mikkosaari.fi/ Mikko Saari

    This is wrong:

    if (!is_array($types[‘show’])) $types[‘event’] = array();

    You need to have two lines:

    if (!is_array($types[‘show’])) $types[‘show’] = array();
    if (!is_array($types[‘event’])) $types[‘event’] = array();

  • carletto0282

    Hi Mikko.

    Thanks again for your support.

    No more error but even no result to me.
    I made the corrections you gave me but I still get the search result mixed by post_type.

    • http://www.mikkosaari.fi/ Mikko Saari

      Are you sure Relevanssi is actually active and provides the search results?

      • carletto0282

        Of course I am.

        Could be the fact that I customize my search results with a custom function to render differently posts of different post types?

      • tatamata

        have the same problem, no results displayed. how can i make sure relevanssi is active and provides search results?

        • http://www.mikkosaari.fi/ Mikko Saari

          Try the “Show breakdown” option. If nothing appears, Relevanssi is not active. You can also try and see if the results change when you deactivate Relevanssi.

  • http://www.mikkosaari.fi/ Mikko Saari

    Could be. The function you have above is correct and should sort the results by type and if it doesn’t, something else is messing up the order.

  • Dean Bolton

    This is just what I needed. Thank you Mikko!

    I basically wanted to separate posts and pages in the search results. Below is my final result. Note that $types[‘page’] is singular.

    *** functions.php ***

    function separate_result_types($hits) {
    $types = array();

    // split the post types in array $types
    if (!empty($hits)) {
    foreach ($hits[0] as $hit) {
    if (!is_array($types[$hit->post_type])) $types[$hit->post_type] = array();
    array_push($types[$hit->post_type], $hit);
    }
    }

    // merge back to $hits in the desired order
    if (!is_array($types[‘post’])) $types[‘post’] = array();
    if (!is_array($types[‘page’])) $types[‘page’] = array();
    $hits[0] = array_merge($types[‘page’], $types[‘post’]);
    return $hits;
    }
    add_filter(‘relevanssi_hits_filter’, ‘separate_result_types’);

    • Christoph

      That’s what i needed, thanks! How would i wrap a div around the output for each post type? Thanks for any help!

      • http://www.mikkosaari.fi/ Mikko Saari

        On the search results template, check for $post->post_type and when it changes, adjust the divs.

        • http://intelliweb.net/ Intelliweb

          Could you elaborate on how this might be accomplished? I would like to add a heading in for each post type but am struggling to get it working.

  • Mehdi

    Hi, i have this solution, much shorter !

    function my_compare_type($a, $b)
    {
    return strnatcmp($a->post_type, $b->post_type);
    }

    function my_search_orderby( $search )
    {
    $searchlist=$search[0];
    usort($searchlist, ‘my_compare_type’);
    return array($searchlist);
    }

    add_filter(‘relevanssi_hits_filter’, ‘my_search_orderby’ );

    • http://www.mikkosaari.fi/ Mikko Saari

      Nice, if alphabetical order is fine (instead of arbitrary order), then that sure is much shorter solution. Thanks!

  • http://sge.lclark.edu Jim Proctor

    Greetings! I am looking for a way to search by custom post type, and as a preliminary I added Dean’s code posted above to wp-includes > functions.php, but my site barfed (failed to load) so I removed it. Ideas?

    As noted above, what I’d like is not simply to sort results by post type, but to search by post type, e.g. as suggested in

    http://www.wpbeginner.com/wp-tutorials/how-to-create-advanced-search-form-in-wordpress-for-custom-post-types/

    This particular code does not seem to work with Relavanssi, however. And ideally, the user would check boxes for each desired post type (default = all checked) in the search widget rather than modifying search results.

    Would sure appreciate insights. We are running Relevanssi Premium v.1.8.2.1 and WP v.3.4.1, btw.

    Regards,

    Jim P.

    • http://www.mikkosaari.fi/ Mikko Saari

      In order to make that work for Relevanssi, you are better off with “post_types”, instead of “post_type”. That’s better.

      You can list several post types, you just need to list them as a comma-separated list. I’m not sure what that kind of form does – maybe it works, but if it doesn’t, you’ll have to modify the form contents to a comma-separated list. That’s easy with the “relevanssi_modify_wp_query” filter, which lets you modify what’s in the $wp_query->query_vars[] array before Relevanssi sees it.

  • Max Hodges

    >I haven’t tested this code,

    why not? if you’re going to write developer articles for this product you shouldn’t leave testing and fixing example code as an exercise for the reader.

    • http://www.mikkosaari.fi/ Mikko Saari

      Because this is not complete code that you could use anyway, you’ll have to customize it a lot in any case. To test that the code works, I’d have to make it more specific to my test blog, which would make it less useful as an example.

      So, that is the basic idea and that’s how it works, but it’s not something you can slap on functions.php and have it work out of the box.

  • Max Hodges

    Maybe useful: here’s my relevanssi_hits_filter

    can sort (asc and desc) by
    -a meta_value (called ‘_likes’ in my case)
    -wordpress total_comments count

    http://pastebin.com/ZiMzMw4F

  • Scott Orchard

    I noticed a bug of some kind, the plugin doesn’t seem to be searching all the custom post types I’m using, even though they’re not excluded from search and active on the settings page.

    I’m using the following hits filter here:
    http://thinkdev.thinkwellgroup.com/?s=harry+potter&submit=Search


    add_filter('relevanssi_hits_filter', 'separate_result_types');
    function separate_result_types($hits) {
    $types = array();

    // Split the post types in array $types
    if (!empty($hits)) {
    foreach ($hits[0] as $hit) {
    if (!is_array($types[$hit->post_type])) $types[$hit->post_type] = array();
    array_push($types[$hit->post_type], $hit);
    }
    }

    // Merge back to $hits in the desired order
    if (!is_array($types['projects'])) $types['projects'] = array();
    if (!is_array($types['news'])) $types['news'] = array();
    if (!is_array($types['thinkwellians'])) $types['thinkwellians'] = array();
    if (!is_array($types['post'])) $types['post'] = array();
    if (!is_array($types['page'])) $types['page'] = array();

    $hits[0] = array_merge($types['projects'], $types['news'], $types['thinkwellians'], $types['post'], $types['page']);
    return $hits;
    }

    Thinkwellians, which are basically team members don’t show up on the search page.

    On the old development version of the site here:
    http://think.scottorchard.com/?s=harry+potter&submit=Search

    The following code allows all custom post types to show up on the search page:


    function filter_search($query) {
    if ($query->is_search) {
    $query->set('post_type', array('post', 'page', 'projects', 'news', 'thinkwellians'));
    };
    return $query;
    };
    add_filter('pre_get_posts', 'filter_search');

    I’m using 1.10.4 on the site. Also if I add the simple filter_search function to the site, Relevanssi correctly shows all custom post types.

    I’m OK with including the extra code on the client’s site, just wanted you to be aware.

  • http://www.mikkosaari.fi/ Mikko Saari

    For quicker response, please use the contact form on the “Support” page.

    Can the Thinkwellians be found with any query whatsoever? Are they being indexed at all? That is, is the problem in finding them in indexing or in searching?

    • http://scottorchard.com/ Scott Orchard

      As far as I can tell Thinkwellians is not showing up in searches. When I added the code to include them in the search query as a filter, they show up correctly.

      • http://www.mikkosaari.fi/ Mikko Saari

        Can you give me access to your dev site (enough to let me modify files), so I could take a look at it? Email me at mikko @ mikkosaari.fi.

        If they are being indexed and just cannot be found, then it sounds to me there’s something blocking them from the search results. Do you have any code to that effect, perhaps restricting the post types in use?

        If you do a var_dump($wp_query->query_vars); on the search results page, what do you get? Is there a clue, for example in the $wp_query->query_vars[‘post_type’] variable?

      • http://www.mikkosaari.fi/ Mikko Saari

        Scott, at least on the dev site your SearchFilter() function is blocking the Thinkwellians from the search. Disable it, and they appear. You don’t need the SearchFilter() with Relevanssi, as Relevanssi handles the post types.

        • http://scottorchard.com/ Scott Orchard

          Thank you, I thought I had disabled that before I sent you the link. This wasn’t working at all yesterday or the day before and now it’s working fine. I didn’t add the SearchFilter() until yesterday.
          Thank you again for your help!