按相关性排序Wordpress搜索

时间:2013-07-18 00:07:23

标签: wordpress search relevance

我已经为我正在研究的Wordpress网站创建了一个非常高级的搜索。允许访问者按不同的分类法过滤结果,按日期或自定义字段以及正常的自由文本搜索(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')这样的东西吗?

3 个答案:

答案 0 :(得分:5)

我认为您可以毫无问题地使用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'自定义帖子类型,搜索工作非常精细,只是相关结果。如果安装了php 5.3+,您也可以使用

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

此外,如果您使用Relevanssi插件,则可以使用其设置页面设​​置post_type,而不是在$qry->set( 'post_type', array(...) )文件中使用此functions.php

以下给出的Scree镜头

enter image description here

答案 1 :(得分:4)

好的,毕竟我最终使用了Relevanssi。但是进行了一些修改。

首先,过滤分类法非常容易,因为这是在Relevanssi中构建的,我需要做的就是将我的<select>元素的名称更改为分类名称+将值更改为slugs:< / p>

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

其次,要允许按自定义字段排序,我必须使用relevanssi_hits_filter过滤器。与pre_get_postsrelevanssi_modify_wp_query(Sheikh Heera亲切建议)不同,此过滤器会传递帖子数组,而不会传递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开发,这只支持高级版本,但我认为我设法解决它。首先,即使?s为空,我也强制WP显示搜索页面:

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

其次,如果?s为空,我告诉Relevanssi提取所有帖子,默认情况下它根本不会获取任何帖子。不幸的是,在这样做时,自定义分类法的默认行为停止工作(我的代码覆盖了它),所以我不得不在这段代码中手动检查分类法:

<?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指出我正确的方向。我不确定是谁给出了正确的答案,虽然看到我真的无法使用你建议的东西。

答案 2 :(得分:0)

刚刚发现 WP 已经将其作为核心。

https://developer.wordpress.org/reference/classes/wp_query/中,查看“orderby”=>“relevance”参数。

<块引用>

按以下顺序按搜索词排序:首先,是否 整个句子匹配。其次,如果所有的搜索词都是 标题内。第三,如果任何搜索词出现在 标题。还有,第四,如果完整的句子出现在内容中。