8

我为我正在使用 atm 的 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')你认为的东西吗?

4

3 回答 3

4

好的,所以我最终还是使用了 Relevanssi。但有不少修改。

首先,分类法过滤非常简单,因为它内置在 Relevanssi 中,我需要做的就是将<select>元素的名称更改为分类名称 + 将值更改为 slug:

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

其次,为了允许按自定义字段排序,我必须使用relevanssi_hits_filter过滤器。与pre_get_postsor不同relevanssi_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 为我指明了正确的方向。尽管看到我真的无法使用您建议的东西,但我不确定该给谁正确答案。

于 2013-07-23T01:11:37.843 回答
4

我认为您可以Relevanssi毫无问题地使用,但需要使用filter挂钩,请查看relevansi_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

截图如下

在此处输入图像描述

于 2013-07-20T20:04:49.303 回答
0

刚刚发现 WP 已经有这个核心。

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

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

于 2021-04-22T10:46:28.223 回答