query_posts - использование meta_compare для сравнения значений мета-полей (больше, меньше или равно)

22 сент. 2010 г., 23:18:01
Просмотры: 30.7K
Голосов: 3

Я использую query_posts( $args ) для фильтрации цикла Loop. Мне нужно отфильтровать записи на основе их meta_value "vote", иногда меньше чем, иногда равно и так далее...

Я определенно хочу использовать функцию query_posts() и передавать мой фильтр через $args! Я не хочу использовать add_filter('posts_where', 'filter_where'); и затем добавлять оператор AND к запросу.

Я хочу использовать встроенную функциональность WordPress для фильтрации записей с помощью meta_key, meta_value и meta_compare таким образом:

$args = array( 'meta_key'=>'vote', 'meta_compare'=>'>=', 'meta_value'=>5, 'posts_per_page'=>100 ) )

query_posts( $args );

Результат этого запроса:

SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id) WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') AND wp_postmeta.meta_key = 'vote' AND wp_postmeta.meta_value >= '5' GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 100

Проблема в следующем:

wp_postmeta.meta_value >= '5' 

Должно быть:

wp_postmeta.meta_value >= 5

Тогда это будет работать нормально.

Я не понимаю, почему WordPress добавляет кавычки.

Я использую предопределенные параметры WordPress (<, >, <=, >=) и очевидно, что это будет работать только с числами, а не со строками, которые должны быть в кавычках.

В документации говорится:

Возвращает записи с ключом произвольного поля 'miles' со значением произвольного поля, которое МЕНЬШЕ ИЛИ РАВНО 22

query_posts('meta_key=miles&meta_compare=<=&meta_value=22');

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

Начиная с WP 3.1, вы можете привести значение метаполя к любому типу, используя аргумент 'type' в 'meta_query':

$args = array(
  'meta_query'=> array(
    array(
      'key' => 'vote', // Ключ метаполя
      'compare' => '>=', // Оператор сравнения
      'value' => 5, // Значение для сравнения
      'type' => 'numeric', // Тип значения (числовой)
    )
  )
  'posts_per_page' => 100 // Количество записей на странице
) );

query_posts( $args ); // Выполнение запроса
16 мар. 2011 г. 17:57:40
Комментарии

Это отличный ответ — полностью решает проблему.

Samuel Hulick Samuel Hulick
23 окт. 2011 г. 14:24:21

''type' => 'numeric',' решил мою проблему Но я сомневаюсь, что там не должно быть запятой

vaibhav vaibhav
2 янв. 2013 г. 19:36:49
1

При беглом просмотре документации, кажется, что meta_value предназначен для строк, а для числовых значений есть meta_value_num.

Смотрите Параметры Orderby

Обновление

Провёл небольшое исследование.

meta_value_num действительно игнорируется при фильтрации. Думаю, они просто забыли добавить эту часть. :)

Проблема в том, что WP_Query корректно получает число как int (передача в виде массива не имеет значения), но он передаёт сгенерированное условие meta_compare через $wpdb->prepare() и явно помечает значение как строку %s. В этом случае prepare принудительно обрамляет его в одинарные кавычки.

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

22 сент. 2010 г. 23:31:57
Комментарии

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

User User
22 сент. 2010 г. 23:37:29
6

Я рекомендую сначала преобразовать ваш массив $args в строку перед передачей в query_posts. Когда вы создаете массив $args, система автоматически преобразует число 5 в строку "5" при преобразовании массива обратно в строку.

Поэтому лучше использовать такую запись:

query_posts('meta_key=vote&meta_compare=>=&meta_value=5&posts_per_page=100');

Таким образом, в query_posts передается та же информация, но число 5 будет обрабатываться как число, а не как строка "5".


Обновление

Как выяснилось, meta_value хранит значения в виде строк, а не чисел, что делает сравнение "больше/меньше" неэффективным. Однако после дополнительного исследования я обнаружил флаг запроса meta_value_num.

Если выполнить следующий вызов query_posts:

query_posts('meta_key=vote&meta_compare=>=&meta_value=5&posts_per_page=100&orderby=meta_value_num');

То вы получите желаемое поведение. meta_value_num указывает WordPress интерпретировать значения meta_value как числа, а не строки.

22 сент. 2010 г. 23:29:24
Комментарии

Я пробовал, это дает точно такой же результат. На самом деле, я даже проследил путь от функции к функции в WordPress-Core, и строка разбивается на & и преобразуется в массив перед обработкой....

User User
22 сент. 2010 г. 23:33:55

Согласно Codex: Обратите внимание, что значение 99 будет считаться больше 100, так как данные хранятся в виде строк, а не чисел. Таким образом, meta_value действительно хранится как строка... поэтому WordPress добавляет кавычки. Следующий вопрос: можете ли вы описать, в чем именно "не работает"? Возвращает ли он вообще какие-либо данные?

EAMann EAMann
22 сент. 2010 г. 23:47:45

Да, вы правы! Как я уже говорил выше, что бы я ни делал, значение оборачивается в '5'. MySQL не может сравнивать что-то на числовом уровне, если оно обернуто в '', поэтому мне интересно, почему WordPress реализовал эту функцию, если она не работает. Нет, он возвращает результат, но не тот, который ожидается.

User User
22 сент. 2010 г. 23:50:38

Смотрите мое обновление выше. Добавление orderby=meta_value_num должно решить проблему, если у вас WP 2.8.4 или новее.

EAMann EAMann
23 сент. 2010 г. 00:12:55

Спасибо за все усилия. Но это тоже не сработало. Я действительно глубоко изучил эту тему, и это просто не поддерживается в WP. Я создам тикет по этой проблеме, потому что ее действительно легко исправить, и это откроет столько возможностей!

User User
23 сент. 2010 г. 21:31:34

@Joakim Да, это поддерживается WP. Прочтите тикет, на который я ссылался выше, где была добавлена эта функция. Возможно, вы можете предоставить нам более крупный пример кода того, что вы пытаетесь сделать... возможно, проблема в другом.

EAMann EAMann
23 сент. 2010 г. 22:05:47
Показать остальные 1 комментариев
0

WordPress обрабатывает все 'value' как строки и добавляет к ним одинарные кавычки в итоговом запросе, поэтому SQL также вынужден обрабатывать их как строки, а не числа. Вы можете убрать эти кавычки с помощью фильтра:

add_filter('get_meta_sql', function($data) {
  $regex = "/'(-?\d+)'/";
  $data['where'] = preg_replace($regex, "$1", $data['where']);
  return $data;
});

И убедитесь, что у вас указан 'type' => 'NUMERIC' или аналогичный тип

7 февр. 2025 г. 18:42:35