Ordenar la búsqueda de WordPress por relevancia

8 minutos de lectura

avatar de usuario
boya de poder

Creé una búsqueda bastante avanzada para un sitio de WordPress en el que estoy trabajando atm. Permitir a los visitantes filtrar los resultados por diferentes taxonomías, ordenarlos por fecha o campos personalizados, así como la búsqueda normal de texto libre (que WP ofrece de forma predeterminada).

He logrado esto usando el pre_get_posts filtro y simplemente agregando mis cosas a la consulta, algo como esto: (tenga en cuenta que he omitido algunos controles de cordura y otro código)

<?php
add_filter('pre_get_posts', 'my_search');

function my_search ($qry) {
    # Include more post types
    $qry->set('post_type', array('foo', 'bar'));

    if ($_GET['myorder'] == 'price') {
        $qry->set('orderby', 'meta_value_num');
        $qry->set('meta_key', 'price');
        $qry->set('order', 'ASC');
    }
    else {
        $qry->set('orderby', 'date');
        $qry->set('order', 'DESC');
    }
}

Ahora me gustaría agregar otra forma de ordenar las publicaciones, es decir, por relevancia. Entiendo que esta es una solicitud muy común y la mayoría de las soluciones al problema que he visto incluyen el uso del complemento Relevanssi. Dado que ya escribí mi propio “complemento” (bueno, al menos el código) y tengo todos mis formularios de búsqueda y listados configurados para usarlo, cambiar a Relevanssi no será demasiado fácil en este momento.

Entonces, me gustaría saber si alguien conoce alguna forma (preferiblemente) fácil de agregar esto con el código que ya tengo.

Según tengo entendido, WP hace su búsqueda usando LIKE en vez de MATCH() y por eso ni siquiera tener una puntuación de relevancia para ordenar. Si esto es correcto, supongo que tendría que escribir mi propia consulta por completo. ¿Cómo puedo hacer esto sin estropear la paginación de WP, etc.? O podría agregar algo como $qry->set('WHERE', "MATCH(post_content) AGAINST('$q' IN BOOLEAN MODE) AS relevance"); $qry->set('sortby', 'relevance') ¿Qué te parece?

  • Sé que este complemento hace un muy buen trabajo: Relevantes. Tal vez ayude a llenar los vacíos.

    – brasofilo

    20 de julio de 2013 a las 1:29

  • Gracias, pero si lees toda la pregunta verás por qué no quiero usar eso.

    – boya de energía

    20 de julio de 2013 a las 11:30

  • Sí, lo entendí, solo pensé que tal vez se podrían extraer algunas cosas útiles de él. ¡Buena suerte, gran Q!

    – brasofilo

    20 de julio de 2013 a las 11:33

  • A Relevanssi no le va bien con los que no están en inglés.

    – Khom Nazid

    9 abr a las 23:49

avatar de usuario
el alfa

creo que puedes usar Relevanssi sin ningún problema pero necesita usar un filter anzuelo, comprobar relevantesi_modify_wp_query para más detalles, consulte el siguiente código

function func_reli($qry){
    $qry->set( 'post_type', array( 'post', 'page', 'restaurant', 'products' ) );

    if ($_GET['myorder'] == 'price') {
        $qry->set('orderby', 'meta_value_num');
        $qry->set('meta_key', 'price');
        $qry->set('order', 'ASC');
    }
    else {
        $qry->set('orderby', 'date');
        $qry->set('order', 'DESC'); // <-- set (in your code 'add' is used)
    }
    return $qry; // <-- must return, in your code you didn't
}
add_filter('relevanssi_modify_wp_query', 'func_reli');

He probado este código y simplemente funciona bien. En este ejemplo he usado 'restaurant' y 'products' los tipos de publicaciones personalizadas y la búsqueda funcionan muy bien, solo los resultados relevantes. También puedes usar si php 5.3+ esta instalado

add_filter('relevanssi_modify_wp_query', function($qry){
    // Same code
});

Además, si usas Relevantes complemento, puede usar su página de configuración para configurar post_type en lugar de usar esto ($qry->set( 'post_type', array(...) )) en tus functions.php expediente.

Captura de pantalla dada a continuación

ingrese la descripción de la imagen aquí

  • Gracias por una muy buena respuesta, probaré Relevanssi y volveré.

    – boya de energía

    21 de julio de 2013 a las 22:04

  • Ok, esto parecía prometedor pero por alguna razón no está funcionando. Parece que puedo ordenar por fecha, pero tratar de ordenar por mi campo personalizado da como resultado el mismo orden que la relevancia (o nada establecido). No tengo idea de por qué. Parece que la mayoría de la gente usa el relevanssi_hits_filter filter para agregar su propio tipo, pero eso parece mucho más complicado (no puede usar el objeto WPQuery, sino que debe ordenar una matriz usted mismo). ¿Ideas?

    – boya de energía

    22/07/2013 a las 19:50

  • También lo necesito para trabajar con búsquedas vacías y filtrar por taxonomías personalizadas. No parece ser tan fácil como sugiere esta respuesta.

    – boya de energía

    22 de julio de 2013 a las 19:55

  • Ok, terminé usando Relevanssi después de todo, pero con un gancho diferente y un código completamente diferente (el relevanssi_hits_filter mencioné antes). tuve que usort() la matriz de publicaciones yo mismo en lugar de confiar en la configuración “ordenar por” de WP. Sin embargo, funciona.

    – boya de energía

    23 de julio de 2013 a las 1:12

  • Me alegra saber eso, ¿te importaría compartirlo con la comunidad?

    – El alfa

    23 de julio de 2013 a las 1:16

