Получить пост с несколькими мета-ключами и значениями
Я пытаюсь получить пост на основе следующих мета-ключей.
post_code
со значением432C
location
со значениемXYZ
Оба принадлежат произвольному типу записи (CPT). Я пытаюсь получить пост с обоими этими мета-значениями.
Мне нужно не условие OR (ИЛИ), а условие AND (И). Я пробовал несколько объектов WP_Query
и до сих пор не нашел решения после нескольких часов поисков.

Это должно сработать. По умолчанию используется отношение 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 );

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

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

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

Правка снова: Ах, я не ответил на вопрос. Вам нужно выбрать 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()
.

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

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

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

РЕШЕНИЕ
Приведенное ниже решение сработало, однако мне хотелось бы понять, как именно оно работает.
Вот как это работает:
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'

Я попробовал использовать решение с 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

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

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