Wordpress - Query to sort a list by meta key first (if it exists), and show remaining posts without meta key ordered by title
Thank you everyone for your help!
In the end the query below got me the results I desired - which was to show and sort the posts by a custom field of "publication_date" first - sorting by the date, and if there were multiple of the same date (say, 4 marked June 2013), it would sort those by title. Then, after it runs through all the posts that have the Publication Date filled in it will loop through again the remaining posts, alphabetically by title.
This gets me the results set in the same query, and keeps my pagination:
$term = get_queried_object();
the_post();
$wp_query = new WP_Query( array(
'post_type' => 'resource',
'tax_query' => array(
array(
'taxonomy' => 'resource_types',
'field' => 'slug',
'terms' => $term->name,
)),
'meta_query' => array(
'relation' => 'OR',
array( //check to see if date has been filled out
'key' => 'publication_date',
'compare' => '=',
'value' => date('Y-m-d')
),
array( //if no date has been added show these posts too
'key' => 'publication_date',
'value' => date('Y-m-d'),
'compare' => 'NOT EXISTS'
)
),
'meta_key' => 'publication_date',
'orderby' => 'meta_value title',
'order' => 'ASC',
'paged' => $paged,
'posts_per_page' => '10',
));
Few years later, the code posted by CSSGirl wasn't working for me because there were some posts that didn't have the meta key or the meta key was empty so this is what I had to do to have all the posts ordered by date and show the ones with a meta key value display first:
$args = array(
'post_type' => $type,
'post_status' => 'publish',
'nopaging' => TRUE,
'meta_query' => array(
'relation' => 'OR',
array(
'key' => $meta_key,
'compare' => 'NOT EXISTS',
),
array(
'relation' => 'OR',
array(
'key' => $meta_key,
'value' => 'on',
),
array(
'key' => $meta_key,
'value' => 'on',
'compare' => '!=',
),
),
),
'orderby' => array( 'meta_value' => 'DESC', 'date' => 'DESC' ),
);
I think you'd need to do 2 separate loops. You can capture all the posts found in the first loop and exclude them from the secondary loop easily enough:
$found_posts = array();
while($loop->have_posts()): $loop->the_post();
// loop stuff
$found_posts[] = get_the_id();
endwhile;
wp_reset_query();
$args = array(
// other args
'post__not_in' => $found_posts,
);
Then run your second loop.