meta_query с мета-значениями в виде сериализованных массивов
Я работаю над проектом, в котором создаю произвольный тип записи и пользовательские данные, вводимые через мета-боксы, связанные с моим произвольным типом записи. По определенным причинам я решил закодировать мета-боксы таким образом, что поля ввода в каждом мета-боксе являются частью массива. Например, я сохраняю долготу и широту:
<p>
<label for="latitude">Широта:</label><br />
<input type="text" id="latitude" name="coordinates[latitude]" class="full-width" value="" />
</p>
<p>
<label for="longitude">Долгота:</label><br />
<input type="text" id="longitude" name="coordinates[longitude]" class="full-width" value="" />
</p>
По какой-то причине мне понравилась идея иметь одну запись postmeta для каждого мета-бокса. В хуке save_post
я сохраняю данные следующим образом:
update_post_meta($post_id, '_coordinates', $_POST['coordinates']);
Я сделал это потому, что у меня есть три мета-бокса, и мне нравится иметь всего 3 значения postmeta для каждой записи; однако теперь я осознал потенциальную проблему. Мне может понадобиться использовать WP_Query для извлечения только определенных записей на основе этих мета-значений. Например, я могу захотеть получить все записи, у которых значения широты выше 50. Если бы эти данные хранились в базе данных по отдельности, возможно, используя ключ latitude
, я бы сделал что-то вроде:
$args = array(
'post_type' => 'my-post-type',
'meta_query' => array(
array(
'key' => 'latitude',
'value' => '50',
'compare' => '>'
)
)
);
$query = new WP_Query( $args );
Поскольку широта является частью postmeta _coordinates
, этот способ не сработает.
Итак, мой вопрос: существует ли способ использовать meta_query
для запроса к сериализованному массиву, как в моем сценарии?

