Вложенный мета-запрос с несколькими ключами отношений


Мне любопытно, может ли Wordpress запускать вложенные meta_query, каждый из которых имеет разные ключи отношений? Начиная с Wordpress 3.0, tax_query способен выполнять эту функцию; Мне интересно, имеет ли это эквивалент с meta_query.

$results = query_posts( array(
    'post_type' => 'event_id',
    'meta_query' => array(
        'relation' => 'AND',
        array(
            'relation' => 'OR',
            array(
                'key' => 'primary_user_id',
                'value' => $user_id
            ),
            array(
                'key' => 'secondary_user_id',
                'value' => $user_id
            )
        ),
        array(
            'key' => 'date',
            'value' => array( $start_date, $end_date ),
            'type' => 'DATETIME',
            'compare' => 'BETWEEN'
        )
    )
) );

Ссылки:

Author: Community, 2012-12-05

3 answers

Вопрос был для Wordpress 3.0, но на всякий случай у кого-то есть такой же вопрос для более поздней версии, из Кодекса Wordpress:

"Начиная с версии 4.1, предложения meta_query могут быть вложенными для построения сложных запросов".

Https://developer.wordpress.org/reference/classes/wp_query/#custom-field-post-meta-parameters Таким образом, этот запрос должен работать в текущей версии Wordpress.

 23
Author: Gustavo, 2020-02-17 05:15:36

Это кажется невозможным. Пожалуйста, кто-нибудь, поправьте меня, если я ошибаюсь.

Параметр meta_query фактически будет преобразован в объект WP_Meta_Query, и проверка relation не будет углубляться в wp-includes/meta.php, и происходит только один раз на верхнем уровне:

if ( isset( $meta_query['relation'] ) && strtoupper( $meta_query['relation'] ) == 'OR' ) {
    $this->relation = 'OR';
} else {
    $this->relation = 'AND';
}

Возможным решением для этого является создание собственного соединения для этого запроса.

$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;
}

И если вам нужны дополнительные проверки и правила, вы также можете использовать фильтр posts_where.

 9
Author: vmassuchetto, 2013-01-18 13:02:31

Тем временем это возможно, см. Документацию с примером и объяснением:

Https://codex.wordpress.org/Class_Reference/WP_Query#Custom_Field_Parameters

И другой пример 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',
        ),
    )
),
 7
Author: Ramon Fincken, 2020-08-28 00:57:00