WP_query: meta_key con regla personalizada para valor específico

5 may 2013, 20:59:11
Vistas: 22.6K
Votos: 2

Me encuentro atascado con un código de WP_Query. Aquí está:

$args = array(
      'post_type' => 'post',
      'meta_query'=> array(
          'key' => 'karma',
          'compare' => '>=',
          'value' => 0,
          'type' => 'numeric'),
        'posts_per_page' => 9,
        'meta_key' => 'karma',
        'orderby' => 'meta_value_num', 
        'order' => 'DESC',
        'post__not_in' => $dont_show_me
    );

Lo que quiero hacer:

Mostrar todas las entradas con karma >= 0 (esto funciona bien con este código). PERO si hay entradas con karma = 100, mostrar solo 3 de ellas + el resto de las entradas.

Ejemplos: 9 entradas con karma = 150, 133, 100, 100, 100, 100, 100, 33, 11.

Quiero mostrar: 150, 133, 100, 100, 100, 33, 11. (Solo se permiten 3 entradas con karma = 100).

¿Tienen alguna idea de cómo lograr esto? ¿Tal vez un add_filter('posts_where');?

ACTUALIZACIÓN: Vale, lo conseguí funcionar, basado en la respuesta de @s_ha_dum. Es un poco complicado, pero el resultado funciona ;)

$args = array(
       // Buscar las últimas 9 entradas con karma = 100
       'post_type' => 'post',
       'meta_query'=> array(
          array(
              'key' => 'karma',
              'compare' => '=', 
              'value' => 100,
              'type' => 'numeric'
           )
        ),
       'posts_per_page' => 9,
       'meta_key' => 'karma',
       'orderby' => 'meta_value_num', 
       'order' => 'DESC',
       'post__not_in' => $dont_show_me
    );
    $karma_qry = new WP_Query($args);

    if (!empty($karma_qry->posts)) {
        $i = 0;
        foreach ($karma_qry->posts as $p) {
            $i++;
            // Verificar si hay más de 3 entradas con karma = 100
            // Agregarlas al array $dont_show_me
            if($i > 3){
                $dont_show_me[] = $p->ID;
            }
        }
    }

    // Configurar la consulta final que excluye las entradas adicionales con karma = 100
    $args['meta_query'][0]['compare'] = '>=';
    $args['meta_query'][0]['value'] = 0;
    $args['post__not_in'] = $dont_show_me;

    $wp_query = new WP_Query($args);
0
Todas las respuestas a la pregunta 1
4

Un meta_query es un array de arrays. Revisa los ejemplos en el Codex.

 $args = array(
   'post_type' => 'my_custom_post_type',
   'meta_key' => 'age',
   'orderby' => 'meta_value_num',
   'order' => 'ASC',
   'meta_query' => array(
       array(
           'key' => 'age',
           'value' => array(3, 4),
           'compare' => 'IN',
       )
   )
 );
 $query = new WP_Query($args);

Lo que tienes es solo un array. Eso podría estar causando problemas. Lo que quieres hacer es esto:

$args = array(
   'post_type' => 'post',
   'meta_query'=> array(
      array(
          'key' => 'karma',
          'compare' => '>=', // limitar a "valor de karma = 100"
          'value' => 0, // limitar a "valor de karma = 100"
          'type' => 'numeric'
       )
    ),
   'posts_per_page' => 9,
   'meta_key' => 'karma',
   'orderby' => 'meta_value_num', 
   'order' => 'DESC',
   'post__not_in' => $dont_show_me
);

Sin embargo, para llegar a la pregunta en sí, no puedes hacer una lógica tan complicada como necesitas...

Mostrar todos los posts con karma >= 0 (funciona bien con este código). PERO si hay posts con karma = 100, mostrar solo 3 de ellos + el resto de posts.

... con una sola WP_Query. Eso suena como que quieres obtener 3, y solo 3, posts con karma mayor a 100, y completar el resto con cualquier otro. Eso sería complicado con SQL puro. Creo que es posible en SQL pero tendría que pensarlo mucho para estar seguro, y aún más para hacerlo funcionar.

Sugeriría dos consultas: una para obtener los "mayores a 100" y una segunda para el resto.

$dont_show_me = array(1);
$args = array(
   'post_type' => 'post',
   'meta_query'=> array(
      array(
          'key' => 'karma',
          'compare' => '>=', 
          'value' => 100,
          'type' => 'numeric'
       )
    ),
   'posts_per_page' => 3,
   'meta_key' => 'karma',
   'orderby' => 'meta_value_num', 
   'order' => 'DESC',
   'post__not_in' => $dont_show_me
);
$karma_qry = new WP_Query($args);

if (!empty($karma_qry->posts)) {
  $args['posts_per_page'] = 9 - $karma_qry->found_posts;
  $args['meta_query'][0]['value'] = 0;
  foreach ($karma_qry->posts as $p) {
      // asumiendo que $dont_show_me es un array
      $dont_show_me[] = $p->ID;
  }
  $args['post__not_in'] = $dont_show_me;
} else {
  $args['posts_per_page'] = 9;
  $args['meta_query'][0]['value'] = 0;
}

$the_rest_qry = new WP_Query($args);

No puedo probar esto ya que no tengo tus datos de karma en mi servidor, pero estoy bastante seguro de que es correcto. Debería llevarte la mayor parte del camino, al menos.

5 may 2013 21:40:22
Comentarios

Gracias por tu respuesta. Pero tu código solo muestra publicaciones con karma = 100. Yo quiero mostrar todas las publicaciones con karma >= 0 PERO si la publicación tiene karma = 100, solo mostrar 3 de ellas. (Editaré mi pregunta).

hawkidoki hawkidoki
5 may 2013 22:12:37

@hawkidoki : mira la edición.

s_ha_dum s_ha_dum
6 may 2013 00:12:49

¡Solución realmente interesante! Para otras personas, hay un error cerca del final de tu código $args['post__no_in'] (es post__not_in).

Tu solución parece funcionar, aunque debo ajustarla un poco, pero la idea es genial :) ¡Muchas gracias!

hawkidoki hawkidoki
6 may 2013 01:23:41

@hawkidoki : Corregiré ese error. Gracias. Tanto las preguntas como las respuestas son editadas por la comunidad aquí, como un wiki. Puedes corregir errores como ese tú mismo.

s_ha_dum s_ha_dum
6 may 2013 02:39:11