在请求的WHERE语句中使用OR代替AND的单个META_QUERY查询

时间:2014-05-06 作者:cfx

我希望本机WordPress搜索输入除了标准标题和内容搜索之外,还可以搜索元数据,但是设置meta_query 添加AND 当我需要的是OR.

我的职能:

function search_faqs_metadata($query) {
  if(!is_admin() && $query->is_main_query()) {
    if($query->is_search) {
      $query->set(\'meta_query\', array(array(
        \'key\' => \'_faqs\',
        \'value\' => $query->query_vars[\'s\'],
        \'compare\' => \'LIKE\'
      )));
    }
  }
}
add_action(\'pre_get_posts\', \'search_faqs_metadata\');
问题是它生成的查询:

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 \'%foobar%\') OR (wp_posts.post_content LIKE \'%foobar%\')
  )
)
AND (wp_posts.post_password = \'\')
AND wp_posts.post_type IN (\'post\', \'page\', \'attachment\')
AND (wp_posts.post_status = \'publish\')
AND (  //I need this to be an OR!
  (wp_postmeta.meta_key = \'_faqs\' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE \'%foobar%\')
)
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_title LIKE \'%foobar%\' DESC, wp_posts.post_date DESC LIMIT 0, 10
因此,除非帖子标题/内容AND 元数据与搜索词匹配。

我知道有一个relation 的参数meta_query 但它仅在比较多个元数据值时有效。

目前我正在跑步str_replace() 在最后一个查询上更改最后一个AND 变成一个OR. 我选择这种方法是因为,虽然有黑客行为,但它依赖于我需要添加多少代码才能成功进行调整:

function search_where_or_metadata($where) {
  if(is_search()) {
    global $wp_query;
    $new_where = $where;
    $new_where = str_replace(\'AND ( (wp_postmeta.meta_key\', \'OR ( (wp_postmeta.meta_key\', $where);
    return $new_where;
  }
  return $where;
}
add_filter(\'posts_where\', \'search_where_or_metadata\');
EDIT下面是一个更好的函数,它使用更合适的过滤器来更改ANDOR:

function change_meta_key_where_from_and_to_or($sql) {
  if(is_search()) {
    $sql[\'where\'] = substr($sql[\'where\'], 1, 3) == \'AND\' ? substr_replace($sql[\'where\'], \'OR\', 1, 3) : $sql[\'where\'];
  }
  return $sql;
}
add_filter(\'get_meta_sql\', \'change_meta_key_where_from_and_to_or\');
有没有更好的办法改变决赛AND 变成一个OR?

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

我认为最短和最好的方法是(1)修改查询:

function search_faqs_metadata($query) {
  if(!is_admin() && $query->is_main_query()) {
    if($query->is_search) {
      $query->set(\'meta_query\', array(array(
        \'key\' => \'_faqs\',
        \'value\' => $query->query_vars[\'s\'],
        \'compare\' => \'LIKE\'
      )));
    }
  }
}
add_action(\'pre_get_posts\', \'search_faqs_metadata\');
然后(2)更换AND 具有OR 通过get_meta_sql 过滤器:

function change_meta_key_where_from_and_to_or($sql) {
  if(is_search()) {
    $sql[\'where\'] = substr($sql[\'where\'], 1, 3) == \'AND\' ? substr_replace($sql[\'where\'], \'OR\', 1, 3) : $sql[\'where\'];
  }
  return $sql;
}
add_filter(\'get_meta_sql\', \'change_meta_key_where_from_and_to_or\');

SO网友:Manny Fleurmond

找到了一个可能实现此目的的教程:http://www.deluxeblogtips.com/2012/04/search-all-custom-fields.html

基本要点是使用自定义mySQL查询找到具有适当元的帖子的帖子ID,然后将这些ID提供给查询:

function wpse143477_parse_clauses($clauses, $query) {
    if(!is_admin() && $query->is_main_query()) {
        if($query->is_search) {
            $keyword = $query->get(\'s\');
            $keyword = \'%\' . like_escape( $keyword ) . \'%\';
            $post_ids = $wpdb->get_col( $wpdb->prepare( "
                SELECT DISTINCT post_id FROM {$wpdb->postmeta}
                WHERE meta_key = \'_faqs\' AND meta_value LIKE \'%s\'
            ", $keyword ) );
            if( !empty( $post_ids )) {
                $clauses[\'where\'] .= " OR {$wpdb->posts}.ID IN (" . implode( \', \', $post_ids ) . \')\';
            }
        }
    }

    return $clauses;
}
add_filter( \'posts_clauses\', \'wpse143477_parse_clauses\', 10, 2 );

结束

相关推荐

用MySQL取代img src?

我试着用Enable Media Replace Plugin 用更新版本替换网站上的某些图像。可以选择更新站点上使用文件的所有实例,但这仅适用于原始图像。WordPress自动生成每个图像的多个不同大小,并使用-img-size.jpg. 插件不会更新这些已调整大小的图像的名称,因此使用它们的任何地方(例如,任何地方)现在都是一个损坏的图像。我查看了post HTML,所有内容如下所示:<a href=\"example.com/wp-content/uploads/2013/12/newfile