Получить пост с несколькими мета-ключами и значениями

2 сент. 2016 г., 09:12:26
Просмотры: 38.9K
Голосов: 11

Я пытаюсь получить пост на основе следующих мета-ключей.

  • post_code со значением 432C
  • location со значением XYZ Оба принадлежат произвольному типу записи (CPT). Я пытаюсь получить пост с обоими этими мета-значениями.

Мне нужно не условие OR (ИЛИ), а условие AND (И). Я пробовал несколько объектов WP_Query и до сих пор не нашел решения после нескольких часов поисков.

2
Комментарии

Какой именно WP_Query код вы пробовали?

RRikesh RRikesh
2 сент. 2016 г. 09:26:08

$args = array( 'post_type' => 'courses', 'meta_query' => array( array( 'key' => 'post_code', 'value' => '432C', ), array( 'key' => 'location', 'value' => 'XYZ', ), ), ); $query = new WP_Query( $args );

Sheraz Ahmed Sheraz Ahmed
2 сент. 2016 г. 09:34:15
Все ответы на вопрос 6
3
17

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

$args = array(
    'post_type'  => 'wpse_cpt',
    'meta_query' => array(
        array(
            'key'     => 'post_code',
            'value'   => '432C',
        ),
        array(
            'key'     => 'location',
            'value'   => 'XYZ',
        ),
    ),
);
$query = new WP_Query( $args );
2 сент. 2016 г. 09:31:02
Комментарии

Я пробовал это, но получаю слишком много информации. Я пытаюсь получить результаты используя $wpdb.. Это возможно?

Sheraz Ahmed Sheraz Ahmed
2 сент. 2016 г. 09:36:11

Это вернёт результаты, которые вы описали в своём вопросе. Так что вам либо нужно сделать более специфичный запрос, либо убедиться, что ваши записи имеют точные метаданные.

Jeremy Ross Jeremy Ross
2 сент. 2016 г. 16:42:10

И да, вы можете использовать $wpdb, но вы получите те же результаты, если используете те же критерии. WP_Query проще и безопаснее.

Jeremy Ross Jeremy Ross
2 сент. 2016 г. 16:43:24
0
$args = array(
    'post_type'  => 'wpse_cpt',
    'meta_query' => array(
        'relation' => 'AND' //**** Используйте AND или OR в зависимости от требуемого условия WHERE
        array(
            'key'     => 'post_code',
            'value'   => '432C',
        ),
        array(
            'key'     => 'location',
            'value'   => 'XYZ',
        ),
    ),
);
$query = new WP_Query( $args );
2 сент. 2016 г. 16:23:26
4

Правка снова: Ах, я не ответил на вопрос. Вам нужно выбрать a.*, чтобы получить все столбцы записей с соответствующими значениями ключей, вместо выбора c.meta_value.

Следующий SQL-запрос/$wpdb выберет все значения meta_value для записей с типом $postType и ключом метаданных $metaKey. Таким образом, будут выбраны все различные значения для заданного мета-ключа (через '$metaKey'). Таблица term_relationships — это вспомогательная таблица WordPress для связей между таблицами. wp_posts — это таблица 'записей' WordPress, а wp_postmeta — таблица 'метаданных записей' WordPress. (Примечание: если вы используете пользовательские таблицы, имена этих таблиц будут отличаться.)

~ Отредактировано, добавлены 'поясняющие' заметки по просьбе @MikeNGarrett

/* $wpdb — это глобальная переменная, предоставляемая 'движком' WordPress
** для выполнения запросов к таблицам базы данных WordPress. 
*/
global $wpdb; 
$postType = 'mycustomposttype';
$metaKey = 'mymetakey';
$query = "
    SELECT c.meta_value 
    FROM wp_posts a 
    LEFT JOIN wp_term_relationships b 
        ON (a.ID = b.object_id) 
    LEFT JOIN wp_postmeta c 
        ON (a.ID = c.post_id) 
    WHERE a.post_type = %s AND c.meta_key = %s";

$metaValues = $wpdb->prepare($query, [$postType, $metaKey]);
$metaValues = $wpdb->get_results($metaValues);

Примечания: Я просто повторно использую переменную $metaValues. Нет другой причины записывать результаты prepare() обратно в переменную $metaValues. Однако вам нужно передать $metaValues в get_results().

8 мая 2019 г. 16:56:16
Комментарии

Привет, Эрик! Не мог бы ты предоставить немного больше контекста? Особенно ответив на вопросы "Что делает этот код?" и "Почему это лучший способ достичь цели?"

