META_QUERY COMPARE=‘!=’具有多个自定义字段

时间:2014-03-07 作者:etiennedi

帖子具有以下自定义字段:

\'my_custom_field\' => 1
\'my_custom_field\' => 2
\'my_custom_field\' => 3
我现在想查询所有不包含“my\\u custom\\u field”值2的帖子。我正在尝试:

$args = Array(\'posts_per_page\' => -1,
    \'post_type\' => \'page\',
    \'meta_query\' => array(
      array(
        \'key\' => \'my_custom_field\',
        \'value\' => 2,
        \'compare\' => \'!=\'
      )
    )
  );
但是,这仍然返回我的示例帖子,因为我的示例帖子有一个“my\\u custom\\u field”字段,其值不是2(1和3)。我需要将查询改为“排除至少有一个“my\\u custom\\u field”字段值为2的帖子”。

有人能帮我吗?谢谢

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

这可能需要编写带有子查询的自定义sql:

$results = $wpdb->get_results("
    SELECT * 
    FROM $wpdb->posts 
    WHERE ID NOT IN (
      SELECT post_id FROM $wpdb->postmeta
      WHERE meta_key = \'my_custom_field\' and meta_value = 2
    )
");
然后遍历结果,如下所示described here.

SO网友:gmazzap

@TomJNowell@s_ha_dum 您在评论中说,在您的情况下,自定义分类法可能比自定义字段更好,因为很容易获得没有分类法术语的帖子。

也就是说,我理解,如果您已经编写了很多代码,或者正在使用第三方代码,那么转向自定义分类法可能很难/不可能。

Aswer由提供@elleeott 然而,works并不灵活,因为您不能更改每页的帖子、元值等。。

我将为您提供类似的解决方案,但要灵活一点,您可以根据需要对其进行微调。

本质上只是一个扩展WP_Query 并对请求应用筛选器以执行所需的

class MyMetaQuery extends WP_Query {

   protected $do_posts_request_filter = TRUE;

   function get_posts() {
     $this->query_vars[\'suppress_filters\'] = FALSE; // force do filters
     add_action( \'posts_request\', array( $this, \'filter_request\' ), 999 );
     parent::get_posts();
     $this->do_posts_request_filter = FALSE; // run only once
   }

   /* build the sql request */
   function filter_request( $request ) {
      if ( ! $this->do_posts_request_filter ) return $request;
      $q = $this->get(\'meta_query\');
      if ( empty($q) || ! is_array($q) || ! isset($q[0][\'key\']) ) return $request;
      global $wpdb;
      $k = $q[0][\'key\'];
      $v = isset( $q[0][\'value\'] ) ? $q[0][\'value\'] : \'\';
      if ( is_array( $v ) ) $v = implode( \',\', $v );
      $mcompare = isset( $q[0][\'compare\'] ) ? $q[0][\'compare\'] : \'IN\';
      if ( ! in_array( $mcompare, array(\'IN\', \'NOT IN\', \'=\', \'!=\') ) ) {
        $mcompare = \'IN\';
      }
      if ( $mcompare === \'!=\' ) $mcompare = \'NOT IN\';
      if ( $mcompare === \'=\' ) $mcompare = \'IN\';
      $ppage = $this->get(\'posts_per_page\') ? : get_option(\'posts_per_page\');
      $limit = $wpdb->prepare(\' LIMIT %d\', $ppage);
      if ( substr_count( $limit, \'-1\' )  ) $limit = \'\';
      if ( $limit && $this->get(\'nopaging\') ) $limit = \'\';
      $type_compare = \'IN\';
      $type = $this->get(\'post_type\') ? : \'post\';
      if ( is_array( $type ) ) $type = implode(\',\', $type );
      if ( $type === \'any\' ) {
        $type_compare = \'NOT IN\';
        $status = \'-1\';
      }
      $status_compare = \'IN\';
      $status = $this->get(\'post_status\') ? : \'publish\';
      if ( is_array($status) ) $type = implode(\',\', $status);
      if ( $status === \'any\' ) {
        $status_compare = \'NOT IN\';
        $status = \'-1\';
      }
      $query = "
        SELECT SQL_CALC_FOUND_ROWS $wpdb->posts.* FROM $wpdb->posts
        INNER JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id
        WHERE post_type $type_compare (%s)
        AND post_status $status_compare (%s)
        AND $wpdb->postmeta.meta_key = %s
        AND ID NOT IN (
          SELECT DISTINCT post_id FROM $wpdb->postmeta
          WHERE meta_key = %s and CAST(meta_value AS CHAR) $mcompare (%s)
        )
      ";
      return $wpdb->prepare( $query, $type, $status, $k, $k, $v ) . $limit;
   }

}
之后,不用WP_Query 你必须使用MyMetaQuery 类别:

$args = array(
  \'posts_per_page\' => -1,
  \'post_type\' => \'page\',
  \'meta_query\' => array(
    array( \'key\' => \'my_custom_field\', \'value\' => 2, \'compare\' => \'!=\' )
  )
);

$query = new MyMetaQuery( $args );

if ( $query->have_posts() ) {
  while( $query->have_posts() ) {
    $query->the_post(); 
    // do what you want here
  }
  wp_reset_postdata();
}
请注意,自定义类只接受以下参数:

  • \'post_type\', 可以是单个类型、逗号分隔的字符串或类型数组或“任意”\'post_status\' 可以是单个状态、逗号分隔的字符串或状态数组或“任意”\'posts_per_page\' 可以是一个posistive数字或“-1”\'nopaging\' 可以是TRUEFALSE. 设置为TRUE将返回覆盖“每页帖子”的所有帖子\'meta_query\' 接受多维数组,就像WP_Query. 请注意,您只能传递一个查询数组,任何其他查询都将被忽略。查询数组接受以下作为数组键:\'key\', \'value\'\'compare\'. \'value\' 可以是单个值、逗号分隔的字符串或值数组。\'compare\' 可以是“”IN“”、“”NOT IN“”、“”、“”和“”!=”
结束

相关推荐