Como personalizar la búsqueda con WP_Query y meta_query en WordPress

Contents

Introducción

Este tutorial explica en detalle cómo personalizar la búsqueda en WordPress usando WP_Query y meta_query. Verás desde conceptos básicos hasta trucos avanzados para buscar y filtrar por campos meta (custom fields), combinar condiciones, ordenar por meta values, y cómo integrar la búsqueda de meta values con la búsqueda estándar. También incluimos ejemplos de código listos para copiar y adaptar.

Conceptos clave

  • WP_Query: la clase principal para consultar posts en WordPress. Permite pasar parámetros como post_type, s (término de búsqueda), meta_query, tax_query, orderby, etc.
  • meta_query: argumento de WP_Query para filtrar resultados según valores en la tabla wp_postmeta. Permite múltiples reglas y relaciones (AND / OR).
  • Performance: las consultas que unen con wp_postmeta suelen ser lentas en bases de datos grandes. Es importante limitar joins, indexar cuando sea posible y considerar soluciones alternativas (tabla personalizada, búsqueda externa, caché).
  • Seguridad: siempre sanitiza la entrada del usuario (sanitize_text_field, intval) y evita concatenar entradas directamente en SQL sin preparación.

Cómo funciona la búsqueda por defecto en WordPress

La búsqueda por defecto (parámetro s en WP_Query) busca en post_title y post_content (y post_excerpt en algunas versiones/ajustes). No incluye automáticamente los valores de postmeta. Para incluir meta values en la búsqueda hay que:

  • Filtrar la consulta SQL (posts_join, posts_where y posts_distinct) para unir y buscar en wp_postmeta.
  • O construir meta_query explícitos que busquen un término concreto en meta keys específicas.

Uso básico de WP_Query con meta_query

La estructura básica de meta_query es un array de arrays. Cada entrada puede contener: key, value, compare y type. Además hay una clave superior relation que puede ser AND u OR.

Ejemplo: buscar posts con un meta_key igual a un valor

lt?php
args = array(
  post_type      =gt post,
  posts_per_page =gt 10,
  meta_query     =gt array(
    array(
      key     =gt mi_meta_key,
      value   =gt valor-buscado,
      compare =gt =,
      type    =gt CHAR,
    ),
  ),
)

query = new WP_Query(args)

if ( query-gthave_posts() ) {
  while ( query-gthave_posts() ) {
    query-gtthe_post()
    // salida del post...
  }
  wp_reset_postdata()
}
?gt

Comparadores y tipos comunes

  • compare: =, !=, LIKE, NOT LIKE, IN, NOT IN, BETWEEN, NOT BETWEEN, EXISTS, NOT EXISTS, gt, lt, gt=, lt=.
  • type: NUMERIC, BINARY, CHAR, DATE, DATETIME, DECIMAL, SIGNED, UNSIGNED. Define cómo compara MySQL.

Ejemplo: rango numérico (BETWEEN)

lt?php
args = array(
  post_type =gt producto,
  meta_query =gt array(
    array(
      key     =gt precio,
      value   =gt array(100, 500),
      compare =gt BETWEEN,
      type    =gt NUMERIC,
    ),
  ),
)

query = new WP_Query(args)
?gt

Ejemplo: filtrar por existencia de meta_key

lt?php
args = array(
  post_type =gt post,
  meta_query =gt array(
    array(
      key     =gt campo_opcional,
      compare =gt EXISTS,
    ),
  ),
)
query = new WP_Query(args)
?gt

Combinando meta_query con tax_query y búsqueda por texto

Puedes combinar meta_query con tax_query o el parámetro s. WP_Query ejecutará todas las condiciones, pero recuerda: s no busca meta values a menos que modifiques la consulta SQL.

Ejemplo: combinar meta_query, tax_query y ordenar por meta

lt?php
args = array(
  post_type      =gt producto,
  posts_per_page =gt 12,
  s              =gt bicicleta,
  meta_key       =gt precio,
  orderby        =gt meta_value_num,
  order          =gt ASC,
  meta_query     =gt array(
    relation =gt AND,
    array(
      key     =gt precio,
      value   =gt array(200, 1500),
      compare =gt BETWEEN,
      type    =gt NUMERIC,
    ),
    array(
      key     =gt stock,
      value   =gt 0,
      compare =gt >,
      type    =gt NUMERIC,
    ),
  ),
  tax_query => array(
    array(
      taxonomy =gt categoria_producto,
      field    =gt slug,
      terms    =gt deporte,
    ),
  ),
)
query = new WP_Query(args)
?gt

Buscar el término de búsqueda también dentro de meta values

Si quieres que el término introducido en el campo de búsqueda busque también dentro de ciertos campos meta (por ejemplo subtitle, sku, author_name guardado en meta), debes modificar la SQL que genera WordPress porque s sólo cubre título y contenido por defecto. A continuación hay un enfoque común: añadir JOIN y WHERE para buscar en postmeta y asegurar DISTINCT para evitar duplicados.

