¿Cómo hacer que la búsqueda incluya datos de wp_postmeta?

8 dic 2011, 15:51:39
Vistas: 47.7K
Votos: 16

Tengo un sitio que usa Advanced Custom Fields para crear y almacenar varios fragmentos de información relevante. Estos necesitan ser incluidos en la búsqueda general principal, que por defecto solo busca en el título y el contenido principal.

He encontrado bastante información sobre cómo obtener resultados de búsqueda basados en fragmentos específicos de postmeta, pero tengo un problema con eso. Hay una cantidad potencialmente ilimitada de campos posibles en postmeta para buscar.

La solución podría ser buscar cualquier cosa en postmeta o cualquier cosa con un meta_key que coincida con esta expresión regular: content_section_[0-9]{1,4}_content_.{2,8}

Ejemplos de meta_keys que deberían coincidir son:

content_section_0_content_title
content_section_0_content_title
content_section_4_content_subtitle
content_section_8_content_text

Cualquier forma en que pueda modificar los campos buscados para incluir el postmeta sería muy apreciada.

2
Comentarios

¿y la pregunta es?

Naoise Golden Naoise Golden
8 dic 2011 23:31:53

La búsqueda en WordPress no busca datos del meta de las publicaciones - solo busca en los campos de título y contenido. Actualizaré la pregunta principal para aclararlo.

Jodi Warren Jodi Warren
9 dic 2011 02:53:07
Todas las respuestas a la pregunta 6
2
11

Añade esto a tu plugin o al archivo functions.php de tu tema. El siguiente ejemplo incluirá 'your_key' en las búsquedas. Puedes incluir todas tus claves repitiendo el array.


function me_search_query( $query ) {
  if ( $query->is_search ) {
    $meta_query_args = array(
      array(
        'key' => 'your_key',
        'value' => $query->query_vars['s'] = '',
        'compare' => 'LIKE',
      ),
    );
    $query->set('meta_query', $meta_query_args);
  };
}
add_filter( 'pre_get_posts', 'me_search_query');
10 sept 2015 01:32:09
Comentarios

Esto solo coincidirá con publicaciones que coincidan con el término de búsqueda en el título/contenido y en el campo meta, lo cual no es cómo funciona típicamente una búsqueda de texto completo.

David David
9 jul 2017 19:16:13

Esto será extremadamente lento ya que los valores meta no están indexados.

vancoder vancoder
18 ago 2020 21:31:38
3

Esta función debería funcionar, incluso después de la actualización de seguridad de WP 4.8.3.

Uso:

// Haz esto en functions.php

add_meta_field_to_search_query('right_data');
add_meta_field_to_search_query('extra_search_terms');

Implementación:

/* AÑADIR CAMPO META A LA CONSULTA DE BÚSQUEDA */

function add_meta_field_to_search_query($field){
  if(isset($GLOBALS['added_meta_field_to_search_query'])){
    $GLOBALS['added_meta_field_to_search_query'][] = '\'' . $field . '\'';

    return;
  }

  $GLOBALS['added_meta_field_to_search_query'] = array();
  $GLOBALS['added_meta_field_to_search_query'][] = '\'' . $field . '\'';

  add_filter('posts_join', function($join){
      global $wpdb;

      if (is_search()){    
          $join .= " LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id ";
      }

      return $join;
  });

  add_filter('posts_groupby', function($groupby){
      global $wpdb;

      if (is_search()) {    
          $groupby = "$wpdb->posts.ID";
      }

      return $groupby;
  });

  add_filter('posts_search', function($search_sql){
      global $wpdb;

      $search_terms = get_query_var('search_terms');

      if(!empty($search_terms)){
        foreach ($search_terms as $search_term){
            $old_or = "OR ({$wpdb->posts}.post_content LIKE '{$wpdb->placeholder_escape()}{$search_term}{$wpdb->placeholder_escape()}')";
            $new_or = $old_or . " OR ({$wpdb->postmeta}.meta_value LIKE '{$wpdb->placeholder_escape()}{$search_term}{$wpdb->placeholder_escape()}' AND {$wpdb->postmeta}.meta_key IN (" . implode(', ', $GLOBALS['added_meta_field_to_search_query']) . "))";
            $search_sql = str_replace($old_or, $new_or, $search_sql);
        }
      }

      $search_sql = str_replace( " ORDER BY ", " GROUP BY $wpdb->posts.ID ORDER BY ", $search_sql );

      return $search_sql;
  });
}

Varias personas han hecho esto de diferentes maneras:

http://websmartdesign.nz/searching-structured-post-data-with-wordpress/ https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/

28 ago 2017 13:42:45
Comentarios

El enlace para adambalee.com funcionó para mí. Simplemente realiza una búsqueda general en todos los meta datos de las publicaciones.

Joe Joe
29 ene 2019 17:09:24

Igualmente, la solución vinculada en https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/ funcionó para mí en WordPress 5.1.1...

