Я пытаюсь запустить meta_query с массивом значений и выполнить его поиск, если все присутствуют в мета-значении, которое хранится в сериализованном массиве. Это возможно?
Мои аргументы для запроса следующие (обратите внимание, что это вложено в класс):
$args = array(
'post_type' => $this->posttype,
'posts_per_page' => '9',
'paged' => $paged,
'orderby' => 'meta_value_num',
'order' => 'DESC',
'meta_key' => 'lumens',
'meta_query' => array(
array(
'key' => 'mount',
'value' => array('pendant' , 'wall'),
'compare' => 'IN'
)
)
);
Пример хранимых метаданных находится в сериализованном массиве, аналогичном приведенному ниже:
a:4:{i:0;s:7:"pendant";i:1;s:15:"surface-ceiling";i:2;s:4:"wall";i:3;s:14:"aircraft-cable";}
Мой запрос не даст соответствующих результатов, что бы я ни пытался. Теперь я понимаю, что мне, вероятно, следовало бы хранить каждое значение в другом мета-ключе, а не в массиве, однако уже сейчас существует много записей для изменения метаданных.
ОБНОВИТЬ:
Это был мой обходной путь, похожий на подход @Leander; Я не хотел изменять сериализованные входы из-за количества записей в базе данных, и я забыл упомянуть одну вещь: я использовал CMB2 Developer Toolkit который сохраняет поля-флажки как сериализованные данные.
// This is pulled from a user input
$meta_queries = array('pendent' , 'wall');
// Metaqueries are passed through loop to create single entries with the like comparison operator
foreach($meta_queries as $key => $value){
$meta_query = array(
'key' => '_tf_' . $key,
// Serialize the comparison value to be more exact
'value' => serialize(strval($value)),
'compare' => 'LIKE',
);
}
// Generate $args array
$args = array(
'post_type' => $this->posttype,
'posts_per_page' => '9',
'paged' => $paged,
'orderby' => 'meta_value_num',
'order' => 'DESC',
'meta_key' => 'lumens',
'meta_query' => $meta_queries
);
Я не заметил большой проблемы с производительностью при заполнении данных. Я полагаю, что этот подход должен быть переработан, если для обработки требуется огромное количество данных.
Просто столкнулся с той же проблемой …!
У меня есть несколько тегов, хранящихся в массиве / настраиваемом поле, и я использую форму поиска для запросов к моим сообщениям, где пользователю должно быть разрешено искать несколько тегов, поэтому по сути мне нужно сравнить массив с другим массивом.
Теперь я понимаю, что мне, вероятно, следовало бы хранить каждое значение в другом мета-ключе, а не в массиве, однако уже сейчас существует много записей для изменения метаданных.
Я предположил бы, что это произведет довольно накладные расходы, не рекомендовал бы это …
Подход / Обходной путь
Я работаю с пользовательским вводом в виде строки, создаю массив из строки, чтобы проверить его размер, и в зависимости от размера я создаю одиночные LIKE-сравнения, которые отлично работают с данными моего массива.
$tags_string = get_query_var( 'p_tags' ); // form submitted data
$tags_array = explode( ',', $tags_string ); // create array
if ( count( $tags_array ) > 1 ) { // check if more then one tag
$meta_query['p_tags']['relation'] = 'AND';
foreach($tags_array as $tag) { // create a LIKE-comparison for every single tag
$meta_query['p_tags'][] = array( 'key' => 'YOUR_KEY', 'value' => $tag, 'compare' => 'LIKE' );
}
} else { // if only one tag then proceed with simple query
$meta_query['p_tags'] = array( 'key' => 'YOUR_KEY', 'value' => $tags_string, 'compare' => 'LIKE' );
}
Args output (демо)
[meta_query] => Array
(
[p_tags] => Array
(
[relation] => AND
[0] => Array
(
[key] => basic_tags
[value] => adobe
[compare] => LIKE
)
[1] => Array
(
[key] => basic_tags
[value] => stone
[compare] => LIKE
)
)
)
Обратите внимание: В зависимости от размера вашего массива (ов), количества отправляемых запросов и т. Д. Это решение может быть не самым эффективным из доступных.
Другим подходом может быть расширение FIND_IN_SET для запросов WordPress, увидеть эту суть.
Цените любой вклад, касающийся производительности или улучшения качества кода.
Слишком много записей, чтобы изменить метаданные сейчас
Затем запустите скрипт (PHP-скрипт или MySQL напрямую) и создайте правильные пары meta_key => meta_value, затем удалите сериализованный столбец. Сериализованные данные должны храниться в базе данных, только если они должны быть извлечены как таковые. Если вы ленивы и все еще хотите иметь только один столбец, сохраните данные как JSON, а затем запросите их как JSON (современные версии MySQL позволяют запрашивать данные json из столбца типа JSON). Удачи с этим.
Но если вы будете настаивать на том, чтобы данные оставались сериализованными, уверяю вас, вы или кто-либо другой, кто поддерживает ваш проект, будут биться головой о каждой связанной небольшой функции, которую вам нужно реализовать.