Filter out a meta key in the Search results page with two CPT

I have two CPT: Listings and Events. In Events I have custom fields for the start and end dates. What I need is a way to filter out any events that are past the current date.

What I have right now is:

function search_pre_get_posts( $query ) {   
    if ( is_search() && $query->is_main_query() ) {          
        $currentdate =  current_time('Ymd');        
        global $wp_query;
        $args = array_merge( 
            $wp_query->query_vars, 
            array(
                'meta_query'=> array( array(
                    'key' => 'DTEND',
                    'compare' => '>=',
                    'value' => $currentdate,
                )),
            )
        );
        query_posts( $args );
    }
}
add_action( 'pre_get_posts', 'search_pre_get_posts' );

This does filter out the past events, but it also removes all Listings. What I need is a way to add an IF statement to run this meta query only for ‘events’.

Anyone have an idea of how to do this? Whenever I put an IF statement anywhere in there, using a get_post_type(), like 'events' == get_post_type(), it breaks the whole filter.

Solutions Collecting From Web of "Filter out a meta key in the Search results page with two CPT"

You could add a second array to check if the ‘DTEND’ value is not set:

    $args = array_merge( 
        $wp_query->query_vars, 
        array(
            'meta_query'=> array( 
                'relation' => 'OR',
                array(
                     'key' => 'DTEND',
                     'compare' => '>=',
                     'value' => $currentdate,
                ),
                array(
                     'key' => 'DTEND',
                     'compare' => 'NOT EXISTS',
                )
            ),
        )
    );

That way, any custom posts without a DTEND meta value will also be allowed.

Ok, @guiniveretoo nailed it, with a couple edits:

Ok, @guiniveretoo, you nailed it!

With a couple tweaks, this is what I used and it works:

function search_pre_get_posts( $query ) {
global $wp_query;
if ( is_search() && $query->is_main_query()   ) {

$currentdate =  current_time('Ymd');

$args = array_merge( 
    $wp_query->query_vars, 
    array(
            'meta_query'=> array( 
            'relation' => 'OR',
            array(
                 'key' => 'DTEND',
                 'compare' => '>=',
                 'value' => $currentdate,
            ),
            array(
                 'key' => 'DTEND',
                 'compare' => 'NOT EXISTS',
            )
        ),
    )
);

     query_posts( $args );

}

}

add_action( 'pre_get_posts', 'search_pre_get_posts' );'

Now, i just need to figure out how to sort the ‘events’ CPT by a meta key ‘DTSTART’, so the events that are coming up get listed first….

@Aaron, here is an alternate version of your solution, including sorting:

function search_pre_get_posts( $query ) {
    if ( $query->is_search() && $query->is_main_query()   ) {   
        $currentdate =  current_time('Ymd');
        $query->set( 
            'meta_query',
            array(
                'relation' => 'OR',
                array(
                     'key' => 'DTEND',
                     'compare' => '>=',
                     'value' => $currentdate,
                ),
                array(
                     'key' => 'DTEND',
                     'compare' => 'NOT EXISTS',
                )
            )
        );

        $query->set( 'orderby', 'meta_value' );
    }
}

add_action( 'pre_get_posts', 'search_pre_get_posts' );'

Big difference: $query is passed by reference, so you don’t need to call $wp_query or query_posts (which you should never call anyway). Also, setting orderby by meta_value will sort the posts by the meta value.