How to put posts with some taxonomy on top of others in `pre_get_posts`

You could try modifying the tax query to use the relation parameter and add a second clause that matches any post that does not have the matched string value in the meta array.

See Taxonomy Parameters.

EDIT: Thank you for pointing that out, Tom. You’re correct, I’ve updated to reflect.

function group_matched_posts_at_top( $query ) {

// Check if this is the main query and not in the admin area
if( !$query->is_main_query() || is_admin() )
    return;

// Define the tax query with two clauses (matched and not matched)
$taxquery = array(
    'relation' => 'OR', // Set the relation to OR to include posts that match either clause
    array(
        'taxonomy' => 'mymeta',
        'field' => 'slug',
        'terms' => 'matchedstring',
        'operator' => 'IN' // use the operator parameter to specify the comparison operator
    ),
    array(
        'taxonomy' => 'mymeta',
        'field' => 'slug',
        'terms' => 'matchedstring',
        'operator' => 'NOT IN' // use the operator parameter to specify the comparison operator
    )
);

// Set the tax query and meta key parameters for the query
$query->set( 'tax_query', $taxquery );
$query->set( 'meta_key', 'mymeta' );

// Set the orderby parameter to sort by the value of the "mymeta" field in descending order (so that matched posts appear first), and then by date in descending order (so that the most recent posts appear first within each group).
$query->set( 'orderby', array( 'meta_value' => 'DESC', 'date' => 'DESC' ) );


add_action( 'pre_get_posts', 'group_matched_posts_at_top' );

The main changes are as follows:

  • I’ve used the “taxonomy” parameter to specify the taxonomy to query.

  • I’ve used the “operator” parameter instead of “compare” to specify the comparison operator (IN or NOT IN).

  • I’ve added the “field” parameter with a value of “slug” to specify that we’re comparing the term slug (i.e., the term’s “mymeta” field).

These changes should make the query work with a term/taxonomy meta field, which was not supported by my earlier solution.