jsmod jsmod
29 mar 2019 17:55:20

¿encontraste una manera de buscar solo en algunos campos personalizados? Tengo muchos y casi cada búsqueda coincide con algún contenido incluso si es solo para el administrador.

v3nt v3nt
16 jun 2020 18:59:42
1

Esta es una respuesta mejorada de Ahmed:

function me_search_query( $query ) {
  if ( $query->is_search ) {
    $meta_query_args = array(
      array(
        'key' => 'your_key', // Cambia 'your_key' por tu clave de metadato real
        'value' => $query->query_vars['s'], // Valor de búsqueda
        'compare' => 'LIKE', // Comparación tipo LIKE
      ),
    );
    $query->set('meta_query', $meta_query_args);
    add_filter( 'get_meta_sql', 'me_replace_and_with_or' );
  };
}

function me_replace_and_with_or( $sql ) {
    if ( 1 === strpos( $sql['where'], 'AND' ) ) {
        $sql['where'] = substr( $sql['where'], 4 );
        $sql['where'] = ' OR ' . $sql['where'];
    }

    // Asegurarse que este filtro solo se ejecute una vez para la consulta de metadatos
    remove_filter( 'get_meta_sql', 'me_replace_and_with_or' );
    return $sql;
}

add_filter( 'pre_get_posts', 'me_search_query');

El problema es que WordPress genera consultas de metadatos con el operador "AND", lo que mostraría solo las publicaciones que tienen la cadena de búsqueda en ambos lugares - título Y metadatos, o contenido Y metadatos. Por lo tanto, necesitamos crear un filtro adicional para cambiar "AND" a "OR" (y luego eliminar ese filtro para no afectar nada más).

29 dic 2018 18:28:28
Comentarios

Cambiar el AND por OR rompe la lógica SQL para filtrar el tipo de POST, por lo que la búsqueda se aplicará a todos los tipos de entradas, incluyendo adjuntos. Todavía estoy intentando encontrar una solución viable que funcione con búsqueda y filtros combinados en un CPT

Alan Fuller Alan Fuller
2 nov 2021 17:12:47
0

Si estás dispuesto a usar un plugin, Relevanssi - Una búsqueda mejorada podría valer la pena probarlo.

La versión estándar (gratuita) soporta la búsqueda en metadatos de entradas.

9 dic 2011 04:36:01
0

Esta es la solución más simple y actualmente funcional. Ninguna de las anteriores me funcionó. Está probado y funciona con WordPress 5.3.1.

Coloca el siguiente código en tu archivo functions.php para engancharlo al filtro posts_clauses.

/**
 * Incluir campos meta en la búsqueda
 * 
 * @author Mindaugas // meevly.com
 * @link https://meevly.com/services/custom-wordpress-themes-and-plugins/
 * 
 * @param array $pieces partes de la consulta.
 * @param WP_Query $args objeto de la consulta.
 * @return array
 */
function mv_meta_in_search_query( $pieces, $args ) {
    global $wpdb;

    if ( ! empty( $args->query['s'] ) ) { // solo ejecutar en consultas de búsqueda.
        $keywords        = explode(' ', get_query_var('s'));
        $escaped_percent = $wpdb->placeholder_escape(); // WordPress escapa "%" desde la versión 4.8.3, por lo que no podemos usar el carácter de porcentaje directamente.
        $query           = "";

        foreach ($keywords as $word) {
            $query .= " (unique_postmeta_selector.meta_value LIKE '{$escaped_percent}{$word}{$escaped_percent}') OR ";
        }

        if ( ! empty( $query ) ) { // añadir las opciones WHERE y JOIN necesarias.
            $pieces['where'] = str_replace( "((({$wpdb->posts}.post_title LIKE '{$escaped_percent}", "( {$query} (({$wpdb->posts}.post_title LIKE '{$escaped_percent}", $pieces['where'] );
            $pieces['join'] = $pieces['join'] . " INNER JOIN {$wpdb->postmeta} AS unique_postmeta_selector ON ({$wpdb->posts}.ID = unique_postmeta_selector.post_id) ";
        }
    }

    return $pieces;
}
add_filter( 'posts_clauses', 'mv_meta_in_search_query', 20, 2 );

Y tu consulta debería verse así. Por favor, ten en cuenta que suppress_filters => false es obligatorio! No funcionará sin ello.

$search_posts_array = array(
    'suppress_filters' => false,
    's'                => $keyword,
);

$search_results = get_posts( $search_posts_array );
9 ene 2020 13:18:39
0
-1

No estoy seguro, pero para obtener todas las claves/valores de campos personalizados para la búsqueda predeterminada se requeriría una llamada a la base de datos usando wpdb.

La alternativa a los plugins mencionados por goto10 es una solución mucho más sencilla.
Search Everything, WP Custom Fields Search

9 dic 2011 05:13:03