MikeNGarrett MikeNGarrett
8 мая 2019 г. 17:56:07

@MikeNGarrett, добавил пояснения. По сути, вы можете возвращать любые значения из любой из этих трех таблиц с помощью запроса. Вам нужно лишь изменить таблицу, из которой вы запрашиваете/сравниваете данные, используя a, b, c и точку перед именем столбца.

Eric Shoberg Eric Shoberg
8 мая 2019 г. 22:47:29

@MikeGarrett, на вопрос "Почему это лучший способ достичь цели?". Честно говоря, я не уверен, что это 'лучший' способ. Однако он работает. Мне было бы интересно, если бы кто-то нашел более эффективный/быстрый вариант. На данный момент, исходя из моих текущих знаний и возможностей, я считаю этот метод наименее ресурсоемким.

Eric Shoberg Eric Shoberg
8 мая 2019 г. 23:06:46

Спасибо! Выглядит отлично

MikeNGarrett MikeNGarrett
9 мая 2019 г. 18:49:27
0

РЕШЕНИЕ

Приведенное ниже решение сработало, однако мне хотелось бы понять, как именно оно работает.

Вот как это работает:

SELECT * FROM wp_posts p, wp_postmeta m1, wp_postmeta m2
    WHERE p.ID = m1.post_id and p.ID = m2.post_id
    AND m1.meta_key = 'key1' AND m1.meta_value = 'value1'
    AND m2.meta_key = 'key2' AND m2.meta_value =  'value2'
    AND p.post_type = 'cpt' AND p.post_status = 'published'
15 июл. 2017 г. 11:24:51
0

Я попробовал использовать решение с WP_Query, предложенное выше, но получил пустой результат. Вариант, предложенный Sheraz Ahmed, работает отлично. Вот мой собственный вариант, если он кому-то пригодится:

//база данных
wp_posts
+---------+--------------------+--------------+
|  ID     | post_title         | post_type    |
+---------+--------------------+--------------+
| 8567    | Введение в MySQL   | talk         |
+---------+--------------------+--------------+
| 8590    | Введение в PHP     | talk         |
+---------+--------------------+--------------+

wp_postmeta
+---------------+------------+----------------+
|  post_id      | meta_key   | meta_value     |
+---------------+------------+----------------+
| 8567          | speaker    | Джон Доу       |
+---------------+------------+----------------+
| 8567          | year_of    | 2021           |
+---------------+------------+----------------+
| 8590          | speaker    | Джон Доу       |
+---------------+------------+----------------+
| 8590          | year_of    | 2021           |
+---------------+------------+----------------+


//поиск по спикеру и году
$speaker = "Джон Доу";
$year_of = "2021";

$talks = $wpdb->get_results(  
     $wpdb->prepare( 
         'SELECT post_title, meta_value AS speaker 
         FROM '.$wpdb->prefix.'posts AS pt, '.$wpdb->prefix.'postmeta AS pm 
         WHERE post_type = %s AND pm.post_id = pt.id AND ( meta_key = %s AND meta_value = %s ) 
         AND post_id IN ( SELECT post_id FROM nm_postmeta WHERE meta_key = %s AND meta_value = %s )',
         array( 'talk', 
                'speaker', 
                $speaker, 
                'year_of', 
                $year_of )
    )
);
                
foreach ( $talks as $talk ) {
    echo "<p>".$talk->speaker.': '.$talk->post_title."</p>";
}

Джон Доу: Введение в MySQL

Джон Доу: Введение в PHP

12 сент. 2021 г. 22:48:35
3
-1

Попробовал следующие параметры объекта

array(
            'key' => 'post_code',
            'value' =>'432C',
            'compare' => '='
        ),
        array(
            'relation' =>'AND',
             array(

            'key' => 'location',
            'value' => 'XYZ',
             'compare' => '=',

          ),
        )
2 сент. 2016 г. 09:28:41
Комментарии

Было бы здорово, если бы вы объяснили код и то, как он решает проблему.

bravokeyl bravokeyl
2 сент. 2016 г. 09:33:18

Я уже объяснил это, пожалуйста, попробуйте использовать эти параметры, с их помощью проблема решится автоматически.

Manthan Dave Manthan Dave
2 сент. 2016 г. 09:34:57

Вам следует объяснить, почему этот код будет работать.

RRikesh RRikesh
2 сент. 2016 г. 09:37:50