Нет, это невозможно и даже может быть опасно.
Не существует надежного способа сделать это без столкновения с подводными камнями, такими как поиск 10
, который также найдет 100
или 210
, или совпадение с неправильным подзначением и т.д. Подобные решения ненадежны и имеют проблемы с производительностью и безопасностью.
Сериализованные данные — это вектор атаки и серьезная проблема для производительности.
Я рассмотрю:
- Исправление и возможность запросов
- Почему нельзя запрашивать внутри сериализованных данных?
- Почему
LIKE
не является решением
- Почему
- Примечание о хранении записей/сущностей/объектов как сериализованных объектов в метаданных
- Безопасность и сериализованные объекты
- Что делать, если у меня есть список ID?
- Что делать, если у меня есть массив именованных элементов?
- Полный обход проблемы
- Заключение
Но что насчет LIKE
?
Вы могли видеть благонамеренные вопросы, предлагающие использовать LIKE
для решения этой проблемы. Разве это не решает проблему? Это не решение, а обманчивый путь.
Есть несколько серьезных проблем:
- ложные совпадения, поиск
test
сLIKE
также найдетtest
,testing
,untested
и другие значения - нет способа ограничить это подключами для массивов с ключами или объектов
- невозможно выполнить сортировку
- очень медленно и ресурсоемко
LIKE
будет работать только в ограниченных и нереалистичных ситуациях, а также несет серьезные потери производительности.
Исправление и возможность запросов
Я настоятельно рекомендую десериализовать ваши данные и изменить процедуру сохранения. Примерно такой код должен преобразовать ваши данные в новый формат:
$args = [
'post_type' => 'my-post-type',
'meta_key' => '_coordinates',
'posts_per_page' => -1,
];
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
// получаем данные
$c = get_post_meta( $post->ID, '_coordinates', true );
// сохраняем в новом формате: отдельные метаданные, таксономия и т.д.
add_post_meta( $post->ID, '_longitude', $c['longitude'] );
add_post_meta( $post->ID, '_latitude', $c['latitude'] );
// Опционально: очищаем старые метаданные
delete_post_meta( $post->ID, '_coordinates', $c );
}
wp_reset_postdata();
}
Теперь вы сможете выполнять запросы с отдельными ключами.
Если вам нужно хранить несколько долгот и широт, вы можете сохранить несколько метаданных с одинаковым именем. Просто используйте третий параметр get_post_meta
, и он вернет их все как массив.
Почему нельзя запрашивать внутри сериализованных данных?
MySQL видит это просто как строку и не может разбить ее на структурированные данные. Разделение на структурированные данные — это именно то, что делает код выше.
Вы можете попытаться запросить частичные фрагменты данных, но это будет крайне ненадежно, дорого, медленно и хрупко, с множеством крайних случаев. Сериализованные данные не предназначены для SQL-запросов и не имеют регулярного и постоянного формата.
Помимо затрат на частичный поиск строк, запросы к метаданным медленны, а сериализованные данные могут меняться в зависимости от длины содержимого, что делает поиск невероятно дорогим, если не невозможным, в зависимости от искомого значения.
Примечание о хранении записей/сущностей/объектов как сериализованных объектов в метаданных
Вы можете захотеть сохранить запись транзакции в метаданных поста или другую структуру данных в метаданных пользователя, а затем столкнуться с вышеуказанной проблемой.
Решение здесь не в том, чтобы разбить их на отдельные метаданные, а в осознании, что они вообще не должны быть метаданными, а должны быть пользовательским типом записи. Например, журнал или запись могут быть пользовательским типом записи с исходным постом в качестве родителя или связанным через таксономию.
Безопасность и сериализованные объекты
Хранение сериализованных PHP-объектов через функцию serialize
может быть опасно, что печально, так как передача объекта в WordPress приведет к его сериализации. Это связано с тем, что при десериализации объекта создается объект, и все его методы пробуждения и конструкторы выполняются. Это может не казаться большой проблемой, пока пользователь не сможет проскользнуть тщательно сформированный ввод, приводящий к удаленному выполнению кода, когда данные читаются из базы данных и десериализуются WordPress.
Этого можно избежать, используя JSON, что также упрощает запросы, но гораздо проще и быстрее просто правильно хранить данные и избегать структурированных сериализованных данных с самого начала.
Что делать, если у меня есть список ID?
Вы можете попытаться передать WordPress массив или превратить его в список, разделенный запятыми, но в этом нет необходимости!
Ключи метаданных поста не уникальны, вы можете сохранять один и тот же ключ несколько раз, например:
$id = ...;
add_post_meta( $id, 'mylist', 1 );
add_post_meta( $id, 'mylist', 2 );
add_post_meta( $id, 'mylist', 3 );
add_post_meta( $id, 'mylist', 4 );
add_post_meta( $id, 'mylist', 5 );
add_post_meta( $id, 'mylist', 6 );
Но как получить данные обратно? Вы замечали, что вызовы get_post_meta
имеют третий параметр, который всегда установлен в true? Установите его в false
:
$mylist = get_post_meta( $id, 'mylist', false );
foreach ( $mylist as $number ) {
echo '<p>' . esc_html( $number ) . '</p>;
}
Что делать, если у меня есть массив именованных элементов?
Что если я хочу сохранить эту структуру данных так, чтобы можно было запрашивать поля?
{
"foo": "bar",
"fizz": "buzz"
"parent": {
"child": "value"
}
}
Это просто: разбейте их с префиксами:
add_post_meta( $id, "tomsdata_foo", "bar" );
add_post_meta( $id, "tomsdata_fizz", "buzz" );
add_post_meta( $id, "tomsdata_parent_child", "value" );
И если вам нужно перебрать некоторые из этих значений, используйте get_post_meta( $id );
, чтобы получить все метаданные поста и перебрать ключи, например:
$all_meta = get_post_meta( $id );
$look_for = 'tomsdata_parent';
foreach ( $all_meta as $key => $value ) {
if ( substr($string, 0, strlen($look_for)) !== $look_for ) {
continue; // не совпадает, пропускаем!
}
echo '<p>' . $key . ' = ' . $value . '</p>';
}
Что выведет:
<p>tomsdata_parent_child = value</p>
Помните, когда WordPress загружает пост, он одновременно загружает все его метаданные, поэтому вызовы get_post_meta
очень дешевы и не вызывают дополнительных запросов к базе данных.
Полный обход проблемы
Если вы знаете, что вам нужно будет искать/запрашивать/фильтровать по подзначению, почему бы просто не сохранить дополнительное метаданное с этим значением, чтобы можно было его искать?
Заключение
Таким образом, вам не нужно хранить структурированные данные в виде строки в базе данных, и вам не следует этого делать, если вы планируете искать/запрашивать/фильтровать эти значения.
Возможно, можно использовать регулярное выражение и LIKE
, но это крайне ненадежно, не работает для большинства типов данных и очень, очень медленно и ресурсоемко для базы данных. Вы также не можете выполнять математические операции с результатами, как это можно было бы сделать, если бы они были отдельными значениями.

