LIKE %...% Мета-запрос

8 февр. 2013 г., 17:56:02
Просмотры: 40.6K
Голосов: 4

У меня есть сериализованный массив в качестве мета-значения, и я пытаюсь выполнить WP Query, чтобы найти определенное значение в этом сериализованном массиве.

Вот пример поля сериализованного массива:

a:6:{i:0;s:3:"173";i:1;s:3:"172";i:2;s:3:"171";i:3...

Вот мой запрос, но он не работает: ID, которые я ищу, также являются числовыми.

$practiceArgs = array(
    'post_type' => 'attorney', // тип записи: адвокат
    'post_status' => 'publish', // статус: опубликовано
    'posts_per_page' => -1,
    'meta_query' => array(
                        array(
                              'key' => 'practice_area', // ключ: область практики
                              'value' => $post->ID,
                              'compare' => 'LIKE',
                              'type' => 'NUMERIC'
                              )
                        )
);

Я пробовал использовать 'value' => '%'.$post-ID.'%' в моих запросах, но это тоже не работает.

У кого-нибудь был опыт работы с подобным?

0
Все ответы на вопрос 4
0
15

Я столкнулся с такой же проблемой сегодня. В обоих наших случаях существует отличное решение. Поскольку сериализованные данные, которые мы ищем, представляют собой просто идентификаторы и всегда заключены в кавычки, нам достаточно включить кавычки в сам запрос. Это устраняет проблему ложных срабатываний при поиске.

Вам просто нужно изменить meta query следующим образом:

array(
    'key' => 'practice_area',
    'value' => '"'.$post->ID.'"',
    'compare' => 'LIKE',
)

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

13 мая 2014 г. 19:52:31
0

Я однажды столкнулся с этой проблемой, и это определенно не самое приятное место. Подход, который вы используете, никогда не даст вам стабильного результата — ваш поиск будет выдавать множество ложных срабатываний (например, поиск по ID записи 43 вернет 143, 243, 1431, 1432 и т. д.).

На мой взгляд, у вас есть два варианта:

  • Пересмотреть способ сохранения метаданных: используйте массивы для данных, которые нужны только при отображении записи, но не для данных, по которым нужно фильтровать записи. Для последних используйте отдельные мета-ключи в базе данных — это намного быстрее, запросы проще кодировать, и вы можете быть уверены, что полностью контролируете результаты запросов. Не беспокойтесь о слишком большом количестве строк в таблице postmeta: для этого они и существуют.
  • Если по какой-то причине вам нужно хранить несколько полей в одной строке базы данных, не полагайтесь на стандартную сериализацию: используйте CSV, желательно с каким-то префиксом, чтобы избежать ложных срабатываний. Например, "id:43,id:54,foo:bar,id:57,", а затем ищите 'id:{post_ID},' (обратите внимание, что все значения должны заканчиваться запятыми, чтобы безопасно использовать двойные подстановочные знаки в LIKE-запросе). Это своего рода хак, но он надежнее, чем ваш текущий подход.

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

9 февр. 2013 г. 16:22:27
0

В WordPress LIKE работает не так, как Mysql Like, поэтому 'value' => '%'.$post-ID.'%' не сработает.

Вы можете попробовать версию с REGEXP. Например:

'meta_query' => array(
    array(
        'key'       => 'attorney',
        'value'     => '^'.$post-ID,
        'compare'   => 'REGEXP',
    )
)

Должно искать все элементы, где attorney начинается со значения $post-ID.

4 дек. 2019 г. 00:20:21
3

Вы не можете использовать LIKE с numeric (по крайней мере, я почти уверен, что нельзя). numeric попытается преобразовать всё value в число. Это не сработает, так как значение не является числом. Это первая ошибка.

Во-вторых, чтобы передать символ % буквально, нужно удвоить его до %%. Примечание: я не помню точно насчёт meta_query. Я экстраполирую из того, что требуется для передачи % через $wpdb->prepare. Думаю, здесь то же самое. Примечание: Оказывается, это верно только для $wpdb->prepare. Код был отредактирован.

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

$practiceArgs = array(
    'post_type' => 'attorney',
    'post_status' => 'publish',
    'posts_per_page' => -1,
    'meta_query' => array(
      array(
        'key' => 'practice_area',
        'value' => $post->ID,
        'compare' => 'LIKE'
      )
    )
);

Надеюсь, это поможет вам продвинуться дальше. Если не сработает, я вернусь к этому вопросу.

Примечание: Я вставил ваш (некорректный) сериализованный массив в свою базу данных и запустил приведённый выше код. Если всё настроено правильно — метаполя, типы записей и т.д. — код работает. Если у вас не срабатывает, значит, проблема в чём-то другом — возможно, вы ожидаете совпадения там, где его нет.

Я предполагаю, что у каждого из ваших записей типа 'attorney' будет массив подобного вида. Если это так, код должен работать. Однако я бы рекомендовал использовать несколько строк practice_area вместо сериализованного массива. = — более эффективный запрос, чем LIKE, особенно с подстановочными знаками, и результаты должны быть точнее. Индексация (в MySQL) также будет работать лучше.

8 февр. 2013 г. 18:11:50
Комментарии

К сожалению, он по-прежнему возвращает NIL. Есть другие идеи?

Troy Troy
8 февр. 2013 г. 20:59:49

Ваш комментарий относительно '%' верен только при использовании $wpdb->prepare. При использовании query_posts использование '%' не требуется: WordPress автоматически добавляет их за вас, хотите вы этого или нет.

Tomas Buteler Tomas Buteler
9 февр. 2013 г. 16:25:00

@tbuteler В этом случае WordPress также автоматически экранирует % в %%.

Robbert Robbert
10 дек. 2013 г. 09:31:17