0

I'd like to replace the existing search function with an external query (from Solr) but I'm having trouble showing the results in the search.php page. This is the code I have in functions.php:

add_action('pre_get_posts', 'my_search_query');

function my_search_query($query) {
    if($query->is_search() && $query->is_main_query() && get_query_var('s', false)) {   

    $desired_query = get_query_var('s', false);

    $url = 'http://{SOLR_SERVER}:8983/solr/{CORE}/select?indent=on&q=' . $desired_query . '~2&wt=json';
    $result = file_get_contents($url);
    $data = json_decode($result, true);

    $ids = array();
    foreach ($data['response']['docs'] as $item)
    {
        array_push($ids, $item['id']);
    }

    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
    $query = new WP_Query(array(
        'post__in' => $ids,
        'post_type' => array('last-news','blog'), 
        'paged' => $paged, 
        'posts_per_page' => 5,
    ));

}
return $query;
}

And this is the search.php:

<section class="content">
    <div class="page-title pad group">
        <h1>
        <?php if ( have_posts() ): ?><i class="fa fa-search"></i><?php endif; ?>
        <?php if ( !have_posts() ): ?><i class="fa fa-exclamation-circle"></i><?php endif; ?>
        <?php echo $wp_query->found_posts  ?>
        <?php _e('Search Results','theme'); ?>
        </h1>
    </div>

    <div class="pad group">

        <div class="notebox">
            <?php _e('Found','theme'); ?> "<span><?php echo get_search_query(); ?></span>".
            <?php if ( !have_posts() ): ?>
                <?php _e('Try with another term:','theme'); ?>
            <?php endif; ?>
            <div class="search-again">
                <?php get_search_form(); ?>
            </div>
        </div>

        <?php 
            if ( have_posts() ) : ?>

            <div class="post-list group">
                <?php $i = 1;  while ( have_posts() ): the_post(); 
                echo '<div class="post-row">';
                 get_template_part('content'); echo '</div>'; endwhile;  ?>
            </div><!--/.post-list-->

            <?php get_template_part('inc/pagination'); ?>

        <?php endif; ?>

    </div><!--/.pad-->

</section><!--/.content-->

The echo $wp_query->found_posts returns the number '100' so it seems to be getting something but then the have_posts() functions returns a false value.

What am I doing wrong? I just want to return the posts in the $ids array whenever a search is done, I don't need no other filter.

Edit (alternative solution):

I also can do something like this:

add_action('pre_get_posts', 'my_search_query');
function my_search_query($query) {
    if($query->is_search() && $query->is_main_query() && get_query_var('s', false)) {   

    $desired_query = get_query_var('s', false);

    $url = 'http://{SOLR_SERVER}:8983/solr/{CORE}/select?indent=on&q=' . $desired_query . '~2&wt=json';
    $result = file_get_contents($url);
    $data = json_decode($result, true);

    $ids = array();
    foreach ($data['response']['docs'] as $item)
    {
        array_push($ids, $item['id']);
    }

    $query->set('post__in', $ids );
}
return $query;
}

The problem with this one is that the search, as I could understand, is going to be run with the search term and only will return the posts matching the term within the specific post ids. I don't want to make this operation, as I already did it with solr. Also, Solr allows me to make a Fuzzy query, but this won't work in this setting because the wordpress search will return 0 results, not finding the exact term.

2 Answers 2

2

You can't return a query object from a pre_get_posts action. In fact, it shouldn't return anything, the query object is passed by reference.

Your second attempt is close, you can unset the s query var so WordPress doesn't try to search on that term. Of course, now s has no value, so any functions that try to output the search term will just get an empty string.

add_action('pre_get_posts', 'my_search_query');
function my_search_query($query) {
    if($query->is_search() && $query->is_main_query() && get_query_var('s', false)) {
        // get your $ids, then
        unset( $query->query_vars['s'] );
        $query->set( 'post__in', $ids );
    }
}
2
  • Unsetting query_vars outputs an error in the query and I end up getting no results.
    – Rod0n
    Commented May 17, 2017 at 18:44
  • The error probably tells you what the problem is, I can't guess what it might be though, I don't get an error with a default install and theme.
    – Milo
    Commented May 17, 2017 at 19:03
1

Here is a little more on the answer here with some comments about what we're doing at each step, and how to convert it to work within WordPress' DB as well

#run before posts are grabbed from DB
add_action('pre_get_posts', 'my_search_query');
function my_search_query($query) {
    #global $wpdb; # used for internal with WP searching
    #is this query the main search query, and is there a search query provided?
    if($query->is_search() && $query->is_main_query() && get_query_var('s', false)) {

        #fun SQL goes here

            #INTERNAL
            #$sql = "" #SQL query
            #$results = $wpdb->get_results( $sql ); # used for internal with WP searching

            #EXTERNAL
            #$url = 'http://yourapi.com/json'; #go out to an api or something
            #$result = file_get_contents($url);
            #$results = json_decode($result, true);

        #create array to hold returned ids
        $ids = array();
        #loop through each and grab ID
        foreach ($results as $item) {
            array_push($results, $item['id']);
        }
        #make sure there are posts if you're going to replace search
        if( ! empty( $ids )) { 
            #Tell original WP search to shove it
            unset( $query->query_vars['s'] );
            #replace the current query with your results
            $query->set( 'post__in', $ids );

        }

    }
    #send back the query whether we touched it, or it didn't match our parameters
    return $query;
}

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.