query_posts -> usando meta_compare / donde meta value es menor, mayor o igual

22 sept 2010, 23:18:01
Vistas: 30.7K
Votos: 3

Estoy usando query_posts( $args ) para filtrar el Loop. Quiero filtrar posts basados en su meta_value "vote", a veces menor que, a veces igual y así sucesivamente....

Definitivamente quiero usar la función query_posts() y pasar mi filtro a través de $args! No quiero usar add_filter('posts_where', 'filter_where'); y luego agregar una declaración AND a la consulta.

Quiero usar la funcionalidad proporcionada por WordPress para filtrar posts con meta_key, meta_value y meta_compare así:

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

query_posts( $args );

El resultado de esto es:

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

El problema de esto es:

wp_postmeta.meta_value >= '5' 

Debería ser:

wp_postmeta.meta_value >= 5

Entonces funcionaría bien.

No entiendo por qué WordPress agrega comillas.

Estoy usando el parámetro predefinido de WordPress (<, >, <=, >=) y es obvio que esto solo funcionará con números y no con cadenas que necesitarían estar entre comillas.

La documentación dice:

Devuelve posts con una clave de campo personalizado 'miles' con un valor de campo personalizado que es MENOR O IGUAL A 22

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

0
Todas las respuestas a la pregunta 4
2
12

Desde WP 3.1, puedes convertir el valor meta a cualquier tipo que desees usando el argumento 'type' en 'meta_query':

$args = array(
  'meta_query'=> array(
    array(
      'key' => 'vote',
      'compare' => '>=',
      'value' => 5,
      'type' => 'numeric',
    )
  )
  'posts_per_page' => 100
) );

query_posts( $args );
16 mar 2011 17:57:40
Comentarios

Esta es una gran respuesta - funciona perfectamente.

Samuel Hulick Samuel Hulick
23 oct 2011 14:24:21

''type' => 'numeric',' resolvió mi problema Pero dudo que no debería contener coma

vaibhav vaibhav
2 ene 2013 19:36:49
1

Al echar un vistazo rápido a la documentación, parece que meta_value está destinado para cadenas de texto y para valores numéricos existe meta_value_num.

Consulta Parámetros de Orderby

Actualización

Investigué un poco.

meta_value_num efectivamente es ignorado para el propósito de filtrado. Creo que simplemente olvidaron agregar esa parte. :)

El problema es que WP_Query recibe correctamente el número como int (pasarlo como array no importa), pero pasa la condición generada de meta_compare a través de $wpdb->prepare() y marca explícitamente el valor como %s (cadena). En este caso, prepare fuerza el entrecomillado simple.

Así que parece que tendrás que filtrar posts_where después de todo. Puedes intentar simplemente eliminar las comillas de esa cadena específica en lugar de generar la condición manualmente.

22 sept 2010 23:31:57
Comentarios

este uso está destinado solo para ordenar datos... pero lo probé y no funciona. Cuando vi tu respuesta pensé "hombre, esa es la solución"...

User User
22 sept 2010 23:37:29
6

Recomiendo analizar tu array $args y convertirlo a una cadena antes de pasarlo a query_posts. Cuando creas el array $args, el sistema convertirá automáticamente el número 5 en una cadena "5" cuando el array se convierta de nuevo en una cadena.

Así que usa esto en su lugar:

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

Eso sigue pasando la misma información a query_posts, pero debería pasar el número 5 en lugar de la cadena "5".


Actualización

Como ahora hemos descubierto que meta_value almacena cadenas en lugar de números, y no se puede hacer efectivamente una comparación de mayor que/menor que con cadenas. Sin embargo, después de investigar un poco más, encontré la bandera de consulta meta_value_num.

Si ejecutas la siguiente llamada a query_posts:

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

Entonces deberías obtener el comportamiento que deseas. meta_value_num le indica a WordPress que evalúe tus meta_value como números en lugar de cadenas.

22 sept 2010 23:29:24
Comentarios

Intenté que produjera exactamente lo mismo. De hecho, seguí el camino de función en función en el núcleo de WordPress y la cadena se divide en & y se convierte en un array antes de procesarse...

User User
22 sept 2010 23:33:55

Según el Codex: Nota: el valor 99 será considerado mayor que 100 ya que los datos se almacenan como cadenas, no como números. Por lo tanto, meta_value se está almacenando como una cadena... por eso WordPress añade las comillas. Mi siguiente pregunta sería, ¿puedes describir cómo esto "no funciona"? ¿Está devolviendo datos al menos?

EAMann EAMann
22 sept 2010 23:47:45

¡Sí, tienes razón! Como dije antes, no importa lo que haga, se envuelve en '5'. MySQL no puede comparar algo a nivel numérico si está envuelto en '', así que me pregunto por qué WordPress ha implementado esta función si no funciona. No, devuelve resultados pero simplemente no los deseados.

User User
22 sept 2010 23:50:38

Mira mi actualización anterior. Agregar orderby=meta_value_num debería solucionar el problema si estás ejecutando WP 2.8.4 o posterior.

EAMann EAMann
23 sept 2010 00:12:55

Gracias por todos los esfuerzos. Pero eso tampoco funciona. Realmente investigué a fondo este tema y simplemente no está soportado por WP. ¡Crearé un ticket para este issue porque es realmente fácil de solucionar y permitiría muchas cosas!

User User
23 sept 2010 21:31:34

@Joakim Sí, esto está soportado por WP. Lee el ticket que referencié arriba donde se agregó esta funcionalidad. Tal vez podrías compartirnos un fragmento de código más grande de lo que estás intentando hacer... podría haber un problema diferente.

EAMann EAMann
23 sept 2010 22:05:47
Mostrar los 1 comentarios restantes
0

WordPress trata todos los 'valores' como cadenas de texto y les añade comillas simples en la consulta final, por lo que SQL también se ve obligado a tratarlos como cadenas y no como números. Puedes eliminar estas comillas con un filtro:

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

Y asegúrate de tener 'type' => 'NUMERIC' o similar

7 feb 2025 18:42:35