Ok, terminé usando Relevanssi después de todo. Pero con bastantes modificaciones.

En primer lugar, el filtrado de taxonomías fue bastante fácil ya que esto está integrado en Relevanssi, todo lo que tenía que hacer era cambiar los nombres de mis <select> elementos a los nombres de la taxonomía + cambiar los valores a los slugs:

<select name="custom_taxonomy">
    <option value="some-term">Some term</option>
    ...
</select>

En segundo lugar, para permitir la clasificación por un campo personalizado, tuve que usar el relevanssi_hits_filter filtrar. A diferencia de pre_get_posts o relevanssi_modify_wp_query (que Sheikh Heera sugirió amablemente), este filtro pasa la variedad de publicaciones y no un objeto WP_Query. Cuando traté de usar el objeto WP_Query, el orden simplemente se negó a cambiar. Aquí se explica básicamente cómo hacer su propia ordenación con relevanssi_hits_filter:

<?php
add_filter('relevanssi_hits_filter', 'h5b_hits_filter');

function h5b_hits_filter ($hits) {
    global $wp_query;

    if (isset($wp_query->query_vars['orderby']) and $wp_query->query_vars['orderby'] == 'price') {
        if (count($hits[0])) {
            usort($hits[0], 'h5b_sort_by_price');
        }
    }

    return $hits;
}

function h5b_sort_by_price ($a, $b) {
    $priceKey   = 'price';
    $aPrice     = get_post_meta($a->ID, $priceKey, true);
    $bPrice     = get_post_meta($b->ID, $priceKey, true);
    $aPrice     = $aPrice ? $aPrice : 10000000;
    $bPrice     = $bPrice ? $bPrice : 10000000;

    if ($aPrice == $bPrice) {
        return 0;
    }

    return ($aPrice < $bPrice) ? -1 : 1;
}

Esto también ayudó con un problema anterior que tuve en las publicaciones que faltaba la clave de “precio” no apareció en las búsquedas. Ahora lo hacen, y la razón por la que les doy un precio de “10000000” es para que aparezcan. después los que si tienen precio.

Finalmente, también necesitaba búsquedas vacías trabajar. Según el desarrollador de Relevanssi, esto solo es compatible con la versión Premium, pero creo que logré solucionarlo. Primero obligué a WP a mostrar la página de búsqueda incluso si ?s estaba vacío:

<?php
add_filter('request', 'h5b_allow_empty_search');

function h5b_allow_empty_search ($qryVars) {
    if (isset($_GET['s']) and empty($_GET['s'])) {
        $qryVars['s'] = ' ';
    }

    return $qryVars;
}

En segundo lugar, le dije a Relevanssi que buscara todos publica si ?s estaba vacío, por defecto no obtendrá ninguna publicación. Desafortunadamente, al hacer esto, el comportamiento predeterminado con taxonomías personalizadas dejó de funcionar (mi código lo sobreescribió), por lo que también tuve que verificar manualmente las taxonomías en este código:

<?php
add_filter('relevanssi_hits_filter', 'h5b_allow_empty_search_filter');

function h5b_allow_empty_search_filter ($hits) {
    if (isset($_GET['s']) and empty($_GET['s']) and !count($hits[0])) {
        $taxQry = array('relation' => 'AND');

        if (!empty($_GET['custom_taxonomy'])) {
            $taxQry[] = array(
                'taxonomy' => 'custom_taxonomy', 
                'field' => 'slug', 
                'terms' => $_GET['custom_taxonomy']
            );
        }

        $args = array(
            'numberposts' => -1, 
            'post_type' => 'any'
        );

        if (count($taxQry) > 1) {
            $args['tax_query'] = $taxQry;
        }

        $hits[0] = get_posts($args);
    }

    return $hits;
}

Y eso es. Todo parece funcionar y, con suerte, esto ayudará a alguien que tenga solicitudes similares en el futuro.

Realmente espero que WP mejore su ridícula búsqueda en el futuro. Ordenar por relevancia debería ser algo que esté disponible en el CMS imo más popular del mundo.

Gracias @Sheikh Heera por indicarme la dirección correcta. No estoy seguro de a quién darle la respuesta correcta, ya que realmente no podría usar las cosas que sugeriste.

Acabo de descubrir que WP ya tiene esto en el núcleo.

En https://developer.wordpress.org/reference/classes/wp_query/mire el parámetro “orderby” => “relevance”.

Ordene por términos de búsqueda en el siguiente orden: Primero, si la oración completa coincide. Segundo, si todos los términos de búsqueda están dentro de los títulos. Tercero, si alguno de los términos de búsqueda aparece en los títulos. Y, cuarto, si en el contenido aparece la frase completa.

  • Esta debería ser la respuesta correcta. ¡Gracias por compartirlo!

    – Khom Nazid

    9 abr a las 23:53

¿Ha sido útil esta solución?