Using meta_query, how can i filter by a custom field and order by another one?

This seems to be a bug in WordPress. WordPress actually modifies the meta_query if you specify orderby and meta_key as query vars. Normally this modification adds the new meta_key as the first array in meta_query array and hence the orderby is applied to the first meta key specified in meta_query.

But when you modify orderby, meta_key and meta_value query_vars in pre_get_posts filter, due to the (it seems to me) bug in WordPress, it add the new array in existing meta query but the new array is not inserted as first array, it gets appended to the existing meta_query. And orderby always gets applied to the first meta_key in meta_query.

So as a workaround until the bug gets fixed you can specify the meta_key again in the meta_query as the first array, as in the following example:

add_filter( 'pre_get_posts', 'my_get_posts' );
function my_get_posts( $query ) {
if ( is_home() ) {
  $query->set( 'post_type', 'event' );
  $query->set( 'meta_key', '_start_date' );
  $query->set( 'orderby', 'meta_value_num' );
  $query->set( 'order', 'ASC' );
  $query->set( 'meta_query', array(
        array(
              'key' => '_start_date'
        ),
        array(
              'key' => '_end_date',
              'value' => time(),
              'compare' => '>=',
              'type' => 'numeric'
        )
  ));
  }
  return $query;
}

Leave a Comment