我已经为我正在研究的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')
这样的东西吗?
答案 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
。
答案 1 :(得分:4)
好的,毕竟我最终使用了Relevanssi。但是进行了一些修改。
首先,过滤分类法非常容易,因为这是在Relevanssi中构建的,我需要做的就是将我的<select>
元素的名称更改为分类名称+将值更改为slugs:< / p>
<select name="custom_taxonomy">
<option value="some-term">Some term</option>
...
</select>
其次,要允许按自定义字段排序,我必须使用relevanssi_hits_filter
过滤器。与pre_get_posts
或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指出我正确的方向。我不确定是谁给出了正确的答案,虽然看到我真的无法使用你建议的东西。
答案 2 :(得分:0)
刚刚发现 WP 已经将其作为核心。
在https://developer.wordpress.org/reference/classes/wp_query/中,查看“orderby”=>“relevance”参数。
<块引用>按以下顺序按搜索词排序:首先,是否 整个句子匹配。其次,如果所有的搜索词都是 标题内。第三,如果任何搜索词出现在 标题。还有,第四,如果完整的句子出现在内容中。