在 wordpress 中对 meta_query 使用 Or 关系

Posted

技术标签:

【中文标题】在 wordpress 中对 meta_query 使用 Or 关系【英文标题】:Use Or relation for meta_query in wordpress 【发布时间】:2015-09-04 03:12:50 【问题描述】:

我尝试在 wordpress 中创建搜索,不仅按标题和内容,还按元字段。

所以我在functions.php中写了:

function custom_search_query( $query ) 
    if ( !is_admin() && $query->is_search ) 

        $query->set('meta_query', array(
            'relation' => 'OR',
            array(
                'key' => 'country_name_work',
                'value' => $query->query_vars['s'],
                'compare' => 'LIKE'
            )
        ));
       $query_vars = $query->query_vars;
       $query_vars['relation'] = 'OR';
    ;


add_filter( 'pre_get_posts', 'custom_search_query');

搜索字段波兰的结果 SQL 是:

SELECT SQL_CALC_FOUND_ROWS  wp_posts.ID FROM wp_posts  INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1  AND wp_posts.ID NOT IN (2,5,12,14,20) AND (((wp_posts.post_title LIKE '%poland%') OR (wp_posts.post_content LIKE '%poland%')))  **AND** ( 
  ( wp_postmeta.meta_key = 'country_name_work' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' )
) AND wp_posts.post_type IN ('post', 'page', 'attachment', 'jobs') AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') GROUP BY wp_posts.ID ORDER BY wp_posts.post_title LIKE '%poland%' DESC, wp_posts.post_date DESC LIMIT 0, 40

如果查询为:

SELECT SQL_CALC_FOUND_ROWS  wp_posts.ID FROM wp_posts  INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1  AND wp_posts.ID NOT IN (2,5,12,14,20) AND (((wp_posts.post_title LIKE '%poland%') OR (wp_posts.post_content LIKE '%poland%')))  **OR** ( 
  ( wp_postmeta.meta_key = 'country_name_work' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' )
) AND wp_posts.post_type IN ('post', 'page', 'attachment', 'jobs') AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') GROUP BY wp_posts.ID ORDER BY wp_posts.post_title LIKE '%poland%' DESC, wp_posts.post_date DESC LIMIT 0, 40

运营商AND 应该是OR。 我尝试了这些建议 - meta_query, how to search using both relation OR & AND? 和 https://wordpress.stackexchange.com/questions/104060/using-or-conditions-in-meta-query-for-query-posts-argument - 但它不能正常工作。

更新:

现在我介绍doublesharp的答案。但我又有问题了。 现在我的代码看起来像:

function post_title_filter( $where, &$query )
    global $wpdb;
    if ( $post_title = $query->get( 'post_title' ) )
        $post_title = $wpdb->esc_like( $post_title );
        $post_title = " '%$post_title%'";
        $title_filter_relation = strtoupper( $query->get( 'post_title_relation' ) ) == 'OR' ? 'OR' : 'AND';
        $where .= " $title_filter_relation $wpdb->posts.post_title LIKE $post_title";
    
    return $where;


function post_content_filter( $where, &$query )
    global $wpdb;
    if ( $post_content = $query->get( 'post_content' ) )
        $post_content = $wpdb->esc_like( $post_content );
        $post_content = " '%$post_content%'";
        $content_filter_relation = strtoupper( $query->get( 'post_content_relation' ) ) == 'OR' ? 'OR' : 'AND';
        $where .= " $content_filter_relation $wpdb->posts.post_content LIKE $post_content";
    
    return $where;

add_filter( 'posts_where', 'post_title_filter', 10, 2 );
add_filter( 'posts_where', 'post_content_filter', 10, 2 );

function custom_search_query( $query ) 
    if ( !is_admin() && $query->is_search) 
        //$query->is_search=false;
        $query->is_search1=true;
        $search = $query->query_vars['s'];
        $query->set( 'post_title', $search );
        $query->set( 'post_title_relation', 'OR' );
        $query->set( 'post_content', $search );
        $query->set( 'post_content_relation', 'OR' );
        $query->set( 'meta_query', array(
            'relation'=>'OR',
            array(
                'key' => 'country_name_work',
                'value' => $query->query_vars['s'],
                'compare' => 'LIKE'
            ),array(
                'key' => 'sex',
                'value' => $query->query_vars['s'],
                'compare' => 'LIKE'
            ),array(
                'key' => 'status',
                'value' => $query->query_vars['s'],
                'compare' => 'LIKE'
            ),array(
                'key' => 'age-from',
                'value' => $query->query_vars['s'],
                'compare' => 'LIKE'
            ),array(
                'key' => 'age-to',
                'value' => $query->query_vars['s'],
                'compare' => 'LIKE'
            ),array(
                'key' => 'exp',
                'value' => $query->query_vars['s'],
                'compare' => 'LIKE'
            ),array(
                'key' => 'work-env',
                'value' => $query->query_vars['s'],
                'compare' => 'LIKE'
            ),array(
                'key' => 'work-conditions',
                'value' => $query->query_vars['s'],
                'compare' => 'LIKE'
            ),array(
                'key' => 'schedule',
                'value' => $query->query_vars['s'],
                'compare' => 'LIKE'
            ),array(
                'key' => 'salary',
                'value' => $query->query_vars['s'],
                'compare' => 'LIKE'
            )
        ));
    

add_filter( 'pre_get_posts', 'custom_search_query' );

生成的查询看起来:

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1 AND (((wp_posts.post_title LIKE '%poland%') OR (wp_posts.post_content LIKE '%poland%'))) AND (wp_posts.post_password = '') AND ( ( wp_postmeta.meta_key = 'country_name_work' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'sex' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'status' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'age-from' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'age-to' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'exp' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'work-env' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'work-conditions' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'schedule' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'salary' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) ) AND wp_posts.post_type IN ('post', 'page', 'attachment', 'jobs') AND (wp_posts.post_status = 'publish') OR wp_posts.post_title LIKE '%poland%' OR wp_posts.post_content LIKE '%poland%' GROUP BY wp_posts.ID ORDER BY wp_posts.post_title LIKE '%poland%' DESC, wp_posts.post_date DESC LIMIT 0, 40

【问题讨论】:

请清理你的代码,它不可读 PHP 完全可读,示例 SQL 没有格式化为代码,只是作为示例。 Pieter,代码已经格式化了,请看问题。 查看wordpress.stackexchange.com/questions/18703/… 对于您的新示例代码,您需要使用OR 作为顶层,默认为AND。添加$query->set( 'relation', 'OR' ); 【参考方案1】:

您需要使用posts_where 过滤器添加到WP_Query 生成的WHERE 语句。此示例添加了两个额外的参数 - post_titlepost_title_relation,以允许您找到标题为 LIKE 的值 OR 以及具有该值的 meta_key

使用posts_wherepre_get_posts 过滤器

function post_title_filter( $where, &$query )
    global $wpdb;
    if ( $post_title = $query->get( 'post_title' ) )
        $post_title = $wpdb->esc_like( $post_title );
        $post_title = " '%$post_title%'";
        $title_filter_relation = strtoupper( $query->get( 'post_title_relation' ) ) == 'OR' ? 'OR' : 'AND';
        $where .= " $title_filter_relation $wpdb->posts.post_title LIKE $post_title";
    
    return $where;

add_filter( 'posts_where', 'post_title_filter', 10, 2 );

function custom_search_query( $query ) 
    if ( !is_admin() && $query->is_search ) 
        $search = $query->query_vars['s'];
        $query->set( 'post_title', $search );
        $query->set( 'post_title_relation', 'OR' );
        $query->set( 'meta_query', array(
            array(
                'key' => 'country_name_work',
                'value' => $query->query_vars['s'],
                'compare' => 'LIKE'
            )
        ));
    

add_filter( 'pre_get_posts', 'custom_search_query' );

直接使用 WP_Query 的示例

$search = 'test';
$args = array(
    'post_title' => $search,
    'post_title_relation' => 'OR',
    'meta_query' => array(
        array(
            'key' => 'test',
            'value' => $search,
            'compare' => 'LIKE'
        )
    )
);
$query = new WP_Query( $args );

【讨论】:

doublesharp,谢谢你的回答,很有用,但是我的代码钢不行。 您的新示例代码与您的第一个示例不同 :)

以上是关于在 wordpress 中对 meta_query 使用 Or 关系的主要内容,如果未能解决你的问题,请参考以下文章

在 Wordpress meta_query 中使用动态多维数组

如何在 wordpress 中对用户进行身份验证?

Wordpress - 在类别存档中使用 wp_query - 如何显示适当的类别?

php 在WP中使用meta_query和date

如何向 meta_query 添加过滤器,例如仅查找 Roma Numeric

php WP_Query与Meta_Query