Exclude top-level pages from search results

With the following code I can exclude all posts and pages that are top-level, but I would like to apply this only to pages, not to posts (but I still want all posts in the results):

function search_filter( $query )
{
    if(
        $query->is_search 
        AND $query->is_main_query()
        )
    {
        $query->set( 'post_parent__not_in', array( 0 ) );
        $query->set( 'post_type', array( 'post', 'page' ) );
    }
    return $query;
}

At the moment all my posts have 0 as post_parent, so they all get excluded from the results.

Related posts

1 comment

  1. I wonder if this will work for you:

    function search_filter( $query )
    {
        if( $query->is_search AND $query->is_main_query() )
        {
            // $query->set( 'post_parent__not_in', array( 0 ) ); // We comment this out here 
            $query->set( 'post_type', array( 'post', 'page' ) );
        }
        return $query;
    }
    add_action( 'pre_get_posts', 'search_filter' );
    

    and

    function wpse_120638( $where, $query ) 
    {
        global $wpdb;
    
        if( $query->is_search AND $query->is_main_query() )
        {
                $from = "AND $wpdb->posts.post_type IN ('post', 'page')";
                $to   = "AND ( ( $wpdb->posts.post_parent NOT IN (0) 
                         AND $wpdb->posts.post_type IN ('page') ) 
                         OR $wpdb->posts.post_type IN ('post') ) ";
    
            $where = str_replace( $from, $to, $where );                                   
        }
    
        return $where;
    }
    add_filter( 'posts_where', 'wpse_120638', 10, 2 );
    

Comments are closed.