So after @Nicolai found that blurb in the WP source confirming that I can’t use multiple parameters in the orderby
if I am ordering by relevance
I had to go a different route. However, this route only works if I don’t care for pagination. There probably is a way to put it back, but I’m working on a different solution now and I no longer need to stay on the code I have in my question.
So I kept the function to alter the query on pre_get_posts
and removed anything regarding post meta/meta queries:
function modify_search_results_order( $query ) {
if ( $query->is_main_query() && is_search() && ! is_admin() ) {
$get_expired_events = Event_Helpers::get_expired_event_ids();
$query->query_vars['posts_per_page'] = - 1;
$query->query_vars['order'] = 'DESC';
$query->query_vars['is_search'] = true;
$query->query_vars['post__not_in'] = $get_expired_events;
$query->query_vars['orderby'] = 'relevance';
$query->query_vars['post_status'] = 'publish';
}
return $query;
}
Then in my search template, I call a function that alters the query after pre_get_posts
to look for the priority posts, unset them from the main query, and place them back on top:
//in search.php
$wp_query->posts = Search_Modify_Query::rearrange_search_query_for_priority_relevance( $wp_query->posts );
//in PHP Class
public static function rearrange_search_query_for_priority_relevance( $query ) {
//get prioritized ids
$get_prioritized = self::get_priority_search_post_ids();
$get_results_ids = [];
if ( ! is_array( $get_prioritized ) || ! $get_prioritized ) {
return $query;
}
//save all ids from current search results query
foreach ( $query as $key => $post ) {
$get_results_ids[ $key ] = $post->ID;
}
if ( ! $get_results_ids ) {
return $query;
}
//check if there are priority posts in results
if ( array_intersect( $get_prioritized, $get_results_ids ) ) {
$priority_matches = array_intersect( $get_results_ids, $get_prioritized );
$priority_query = false;
//if there are priority matches, pluck them out to put them on top
if ( $priority_matches ) {
foreach ( $priority_matches as $key => $priority_match ) {
//save these into new array first
$priority_query[ $key ] = $query[ $key ];
//then unset them from main query
unset( $query[ $key ] );
}
if ( $priority_query && is_array( $priority_query ) ) {
//then re-add them on top of main query
return array_merge( $priority_query, $query );
} else {
return $query;
}
}
}
return $query;
}
This works fine but because I needed to have ALL the results to do the comparison with my “priority post” ids vs the results ids, I had to set posts_per_page
to -1. So while it works, unless I find a way to put back pagination or write something custom, the search results will give me all of the results on search.php whether it’s 5 or 500. Still, I’m placing this code here in case it helps someone else in the long run.
For my case though, I’ve decided to do two separate queries and I confirmed we don’t care about having duplicates. So I’ll query just the priority posts matching the search term above the main search results query.