Ejemplo: incluir meta_value en la búsqueda global

lt?php
// Añade estos filtros en functions.php o en un plugin.
// Atención: usa sanitización y condiciones para no afectar otras consultas.
add_filter(posts_join, mi_join_postmeta_para_busqueda)
add_filter(posts_where, mi_where_postmeta_para_busqueda)
add_filter(posts_distinct, mi_distinct_postmeta_para_busqueda)

function mi_join_postmeta_para_busqueda(join) {
  global wpdb
  if ( is_search()  !is_admin() ) {
    join .=  LEFT JOIN wpdb->postmeta AS pm ON (wpdb->posts.ID = pm.post_id) 
  }
  return join
}

function mi_where_postmeta_para_busqueda(where) {
  global wpdb, wp_query
  if ( is_search()  !is_admin() ) {
    search = get_query_var(s)
    if ( ! empty( search ) ) {
      // Escapa el término de búsqueda correctamente
      like = % . wpdb-gtesc_like( search ) . %
      like = esc_sql( like )
      // Añade condición para meta_value (aquí se busca en cualquier meta_key)
      where .=  OR (pm.meta_value LIKE {like}) 
    }
  }
  return where
}

function mi_distinct_postmeta_para_busqueda(distinct) {
  if ( is_search()  !is_admin() ) {
    return DISTINCT
  }
  return distinct
}
?gt

Notas sobre este enfoque:

  • Busca en cualquier meta_key porque el JOIN no está restringido. Puedes limitarlo a una o varias meta_keys añadiendo AND pm.meta_key IN (clave1,clave2) en la cláusula ON o en WHERE.
  • Hay que tener cuidado con duplicados (por eso DISTINCT).
  • Es costoso en tablas grandes. Considera limitar con una condición adicional o implantar caché.

Ejemplo alternativo: usar meta_query LIKE con valores exactos de meta_key

Si conoces las meta_keys que quieres buscar, puedes construir una meta_query con varios elementos que = o LIKE el término de búsqueda. Así no necesitas manipular SQL globalmente.

lt?php
search = sanitize_text_field( get_search_query() )

args = array(
  post_type  =gt post,
  s          =gt , // opcional: dejar vacío para no duplicar lógica de búsqueda
  meta_query =gt array(
    relation =gt OR,
    array(
      key     =gt subtitle,
      value   =gt search,
      compare =gt LIKE,
      type    =gt CHAR,
    ),
    array(
      key     =gt sku,
      value   =gt search,
      compare =gt LIKE,
      type    =gt CHAR,
    ),
  ),
)

query = new WP_Query(args)
?gt

Cómo ordenar por meta value

Usa meta_key y orderby =gt meta_value o meta_value_num para ordenar por el valor de un campo meta. Si hay varios criterios de ordenación, puedes pasar un array en orderby.

lt?php
args = array(
  post_type =gt producto,
  meta_key  =gt precio,
  orderby   =gt meta_value_num,
  order     =gt DESC,
)
query = new WP_Query(args)
?gt

Casos avanzados y consideraciones

  • Nesting complejo (grupos dentro de grupos): WP_Query soporta relation para un nivel. Si necesitas grupos anidados con prioridades diferentes (por ejemplo, (A AND B) OR (C AND D)), la forma sencilla con WP_Meta_Query es limitada. En ese caso presta atención a filtros SQL (posts_clauses) o construye múltiples consultas y combina resultados en PHP.
  • Campos serializados: Buscar dentro de arrays serializados es frágil. Mejor normalizar datos o usar tablas/taxonomías alternativas.
  • Índices y rendimiento: wp_postmeta no indexa meta_value por defecto. Si dependes mucho de búsquedas por meta_value, considera una tabla personalizada con índices adecuados, o usar soluciones de búsqueda (Elasticsearch, Algolia, etc.).
  • Caché y transients: Para consultas costosas, guarda resultados en transient o usa object cache para reducir número de consultas al DB.
  • Seguridad: Sanitiza: sanitize_text_field, intval. Para fragmentos SQL use wpdb-gtprepare cuando construyas consultas manuales. Evita concatenar sin escapar.

Buenas prácticas

  1. Especifica siempre post_type si no quieres todos los tipos (evita overhead).
  2. Limita meta_query solo a las claves necesarias.
  3. Usa meta_key amp meta_value cuando necesites filtros simples y rendimiento.
  4. Prueba la consulta en entornos con datos reales para medir impacto.
  5. Considera búsquedas asincrónicas o índices externos si el dataset es grande.

Recursos útiles

Resumen práctico

WP_Query meta_query te permiten filtrar posts por campos meta con granularidad y flexibilidad. Para buscar texto dentro de meta values tienes dos enfoques principales: construir meta_query con LIKE para claves conocidas, o extender la consulta SQL (JOIN WHERE) para incluir meta_value en la búsqueda global. La segunda opción es más poderosa pero también más costosa, por lo que hay que usarla con precaución y aplicar caché o limitar el alcance cuando sea necesario.



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 *