hooks - Re-order search results with posts_orderby filter and post meta value

admin2025-06-03  2

I'd like to re-order the search results based on post meta and date . The post meta key is _prioritize_s and the value isn't important. So in a "normal" meta query, I'd just write the compare parameters to check EXISTS/NOT EXISTS. While I have experience with meta queries, I've never had to re-order search results until now, so I'd appreciate any help.

This is how I'd like to re-order the search results:

  • Check if posts with post meta _prioritize_s exists within search results
  • If they do, put those on top of the results in date order (from recent to oldest). After these posts are shown, show the remaining search results underneath in their default order.
  • If there are no posts with this post meta among the search results, order by whatever is default

It looks like I have to use 2 filters, one to join and one to set the order. It seems like it's kind of working, but the order isn't right? Thoughts?

Updated Code from this sample

    add_filter( 'posts_join', 'modify_search_results_join' );
    add_filter( 'posts_orderby', 'modify_search_results_order', 10, 2 );


    function modify_search_results_join( $orderby ) {
        global $wpdb;

        if ( ! is_admin() && is_search() ) {
            $orderby .= "LEFT JOIN (
            SELECT *
            FROM $wpdb->postmeta
            WHERE meta_key =  '_prioritize_s' ) AS postmeta ON $wpdb->posts.ID = postmeta.post_id";

            return $orderby;
        }

        return $orderby;
    }

    function modify_search_results_order( $orderby, $query ) {
        global $wpdb;
        //how do I order the results by _prioritize_s set to 'yes'?
        $orderby = "postmeta.meta_value+'' DESC";

        return $orderby;
    }

I'd like to re-order the search results based on post meta and date . The post meta key is _prioritize_s and the value isn't important. So in a "normal" meta query, I'd just write the compare parameters to check EXISTS/NOT EXISTS. While I have experience with meta queries, I've never had to re-order search results until now, so I'd appreciate any help.

This is how I'd like to re-order the search results:

  • Check if posts with post meta _prioritize_s exists within search results
  • If they do, put those on top of the results in date order (from recent to oldest). After these posts are shown, show the remaining search results underneath in their default order.
  • If there are no posts with this post meta among the search results, order by whatever is default

It looks like I have to use 2 filters, one to join and one to set the order. It seems like it's kind of working, but the order isn't right? Thoughts?

Updated Code from this sample

    add_filter( 'posts_join', 'modify_search_results_join' );
    add_filter( 'posts_orderby', 'modify_search_results_order', 10, 2 );


    function modify_search_results_join( $orderby ) {
        global $wpdb;

        if ( ! is_admin() && is_search() ) {
            $orderby .= "LEFT JOIN (
            SELECT *
            FROM $wpdb->postmeta
            WHERE meta_key =  '_prioritize_s' ) AS postmeta ON $wpdb->posts.ID = postmeta.post_id";

            return $orderby;
        }

        return $orderby;
    }

    function modify_search_results_order( $orderby, $query ) {
        global $wpdb;
        //how do I order the results by _prioritize_s set to 'yes'?
        $orderby = "postmeta.meta_value+'' DESC";

        return $orderby;
    }
Share Improve this question edited Feb 13, 2019 at 16:07 RachieVee asked Feb 11, 2019 at 21:02 RachieVeeRachieVee 8303 gold badges9 silver badges25 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 0

Probably it's just a JOIN problem: the SELECT query has no postmeta fields to order by. Try to implement the second answer from this question.

That is, paste this code in your file.

function custom_posts_join($join){
     global $wpdb;

     $join .= " LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id ";

     return $join;
}
add_filter( 'posts_join' , 'custom_posts_join');

After much googling and brainstorming with someone else, it turns out that I may have been overcomplicating this. I was under the impression that I could not use the pre_get_posts hook when it came to search results. Turns out, I can. I used a meta query to check whether the post meta exists or doesn't exist. I also included checks to prevent the function from running if it wasn't the main query, was admin or wasn't search.

Here is what's working for me:


    add_filter( 'pre_get_posts', 'modify_search_results_order', 10, 2 );


    function modify_search_results_order( $query ) {
        if ( ! $query->is_main_query() || is_admin() || ! is_search() ) {
            return $query;
        }

        $query->query_vars['order'] = 'DESC';
        $query->query_vars['orderby']    = 'meta_value date';
        $query->query_vars['meta_query'] = [
            'relation' => 'OR',
            array(
                'key'   => '_prioritize_s',
                'compare' => 'EXISTS'
            ),
            array(
                'key'     => '_prioritize_s',
                'compare' => 'NOT EXISTS'
            )
        ];

        return $query;
    }
转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1748910434a314738.html

最新回复(0)