Для тех, кто проходит мимо, не прекращайте чтение: более полезные (и свежие) ответы находятся ниже

Что если у меня есть массив ID для сохранения - и они не представляют разные ключи, под которыми я мог бы их сохранить, такие как 'latitude' и т.д., а только один ключ для всех (например, при сохранении связей и т.п.). Что делать в таком случае? Решение от @rabni?

Вы можете хранить ключ более одного раза, пары ключ-значение не уникальны. Что касается связей, для этого существуют таксономии. Если вы используете метаданные для сопоставления нескольких элементов с чем-то, лучше поместите их в термин таксономии

Конечно, это возможно. Да, вам нужно убедиться, что значения уникальны, что является основной сутью таких postmeta. Обычно такие сериализованные значения происходят из чекбоксов, которые являются массивами. Каждый чекбокс в наборе должен иметь уникальное значение. А если нет — они должны убедиться, что его опция (в php: ключ массива) уникальна, чтобы её можно было найти.
Позже, запрос — это простая задача по сравнению с вашим решением:
'meta_query' => array(
array(
'key' => 'thekey',
'value' => 'thevalue',
'compare' => 'LIKE',
'type' => 'CHAR',
),
),

@BedaSchmid это не делает то, что вы думаете. Если бы вы прочитали мой ответ, то увидели бы, что я затронул пункт про LIKE
и указал на серьёзные недостатки, которые делают его ненадёжным и вызывают ошибки. Смотрите часть под названием "А что насчёт LIKE?". Я отредактировал свой ответ, переместив её выше для тех, кто не читает ответ целиком — за годы таких накопилось несколько.

@TomJNowell — из всех 4 перечисленных причин только одна является серьёзной проблемой, и, как я пояснил в комментарии, её можно избежать. Медленно? Да. Любой meta query работает медленно. Сортировка? Ладно. Допустим, если вам действительно нужно делать запросы по этому полю, можно закрыть глаза на сортировку. В любом случае сортировка по массиву, где может быть выбрано несколько значений, выглядит странно. Возможно делать запросы по таким значениям, и это не возвращает неточных результатов, при условии, что сериализованный массив содержит уникальные значения, как я упомянул в своём комментарии.

Я также столкнулся с такой ситуацией. Вот что я сделал:
$args = array(
'post_type' => 'my-post-type', // Тип записи
'meta_query' => array( // Мета-запрос
array(
'key' => 'latitude', // Ключ мета-поля
'value' => sprintf(':"%s";', $value), // Форматируем значение
'compare' => 'LIKE' // Оператор сравнения
)
)
);
Надеюсь, это поможет

Мне очень понравилось это решение. К сожалению, оно не применимо, когда $value
также является ID. В этом случае я предлагаю создать две функции: одну для добавления символа к каждому элементу массива перед сохранением данных, и другую для удаления этого символа перед использованием данных. Таким образом, сериализованный индекс i:2
не будет путаться с i:D2
"реальных" данных. Параметр meta query тогда должен принять вид 'value' => sprintf(':"D%s";', $value),
, и вы сохраните корректную функциональность этого замечательного ответа!

Это тоже идеально сработало у меня. Хотя сначала испытал мини-панику, когда увидел принятое решение

@Erenor Paz, я только что опубликовал решение, которое хорошо работает как с ID, так и со строками: https://wordpress.stackexchange.com/a/299325/25264

использование LIKE
— отличный и быстрый способ положить ваш сервер (не говоря уже о ложных срабатываниях), вам лучше иметь очень хорошее кеширование.

Обратите внимание, что с этим решением будет совпадать любое подзначение с этим значением. Так что если вы ищете широту 5
, это также совпадёт с долготой 5
. Это менее критично для данного конкретного случая, но за этим нужно следить. Также невозможно сортировать результаты, и нельзя выполнять какую-либо логику/математику, например, получить все значения, которые больше или меньше числа

