I'm trying to use get_posts() to pull articles that have not been assigned a specific custom field. For example (not working):

$articles = get_posts(array(
  'post_parent' => 0,
  'post_type' => 'custom-type',  
  'meta_query' => array(
      'key' => 'alternate_page',
      'value' => array(0, '', null),
      'compare' => 'IN'

Basically, I want all 'custom-type' articles that don't have a parent and don't have the 'alternate_page' custom field assigned.

I've read elsewhere about doing two queries, one for all articles that have the custom field, getting and array of their IDs, and using the '__post_not_in' parameter, but this seems tedious.

Is it possible to do in one query like above? Thanks.

1 Answer 1


You can do it with a posts_where filter and a subquery. Note that you have to explicitly set suppress_filters to false, as get_posts normally ignores filters:

function wpse28018_posts_where( $where ) {
    global $wpdb;
    $where .= " AND {$wpdb->posts}.ID NOT IN ( SELECT DISTINCT post_id FROM {$wpdb->postmeta} WHERE meta_key = 'alternate_page' )";
    return $where;

// add the filter
add_filter( 'posts_where' , 'wpse28018_posts_where' );

// do the query
$articles = get_posts(array(
  'post_parent' => 0,
  'post_type' => 'custom_type',  
  'suppress_filters' => false     

// remove the filter so other queries aren't affected.
remove_filter( 'posts_where' , 'wpse28018_posts_where' );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.