Enhanced WordPress Search

时间:2016-08-09 作者:Mhluzi Bhaka

我一直在尝试各种方法创建一个用户表单,允许人们使用以下字段搜索WordPress网站:

All of these words: < input field >
The exact phrase: < input field >
Any of these words: < input field >
None of these words: < input field >
然而,我只是没有让它发挥作用-这在WordPress场景中是否可能?

我原以为我可以通过某种方式操纵“s”参数并传入加号、减号和双引号等运算符,但这似乎不起作用。

我在WordPress search上找到的每个插件或页面都显示了针对类别或标签等的各种方式和方法,但都没有显示实际处理“s”参数本身的方式和方法

这真的有可能吗?还是我走错了路?

1 个回复
最合适的回答,由SO网友:David 整理而成

这在某种程度上是可能的,因为您可以对SQL查询进行短语化以匹配您的条件,但它的性能不会很好,因为MySQL表结构不是为这种全文搜索而设计的。

然而,解决方案需要的不仅仅是将搜索查询(用户输入)传递给默认的WordPresss 查询变量。您必须手动调整完整的SQL查询。

首先,让我们看看每个条件的具体MySQL子句。在示例中,我假设用户的搜索查询是lorem ipsum dolor.

All of these words

WHERE 1=1 AND
    `post_content` LIKE "%lorem%"
AND 
    `post_content` LIKE "%ipsum%"
AND 
    `post_content` LIKE "%dolor%"
该示例仅显示WHERE 子句,仅与post_content 领域由于我们希望结果与所有三个单词匹配,因此我们单独查找每个单词,并将每个比较与AND. % 是一个通配符,表示MySQL可能有其他字符或没有其他字符。

The exact phrase

WHERE 1=1 AND
    `post_content` LIKE "%lorem ipsum dolor%"
在这种情况下,我们匹配的是确切的短语。

Any of these words

WHERE 1=1 AND
    `post_content` LIKE "%lorem%"
OR 
    `post_content` LIKE "%ipsum%"
OR
    `post_content` LIKE "%dolor%"
除了替换AND 使用OR 因为我们想要所有这些单词中的一个或多个。

WHERE 1=1 AND
    `post_content` LIKE "%lorem%"
OR 
    `post_content` LIKE "%ipsum%"
OR
    `post_content` LIKE "%dolor%"
 最后,我们反转逻辑,搜索与搜索查询中的每个单词不匹配的条目。

过滤WordPress查询的重要过滤器,以更改WHERE 调用WordPress DB查询中的子句posts_where.

只影响我将开始的主查询pre_get_posts 将回调分配给posts_where:

<?php

add_action(
    \'pre_get_posts\',
    function( WP_Query $main_query ) {
        // Don\'t filter custom queries
        if ( ! $main_query->is_main_query() )
            return;

        // Validate the request if it comes from your search form
        if ( ! wpse235391_is_custom_search() ) {
            return;
        }

        add_filter(
            \'posts_where\',
            function( $where, WP_Query $query ) use ( $main_query ) {
                // Don\'t filter other queries than our main query
                if ( $query !== $main_query ) {
                    return $where;
                }

                // Validate and sanitize your search query here
                // Don\'t forget to use esc_sql() on each term!
                $search_query = trim( $_GET[ \'search_input\' ] );
                $search_words = explode( \' \', $search_query );
                // remove empty words
                $search_words = array_filter(
                    $search_words,
                    function( $value ) {
                        return $value !== \'\';
                    }
                );
                array_map( \'esc_sql\', $search_words );

                // Build the WHERE clause according to your request

                return $where;
            }
        );
    }
);
请注意,这段代码只是一个应该描述一般过程的示例。我不建议在生产中使用此代码,因为它是不可测试的。匿名函数的使用只是将代码减少到关键部分的一种方法。此外,它还没有经过我自己的测试,可能需要进一步的改进来提高互操作性。E、 g.条件标记is_search() 将返回FALSE 在这种情况下。

与默认的WordPress查询相比,这些查询的可伸缩性将非常昂贵。这意味着,如果你有一个大的数据池,它们会运行得很慢;如果你希望在搜索中获得高流量,它们会给你的MySQL服务器带来压力(例如,使用自动建议UI的搜索)。没有什么可以完全“优化”,我们正达到MySQL的极限。在这些情况下,更好的方法是使用优化的搜索索引,如SolrElasticsearch.