Вы действительно потеряете возможность эффективно запрашивать свои данные при сериализации записей в базу данных WordPress.
Общее повышение производительности и экономия, которые, как вам кажется, достигаются за счёт сериализации, не будут заметны в значительной степени. Вы можете получить немного меньший размер базы данных, но стоимость SQL-запросов будет высокой, если вы когда-нибудь попытаетесь запросить эти поля и сравнить их каким-либо полезным и осмысленным образом.
Вместо этого используйте сериализацию для данных, которые вы не планируете запрашивать таким образом, а будете получать только пассивно через прямой вызов WordPress API get_post_meta()
— с помощью этой функции вы также можете распаковать сериализованную запись для доступа к её свойствам массива.
Фактически, если присвоить значение true, как в примере:
$meta = get_post_meta( $post->ID, 'key', true );
Данные будут возвращены в виде массива, с которым вы сможете работать в обычном режиме.
Вы можете сосредоточиться на других оптимизациях базы данных/сайта, таких как кэширование, минификация CSS и JS, а также использование таких сервисов, как CDN, если это необходимо. Это лишь несколько примеров... WordPress Codex — хорошая отправная точка для изучения этой темы: ЗДЕСЬ

Я считаю, что есть 2 решения, которые могут попытаться решить проблему хранения результатов как в виде строк, так и целых чисел. Однако важно отметить, как уже указывали другие, что невозможно гарантировать целостность результатов, сохраненных как целые числа, потому что эти значения хранятся в виде сериализованных массивов, где индексы и значения сохраняются по одному и тому же шаблону. Пример:
array(37,87);
сохраняется как сериализованный массив, вот так:
a:2:{i:0;i:37;i:1;i:87;}
Обратите внимание на i:0
как первую позицию массива и i:37
как первое значение. Шаблон одинаковый. Но давайте перейдем к решениям.
1) Решение с REGEXP
Это решение работает для меня независимо от того, сохранено ли мета-значение как строка или число / ID. Однако оно использует REGEXP
, что не так быстро, как использование LIKE
.
$args = array(
'post_type' => 'my-post-type',
'meta_query' => array(
array(
'key' => 'latitude',
'value' => '\;i\:' . $value . '\;|\"' . $value . '\";',
'compare' => 'REGEXP'
)
)
);
2) Решение с LIKE
Я не уверен насчет разницы в производительности, но это решение использует LIKE
и также работает как для чисел, так и для строк.
$args = array(
'post_type' => 'my-post-type',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'latitude',
'value' => sprintf(':"%s";', $value),
'compare' => 'LIKE'
),
array(
'key' => 'latitude',
'value' => sprintf(';i:%d;', $value),
'compare' => 'LIKE'
)
)
);

REGEXP
хорош в определенных ситуациях, но если можно использовать LIKE
, я считаю, что это предпочтительный метод. Старая ссылка, но все еще довольно полезная, на мой взгляд: https://thingsilearn.wordpress.com/2008/02/28/mysql-query-speed-regexp-vs-like/ :-)

@ErenorPaz Вы правы. LIKE
работает быстрее. Но это решение, которое работает как со строками, так и с числами

Да..так что ответ (как всегда): зависит от ситуации, если можно использовать "LIKE" — это предпочтительно, в противном случае REGEXP тоже подойдет :-)

@ErenorPaz, я отредактировал свой ответ, добавив новое решение, которое использует LIKE
, но работает как с числами, так и со строками. Я не уверен насчёт производительности, так как приходится сравнивать результаты с помощью OR

