Wordpress - Nested meta_query with multiple relation keys
The question was for Wordpress 3.0, but just in case someone has the same question for a more recent version, from Wordpress Codex:
"Starting with version 4.1, meta_query clauses can be nested in order to construct complex queries."
https://developer.wordpress.org/reference/classes/wp_query/#custom-field-post-meta-parameters So, that query should work on the current Wordpress version.
That seems to be impossible. Please someone correct me if I'm wrong.
The meta_query
parameter will actually be transformed into a WP_Meta_Query
object, and the relation
verification won't go deeper in wp-includes/meta.php
, and occurs just once in the top level:
if ( isset( $meta_query['relation'] ) && strtoupper( $meta_query['relation'] ) == 'OR' ) {
$this->relation = 'OR';
} else {
$this->relation = 'AND';
}
A possible solution for this is to build your own JOIN for this query.
$query = new WP_Query( array(
...
'my_meta_query' => true,
'suppress_filters' => false
) );
add_filter( 'posts_join', 'my_meta_query_posts_join', 10, 2 );
function my_meta_query_posts_join( $join, $query ) {
if ( empty( $query->query_vars['my_meta_query'] ) )
return $join;
global $wpdb;
$new_join = "
INNER JOIN {$wpdb->postmeta} pm1 ON 1=1
AND pm1.post_id = {$wpdb->posts}.ID
AND pm1.meta_key = '_some_meta_key'
AND pm1.meta_value = 'some_value'
";
return $join . ' ' . $new_join;
}
And if you need further verifications and rules, you can also use the posts_where
filter.
Meanwhile this is possible, see documentation with example and explanation:
https://codex.wordpress.org/Class_Reference/WP_Query#Custom_Field_Parameters
and another example https://wordpress.org/support/topic/wp_query-with-multiple-meta_query/#post-9410992
'meta_query' => array(
'relation' => 'OR',
array(
'relation' => 'AND',
array(
'key' => '_price',
'value' => 1,
'compare' => '>=',
'type' => 'DECIMAL',
),
array(
'key' => '_price',
'value' => 3000,
'compare' => '<=',
'type' => 'DECIMAL',
),
),
array(
'relation' => 'AND',
array(
'key' => '_price',
'value' => 3001,
'compare' => '>=',
'type' => 'DECIMAL',
),
array(
'key' => '_price',
'value' => 6000, //fixed <= to =>
'compare' => '<=',
'type' => 'DECIMAL',
),
)
),