Generally speaking, you could use the WP Transients API to save the query.
// Get any existing copy of our transient data
if ( false === ( $special_query_results = get_transient( 'special_query_results' ) ) ) {
// It wasn't there, so regenerate the data and save the transient
$special_query_results = new WP_Query( 'cat=5&order=random&tag=tech&post_meta_key=thumbnail' );
set_transient( 'special_query_results', $special_query_results, 12 * HOUR_IN_SECONDS );
}
// Use the data like you would have normally...
This article brings up a good point by arguing that it’s not a good idea to store a WP_Query()
object as a transient, and instead suggests storing the post IDs returned from an expensive query in a transient, then using those IDs to create a new WP_Query
. Granted, with this approach we’d be right back to having duplicate queries, but they would be lighter queries.
$cache_key = 'my-expensive-query';
if ( ! $ids = get_transient( $cache_key ) ) {
$query = new WP_Query( array(
'fields' => 'ids',
// ...
) );
$ids = $query->posts;
set_transient( $cache_key, $ids, 24 * HOUR_IN_SECONDS );
}
$query = new WP_Query( array(
'post__in' => $ids,
) );
// while ( $query->have_posts() ) ...