Я только что разобрался с сериализованными полями и смог выполнить по ним запрос. Не используя meta_query, а с помощью SQL-запроса.
global $wpdb;
$search = serialize('latitude').serialize(50);
$query = $wpdb->prepare("SELECT `post_id`
FROM `wp_postmeta`
WHERE `post_id` IN (SELECT `ID` FROM `wp_posts` WHERE `post_type` = 'my-post-type')
AND `meta_key` = '_coordinates'
AND `meta_value` LIKE '%s'",'%'.$search.'%');
$ids = $wpdb->get_col($query);
$args = array(
'post__in' => $ids
'post_type' => 'team' // добавляем тип, потому что по умолчанию будет 'post'
);
$posts = get_posts($args);
Запрос сначала ищет записи с соответствующим post_type, чтобы уменьшить количество записей в wp_postmeta для фильтрации.
Затем я добавил условие WHERE, чтобы дополнительно сократить количество строк, фильтруя по meta_key
.
ID в итоге попадают в массив, как и требуется для get_posts.
P.S. Для хорошей производительности подзапросов требуется MySQL версии 5.6 или выше.

Простой способ обойти эту ситуацию — использовать сравнение LIKE
с сериализованным форматом (длина с типом и самим значением), как показано ниже:
$id = 123; // ID для проверки в сериализованных данных.
//(предполагается, что числа хранятся как строка. В моём случае так и было.)
$args = array(
'post_type' => 'custom_post_type',
'meta_query' => array(
array(
'key' => 'meta_key_to_check_from',
'value' => 's:' . strlen($id) . ':"' . $id . '";',
'compare' => 'LIKE'
)
)
);
$query = new WP_Query( $args );
Если нужно искать по пользовательской таксономии:
$id = 123; // ID для проверки в сериализованных данных.
//(предполагается, что числа хранятся как строка. В моём случае так и было.)
$args = array(
'hide_empty' => false, // также получать термины, которые ещё не используются
'meta_query' => array(
array(
'key' => 'meta_key_to_check_from',
'value' => 's:' . strlen($id) . ':"' . $id . '";',
'compare' => 'LIKE'
)
),
'taxonomy' => 'custom_taxonomy'
);
$terms = get_terms( $args );

Этот пример мне очень помог. Он предназначен специально для плагина S2Members (который сериализует метаданные пользователей). Но он позволяет выполнять запрос к части сериализованного массива внутри meta_key.
Это работает с использованием функции MySQL REGEXP.
Вот источник
Вот код, который запрашивает всех пользователей, проживающих в США. Я легко модифицировал его для запроса одного из моих пользовательских полей регистрации, и он заработал мгновенно.
<?php
global $wpdb;
$users = $wpdb->get_results ("SELECT `user_id` as `ID` FROM `" . $wpdb->usermeta .
"` WHERE `meta_key` = '" . $wpdb->prefix . "s2member_custom_fields' AND
`meta_value` REGEXP '.*\"country_code\";s:[0-9]+:\"US\".*'");
if (is_array ($users) && count ($users) > 0)
{
foreach ($users as $user)
{
$user = /* Получаем полный объект пользователя. */ new WP_User ($user->ID);
print_r($user); /* Получаем полный список свойств при отладке. */
}
}
?>

После прочтения множества советов по выполнению запроса WP_Query
с фильтрацией по сериализованным массивам, вот как я в итоге решил эту задачу: создав массив значений, разделенных запятыми, с помощью функции implode в сочетании с пользовательским SQL-запросом $wpdb
, использующим FIND_IN_SET
для поиска в списке значений, разделенных запятыми, нужного значения.
(это похоже на ответ Томаса, но немного менее ресурсоемко для SQL-запроса)
1. В functions.php:
В файле functions.php (или там, где вы настраиваете метабокс) в функции yourname_save_post()
используйте
update_post_meta($post->ID, 'checkboxArray', implode(",", $checkboxArray)); //добавляем implode
для создания массива со значениями, разделенными запятыми.
Также вам нужно изменить переменную вывода в функции построения метабокса администратора yourname_post_meta()
на
$checkboxArray = explode(",", get_post_custom($post->ID)["checkboxArray"][0]); //добавляем explode
2. В файле шаблона PHP:
Проверка: если вы запустите get_post_meta( $id );
, вы должны увидеть checkboxArray
как массив, содержащий ваши значения, разделенные запятыми, вместо сериализованного массива.
Теперь мы строим наш пользовательский SQL-запрос с помощью $wpdb
.
global $wpdb;
$search = $post->ID;
$query = "SELECT * FROM wp_posts
WHERE FIND_IN_SET( $search, (
SELECT wp_postmeta.meta_value FROM wp_postmeta
WHERE wp_postmeta.meta_key = 'blogLocations'
AND wp_postmeta.post_id = wp_posts.ID )
)
AND ( wp_posts.post_type = 'post' )
AND ( wp_posts.post_status = 'publish' );";
$posts = $wpdb->get_results($query);
foreach ($posts as $post) {
//ваш контент поста здесь
}
Обратите внимание на FIND_IN_SET
— именно здесь происходит вся магия.
Теперь... Поскольку я использую SELECT *
, это возвращает все данные поста, и внутри цикла foreach
вы можете вывести то, что вам нужно (выполните print_r($posts);
, если не знаете, что включено). Это не настраивает "петлю" за вас (мне так больше нравится), но это можно легко изменить для настройки петли, если вы предпочитаете (посмотрите setup_postdata($post);
в кодексе, вам, вероятно, понадобится изменить SELECT *
на выбор только ID постов и $wpdb->get_results
на правильный тип $wpdb
— см. кодекс для $wpdb
также для информации по этой теме).
Что ж, потребовались некоторые усилия, но поскольку wp_query
не поддерживает выполнение 'compare' => 'IN'
для сериализованных или разделенных запятыми значений, этот костыль — ваш лучший вариант!
Надеюсь, это кому-то поможет.

Если вы используете оператор сравнения like
в мета-запросе, он должен корректно работать для поиска внутри сериализованного массива.
$wp_user_search = new WP_User_Query(array(
'meta_query' => array(
array(
'key' => 'wp_capabilities',
'value' => 'subscriber',
'compare' => 'not like'
)
)
)
);
результат:
[query_where] => WHERE 1=1 AND (
( wp_usermeta.meta_key = 'wp_capabilities'
AND CAST(wp_usermeta.meta_value AS CHAR) NOT LIKE '%subscriber%' )

Если мои метаданные имеют тип массива, я использую этот метод для запроса по мета:
$args = array(
'post_type' => 'fotobank', // Тип записи
'posts_per_page' => -1, // Получить все записи
'meta_query' => array(
array(
'key' => 'collections', // Ключ метаполя
'value' => ':"'.$post->ID.'";', // Ищем ID поста в сериализованном массиве
'compare' => 'LIKE' // Используем LIKE для поиска в строке
)
)
);
$fotos = new WP_Query($args); // Создаем новый запрос

Мне стало любопытно насчет ответов выше, где meta_query
указывал на ключ latitude
вместо _coordinates
. Пришлось проверить, действительно ли в meta-запросах можно адресовать конкретный ключ внутри сериализованного массива. :)
Очевидно, это не так.
Итак, обратите внимание, что правильный ключ для поиска — это _coordinates
, а не latitude
.
$args = array( 'post_type' => 'my-post-type', 'meta_query' => array( array( 'key' => '_coordinates', 'value' => sprintf(':"%s";', $value), 'compare' => 'LIKE' ) ) );
ПРИМЕЧАНИЯ:
Данный подход позволяет искать только точные совпадения. Поэтому поиск по условиям типа все широты больше 50 невозможен.
Для включения поиска по подстроке можно использовать
'value' => sprintf(':"%%%s%%";', $value),
. (не тестировалось)

Вы можете заключить значение в %
, чтобы выполнить запрос сериализованного значения:
$args = array(
'post_type' => 'my-post-type',
'meta_query' => array(
array(
'key' => 'latitude',
'value' => '%' . 50 . '%',
'compare' => '>'
)
)
);
$query = new WP_Query( $args );

У меня такой же вопрос. Возможно, вам нужен параметр 'type'? Посмотрите этот связанный вопрос: Запрос по произвольным полям - Мета-значение является массивом
Попробуйте, возможно, так:
$args = array( 'post_type' => 'my-post-type', 'meta_query' => array( array( 'key' => 'latitude', 'value' => '50', 'compare' => '>', 'type' => 'numeric' ) ) );

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

Да, ты прав. Я попробовал это сегодня утром, и у меня тоже не сработало.
У меня та же проблема. Хранение значения мета-ключа в виде массива. Я начинаю думать, что это невозможно, и вместо этого мне придется хранить их как отдельные мета-поля с одинаковыми именами... и просто правильно управлять их удалением/обновлением.

Я столкнулся с похожей ситуацией при использовании плагина Magic Fields. Возможно, это решение вам подойдет:
$values_serialized = serialize(array('50'));
$args = array(
'post_type' => 'my-post-type',
'meta_query' => array(
array(
'key' => 'latitude',
'value' => $values_serialized,
'compare' => '>'
)
)
);

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

Тогда этот ответ не должен быть помечен как правильный, и безответственно с вашей стороны так делать. Правильным ответом в таком случае будет: "Нет, это невозможно".

Согласен, к тому же WordPress сам обрабатывает сериализацию, serialize()
не требуется в данном случае...

На самом деле ответ @seth-stevenson отличный, когда делаешь именно то, что он сказал, используя плагин "Magic Fields". Поскольку этот плагин по умолчанию сериализует данные определенного типа, это лучший способ сделать ТОЧНОЕ совпадение.
