Сортировка поиска Wordpress по релевантности

Я создал довольно расширенный поиск для сайта Wordpress, над которым я работаю в atm. Позволяет посетителям фильтровать результаты по различным таксономиям, сортировать их по дате или настраиваемым полям, а также обычный бесплатный текстовый поиск (который WP предлагает по умолчанию).

Я выполнил это, используя pre_get_posts фильтр и просто добавив мои вещи в запрос, что-то вроде этого: (обратите внимание, что я пропустил некоторые проверки здравомыслия и другой код)

<?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');
    }
}

теперь я хотел бы добавить еще один способ сортировки сообщений, а именно по релевантности. Я понимаю, что это действительно распространенный запрос, и большинство решений проблемы, которые я видел, включают использование плагина Relevanssi. Поскольку я уже написал свой собственный "плагин" (ну, по крайней мере, код) и все мои формы поиска и списки настроены на использование этого, переключение на Relevanssi не будет слишком легким на данный момент.

Sooo, я хотел бы знать, знает ли кто-нибудь о некотором (желательно) простом способе добавить это с помощью кода, который у меня уже есть получил?

насколько я понимаю, WP выполняет поиск с помощью LIKE вместо MATCH() и именно поэтому он даже не есть оценка релевантности для сортировки. Если это правильно, я предполагаю, что мне придется написать свой собственный запрос вообще? Как я могу это сделать, не испортив разбиение на страницы WP и т. д.? Или я могу добавить что-то вроде $qry->set('WHERE', "MATCH(post_content) AGAINST('$q' IN BOOLEAN MODE) AS relevance"); $qry->set('sortby', 'relevance') ты думаешь?

2 ответов


Я думаю, вы можете использовать Relevanssi без каких либо проблем, но нужно использовать filter крюк, проверить relevanssi_modify_wp_query для получения более подробной информации проверьте следующий код

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');

я тестировал этот код и просто отлично работает. В этом примере я использовал 'restaurant' и 'products' пользовательские типы сообщений и поиск работают очень хорошо, только соответствующие результаты. Вы также можете использовать if php 5.3+ установлен

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

кроме того, если вы используете Relevanssi плагин, вы можете использовать его настройки страницы, чтобы установить post_type вместо этого ($qry->set( 'post_type', array(...) )) в .

осыпь выстрел ниже

enter image description here


ОК, поэтому я в конечном итоге использовал Relevanssi в конце концов. Но с некоторыми изменениями.

прежде всего, фильтрация по таксономиям была довольно простой, так как это встроено в Relevanssi, все, что мне нужно было сделать, это изменить имена моих <select> элементы в имена таксономии + измените значения на слизни:

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

во-вторых, чтобы разрешить сортировку по пользовательскому полю, я должен был использовать relevanssi_hits_filter фильтр. В отличие от pre_get_posts или relevanssi_modify_wp_query (что любезно предложил Шейх Хира), это фильтр получает переданный массив сообщений и не объект WP_Query. Когда я попытался использовать объект WP_Query, заказ просто отказался меняться. Вот в основном, как сделать свой собственный вид с 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;
}

это также помогло с предыдущей проблемой, которую я имел в этих сообщениях, что не хватает ключ "цена"не отображается в поисках. Теперь они это делают, и причина, по которой я даю им цену "10000000", заключается в том, что они появляются после те у этого есть цена.

наконец, мне также нужно пустые поиски на работу. Согласно Relevanssi dev, это поддерживается только в премиум-версии, но я думаю, что мне удалось обойти это. Сначала я заставил WP отобразить страницу поиска, даже если ?s был пуст:

<?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;
}

во-вторых, я сказал Relevanssi, чтобы забрать все посты, если ?s был пуст, по умолчанию он не будет получать никаких сообщений вообще. К сожалению, при этом поведение по умолчанию с пользовательскими таксономиями перестали работать (мой код написал его), поэтому мне пришлось вручную проверять таксономии в этом коде:

<?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;
}

и это все. Кажется, все работает, и, надеюсь, это поможет кому-то, у кого есть подобные запросы в будущем.

Я очень надеюсь, что WP улучшит свой нелепый поиск в будущем. Сортировка по релевантности должна быть чем-то, что доступно в самой популярной в мире CMS imo.

спасибо @Sheikh Heera за указывая мне в правильном направлении. Я не уверен, кому дать правильный ответ, хотя, видя, что я действительно не мог использовать то, что вы предложили.