Replace WordPress Search with Own Algorithm

WordPress is great, no doubt about that. But it’s search functionality is certainly worth improving, or to put it differently — depending on the use case, it requires heavy customization. Example: You want to show search results of products, but you want to decide which products show up first – maybe because there are older and newer versions etc.

The key steps in implementing your own search algorithm are:

  1. Using the pre_get_posts hook to hook into WordPress’ wp_query
  2. Send query to own algorithm
  3. Put the result (post ID’s, that is) unto the “post__in” parameter of wp_query
  4. Run the query.

There are some things to be aware of, though:

1) WordPress re-orders the search results

This defeats one of the big advantages of using your own algorithm, but fortunately wp_query allows the following:

1
$wp_query->set( 'orderby', 'post__in');

That simple. The good point about that is that WP takes care of pagination, and when you change the search order on the frontend, it’s still working and re-ordering and paginating as expected. The drawback: The initial (customized) order of the results cannot be restored, unless the page is reloaded.

2) WordPress overwrites the search results

This is simple to fix as well — just empty the “s” parameter in the query.

3) Because the “s” parameter is empty, the search term doesn’t appear on the result page

This took a little bit of time to experiment, but eventually this is easy to fix as well: Just put the “s” parameter back in before the template redirect.

 

The code can then look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 
add_action( 'pre_get_posts', 'my_pre_get_posts' );
add_action( 'template_redirect' , 'reset_search_query', 100 );
 
function my_pre_get_posts( ) {
        global $wp_query
 
        //only apply if in search 
        if ( $wp_query->is_search() ) {
             //you can set here whether the search replacement should happen in frontend or backend only
             //the below limits it to the frontend
	     if(!is_admin() && isset($_REQUEST['s'])) {
 
                //here you can send the search query to your own search function (not provided here)			
		$results = my_own_searchalgorithm($_REQUEST['s']);
                       //the result must be a simple array with post ids inside
		       if(isset($results)) {
				$wp_query->set( 'post__in', $results);
				$wp_query->set( 's', ''); //reset the search query - this is important
				$wp_query->set( 'orderby', 'post__in'); //keep order of own results
				$wp_query->set( 'post_type', 'product'); //set to desired post type
			} 
                      //if there are no results, wordpress falls back to it's own search
		}
	}
}
function reset_search_query() {
     // we are overwriting search results with our results, and therefore we need to empty the "s" parameter.
     // however, on the results page we need that "s" parameter to be active again - 
     // we can set this here, after the query and before the template reload
     if(!is_admin() && isset($_REQUEST['s'])) {
	   set_query_var('s', $_REQUEST['s']);
		}
}
 
function my_own_searchalgorithm($query) {
      $results = array();
      //include your own algorithm here and return an array with Post IDs, such as array(0 => 1717, 1 => 2874) etc.
      return $results;
}

Post a Comment

You must be logged in to post a comment.