From ed3854948fe69c051daf7f5bae430f46da6ce64d Mon Sep 17 00:00:00 2001 From: Jonny Harris Date: Thu, 31 Mar 2022 10:04:25 +0000 Subject: [PATCH] Taxonomy: Improve performance by taxonomy queries by adding a limitting requested terms. Add a limit to the number of terms requested in taxonomy queries. This improves the performance of the query and the likelihood of hitting an existing term query cache. Props Spacedmonkey, peterwilsoncc, flixos90. Fixes #55360. git-svn-id: https://develop.svn.wordpress.org/trunk@53037 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/class-wp-tax-query.php | 4 + tests/phpunit/tests/query/taxQuery.php | 120 +++++++++++++++++++++++++ 2 files changed, 124 insertions(+) diff --git a/src/wp-includes/class-wp-tax-query.php b/src/wp-includes/class-wp-tax-query.php index eb4b7849e2..862a28f768 100644 --- a/src/wp-includes/class-wp-tax-query.php +++ b/src/wp-includes/class-wp-tax-query.php @@ -637,6 +637,10 @@ class WP_Tax_Query { break; } + if ( ! is_taxonomy_hierarchical( $query['taxonomy'] ) ) { + $args['number'] = count( $terms ); + } + $term_query = new WP_Term_Query(); $term_list = $term_query->query( $args ); diff --git a/tests/phpunit/tests/query/taxQuery.php b/tests/phpunit/tests/query/taxQuery.php index c44f19880f..e67ca6f36e 100644 --- a/tests/phpunit/tests/query/taxQuery.php +++ b/tests/phpunit/tests/query/taxQuery.php @@ -1621,4 +1621,124 @@ class Tests_Query_TaxQuery extends WP_UnitTestCase { $this->assertSameSets( array( $p ), $q->posts ); } + + /** + * @ticket 55360 + * + * @covers WP_Tax_Query::transform_query + */ + public function test_tax_terms_should_limit_query() { + $filter = new MockAction(); + add_filter( 'terms_pre_query', array( $filter, 'filter' ), 10, 2 ); + register_taxonomy( 'wptests_tax', 'post' ); + $name = 'foobar'; + $t = self::factory()->term->create( + array( + 'taxonomy' => 'wptests_tax', + 'name' => $name, + ) + ); + + $p = self::factory()->post->create(); + wp_set_object_terms( $p, array( $t ), 'wptests_tax' ); + + $q = new WP_Query( + array( + 'fields' => 'ids', + 'tax_query' => array( + array( + 'taxonomy' => 'wptests_tax', + 'field' => 'name', + 'terms' => $name, + ), + ), + ) + ); + + $filter_args = $filter->get_args(); + $query = $filter_args[1][1]->request; + + $this->assertSameSets( array( $p ), $q->posts ); + $this->assertStringContainsString( 'LIMIT 1', $query ); + } + + /** + * @ticket 55360 + * + * @covers WP_Tax_Query::transform_query + */ + public function test_tax_terms_should_limit_query_to_one() { + $filter = new MockAction(); + add_filter( 'terms_pre_query', array( $filter, 'filter' ), 10, 2 ); + register_taxonomy( 'wptests_tax', 'post' ); + $name = 'foobar'; + $t = self::factory()->term->create( + array( + 'taxonomy' => 'wptests_tax', + 'name' => $name, + ) + ); + + $p = self::factory()->post->create(); + wp_set_object_terms( $p, array( $t ), 'wptests_tax' ); + + $q = new WP_Query( + array( + 'fields' => 'ids', + 'tax_query' => array( + array( + 'taxonomy' => 'wptests_tax', + 'field' => 'term_id', + 'terms' => array( $t, $t, $t ), + ), + ), + ) + ); + + $filter_args = $filter->get_args(); + $query = $filter_args[1][1]->request; + + $this->assertSameSets( array( $p ), $q->posts ); + $this->assertStringContainsString( 'LIMIT 1', $query ); + } + + /** + * @ticket 55360 + * + * @covers WP_Tax_Query::transform_query + */ + public function test_hierarchical_taxonomies_do_not_limit_query() { + $filter = new MockAction(); + add_filter( 'terms_pre_query', array( $filter, 'filter' ), 10, 2 ); + register_taxonomy( 'wptests_tax', 'post', array( 'hierarchical' => true ) ); + $name = 'foobar'; + $t = self::factory()->term->create( + array( + 'taxonomy' => 'wptests_tax', + 'name' => $name, + ) + ); + + $p = self::factory()->post->create(); + wp_set_object_terms( $p, array( $t ), 'wptests_tax' ); + + $q = new WP_Query( + array( + 'fields' => 'ids', + 'tax_query' => array( + array( + 'taxonomy' => 'wptests_tax', + 'field' => 'name', + 'terms' => $name, + ), + ), + ) + ); + + $filter_args = $filter->get_args(); + $query = $filter_args[0][1]->request; + + $this->assertSameSets( array( $p ), $q->posts ); + $this->assertStringNotContainsString( 'LIMIT 1', $query ); + } }