Filtro y ordenación avanzados en WP_Query

Contents

Introducción

WordPress ofrece WP_Query como la herramienta más flexible para recuperar publicaciones desde la base de datos. Si bien los parámetros básicos (post_type, posts_per_page, etc.) son suficientes para muchos casos, a menudo necesitaremos filtrar y ordenar resultados con criterios complejos: consultas sobre campos personalizados, taxonomías, rangos de fechas o incluso joins avanzados. Este artículo detalla en profundidad filtros y ordenaciones avanzados en WP_Query, mostrando ejemplos prácticos, consejos de rendimiento y referencias a fuentes oficiales.

1. Estructura básica de WP_Query

Un ejemplo mínimo de WP_Query:


args = array(
  post_type      => post,
  posts_per_page => 10,
  order          => DESC,
  orderby        => date,
)
query = new WP_Query( args )
  

1.1 Parámetros básicos

  • post_type: Tipo de contenido (post, page, custom).
  • posts_per_page: Número de resultados por página.
  • paged: Paginación actual.
  • orderby: Campo por el que ordenar (date, title, meta_value…).
  • order: ASC o DESC.

2. Filtros avanzados con parámetros compuestos

WP_Query permite agrupar condiciones para:

  • meta_query: Campos personalizados.
  • tax_query: Taxonomías (categorías, etiquetas, términos personalizados).
  • date_query: Fechas y rangos.

2.1 meta_query

Filtrar según campos meta (custom fields). Recibe un array de arrays con comparadores y tipos.

Parámetro Descripción
key Nombre del campo meta.
value Valor a comparar.
compare Operador (=, !=, >, <, LIKE…).
type Tipo de dato (NUMERIC, CHAR, DATE…).
relation AND / OR para combinar múltiples condiciones.

Ejemplo de uso:


args = array(
  post_type  => product,
  meta_query => array(
    relation => AND,
    array(
      key     => price,
      value   => array(50, 150),
      compare => BETWEEN,
      type    => NUMERIC,
    ),
    array(
      key     => stock_status,
      value   => in_stock,
      compare => =,
    ),
  ),
)
query = new WP_Query( args )
  

2.2 tax_query

Permite filtrar por taxonomías personalizadas o categorías/etiquetas.

  • taxonomy: Nombre de la taxonomía.
  • field: slug, term_id o name.
  • terms: Array de términos.
  • operator: IN, NOT IN, AND.
  • relation: AND / OR para múltiples cláusulas.

Ejemplo:


args = array(
  post_type => event,
  tax_query => array(
    relation => OR,
    array(
      taxonomy => event_type,
      field    => slug,
      terms    => array(conference,webinar),
    ),
    array(
      taxonomy => region,
      field    => term_id,
      terms    => array(4, 7),
      operator => NOT IN,
    ),
  ),
)
query = new WP_Query( args )
  

2.3 date_query

Filtrado en base a fechas de publicación o custom date fields.

  • after, before: Fechas o array con año, mes, día.
  • inclusive: true/false para incluir la fecha límite.
  • column: nombre de columna (post_date, post_modified…)

args = array(
  post_type  => post,
  date_query => array(
    array(
      after     => array(year=>2023,month=>1,day=>1),
      before    => 2023-12-31,
      inclusive => true,
    ),
  ),
)
query = new WP_Query( args )
  

3. Ordenación avanzada

WP_Query permite ordenar por múltiples criterios:

  • orderby como array: array(meta_value_num=>DESC,title=>ASC).
  • Ordenar por campos de taxonomía (term_order), por recuento de comentarios, por relevancia en búsquedas.
  • Combinar meta_key con orderby=meta_value o meta_value_num.

args = array(
  post_type => product,
  meta_key  => rating,
  orderby   => array(
    meta_value_num => DESC,
    date           => ASC,
  ),
)
query = new WP_Query( args )
  

4. Ganchos y filtros para personalizar la SQL

A veces resulta necesario modificar la consulta SQL sin recrear por completo WP_Query:

4.1 posts_where


add_filter(posts_where,mi_posts_where,10,2)
function mi_posts_where(where, query){
  if(query->get(filter_special)){
    global wpdb
    where .=  AND {wpdb->posts}.post_title LIKE %VIP%
  }
  return where
}
  

4.2 posts_join y posts_groupby

Para unir tablas adicionales (por ejemplo, tablas de custom tables o taxonomy):


add_filter(posts_join,mi_posts_join,10,2)
function mi_posts_join(join, query){
  if(query->get(join_custom)){
    global wpdb
    join .=  LEFT JOIN wp_custom_table ct ON ct.post_id = {wpdb->posts}.ID 
  }
  return join
}
  

5. Rendimiento y buenas prácticas

  • Evitar consultas excesivas: Cachear resultados con la API de objetos (Object Caching).
  • Reducir metadatos innecesarios: Solo seleccionar meta_query si es imprescindible.
  • Índices en base de datos: Para tablas meta y taxonomy relations.
  • Transients: Uso de set_transient para respuestas costosas.

6. Ejemplos avanzados combinados

Un caso complejo: listar cursos (course) disponibles, ordenados por rating y fecha de inicio, filtrando precio y categoría:


args = array(
  post_type      => course,
  posts_per_page => 20,
  meta_query     => array(
    relation => AND,
    array(
      key     => start_date,
      value   => date(Y-m-d),
      compare => >=,
      type    => DATE,
    ),
    array(
      key     => price,
      value   => array(0,200),
      compare => BETWEEN,
      type    => NUMERIC,
    ),
  ),
  tax_query      => array(
    array(
      taxonomy => course_category,
      field    => slug,
      terms    => array(web,design),
    ),
  ),
  orderby => array(
    meta_value     => DESC,  // rating (string)
    meta_value_num => ASC,   // student_count (número)
    date           => DESC,
  ),
  meta_key => rating,
)
query = new WP_Query(args)
  

Conclusión

WP_Query es un componente fundamental para controlar el loop de WordPress. Combinar meta_query, tax_query y date_query junto a orderby múltiple permite construir filtros potentes. Para casos extremos, los ganchos posts_where, posts_join y similares facilitan la modificación directa de la SQL. Finalmente, no olvides contemplar el rendimiento: cachea, emplea índices y evita consultas innecesarias.



Acepto donaciones de BAT's mediante el navegador Brave 🙂



Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *