同时按标题内容和元键过滤

时间:2016-06-07 作者:Lukesoft

使用:

$query = new WP_Query();
如何过滤以获取包含字符串一部分的标题、内容或元键的记录。

我目前有

$args=array(
          \'order\'=>\'asc\',
          \'post_type\' => $type,
          \'post_status\' => \'publish\',
          \'meta_query\' => array(
                array(
                        \'key\'     => \'my_meta_key\',
                        \'value\'   => sanitize_text_field($_GET["search"]),
                        \'compare\' => \'LIKE\'
                    )
                ),
          \'posts_per_page\' => -1,
          \'caller_get_posts\'=> 1); 
它目前工作得很好,但没有明显的按标题和内容过滤。

4 个回复
SO网友:Rarst

这种情况在当前的WP API中无法表达。您可以在post meta上使用标题/内容匹配搜索和相似匹配的元查询,但无法在两者之间建立或建立关系。

最接近的API方法是两阶段查询,在这两个阶段中,您可以查询两组结果的ID(一个用于搜索,一个用于元),然后查询它们组合的完整数据。

除此之外,它是领域自定义SQL。这不是不可能的,但相对来说写起来比较难,维护起来也比较难。

SO网友:rAthus

我找不到一个解决方案来查找可以混合在帖子标题、描述和/或一个或多个元中的多个关键字,所以我自己添加了搜索功能。

您只需在函数中添加以下代码。php,并且每当您在WP\\u Query()中使用\'s\'参数并希望它也搜索一个或多个时,只需添加一个\'s\\u meta\\u keys\'参数,该参数是要搜索的meta(s)键的数组:

/************************************************************************\\
|**                                                                    **|
|**  Allow WP_Query() search function to look for multiple keywords    **|
|**  in metas in addition to post_title and post_content               **|
|**                                                                    **|
|**  By rAthus @ Arkanite                                              **|
|**  Created: 2020-08-18                                               **|
|**  Updated: 2020-08-19                                               **|
|**                                                                    **|
|**  Just use the usual \'s\' argument and add a \'s_meta_keys\' argument  **|
|**  containing an array of the meta(s) key you want to search in :)   **|
|**                                                                    **|
|**  Example :                                                         **|
|**                                                                    **|
|**  $args = array(                                                    **|
|**      \'numberposts\'  => -1,                                         **|
|**      \'post_type\' => \'post\',                                        **|
|**      \'s\' => $MY_SEARCH_STRING,                                     **|
|**      \'s_meta_keys\' => array(\'META_KEY_1\',\'META_KEY_2\');            **|
|**      \'orderby\' => \'date\',                                          **|
|**      \'order\'   => \'DESC\',                                          **|
|**  );                                                                **|
|**  $posts = new WP_Query($args);                                     **|
|**                                                                    **|
\\************************************************************************/
add_action(\'pre_get_posts\', \'my_search_query\'); // add the special search fonction on each get_posts query (this includes WP_Query())
function my_search_query($query) {
    if ($query->is_search() and $query->query_vars and $query->query_vars[\'s\'] and $query->query_vars[\'s_meta_keys\']) { // if we are searching using the \'s\' argument and added a \'s_meta_keys\' argument
        global $wpdb;
        $search = $query->query_vars[\'s\']; // get the search string
        $ids = array(); // initiate array of martching post ids per searched keyword
        foreach (explode(\' \',$search) as $term) { // explode keywords and look for matching results for each
            $term = trim($term); // remove unnecessary spaces
            if (!empty($term)) { // check the the keyword is not empty
                $query_posts = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_status=\'publish\' AND ((post_title LIKE \'%%%s%%\') OR (post_content LIKE \'%%%s%%\'))", $term, $term); // search in title and content like the normal function does
                $ids_posts = [];
                $results = $wpdb->get_results($query_posts);
                if ($wpdb->last_error)
                    die($wpdb->last_error);
                foreach ($results as $result)
                    $ids_posts[] = $result->ID; // gather matching post ids
                $query_meta = [];
                foreach($query->query_vars[\'s_meta_keys\'] as $meta_key) // now construct a search query the search in each desired meta key
                    $query_meta[] = $wpdb->prepare("meta_key=\'%s\' AND meta_value LIKE \'%%%s%%\'", $meta_key, $term);
                $query_metas = $wpdb->prepare("SELECT * FROM {$wpdb->postmeta} WHERE ((".implode(\') OR (\',$query_meta)."))");
                $ids_metas = [];
                $results = $wpdb->get_results($query_metas);
                if ($wpdb->last_error)
                    die($wpdb->last_error);
                foreach ($results as $result)
                    $ids_metas[] = $result->post_id; // gather matching post ids
                $merged = array_merge($ids_posts,$ids_metas); // merge the title, content and meta ids resulting from both queries
                $unique = array_unique($merged); // remove duplicates
                if (!$unique)
                    $unique = array(0); // if no result, add a "0" id otherwise all posts will be returned
                $ids[] = $unique; // add array of matching ids into the main array
            }
        }
        if (count($ids)>1)
            $intersected = call_user_func_array(\'array_intersect\',$ids); // if several keywords keep only ids that are found in all keywords\' matching arrays
        else
            $intersected = $ids[0]; // otherwise keep the only matching ids array
        $unique = array_unique($intersected); // remove duplicates
        if (!$unique)
            $unique = array(0); // if no result, add a "0" id otherwise all posts will be returned
        unset($query->query_vars[\'s\']); // unset normal search query
        $query->set(\'post__in\',$unique); // add a filter by post id instead
    }
}
示例使用:

$search= "kewords to search";

$args = array(
    \'numberposts\'   => -1,
    \'post_type\' => \'post\',
    \'s\' => $search,
    \'s_meta_keys\' => array(\'short_desc\',\'tags\');
    \'orderby\' => \'date\',
    \'order\'   => \'DESC\',
);

$posts = new WP_Query($args);
此示例将查找关键字;kewords to search“要搜索的关键字”;在帖子标题、描述和元键“short\\u desc”和“tags”中。

关键字可以在一个或多个文件中找到,按任何顺序,它将返回在任何指定字段中包含所有关键字的任何帖子。

如果希望所有搜索查询都包含这些元键,则可以强制搜索包含在功能中的元键列表,并删除额外的agrument:)

希望这将帮助任何人谁面临同样的问题,我做了!

SO网友:Aniruddha Gawade

我认为这段代码可以满足您的要求:

$q1 = get_posts(array(
    \'post_type\' => \'product\',
    \'post_status\' => \'publish\',
    \'posts_per_page\' => \'-1\',
    \'s\' => get_search_query()
));
$q2 = get_posts(array(
    \'post_type\' => \'product\',
    \'post_status\' => \'publish\',
    \'posts_per_page\' => \'-1\',
    \'meta_query\' => array(
        array(
           \'key\' => \'_sku\',
           \'value\' => get_search_query(),
           \'compare\' => \'LIKE\'
        )
     )
));
$merged = array_merge( $q1, $q2 );
$post_ids = array();
foreach( $merged as $item ) {
    $post_ids[] = $item->ID;
}
$unique = array_unique($post_ids);
if(!$unique){
    $unique=array(\'0\');
}
$args = array(
    \'post_type\' => \'product\',
    \'posts_per_page\' => \'10\',
    \'post__in\' => $unique,
    \'paged\' => get_query_var(\'paged\'),
);
$wp_query = new WP_Query($args);

SO网友:Patrick McCullough

你应该可以继续

\'s\' => get_search_query()
到您现有的查询,否?如下所示:

$args=array(
      \'order\'=>\'asc\',
      \'post_type\' => $type,
      \'post_status\' => \'publish\',
      \'meta_query\' => array(
            array(
                    \'key\'     => \'my_meta_key\',
                    \'value\'   => sanitize_text_field($_GET["search"]),
                    \'compare\' => \'LIKE\'
                )
            ),
      \'s\' => get_search_query(),
      \'posts_per_page\' => -1,
      \'caller_get_posts\'=> 1); 
我在数据库搜索中使用了几乎完全相同的方法,您可以在其中搜索姓氏或名字(存储为自定义字段),然后选择添加关键字,在与自定义字段匹配的帖子中搜索帖子内容。