Reading through the order & orderby documentation, it’s not clear to me whether there is any support to order based on multiple meta_key
values.
Obviously, using meta_query
I can return posts based on multiple key-value pairs, but I want to be able to control the order that these results are returned based on multiple meta_keys
.
For example, I have pages that have multiple categories and each category has a numerical rank. If a user is searching for pages that are in one of three different categories, I can return all the necessary posts with the following:
$query = array(
'order' => 'DESC',
'orderby' => 'meta_value_num',
'meta_query' => array(
'relation' => 'OR',
array( 'key' => 'cat1', 'type' => 'numeric' ),
array( 'key' => 'cat2', 'type' => 'numeric' ),
array( 'key' => 'cat3', 'type' => 'numeric' )
);
);
However, once those are returned, I would like them to be ordered based on the highest numerical value across any one of the categories that results were returned on. In other words, posts with a 9
value in cat1
would appear around the same order as posts with a 9
value in cat3
.
Looking at this answer it seems that a meta_key
isn’t even necessary for 'orderby' => 'meta_value_num'
, but that doesn’t match the documentation for meta_value
, which is far more documented than meta_value_num
… Any clarification would be useful. Thanks!
You might want to check out the query improvements in WP 4.2 for âorderbyâ and âmeta_queryâ. Details are on https://make.wordpress.org/core/2015/03/30/query-improvements-in-wp-4-2-orderby-and-meta_query.
Try to name your meta_query clauses, then order by them.
Following code is untested:
If you look at the get_posts method of WP_Query it’s easy to debug the sql by outputting the variable passed to the
posts_request
filter.The result should look something like this:
The query might look correct at first, but it’s not. It uses the
meta_value
from the first row in the inner join for theORDER BY
clause. In this case that is'cat1'
.To change this behaviour we can use the
posts_orderby
hook to alter theORDER BY
statement and use theMAX
mysql function so that it will use the highest value of all the meta_values instead of just the first row.