最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

wp query - Order Search Results Page by meta_value If no Value Return Remaining Results

programmeradmin1浏览0评论

I am trying to order the search results page of my site by a specific meta_key. The catch is I need to return all results even when there's no value in the meta_key

The posts are custom post types that are events.

The results are already being sorted to a specific set of custom post types using this:

function SearchFilter($query) {
    if (!is_admin() && $query->is_search() ) {
        $query->set('post_type', array( 'event', 'university', 'organization'));
    }
    return $query;
}

add_action('pre_get_posts','SearchFilter', 9999);

There is some other filtering going on in order to filter out events that have passed or those that are set to a custom field of "off". I can post the code used to do that as well, if needed.

Essentially, I can use

$query->set('meta_key', 'wpcf-start-date');
$query->set('orderby', array('meta_value' => 'ASC'));

to order the events by event date. This works well, but won't return any results that have '' (what I assume is null) in the wpcf-start-date field.

I have tried using the answer in this question:

Order posts by custom field and if custom field is empty return remaining posts

But either I don't understand what's going on well enough to customize it for my use, or it just doesn't work for me.

I can provide any additional information upon request.

Any help would be greatly appreciated!


UPDATE:

I was looking again at the other Stack question I refer to. I have this that is working:

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

    $query->set( 'meta_key', 'wpcf-start-date' );
    $query->set( 'orderby', 'meta_value');
    $query->set( 'order', 'DESC');

    add_filter( 'get_meta_sql', 'filterResults' );
}
add_action( 'pre_get_posts', 'sortResults' );

function filterResults( $clauses ) {
    remove_filter( 'get_meta_sql', 'filterResults' );

    // Change the inner join to a left join,
    // and change the where so it is applied to the join, not the results of the query.
    $clauses['join']  = str_replace( 'INNER JOIN', 'LEFT JOIN', $clauses['join'] ) . $clauses['where'];
    $clauses['where'] = '';

    return $clauses;
}

But like the other question, this puts the events without dates at the top and the events with dates at the bottom. The other question suggests using two loops. I can't seem to get two loops working on my site. The search results page is highly customized.

I am trying to order the search results page of my site by a specific meta_key. The catch is I need to return all results even when there's no value in the meta_key

The posts are custom post types that are events.

The results are already being sorted to a specific set of custom post types using this:

function SearchFilter($query) {
    if (!is_admin() && $query->is_search() ) {
        $query->set('post_type', array( 'event', 'university', 'organization'));
    }
    return $query;
}

add_action('pre_get_posts','SearchFilter', 9999);

There is some other filtering going on in order to filter out events that have passed or those that are set to a custom field of "off". I can post the code used to do that as well, if needed.

Essentially, I can use

$query->set('meta_key', 'wpcf-start-date');
$query->set('orderby', array('meta_value' => 'ASC'));

to order the events by event date. This works well, but won't return any results that have '' (what I assume is null) in the wpcf-start-date field.

I have tried using the answer in this question:

Order posts by custom field and if custom field is empty return remaining posts

But either I don't understand what's going on well enough to customize it for my use, or it just doesn't work for me.

I can provide any additional information upon request.

Any help would be greatly appreciated!


UPDATE:

I was looking again at the other Stack question I refer to. I have this that is working:

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

    $query->set( 'meta_key', 'wpcf-start-date' );
    $query->set( 'orderby', 'meta_value');
    $query->set( 'order', 'DESC');

    add_filter( 'get_meta_sql', 'filterResults' );
}
add_action( 'pre_get_posts', 'sortResults' );

function filterResults( $clauses ) {
    remove_filter( 'get_meta_sql', 'filterResults' );

    // Change the inner join to a left join,
    // and change the where so it is applied to the join, not the results of the query.
    $clauses['join']  = str_replace( 'INNER JOIN', 'LEFT JOIN', $clauses['join'] ) . $clauses['where'];
    $clauses['where'] = '';

    return $clauses;
}

But like the other question, this puts the events without dates at the top and the events with dates at the bottom. The other question suggests using two loops. I can't seem to get two loops working on my site. The search results page is highly customized.

Share Improve this question edited May 4, 2019 at 6:16 LoicTheAztec 3,39117 silver badges24 bronze badges asked Nov 7, 2016 at 16:50 Nick TaylorNick Taylor 1379 bronze badges 3
  • Just an idea, if you set the date of events without dates to something far far back, and then wherever you display the actual date in the code you check whether the event's date is this date, then hide it, you can avoid the whole super complicated coding. – Emil Commented Nov 25, 2016 at 11:33
  • 1 Hmm, excellent idea! That actually might work! I will have to experiment with it and see. I'll write back with the results! – Nick Taylor Commented Nov 29, 2016 at 15:44
  • I do believe this would work. But the issue is we have 100's of event pages that would need to be changed. I think we will start doing this moving forward but it will take some time for this method to play out. – Nick Taylor Commented Jan 9, 2017 at 15:10
Add a comment  | 

1 Answer 1

Reset to default 2

You can accomplish this with multiple meta queries.

$query->set( 'meta_query', [
  'relation' => 'OR',
  'wpcf-start-date' => [
    'key' => 'wpcf-start-date',
    'compare' => 'EXISTS',
  ],
 'no-start-date' => [
    'key' => 'wpcf-start-date',
    'compare' => 'NOT EXISTS'
  ],
] );
$query->set( 'orderby', 'wpcf-start-date' );
$query->set( 'order', 'ASC' );

This will tell WP to create a query that will match every post, whether or not is has the key, setting it up as a LEFT JOIN, and then sorts on the value of that key, including those with NULL values.

发布评论

评论列表(0)

  1. 暂无评论