WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

The default search returns all post types, which is what I want. But for one specific custom post type I want to limit the result to a specific meta key value (a custom date that must be greater than today).

Using the pre_get_posts hook and setting the meta_query does get me the correct result for that post type, but it also filters out all post types that do not have that key set.

Is it possible to use the meta_query only for one specific cpt?

That should be clear enough but here's some code nonetheless:

function searchExcludeOldMatches($query) {
    if (!is_admin()&&$query->is_search) {
        $query->set('meta_query', array(
            array(
                'key' => 'cpt-match-date'
                ,'value' => date('Y/m/d',time())
                ,'type' => 'DATE'
                ,'compare' => '>'
            )
        ));
    };
    return $query;
};
add_filter('pre_get_posts','searchExcludeOldMatches');
share|improve this question
up vote 1 down vote accepted

This might not have worked before, but WordPress's meta queries now support the relation parameter. To complete what @s_ha_dum was looking to do, simply add the relation parameter (as OR) and add a second meta query for NOT EXISTS. Example:

function searchExcludeOldMatches( $query ) {
    //if we're on the admin panel, or it's a search, or it's not the post type we want to filter, return the original query
    if( is_admin() || !$query->is_search() || $query->get( 'post_type' ) != 'yourposttype' )
        return $query;

    //this is the query we want to update
    $query->set('meta_query', array(
        'relation' => 'OR',
        array(
            'key' => 'cpt-match-date'
            ,'value' => date('Y/m/d',time())
            ,'type' => 'DATE'
            ,'compare' => '>'
        ),
        array(
            'key' => 'cpt-match-date'
            ,'value' => date('Y/m/d',time())
            ,'type' => 'DATE'
            'compare' => 'NOT EXISTS'
        ),
    ));
    return $query;
}
add_filter('pre_get_posts','searchExcludeOldMatches');

For further reading, check out the WP Meta Query Codex Page: https://codex.wordpress.org/Class_Reference/WP_Meta_Query

Edit Nov 17, 2015: Added filter for custom post type and simplified the conditional statement.

share|improve this answer
    
How does this allow results from "all post types" but apply a restriction based on a meta key to only one post type? You appear to be doing exactly what the OP is trying to avoid: "Using the pre_get_posts hook and setting the meta_query does get me the correct result for that post type, but it also filters out all post types that do not have that key set." – s_ha_dum Nov 17 '15 at 17:14
    
@s_ha_dum Good catch about the custom post type -- I forgot that filter in my comment as I copied some of my code from a production site into this and just updated the values to match your post. Now this meta query will only affect targted post types. But combining an "OR" relation with a "NOT EXISTS", you can get all posts of 'posttype' that either match a value, or do not have a value set, which is what I believe the OP is asking for. – Elliott Post Nov 17 '15 at 21:06

You can limit your query even further...

if (
  !is_admin() 
  && $query->is_search() 
  && ($query->get('post_type') == 'yourposttype')
) { 
  // ...

But if you want to query all post types but restrict those results for only one post type in the same query, you can't do that. You would need a UNION statement, probably, and WP_Query does not support that. You will need to use multiple queries or write your own SQL.

The easiest way to do it is something like this:

$post_ids = new WP_Query(array(
  // query for one post type
  'fields' => 'ids',
  // other parameters
));

$post_ids_2 = new WP_Query(array(
  // query for the others
  'fields' => 'ids',
  // other parameters
));
// join them
$post_ids = $post_ids->posts + $post_ids_2->posts;
$posts_qry = new WP_Query(array('post__in'=> $posts_ids));

But not the most efficient. That is three queries. I mention other possibilities in another thread: Custom query with category exclusion and post-meta "whitelist"

Related

http://wordpress.stackexchange.com/a/79977/21376

share|improve this answer
    
Why? I do not want to limit my search to one post type. – Sjeiti May 15 '13 at 21:35
    
Ah ok... I feared it wasn't possible... I'll work my way around it then. – Sjeiti May 15 '13 at 22:00
    
... and thanks! – Sjeiti May 16 '13 at 4:44

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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