0

On my search results page I have two loops. First loop displays post by meta value and second loop is "regular" loop that display posts by search query:

<section>
    <div class="container">
        <div class="row mb-5">
                
            <?php // a "static" custom loop displaying posts by meta value  
            $featured_posts = new WP_Query( array(
                'post_type' => array( 'cpt-1', 'cpt-2', 'cpt-3' ),
                'post_status' => 'publish',
                'posts_per_page' => -1,
                'meta_query' => array(
                    array(
                        'key'   => 'highlight', // this is a name of ACF field
                        'value' => '1',
                    )
                )
            ) );
            
            echo '<div class="col-12">';
            
            if ( $featured_posts ) {
                    echo '<h3>Highlighted posts (' . $featured_posts->found_posts . '):</h3>';

                    while ( $featured_posts->have_posts() ) : $featured_posts->the_post();
                        get_template_part( 'template-parts/content', 'search' );
                    endwhile;
                
                    wp_reset_postdata();
            } else {
                echo 'No any highlighted post.';
            }
            
            echo '</div>';
            ?>
            
        </div>
        
        <div class="row">
            <div class="col-12">
                
                <?php 
                global $wp_query;
                //$allsearch = new WP_Query( 's=' . $s . '&showposts=0' ); ?>
                
                <h3>The search results (<?php echo $wp_query->found_posts; //echo $allsearch->found_posts; ?>):</h3>
                
                <?php
                if ( have_posts() ) : 
                    //echo '<table>';

                    while ( have_posts() ) : the_post();
                        get_template_part( 'template-parts/content', 'search' );
                    endwhile;
                    //echo '</table>'; ?>
    
                    <div class="pagination-area">
                        <nav class="navigation pagination" role="navigation">
                            <div class="nav-links">

                                <?php
                                global $wp_query;

                                $big = 999999999; // need an unlikely integer

                                echo paginate_links( array(
                                    'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
                                    'format' => '?paged=%#%',
                                    'current' => max( 1, get_query_var('paged') ),
                                    'total' => $wp_query->max_num_pages,
                                    'prev_text'    => __( '«' ),
                                    'next_text'    => __( '»' ),
                                ) );
                                ?>
                                
                            </div>
                        </nav>
                    </div>

                <?php
                else :

                    echo 'No search results.';

                endif; ?>
                    
            </div>
        </div>
    </div>
</section>

The highlighted posts are displaying in both loops. Now I want to exclude them from regular search results loop with pre_get_posts :

function my_custom_search_query( $query ) {
    if( ! is_admin() || $query->is_search() ) {
        $query->set('meta_query', array(
            array(
                'key'   => 'highlight',
                'value' => '0'
            )
        ) );        
    }


}
add_action('pre_get_posts','my_custom_search_query');

This code does not work properly, because:

  1. it removes posts from both loops on search results page, not from only "regular" loop
  2. it removes more than highlighted posts...

I also tried to use here $query->is_main_query() with no success.

6
  • 1
    note that searching via meta_query is very expensive, you should use a custom taxonomy or highlight tag/category to back that field rather than post meta as filtering/searching by term is ultra fast in comparison. Exclusions/NOT IN queries are even more expensive. These types of queries get dramatically slower as the number of posts and post meta increases
    – Tom J Nowell
    May 24 at 19:27
  • That second loop uses the main query, so no matter what, your if needs to check $query->is_main_query(). So if ( ! is_admin() && $query->is_search() && $query->is_main_query() ) should work. And your meta query needs two clauses with an OR relation - first clause: checks if the value is 0, and the other clause is one that has 'compare' => 'NOT EXISTS'. But I agreed with Tom - you could have just assigned the "highlighted" posts in a category (or custom taxonomy term) named Highlighted or something better.. And then your query would become easier.
    – Sally CJ
    May 24 at 21:22
  • Hello @SallyCJ, i'm using "highlight" field at three custom post types. My search page displays results from all of them by various parameters as taxonomies. Your if statement works good and excludes all "highlighted" post from results, but now, it displays results from only one of three custom post types...
    – Juraj
    May 26 at 13:56
  • @TomJNowell, thank You and what means "very expensive" in my case? ACF documentation says, I should to use meta_query array parameter advancedcustomfields.com/resources/true-false :)
    – Juraj
    May 26 at 15:45
  • to query post meta yes, but finding post by their meta is expensive, it has a high resource cost on the database server, the query can takes longer to run and is slower, and it means fewer of these queries can run at the same time reducing the number of people who can view your site at the same time. It's a performance issue, expensive things are slow, cheap things are fast. It's not how you query post meta, it's that you're doing it at all, this is why categories tags and other taxonomies aren't stored in post meta but are stored in dedicated tables that make this type of query fast.
    – Tom J Nowell
    May 26 at 16:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.