Skip to content

Offload any WP_Query to Enterprise Search

When the VIP_ENABLE_VIP_SEARCH_QUERY_INTEGRATION constant is set to true, all standard front-end search queries passed with the s argument (e.g., /?s=) are automatically sent to Elasticsearch.

By default, queries that are not passed as a search argument will not offload to Elasticsearch. Enabling non-standard queries to be offloaded requires a WP_Query argument to be added.

Not all queries should be offloaded to Enterprise Search — queries that do not show evidence of performance issues can continue to be handled by MySQL. Unnecessarily offloading queries can have unexpected negative effects. For example, if every request for a single post is offloaded to Enterprise Search it could result in rate limiting.

Use Query Monitor or the Slow Query Logs panel in the VIP Dashboard to identify slow queries and queries that are poorly performing (i.e. taxonomy and meta queries). Offload the identified slower queries to Enterprise Search, and test with Query Monitor to verify improvements to their performance.

Adding the es parameter

Thees parameter can be used to offload existing MySQL queries to Elasticsearch. When the es parameter is set to true, the es-wp-query adapter is leveraged instead of ElasticPress and effectively maps most SQL queries to Elasticsearch.

The built-in es-wp-query adapter can handle transforming a query into an Elasticsearch request, obtain the search results (generally, a list of Post IDs), and then obtain the post data from the database.

When working with the es parameter, each query should be tested individually to ensure that it is returning the expected results. Adjustments can be made to the query as needed.

Caution

The facets feature in Enterprise Search will not work without ElasticPress, and will fail if es is set to true for search queries.

Using pre_get_posts

When using pre_get_posts, it is important to target the correct query.

In this code example, queries are offloaded using the pre_get_posts hook:

function vip_sample_es_offload( $query ) {
    if ( $query->is_main_query() && ! $query->is_category() ) { // Conditions to offload to ES.
        $query->set( 'es', true );
    }
}
add_action( 'pre_get_posts', 'vip_sample_es_offload' );

The pre_get_posts hook can also be used to selectively offload queries in the WordPress Admin.

WP_Query arguments

The query argument can be added to the argument list where WP_Query (or get_posts) is already being called by adding 'es' => true to the query args:

$query = new WP_Query(
	array(
		'post_type'      => 'post',
		'post_status'    => 'publish',
		'posts_per_page' => 10,
		'es'             => true,
	)
);

If any of the queries are filtering by terms (or taxonomy, e.g. categories), the terms feature will need to be enabled.

The meta and taxonomy filters are not indexed by default and should be reviewed as well.

Advanced usage

AJAX Queries

To offload WP_Queries called by AJAX, use the ep_ajax_wp_query_integration filter:

add_filter( 'ep_ajax_wp_query_integration', '__return_true' );

The ep_ajax_wp_query_integration filter can also be used to enable Enterprise Search to perform Media Library searches in the WordPress Admin.

Query MySQL directly

For simple queries that run very fast, Elasticsearch may not be necessary and querying MySQL directly will work well. Test if a query works well without Elasticsearch by omitting the es parameter, run the query, then monitor both the results and the speed using tools such as New Relic and Query Monitor.

Disable a fallback to MySQL queries

By default, any unsuccessful search query to an Elasticsearch index will fall back to a regular MySQL database query. In some cases, this can cause degraded performance of the database. This is particularly true if the queries that are intended to be handled by Enterprise Search are complex and expensive.

A search query to an Elasticsearch index could be unsuccessful if:

  • It attempts to retrieve more than 10000 documents from an Elasticsearch index
  • Elasticsearch fails to parse the query.
  • It takes more than 2 seconds to complete.

To protect the performance of the database It may be beneficial to prevent queries from falling back to MySQL at all.

In this code example a custom function utilizing the ElasticPress posts_pre_query  filter prevents the MySQL query fallback by returning 0 posts if an Elasticsearch query has failed.

add_filter( 'posts_pre_query', 'prevent_mysql_request_after_es_failed', 999, 2 );
function prevent_mysql_request_after_es_failed( $posts, WP_Query $query ) {
    // If the ES query failed, return an empty array to prevent a MySQL query.
    // Adjust these conditions to match your needs.
    if ( isset( $query->elasticsearch_success ) && false === $query->elasticsearch_success ) {
        return [];
    }
 
    return $posts;
}

ElasticPress offloading via ep_integrate

An ElasticPress approach that should be considered for offloading select queries (if neither the es option nor the direct MySQL options produce the needed search results or speed)—or for searching across sites on a network—is ep_integrate. This option appears similar but behaves differently by bypassing the provided es-wp-query adapter and uses the ElasticPress code instead. This may filter and normalize some special characters, such as apostrophes and quotes in a different way.

Instead of es in the WP_Query arguments, use ep_integrate (set to true). This can be implemented in a case-by-case basis; for example, almost all offloaded queries might use es, and one very specialized query might use ep_integrate.

Review the ElasticPress documentation before using this option. If the query involves terms or users, those features will need to be enabled.

Last updated: February 29, 2024

Relevant to

  • WordPress