Запрос всех записей, где мета-ключ не существует
Я пытаюсь составить запрос для получения всех записей, где определенный meta_key не существует, чтобы затем создать его.
У меня возникли проблемы с поиском этих записей, так как тестируемый запрос, похоже, не работает.
Вот код, который я использую для попытки получить эти записи:
$args = array(
'posts_per_page' => 18,
'cat'=>1955,
'post_status'=>'publish',
'meta_query' => array(
array(
'key' => 'colors',
'compare' => 'NOT EXISTS'
),
));
query_posts($args);
Это не возвращает ничего, если нет записей с ключом colors, но возвращает ids записей с ключом colors, когда этот ключ присутствует (противоположное тому, что мне нужно). Я пробовал использовать EXIST, но безуспешно.
Буду признателен, если кто-то подскажет правильный способ создания нужного мне запроса.
Спасибо!
Я провел дополнительные тесты и, честно говоря, не вижу причин, почему это не должно работать (если только приведенный выше код не является фрагментом, а реальный код соответствует моим примерам ниже). Однако я обнаружил пару моментов, которые могут направить вас в правильное русло.
1) Сам по себе этот meta_query эквивалентен условию "colors IS NULL", т.е. он вернет записи, у которых этот ключ не установлен в таблице postmeta. Это показано выше, и это должно было работать.
'meta_query' => array(
array(
'key' => 'colors',
'compare' => 'NOT EXISTS' // это должно работать...
),
)
2) До WordPress 3.9 установка индекса 'relation' в значение 'OR' меняет это условие. Оно возвращает противоположный результат. Не спрашивайте меня почему. Это особенно важно при выполнении нескольких meta-запросов. Это означает, что изначально невозможно сделать запрос для записей, у которых ключ 'colors' установлен в значение 'blue' (или любое другое) или не установлен вообще. Запрос ниже проигнорирует первое условие и вернет только те записи, которые соответствуют второму условию.
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'colors',
'compare' => 'NOT EXISTS' // не работает
),
array(
'key' => 'colors',
'value' => 'blue'
)
)
3) Однако мы можем обмануть WordPress, заставив его использовать первое условие, если мы установим 'value'. Это значение не должно быть релевантным (оно игнорируется, насколько я знаю), но оно должно быть установлено, чтобы условие NOT EXISTS имело какой-либо эффект.
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'colors',
'compare' => 'NOT EXISTS', // работает!
'value' => '' // Это игнорируется, но необходимо...
),
array(
'key' => 'colors',
'value' => 'blue'
)
)
Это было актуально до WordPress 3.9. Если вы все еще используете более старую версию, это рабочее решение.
Спасибо! И извините за задержку. В итоге я использовал запрос, но в ближайшие часы протестирую ваше решение, чтобы можно было вернуться к нему. Если это сработает, мы сможем помочь и другим. Дам знать, как только проверю. Ещё раз спасибо!
JordanBel
Хорошо написано и подтверждено, что добавление пустого значения возвращает ожидаемые результаты. Скорее всего, это непреднамеренно, возможно стоит проверить trac.wordpress.org на наличие уже созданного тикета. Если его нет, то ошибка воспроизводима.
Taylor Dewey
Спасибо за отличное объяснение и решение, как обойти WP :) Потребовалось время, чтобы добраться сюда - теперь хочется поставить плюс хотя бы 10 раз (если бы только можно было ;))
lorem monkey
Если я использую сравнение EXISTS, к сожалению, значение не игнорируется в новых версиях WP (проверено в 4.2.2)
Igor Jerosimić
Обратите внимание на orderby meta_key, который также может быть в вашем запросе! Wordpress жестко прописывает WHERE meta_key = value для сортировки по мета-полю!
Chizzle
"Баг" с EXISTS и NOT EXISTS, который требовал указания значения, был исправлен в WP 3.9
trex005
trex005 прав: "(Примечание: Из-за бага #23268, значение обязательно для корректной работы сравнений NOT EXISTS до версии 3.9. Вы должны указать какую-либо строку для параметра value. Пустая строка или NULL НЕ сработают. Однако, любая другая строка подойдет и НЕ появится в вашем SQL при использовании NOT EXISTS. Нужно вдохновение? Как насчет 'bug #23268'.)"
jave.web