如何改进此管理查询片段以避免在非元搜索上生成重复结果?

时间:2013-08-22 作者:jnthnclrk

我一直在玩弄代码片段,这些代码片段将元数据添加到管理搜索中。

我找到的最好的片段是Stefano on this question.

然而,在搜索非元术语时,它似乎有一个恼人的bug。

下面是我在本地安装的dev的一些抓取。我已经在屏幕上打印了2个MySQL查询。

我用于测试的单个CPT帖子的视图

View of the single CPT post I'm using to test

这是按预期工作的代码,允许我从管理员搜索元数据

This is the code working as expected and allowing me to search meta data from admin

不幸的是,代码在非元匹配上创建了重复项,在本例中是在文章标题上

Unfortunately the code creates duplicates on non-meta matches, in this case on post title

一个抓图,显示重复的帖子状态、帖子类型和帖子祖先!A grab showing the post status, post type and post ancestors of dupes

这是我正在运行的代码,它基本上与Stefano的相同,但我只是粗略地尝试让查询工作起来。

/*
 * Search custom fields from admin keyword searches
 */

function rel_search_join( $join ) {
    global $pagenow, $wpdb;
    if ( is_admin() && $pagenow == \'edit.php\' && $_GET[\'post_type\'] == \'listings\' && $_GET[\'s\'] != \'\') {    
        $join .= \'LEFT JOIN \' . $wpdb->postmeta . \' ON \'. $wpdb->posts . \'.ID = \' . $wpdb->postmeta . \'.post_id \';
    }
    echo \'<br><strong>JOIN</strong>: \';
    print_r ( $join );
    echo \'<br>\';
    return $join;
}
add_filter(\'posts_join\', \'rel_search_join\' );

function rel_search_where( $where ) {
    global $pagenow, $wpdb;
    if ( is_admin() && $pagenow == \'edit.php\' && $_GET[\'post_type\']==\'listings\' && $_GET[\'s\'] != \'\' ) {
        $where = preg_replace( "/\\(\\s*".$wpdb->posts.".post_title\\s+LIKE\\s*(\\\'[^\\\']+\\\')\\s*\\)/", "(".$wpdb->posts.".post_title LIKE $1) OR (".$wpdb->postmeta.".meta_value LIKE $1)", $where );
        $where = str_replace( "OR wp_posts.post_status = \'pending\'", "", $where );
        $where = str_replace( "OR wp_posts.post_status = \'private\'", "", $where );
        $where = str_replace( "OR wp_posts.post_status = \'draft\'", "", $where );
        $where = str_replace( "OR wp_posts.post_status = \'future\'", "", $where );
    }
    echo \'<br><strong>WHERE</strong>: \';
    print_r ( $where );
    echo \'<br>\';
    return $where;
}
add_filter( \'posts_where\', \'rel_search_where\' );  

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

A.GROUP BY 语句可以在JOIN. 对于Wordpress,您可以使用posts_groupby 滤器

add_filter( \'posts_groupby\', \'my_post_limits\' );
function my_post_limits($groupby) {
    global $pagenow, $wpdb;
    if ( is_admin() && $pagenow == \'edit.php\' && $_GET[\'post_type\']==\'listings\' && $_GET[\'s\'] != \'\' ) {
        $groupby = "$wpdb->posts.ID";
    }
    return $groupby;
}

SO网友:souverian

谢谢你们的努力,伙计们。这段代码在很大程度上帮助了我,但使用WP 3.8时,我遇到了一个SQL非唯一表/别名错误,所以我做了一些更改。为了让它在我的设置中工作,我必须设置JOIN语句中使用的$wpdb->postmeta别名。我也只检查了一次,看看是否应该使用挂钩,这样它们就不会每次都开火。希望这对别人有帮助!

global $postmeta_alias, $is_specials_search;
$cpt_name = \'special\';
$postmeta_alias = \'pdpm\'; // Change this to whatever your custom post type is
$is_specials_search = is_admin() && $pagenow==\'edit.php\' && isset( $_GET[\'post_type\'] ) && $_GET[\'post_type\']==$cpt_name && isset( $_GET[\'s\'] );

// Extend search to include \'description\' field
if ( $is_specials_search ) {
  add_filter( \'posts_join\',      \'pd_description_search_join\' );
  add_filter( \'posts_where\',     \'pd_description_search_where\' );
  add_filter( \'posts_groupby\',   \'pd_search_dupe_fix\' );
}

function pd_description_search_join ($join){
  global $pagenow, $wpdb, $postmeta_alias, $is_specials_search;

  if ( $is_specials_search )  
    $join .=\'LEFT JOIN \'.$wpdb->postmeta. \' as \' . $postmeta_alias . \' ON \'. $wpdb->posts . \'.ID = \' . $postmeta_alias . \'.post_id \';

  return $join;
} // END search_join

function pd_description_search_where( $where ){
  global $pagenow, $wpdb, $postmeta_alias, $is_specials_search;

  if ( $is_specials_search )
    $where = preg_replace(
     "/\\(\\s*".$wpdb->posts.".post_title\\s+LIKE\\s*(\\\'[^\\\']+\\\')\\s*\\)/",
     "(".$wpdb->posts.".post_title LIKE $1) OR (".$postmeta_alias.".meta_value LIKE $1)", $where );

  return $where;
} // END search_where

function pd_search_dupe_fix($groupby) {
    global $pagenow, $wpdb, $is_specials_search;

    if ( $is_specials_search )
      $groupby = "$wpdb->posts.ID";

    return $groupby;
} // END pd_search_dupe_fix

结束