From 06d28c278272c3128b3f073bec0d29d6420b79f8 Mon Sep 17 00:00:00 2001 From: Matt Boynes Date: Fri, 26 Feb 2016 16:55:46 -0500 Subject: [PATCH 01/10] Add core's new list of meta query tests --- tests/query/metaQuery.php | 1740 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1740 insertions(+) create mode 100644 tests/query/metaQuery.php diff --git a/tests/query/metaQuery.php b/tests/query/metaQuery.php new file mode 100644 index 0000000..4d54d41 --- /dev/null +++ b/tests/query/metaQuery.php @@ -0,0 +1,1740 @@ +post->create(); + $p2 = self::factory()->post->create(); + $p3 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', 'bar' ); + add_post_meta( $p2, 'oof', 'bar' ); + add_post_meta( $p3, 'oof', 'baz' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'value' => 'bar', + ), + ), + ) ); + + $expected = array( $p1, $p2 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_query_no_value() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + $p3 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', 'bar' ); + add_post_meta( $p2, 'oof', 'bar' ); + add_post_meta( $p3, 'oof', 'baz' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'oof', + ), + ), + ) ); + + $expected = array( $p2, $p3 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_query_single_query_compare_default() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', 'bar' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 'bar', + ), + ), + ) ); + + $expected = array( $p1 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_query_single_query_compare_equals() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', 'bar' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 'bar', + 'compare' => '=', + ), + ), + ) ); + + $expected = array( $p1 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_query_single_query_compare_not_equals() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + $p3 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', 'bar' ); + add_post_meta( $p2, 'foo', 'baz' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 'bar', + 'compare' => '!=', + ), + ), + ) ); + + $expected = array( $p2 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_query_single_query_compare_arithmetic_comparisons() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + $p3 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', '1' ); + add_post_meta( $p2, 'foo', '2' ); + add_post_meta( $p3, 'foo', '3' ); + es_wp_query_index_test_data(); + + // < + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 2, + 'compare' => '<', + ), + ), + ) ); + + $expected = array( $p1 ); + $this->assertEqualSets( $expected, $query->posts ); + + // <= + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 2, + 'compare' => '<=', + ), + ), + ) ); + + $expected = array( $p1, $p2 ); + $this->assertEqualSets( $expected, $query->posts ); + + // >= + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 2, + 'compare' => '>=', + ), + ), + ) ); + + $expected = array( $p2, $p3 ); + $this->assertEqualSets( $expected, $query->posts ); + + // > + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 2, + 'compare' => '>', + ), + ), + ) ); + + $expected = array( $p3 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_query_single_query_compare_like() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', 'bar' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 'ba', + 'compare' => 'LIKE', + ), + ), + ) ); + + $expected = array( $p1 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_query_single_query_compare_not_like() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + $p3 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', 'bar' ); + add_post_meta( $p2, 'foo', 'rab' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 'ba', + 'compare' => 'NOT LIKE', + ), + ), + ) ); + + $expected = array( $p2 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_query_single_query_compare_between_not_between() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + $p3 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', '1' ); + add_post_meta( $p2, 'foo', '10' ); + add_post_meta( $p3, 'foo', '100' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => array( 9, 12 ), + 'compare' => 'BETWEEN', + 'type' => 'NUMERIC', + ), + ), + ) ); + + $expected = array( $p2 ); + $this->assertEqualSets( $expected, $query->posts ); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => array( 9, 12 ), + 'compare' => 'NOT BETWEEN', + 'type' => 'NUMERIC', + ), + ), + ) ); + + $expected = array( $p1, $p3 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_query_single_query_compare_regexp_rlike() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', 'bar' ); + add_post_meta( $p2, 'foo', 'baz' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 'z$', + 'compare' => 'REGEXP', + ), + ), + ) ); + + $expected = array( $p2 ); + $this->assertEqualSets( $expected, $query->posts ); + + // RLIKE is a synonym for REGEXP. + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 'z$', + 'compare' => 'RLIKE', + ), + ), + ) ); + + $expected = array( $p2 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_query_single_query_compare_not_regexp() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', 'bar' ); + add_post_meta( $p2, 'foo', 'baz' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 'z$', + 'compare' => 'NOT REGEXP', + ), + ), + ) ); + + $expected = array( $p1 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_query_relation_default() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + $p3 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', 'foo value 1' ); + add_post_meta( $p1, 'bar', 'bar value 1' ); + add_post_meta( $p2, 'foo', 'foo value 1' ); + add_post_meta( $p2, 'bar', 'bar value 2' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 'foo value 1', + ), + array( + 'key' => 'bar', + 'value' => 'bar value 1', + ), + ), + ) ); + + $expected = array( $p1 ); + $this->assertEquals( $expected, $query->posts ); + } + + public function test_meta_query_relation_or() { + $post_id = self::factory()->post->create(); + add_post_meta( $post_id, 'foo', rand_str() ); + add_post_meta( $post_id, 'foo', rand_str() ); + $post_id2 = self::factory()->post->create(); + add_post_meta( $post_id2, 'bar', 'val2' ); + $post_id3 = self::factory()->post->create(); + add_post_meta( $post_id3, 'baz', rand_str() ); + $post_id4 = self::factory()->post->create(); + add_post_meta( $post_id4, 'froo', rand_str() ); + $post_id5 = self::factory()->post->create(); + add_post_meta( $post_id5, 'tango', 'val2' ); + $post_id6 = self::factory()->post->create(); + add_post_meta( $post_id6, 'bar', 'val1' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo' + ), + array( + 'key' => 'bar', + 'value' => 'val2' + ), + array( + 'key' => 'baz' + ), + array( + 'key' => 'froo' + ), + 'relation' => 'OR', + ), + ) ); + + $expected = array( $post_id, $post_id2, $post_id3, $post_id4 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_query_relation_and() { + $post_id = self::factory()->post->create(); + add_post_meta( $post_id, 'foo', rand_str() ); + add_post_meta( $post_id, 'foo', rand_str() ); + $post_id2 = self::factory()->post->create(); + add_post_meta( $post_id2, 'bar', 'val2' ); + add_post_meta( $post_id2, 'foo', rand_str() ); + $post_id3 = self::factory()->post->create(); + add_post_meta( $post_id3, 'baz', rand_str() ); + $post_id4 = self::factory()->post->create(); + add_post_meta( $post_id4, 'froo', rand_str() ); + $post_id5 = self::factory()->post->create(); + add_post_meta( $post_id5, 'tango', 'val2' ); + $post_id6 = self::factory()->post->create(); + add_post_meta( $post_id6, 'bar', 'val1' ); + add_post_meta( $post_id6, 'foo', rand_str() ); + $post_id7 = self::factory()->post->create(); + add_post_meta( $post_id7, 'foo', rand_str() ); + add_post_meta( $post_id7, 'froo', rand_str() ); + add_post_meta( $post_id7, 'baz', rand_str() ); + add_post_meta( $post_id7, 'bar', 'val2' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'foo' + ), + array( + 'key' => 'bar', + 'value' => 'val2' + ), + array( + 'key' => 'baz' + ), + array( + 'key' => 'froo' + ), + 'relation' => 'AND', + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $post_id7 ); + $this->assertEqualSets( $expected, $query->posts ); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'foo' + ), + array( + 'key' => 'bar', + ), + 'relation' => 'AND', + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $post_id2, $post_id6, $post_id7 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 30681 + */ + public function test_meta_query_compare_exists() { + $posts = self::factory()->post->create_many( 3 ); + add_post_meta( $posts[0], 'foo', 'bar' ); + add_post_meta( $posts[2], 'foo', 'baz' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'fields' => 'ids', + 'meta_query' => array( + array( + 'compare' => 'EXISTS', + 'key' => 'foo', + ), + ), + ) ); + + $this->assertEqualSets( array( $posts[0], $posts[2] ), $query->posts ); + } + + /** + * @ticket 30681 + */ + public function test_meta_query_compare_exists_with_value_should_convert_to_equals() { + $posts = self::factory()->post->create_many( 3 ); + add_post_meta( $posts[0], 'foo', 'bar' ); + add_post_meta( $posts[2], 'foo', 'baz' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'fields' => 'ids', + 'meta_query' => array( + array( + 'compare' => 'EXISTS', + 'value' => 'baz', + 'key' => 'foo', + ), + ), + ) ); + + $this->assertEqualSets( array( $posts[2] ), $query->posts ); + } + + /** + * @ticket 30681 + */ + public function test_meta_query_compare_not_exists_should_ignore_value() { + $posts = self::factory()->post->create_many( 3 ); + add_post_meta( $posts[0], 'foo', 'bar' ); + add_post_meta( $posts[2], 'foo', 'baz' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'fields' => 'ids', + 'meta_query' => array( + array( + 'compare' => 'NOT EXISTS', + 'value' => 'bar', + 'key' => 'foo', + ), + ), + ) ); + + $this->assertEqualSets( array( $posts[1] ), $query->posts ); + } + + /** + * @ticket 18158 + */ + public function test_meta_query_compare_not_exists() { + $post_id = self::factory()->post->create(); + add_post_meta( $post_id, 'foo', rand_str() ); + $post_id2 = self::factory()->post->create(); + add_post_meta( $post_id2, 'bar', rand_str() ); + $post_id3 = self::factory()->post->create(); + add_post_meta( $post_id3, 'bar', rand_str() ); + $post_id4 = self::factory()->post->create(); + add_post_meta( $post_id4, 'baz', rand_str() ); + $post_id5 = self::factory()->post->create(); + add_post_meta( $post_id5, 'foo', rand_str() ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'foo', + 'compare' => 'NOT EXISTS', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $post_id2, $post_id3, $post_id4 ); + $this->assertEqualSets( $expected, $query->posts ); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'foo', + 'compare' => 'NOT EXISTS', + ), + array( + 'key' => 'bar', + 'compare' => 'NOT EXISTS', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $post_id4 ); + $this->assertEquals( $expected, $query->posts ); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'foo', + 'compare' => 'NOT EXISTS', + ), + array( + 'key' => 'bar', + 'compare' => 'NOT EXISTS', + ), + array( + 'key' => 'baz', + 'compare' => 'NOT EXISTS', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $this->assertEquals( 0, count( $query->posts ) ); + } + + /** + * @ticket 29062 + */ + public function test_meta_query_compare_not_exists_with_another_condition_relation_or() { + $posts = self::factory()->post->create_many( 4 ); + update_post_meta( $posts[0], 'color', 'orange' ); + update_post_meta( $posts[1], 'color', 'blue' ); + update_post_meta( $posts[1], 'vegetable', 'onion' ); + update_post_meta( $posts[2], 'vegetable', 'shallot' ); + + $post_3_meta = get_post_meta( $posts[3] ); + foreach ( $post_3_meta as $meta_key => $meta_value ) { + delete_post_meta( $posts[3], $meta_key ); + } + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + 'relation' => 'OR', + array( + 'key' => 'vegetable', + 'value' => 'onion', + ), + array( + 'key' => 'color', + 'compare' => 'NOT EXISTS', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $posts[1], $posts[2], $posts[3] ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 24093 + */ + public function test_meta_query_relation_or_compare_equals() { + $posts = self::factory()->post->create_many( 4 ); + add_post_meta( $posts[0], 'color', 'orange' ); + add_post_meta( $posts[1], 'color', 'blue' ); + add_post_meta( $posts[1], 'vegetable', 'onion' ); + add_post_meta( $posts[2], 'vegetable', 'shallot' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + 'relation' => 'OR', + array( + 'key' => 'vegetable', + 'value' => 'onion', + 'compare' => '=', + ), + array( + 'key' => 'vegetable', + 'value' => 'shallot', + 'compare' => '=', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $posts[1], $posts[2] ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 24093 + */ + public function test_meta_query_relation_or_compare_equals_different_keys() { + $posts = self::factory()->post->create_many( 4 ); + add_post_meta( $posts[0], 'color', 'orange' ); + add_post_meta( $posts[1], 'color', 'blue' ); + add_post_meta( $posts[1], 'vegetable', 'onion' ); + add_post_meta( $posts[2], 'vegetable', 'shallot' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + 'relation' => 'OR', + array( + 'key' => 'vegetable', + 'value' => 'onion', + 'compare' => '=', + ), + array( + 'key' => 'color', + 'value' => 'orange', + 'compare' => '=', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $posts[0], $posts[1] ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 24093 + */ + public function test_meta_query_relation_or_compare_equals_and_in() { + $posts = self::factory()->post->create_many( 4 ); + add_post_meta( $posts[0], 'color', 'orange' ); + add_post_meta( $posts[1], 'color', 'blue' ); + add_post_meta( $posts[1], 'vegetable', 'onion' ); + add_post_meta( $posts[2], 'vegetable', 'shallot' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + 'relation' => 'OR', + array( + 'key' => 'vegetable', + 'value' => 'onion', + 'compare' => '=', + ), + array( + 'key' => 'color', + 'value' => array( 'orange', 'green' ), + 'compare' => 'IN', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $posts[0], $posts[1] ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 24093 + */ + public function test_meta_query_relation_or_compare_equals_and_like() { + $posts = self::factory()->post->create_many( 4 ); + add_post_meta( $posts[0], 'color', 'orange' ); + add_post_meta( $posts[1], 'color', 'blue' ); + add_post_meta( $posts[1], 'vegetable', 'onion' ); + add_post_meta( $posts[2], 'vegetable', 'shallot' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + 'relation' => 'OR', + array( + 'key' => 'vegetable', + 'value' => 'onion', + 'compare' => '=', + ), + array( + 'key' => 'vegetable', + 'value' => 'hall', + 'compare' => 'LIKE', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $posts[1], $posts[2] ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 24093 + */ + public function test_meta_query_relation_or_compare_equals_and_between() { + $posts = self::factory()->post->create_many( 4 ); + add_post_meta( $posts[0], 'number_of_colors', '2' ); + add_post_meta( $posts[1], 'number_of_colors', '5' ); + add_post_meta( $posts[1], 'vegetable', 'onion' ); + add_post_meta( $posts[2], 'vegetable', 'shallot' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + 'relation' => 'OR', + array( + 'key' => 'vegetable', + 'value' => 'shallot', + 'compare' => '=', + ), + array( + 'key' => 'number_of_colors', + 'value' => array( 1, 3 ), + 'compare' => 'BETWEEN', + 'type' => 'SIGNED', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $posts[0], $posts[2] ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 24093 + */ + public function test_meta_query_relation_and_compare_in_same_keys() { + $posts = self::factory()->post->create_many( 4 ); + add_post_meta( $posts[0], 'color', 'orange' ); + add_post_meta( $posts[1], 'color', 'blue' ); + add_post_meta( $posts[1], 'vegetable', 'onion' ); + add_post_meta( $posts[2], 'vegetable', 'shallot' ); + add_post_meta( $posts[3], 'vegetable', 'banana' ); + add_post_meta( $posts[3], 'vegetable', 'onion' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + 'relation' => 'AND', + array( + 'key' => 'vegetable', + 'value' => array( 'onion', 'shallot' ), + 'compare' => 'IN', + ), + array( + 'key' => 'vegetable', + 'value' => array( 'banana' ), + 'compare' => 'IN', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $posts[3] ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 24093 + */ + public function test_meta_query_relation_and_compare_in_different_keys() { + $posts = self::factory()->post->create_many( 4 ); + add_post_meta( $posts[0], 'color', 'orange' ); + add_post_meta( $posts[1], 'color', 'blue' ); + add_post_meta( $posts[1], 'vegetable', 'onion' ); + add_post_meta( $posts[1], 'vegetable', 'shallot' ); + add_post_meta( $posts[2], 'vegetable', 'shallot' ); + add_post_meta( $posts[3], 'vegetable', 'banana' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + 'relation' => 'AND', + array( + 'key' => 'vegetable', + 'value' => array( 'onion', 'shallot' ), + 'compare' => 'IN', + ), + array( + 'key' => 'color', + 'value' => array( 'blue' ), + 'compare' => 'IN', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $posts[1] ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 24093 + */ + public function test_meta_query_relation_and_compare_not_equals() { + $posts = self::factory()->post->create_many( 4 ); + add_post_meta( $posts[0], 'color', 'orange' ); + add_post_meta( $posts[1], 'color', 'blue' ); + add_post_meta( $posts[1], 'vegetable', 'onion' ); + add_post_meta( $posts[2], 'vegetable', 'shallot' ); + add_post_meta( $posts[3], 'vegetable', 'banana' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + 'relation' => 'AND', + array( + 'key' => 'vegetable', + 'value' => 'onion', + 'compare' => '!=', + ), + array( + 'key' => 'vegetable', + 'value' => 'shallot', + 'compare' => '!=', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $posts[3] ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 24093 + */ + public function test_meta_query_relation_and_compare_not_equals_different_keys() { + $posts = self::factory()->post->create_many( 4 ); + + // !shallot, but orange. + add_post_meta( $posts[0], 'color', 'orange' ); + add_post_meta( $posts[0], 'vegetable', 'onion' ); + + // !orange, but shallot. + add_post_meta( $posts[1], 'color', 'blue' ); + add_post_meta( $posts[1], 'vegetable', 'shallot' ); + + // Neither. + add_post_meta( $posts[2], 'color', 'blue' ); + add_post_meta( $posts[2], 'vegetable', 'onion' ); + + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + 'relation' => 'AND', + array( + 'key' => 'vegetable', + 'value' => 'shallot', + 'compare' => '!=', + ), + array( + 'key' => 'color', + 'value' => 'orange', + 'compare' => '!=', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $posts[2] ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 24093 + */ + public function test_meta_query_relation_and_compare_not_equals_not_in() { + $posts = self::factory()->post->create_many( 4 ); + add_post_meta( $posts[0], 'color', 'orange' ); + add_post_meta( $posts[1], 'color', 'blue' ); + add_post_meta( $posts[1], 'vegetable', 'onion' ); + add_post_meta( $posts[2], 'vegetable', 'shallot' ); + add_post_meta( $posts[3], 'vegetable', 'banana' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + 'relation' => 'AND', + array( + 'key' => 'vegetable', + 'value' => 'onion', + 'compare' => '!=', + ), + array( + 'key' => 'vegetable', + 'value' => array( 'shallot' ), + 'compare' => 'NOT IN', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $posts[3] ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 24093 + */ + public function test_meta_query_relation_and_compare_not_equals_and_not_like() { + $posts = self::factory()->post->create_many( 4 ); + add_post_meta( $posts[0], 'color', 'orange' ); + add_post_meta( $posts[1], 'color', 'blue' ); + add_post_meta( $posts[1], 'vegetable', 'onion' ); + add_post_meta( $posts[2], 'vegetable', 'shallot' ); + add_post_meta( $posts[3], 'vegetable', 'banana' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + 'relation' => 'AND', + array( + 'key' => 'vegetable', + 'value' => 'onion', + 'compare' => '!=', + ), + array( + 'key' => 'vegetable', + 'value' => 'hall', + 'compare' => 'NOT LIKE', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $expected = array( $posts[3] ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 23033 + */ + public function test_meta_query_decimal_results() { + $post_1 = self::factory()->post->create(); + $post_2 = self::factory()->post->create(); + $post_3 = self::factory()->post->create(); + $post_4 = self::factory()->post->create(); + + update_post_meta( $post_1, 'decimal_value', '-0.3' ); + update_post_meta( $post_2, 'decimal_value', '0.23409844' ); + update_post_meta( $post_3, 'decimal_value', '0.3' ); + update_post_meta( $post_4, 'decimal_value', '0.4' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'decimal_value', + 'value' => '.300', + 'compare' => '=', + 'type' => 'DECIMAL(10,2)' + ) + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + $this->assertEqualSets( array( $post_3 ), $query->posts ); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'decimal_value', + 'value' => '0.35', + 'compare' => '>', + 'type' => 'DECIMAL(10,2)' + ) + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + $this->assertEqualSets( array( $post_4 ), $query->posts ); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'decimal_value', + 'value' => '0.3', + 'compare' => '>=', + 'type' => 'DECIMAL(10,2)' + ) + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + $this->assertEqualSets( array( $post_3, $post_4 ), $query->posts ); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'decimal_value', + 'value' => '0', + 'compare' => '<', + 'type' => 'DECIMAL(10,2)' + ) + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + $this->assertEqualSets( array( $post_1 ), $query->posts, 'ID' ); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'decimal_value', + 'value' => '0.3', + 'compare' => '<=', + 'type' => 'DECIMAL(10,2)' + ) + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + $this->assertEqualSets( array( $post_1, $post_2, $post_3 ), $query->posts ); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'decimal_value', + 'value' => array( 0.23409845, .31 ), + 'compare' => 'BETWEEN', + 'type' => 'DECIMAL(10, 10)' + ) + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + $this->assertEqualSets( array( $post_3 ), $query->posts ); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'decimal_value', + 'value' => array( 0.23409845, .31 ), + 'compare' => 'NOT BETWEEN', + 'type' => 'DECIMAL(10,10)' + ) + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + $this->assertEqualSets( array( $post_1, $post_2, $post_4 ), $query->posts ); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'decimal_value', + 'value' => '.3', + 'compare' => 'LIKE', + 'type' => 'DECIMAL(10,2)' + ) + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + $this->assertEqualSets( array( $post_1, $post_3 ), $query->posts ); + + $query = new ES_WP_Query( array( + 'meta_query' => array( + array( + 'key' => 'decimal_value', + 'value' => '.3', + 'compare' => 'NOT LIKE', + 'type' => 'DECIMAL(10,2)' + ) + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + $this->assertEqualSets( array( $post_2, $post_4 ), $query->posts ); + + $query = new ES_WP_Query( array( + 'orderby' => 'meta_value', + 'order' => 'DESC', + 'meta_key' => 'decimal_value', + 'meta_type' => 'DECIMAL(10, 2)', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + $this->assertEqualSets( array( $post_4, $post_3, $post_2, $post_1 ), $query->posts ); + } + + public function test_meta_vars_should_be_converted_to_meta_query() { + $q = new ES_WP_Query( array( + 'meta_key' => 'foo', + 'meta_value' => '5', + 'meta_compare' => '>', + 'meta_type' => 'SIGNED', + ) ); + + $this->assertSame( 'foo', $q->meta_query->queries[0]['key'] ); + $this->assertSame( '5', $q->meta_query->queries[0]['value'] ); + $this->assertSame( '>', $q->meta_query->queries[0]['compare'] ); + $this->assertSame( 'SIGNED', $q->meta_query->queries[0]['type'] ); + } + + /** + * @ticket 29604 + */ + public function test_meta_query_with_orderby_meta_value_relation_or() { + $posts = self::factory()->post->create_many( 4 ); + update_post_meta( $posts[0], 'foo', 5 ); + update_post_meta( $posts[1], 'foo', 6 ); + update_post_meta( $posts[2], 'foo', 4 ); + update_post_meta( $posts[3], 'foo', 7 ); + + update_post_meta( $posts[0], 'bar1', 'baz' ); + update_post_meta( $posts[1], 'bar1', 'baz' ); + update_post_meta( $posts[2], 'bar2', 'baz' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'orderby' => 'meta_value', + 'order' => 'ASC', + 'meta_key' => 'foo', + 'meta_query' => array( + 'relation' => 'OR', + array( + 'key' => 'bar1', + 'value' => 'baz', + 'compare' => '=', + ), + array( + 'key' => 'bar2', + 'value' => 'baz', + 'compare' => '=', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $this->assertEquals( array( $posts[2], $posts[0], $posts[1] ), $query->posts ); + } + + /** + * @ticket 29604 + */ + public function test_meta_query_with_orderby_meta_value_relation_and() { + $posts = self::factory()->post->create_many( 4 ); + update_post_meta( $posts[0], 'foo', 5 ); + update_post_meta( $posts[1], 'foo', 6 ); + update_post_meta( $posts[2], 'foo', 4 ); + update_post_meta( $posts[3], 'foo', 7 ); + + update_post_meta( $posts[0], 'bar1', 'baz' ); + update_post_meta( $posts[1], 'bar1', 'baz' ); + update_post_meta( $posts[2], 'bar1', 'baz' ); + update_post_meta( $posts[3], 'bar1', 'baz' ); + update_post_meta( $posts[0], 'bar2', 'baz' ); + update_post_meta( $posts[1], 'bar2', 'baz' ); + update_post_meta( $posts[2], 'bar2', 'baz' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'orderby' => 'meta_value', + 'order' => 'ASC', + 'meta_key' => 'foo', + 'meta_query' => array( + 'relation' => 'AND', + array( + 'key' => 'bar1', + 'value' => 'baz', + 'compare' => '=', + ), + array( + 'key' => 'bar2', + 'value' => 'baz', + 'compare' => '=', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $this->assertEquals( array( $posts[2], $posts[0], $posts[1] ), $query->posts ); + } + + /** + * @ticket 29642 + */ + public function test_meta_query_nested() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + $p3 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', 'bar' ); + add_post_meta( $p2, 'foo2', 'bar' ); + add_post_meta( $p3, 'foo2', 'bar' ); + add_post_meta( $p3, 'foo3', 'bar' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_term_meta_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + 'relation' => 'OR', + array( + 'key' => 'foo', + 'value' => 'bar', + ), + array( + 'relation' => 'AND', + array( + 'key' => 'foo2', + 'value' => 'bar', + ), + array( + 'key' => 'foo3', + 'value' => 'bar', + ), + ), + ), + ) ); + + $expected = array( $p1, $p3 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + /** + * @ticket 29642 + */ + public function test_meta_query_nested_two_levels_deep() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + $p3 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', 'bar' ); + add_post_meta( $p3, 'foo2', 'bar' ); + add_post_meta( $p3, 'foo3', 'bar' ); + add_post_meta( $p3, 'foo4', 'bar' ); + es_wp_query_index_test_data(); + + $query = new ES_WP_Query( array( + 'update_post_meta_cache' => false, + 'update_term_meta_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + 'relation' => 'OR', + array( + 'key' => 'foo', + 'value' => 'bar', + ), + array( + 'relation' => 'OR', + array( + 'key' => 'foo2', + 'value' => 'bar', + ), + array( + 'relation' => 'AND', + array( + 'key' => 'foo3', + 'value' => 'bar', + ), + array( + 'key' => 'foo4', + 'value' => 'bar', + ), + ), + ), + ), + ) ); + + $expected = array( $p1, $p3 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_between_not_between() { + $post_id = self::factory()->post->create(); + add_post_meta( $post_id, 'time', 500 ); + $post_id2 = self::factory()->post->create(); + add_post_meta( $post_id2, 'time', 1001 ); + $post_id3 = self::factory()->post->create(); + add_post_meta( $post_id3, 'time', 0 ); + $post_id4 = self::factory()->post->create(); + add_post_meta( $post_id4, 'time', 1 ); + $post_id5 = self::factory()->post->create(); + add_post_meta( $post_id5, 'time', 1000 ); + es_wp_query_index_test_data(); + + $args = array( + 'meta_key' => 'time', + 'meta_value' => array( 1, 1000 ), + 'meta_type' => 'numeric', + 'meta_compare' => 'NOT BETWEEN' + ); + + $query = new ES_WP_Query( $args ); + $this->assertEquals( 2, count ( $query->posts ) ); + foreach ( $query->posts as $post ) { + $this->assertInstanceOf( 'WP_Post', $post ); + $this->assertEquals( 'raw', $post->filter ); + } + $posts = wp_list_pluck( $query->posts, 'ID' ); + $this->assertEqualSets( array( $post_id2, $post_id3 ), $posts ); + + $args = array( + 'meta_key' => 'time', + 'meta_value' => array( 1, 1000 ), + 'meta_type' => 'numeric', + 'meta_compare' => 'BETWEEN' + ); + + $query = new ES_WP_Query( $args ); + $this->assertEquals( 3, count ( $query->posts ) ); + foreach ( $query->posts as $post ) { + $this->assertInstanceOf( 'WP_Post', $post ); + $this->assertEquals( 'raw', $post->filter ); + } + $posts = wp_list_pluck( $query->posts, 'ID' ); + $this->assertEqualSets( array( $post_id, $post_id4, $post_id5 ), $posts ); + } + + /** + * @ticket 16829 + */ + public function test_meta_default_compare() { + // compare should default to IN when meta_value is an array + $post_id = self::factory()->post->create(); + add_post_meta( $post_id, 'foo', 'bar' ); + $post_id2 = self::factory()->post->create(); + add_post_meta( $post_id2, 'bar', 'baz' ); + $post_id3 = self::factory()->post->create(); + add_post_meta( $post_id3, 'foo', 'baz' ); + $post_id4 = self::factory()->post->create(); + add_post_meta( $post_id4, 'baz', 'bar' ); + $post_id5 = self::factory()->post->create(); + add_post_meta( $post_id5, 'foo', rand_str() ); + es_wp_query_index_test_data(); + + $posts = es_get_posts( array( + 'meta_key' => 'foo', + 'meta_value' => array( 'bar', 'baz' ) + ) ); + + $this->assertEquals( 2, count( $posts ) ); + $posts = wp_list_pluck( $posts, 'ID' ); + $this->assertEqualSets( array( $post_id, $post_id3 ), $posts ); + + $posts = es_get_posts( array( + 'meta_key' => 'foo', + 'meta_value' => array( 'bar', 'baz' ), + 'meta_compare' => 'IN' + ) ); + + $this->assertEquals( 2, count( $posts ) ); + foreach ( $posts as $post ) { + $this->assertInstanceOf( 'WP_Post', $post ); + $this->assertEquals( 'raw', $post->filter ); + } + $posts = wp_list_pluck( $posts, 'ID' ); + $this->assertEqualSets( array( $post_id, $post_id3 ), $posts ); + } + + /** + * @ticket 17264 + */ + public function test_duplicate_posts_when_no_key() { + $post_id = self::factory()->post->create(); + add_post_meta( $post_id, 'city', 'Lorem' ); + add_post_meta( $post_id, 'address', '123 Lorem St.' ); + $post_id2 = self::factory()->post->create(); + add_post_meta( $post_id2, 'city', 'Lorem' ); + $post_id3 = self::factory()->post->create(); + add_post_meta( $post_id3, 'city', 'Loren' ); + es_wp_query_index_test_data(); + + $args = array( + 'meta_query' => array( + array( + 'value' => 'lorem', + 'compare' => 'LIKE' + ) + ) + ); + + $posts = es_get_posts( $args ); + $this->assertEquals( 2, count( $posts ) ); + foreach ( $posts as $post ) { + $this->assertInstanceOf( 'WP_Post', $post ); + $this->assertEquals( 'raw', $post->filter ); + } + $posts = wp_list_pluck( $posts, 'ID' ); + $this->assertEqualSets( array( $post_id, $post_id2 ), $posts ); + } + + /** + * @ticket 15292 + */ + public function test_empty_meta_value() { + $post_id = self::factory()->post->create(); + add_post_meta( $post_id, 'foo', '0' ); + add_post_meta( $post_id, 'bar', 0 ); + $post_id2 = self::factory()->post->create(); + add_post_meta( $post_id2, 'foo', 1 ); + $post_id3 = self::factory()->post->create(); + add_post_meta( $post_id3, 'baz', 0 ); + $post_id4 = self::factory()->post->create(); + add_post_meta( $post_id4, 'baz', 0 ); + $post_id5 = self::factory()->post->create(); + add_post_meta( $post_id5, 'baz', 0 ); + add_post_meta( $post_id5, 'bar', '0' ); + $post_id6 = self::factory()->post->create(); + add_post_meta( $post_id6, 'baz', 0 ); + es_wp_query_index_test_data(); + + $q = new ES_WP_Query( array( 'meta_key' => 'foo', 'meta_value' => '0' ) ); + $this->assertEquals( 1, count ( $q->posts ) ); + foreach ( $q->posts as $post ) { + $this->assertInstanceOf( 'WP_Post', $post ); + $this->assertEquals( 'raw', $post->filter ); + } + $this->assertEquals( $post_id, $q->posts[0]->ID ); + + $posts = es_get_posts( array( 'meta_key' => 'bar', 'meta_value' => '0' ) ); + $this->assertEquals( 2, count ( $posts ) ); + foreach ( $posts as $post ) { + $this->assertInstanceOf( 'WP_Post', $post ); + $this->assertEquals( 'raw', $post->filter ); + } + $posts = wp_list_pluck( $posts, 'ID' ); + $this->assertEqualSets( array( $post_id, $post_id5 ), $posts ); + + $posts = es_get_posts( array( 'meta_key' => 'bar', 'meta_value' => 0 ) ); + $this->assertEquals( 2, count ( $posts ) ); + foreach ( $posts as $post ) { + $this->assertInstanceOf( 'WP_Post', $post ); + $this->assertEquals( 'raw', $post->filter ); + } + $posts = wp_list_pluck( $posts, 'ID' ); + $this->assertEqualSets( array( $post_id, $post_id5 ), $posts ); + + $posts = es_get_posts( array( 'meta_value' => 0 ) ); + $this->assertEquals( 5, count ( $posts ) ); + foreach ( $posts as $post ) { + $this->assertInstanceOf( 'WP_Post', $post ); + $this->assertEquals( 'raw', $post->filter ); + } + $posts = wp_list_pluck( $posts, 'ID' ); + $this->assertEqualSets( array( $post_id, $post_id3, $post_id4, $post_id5, $post_id6 ), $posts ); + + $posts = es_get_posts( array( 'meta_value' => '0' ) ); + $this->assertEquals( 5, count ( $posts ) ); + foreach ( $posts as $post ) { + $this->assertInstanceOf( 'WP_Post', $post ); + $this->assertEquals( 'raw', $post->filter ); + } + $posts = wp_list_pluck( $posts, 'ID' ); + $this->assertEqualSets( array( $post_id, $post_id3, $post_id4, $post_id5, $post_id6 ), $posts ); + } + + /** + * @ticket 31045 + */ + public function test_orderby_clause_key() { + $posts = self::factory()->post->create_many( 3 ); + add_post_meta( $posts[0], 'foo', 'aaa' ); + add_post_meta( $posts[1], 'foo', 'zzz' ); + add_post_meta( $posts[2], 'foo', 'jjj' ); + es_wp_query_index_test_data(); + + $q = new ES_WP_Query( array( + 'fields' => 'ids', + 'meta_query' => array( + 'foo_key' => array( + 'key' => 'foo', + 'compare' => 'EXISTS', + ), + ), + 'orderby' => 'foo_key', + 'order' => 'DESC', + ) ); + + $this->assertEquals( array( $posts[1], $posts[2], $posts[0] ), $q->posts ); + } + + /** + * @ticket 31045 + */ + public function test_orderby_clause_key_as_secondary_sort() { + $p1 = self::factory()->post->create( array( + 'post_date' => '2015-01-28 03:00:00', + ) ); + $p2 = self::factory()->post->create( array( + 'post_date' => '2015-01-28 05:00:00', + ) ); + $p3 = self::factory()->post->create( array( + 'post_date' => '2015-01-28 03:00:00', + ) ); + + add_post_meta( $p1, 'foo', 'jjj' ); + add_post_meta( $p2, 'foo', 'zzz' ); + add_post_meta( $p3, 'foo', 'aaa' ); + es_wp_query_index_test_data(); + + $q = new ES_WP_Query( array( + 'fields' => 'ids', + 'meta_query' => array( + 'foo_key' => array( + 'key' => 'foo', + 'compare' => 'EXISTS', + ), + ), + 'orderby' => array( + 'post_date' => 'asc', + 'foo_key' => 'asc', + ), + ) ); + + $this->assertEquals( array( $p3, $p1, $p2 ), $q->posts ); + } + + /** + * @ticket 31045 + */ + public function test_orderby_more_than_one_clause_key() { + $posts = self::factory()->post->create_many( 3 ); + + add_post_meta( $posts[0], 'foo', 'jjj' ); + add_post_meta( $posts[1], 'foo', 'zzz' ); + add_post_meta( $posts[2], 'foo', 'jjj' ); + add_post_meta( $posts[0], 'bar', 'aaa' ); + add_post_meta( $posts[1], 'bar', 'ccc' ); + add_post_meta( $posts[2], 'bar', 'bbb' ); + es_wp_query_index_test_data(); + + $q = new ES_WP_Query( array( + 'fields' => 'ids', + 'meta_query' => array( + 'foo_key' => array( + 'key' => 'foo', + 'compare' => 'EXISTS', + ), + 'bar_key' => array( + 'key' => 'bar', + 'compare' => 'EXISTS', + ), + ), + 'orderby' => array( + 'foo_key' => 'asc', + 'bar_key' => 'desc', + ), + ) ); + + $this->assertEquals( array( $posts[2], $posts[0], $posts[1] ), $q->posts ); + } + + /** + * @ticket 31045 + */ + public function test_duplicate_clause_keys_should_be_made_unique() { + $q = new ES_WP_Query( array( + 'fields' => 'ids', + 'meta_query' => array( + 'foo_key' => array( + 'key' => 'foo', + 'compare' => 'EXISTS', + ), + array( + 'foo_key' => array( + 'key' => 'bar', + 'compare' => 'EXISTS', + ), + ), + array( + 'foo_key' => array( + 'key' => 'baz', + 'compare' => 'EXISTS', + ), + ), + ), + ) ); + + $this->assertEqualSets( array( 'foo_key', 'foo_key-1', 'foo_key-2' ), array_keys( $q->meta_query->get_clauses() ) ); + } +} From 0fdbdd58f533ade35f6bbf470215292add7e3578 Mon Sep 17 00:00:00 2001 From: Matt Boynes Date: Fri, 26 Feb 2016 17:13:32 -0500 Subject: [PATCH 02/10] Require the meta key to exist in neg meta queries Truthfully, ES_WP_Query was returning better results for such queries, but this ensures parity between the queries. --- class-es-wp-meta-query.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/class-es-wp-meta-query.php b/class-es-wp-meta-query.php index 3ee697e..25091ec 100644 --- a/class-es-wp-meta-query.php +++ b/class-es-wp-meta-query.php @@ -144,7 +144,12 @@ public function get_dsl( $es_query, $type ) { if ( ! empty( $this_filter ) ) { if ( in_array( $meta_compare, array( 'NOT IN', '!=', 'NOT BETWEEN', 'NOT LIKE' ) ) ) { - $filter[] = array( 'not' => $this_filter ); + $filter[] = array( + 'and' => array( + $es_query->dsl_exists( $es_query->meta_map( trim( $q['key'] ) ) ), + array( 'not' => $this_filter ), + ), + ); } else { $filter[] = $this_filter; } From 469ed2718be3632f91575b8e4f0c93e1437294de Mon Sep 17 00:00:00 2001 From: Matt Boynes Date: Fri, 26 Feb 2016 17:28:15 -0500 Subject: [PATCH 03/10] Improve parity with MySQL on LIKE queries --- class-es-wp-meta-query.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/class-es-wp-meta-query.php b/class-es-wp-meta-query.php index 25091ec..3aff427 100644 --- a/class-es-wp-meta-query.php +++ b/class-es-wp-meta-query.php @@ -105,11 +105,8 @@ public function get_dsl( $es_query, $type ) { case 'LIKE' : case 'NOT LIKE' : - if ( '*' == $meta_key ) { - $this_filter = array( 'query' => $es_query->dsl_multi_match( $es_query->meta_map( $meta_key, 'analyzed' ), $meta_value ) ); - } else { - $this_filter = array( 'query' => $es_query->dsl_match( $es_query->meta_map( $meta_key, 'analyzed' ), $meta_value ) ); - } + // The only problem here is that this is a case-sensitive search + $this_filter = array( 'query' => array( 'wildcard' => array( $es_query->meta_map( $meta_key ) => '*' . $meta_value . '*' ) ) ); break; case 'BETWEEN' : @@ -189,4 +186,4 @@ public function get_cast_for_type( $type = '' ) { } return ''; } -} \ No newline at end of file +} From 8aa372615e26eea1894f0708ed8e37433112eae6 Mon Sep 17 00:00:00 2001 From: Matt Boynes Date: Fri, 26 Feb 2016 18:02:36 -0500 Subject: [PATCH 04/10] _doing_it_wrong() on regexp meta queries --- class-es-wp-meta-query.php | 6 ++++++ tests/query/metaQuery.php | 27 ++++++++++++++++++--------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/class-es-wp-meta-query.php b/class-es-wp-meta-query.php index 3aff427..6f5a230 100644 --- a/class-es-wp-meta-query.php +++ b/class-es-wp-meta-query.php @@ -129,6 +129,12 @@ public function get_dsl( $es_query, $type ) { } break; + case 'REGEXP' : + case 'NOT REGEXP' : + case 'RLIKE' : + _doing_it_wrong( 'ES_WP_Query', __( 'ES_WP_Query does not support regular expression meta queries.', 'es-wp-query' ), '0.1' ); + break; + default : if ( '*' == $meta_key ) { $this_filter = array( 'query' => $es_query->dsl_multi_match( $es_query->meta_map( $meta_key, $meta_type ), $meta_value ) ); diff --git a/tests/query/metaQuery.php b/tests/query/metaQuery.php index 4d54d41..5a7963c 100644 --- a/tests/query/metaQuery.php +++ b/tests/query/metaQuery.php @@ -302,7 +302,10 @@ public function test_meta_query_single_query_compare_between_not_between() { $this->assertEqualSets( $expected, $query->posts ); } - public function test_meta_query_single_query_compare_regexp_rlike() { + /** + * @expectedIncorrectUsage ES_WP_Query + */ + public function test_meta_query_single_query_compare_regexp() { $p1 = self::factory()->post->create(); $p2 = self::factory()->post->create(); @@ -322,9 +325,18 @@ public function test_meta_query_single_query_compare_regexp_rlike() { ), ), ) ); + } - $expected = array( $p2 ); - $this->assertEqualSets( $expected, $query->posts ); + /** + * @expectedIncorrectUsage ES_WP_Query + */ + public function test_meta_query_single_query_compare_rlike() { + $p1 = self::factory()->post->create(); + $p2 = self::factory()->post->create(); + + add_post_meta( $p1, 'foo', 'bar' ); + add_post_meta( $p2, 'foo', 'baz' ); + es_wp_query_index_test_data(); // RLIKE is a synonym for REGEXP. $query = new ES_WP_Query( array( @@ -339,11 +351,11 @@ public function test_meta_query_single_query_compare_regexp_rlike() { ), ), ) ); - - $expected = array( $p2 ); - $this->assertEqualSets( $expected, $query->posts ); } + /** + * @expectedIncorrectUsage ES_WP_Query + */ public function test_meta_query_single_query_compare_not_regexp() { $p1 = self::factory()->post->create(); $p2 = self::factory()->post->create(); @@ -364,9 +376,6 @@ public function test_meta_query_single_query_compare_not_regexp() { ), ), ) ); - - $expected = array( $p1 ); - $this->assertEqualSets( $expected, $query->posts ); } public function test_meta_query_relation_default() { From 5feb42944f6f97e4b491b28fb194fd39bd2fa68d Mon Sep 17 00:00:00 2001 From: Matt Boynes Date: Fri, 26 Feb 2016 18:08:00 -0500 Subject: [PATCH 05/10] Improve EXISTS and NOT EXISTS meta queries --- class-es-wp-meta-query.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/class-es-wp-meta-query.php b/class-es-wp-meta-query.php index 6f5a230..c2b23fc 100644 --- a/class-es-wp-meta-query.php +++ b/class-es-wp-meta-query.php @@ -34,8 +34,12 @@ public function get_dsl( $es_query, $type ) { continue; } - if ( isset( $q['compare'] ) && 'EXISTS' == strtoupper( substr( $q['compare'], -6 ) ) ) { - unset( $q['value'] ); + if ( isset( $q['compare'] ) && ! empty( $q['value'] ) ) { + if ( 'EXISTS' == strtoupper( $q['compare'] ) ) { + $q['compare'] = is_array( $q['value'] ) ? 'IN' : '='; + } elseif ( 'NOT EXISTS' == strtoupper( $q['compare'] ) ) { + unset( $q['value'] ); + } } if ( ( isset( $q['value'] ) && is_array( $q['value'] ) && empty( $q['value'] ) ) || ( ! array_key_exists( 'value', $q ) && ! empty( $q['key'] ) ) ) { From 401be2b85c3eb0d98883a7436f843046c8203660 Mon Sep 17 00:00:00 2001 From: Matt Boynes Date: Fri, 26 Feb 2016 18:27:20 -0500 Subject: [PATCH 06/10] Remove duplicate tests --- tests/query/post.php | 303 ------------------------------------------- 1 file changed, 303 deletions(-) diff --git a/tests/query/post.php b/tests/query/post.php index c536fc9..ed8acf7 100755 --- a/tests/query/post.php +++ b/tests/query/post.php @@ -205,139 +205,6 @@ function test_meta_key_not_exists() { $this->assertEquals( 0, count( $posts ) ); } - function test_meta_query_decimal_results() { - $post_1 = $this->factory->post->create(); - $post_2 = $this->factory->post->create(); - $post_3 = $this->factory->post->create(); - $post_4 = $this->factory->post->create(); - $post_5 = $this->factory->post->create(); - - update_post_meta( $post_1, 'decimal_value', '-0.3' ); - update_post_meta( $post_2, 'decimal_value', '0.23409844' ); - update_post_meta( $post_3, 'decimal_value', '0.3' ); - update_post_meta( $post_4, 'decimal_value', '0.4' ); - update_post_meta( $post_5, 'decimal_value', '0.1' ); - - es_wp_query_index_test_data(); - - $query = new ES_WP_Query( array( - 'meta_query' => array( - array( - 'key' => 'decimal_value', - 'value' => '.300', - 'compare' => '=', - 'type' => 'DECIMAL(10,2)' - ) - ), - ) ); - $this->assertEqualSets( array( $post_3 ), wp_list_pluck( $query->posts, 'ID' ) ); - - $query = new ES_WP_Query( array( - 'meta_query' => array( - array( - 'key' => 'decimal_value', - 'value' => '0.35', - 'compare' => '>', - 'type' => 'DECIMAL(10,2)' - ) - ), - ) ); - $this->assertEqualSets( array( $post_4 ), wp_list_pluck( $query->posts, 'ID' ) ); - - $query = new ES_WP_Query( array( - 'meta_query' => array( - array( - 'key' => 'decimal_value', - 'value' => '0.3', - 'compare' => '>=', - 'type' => 'DECIMAL(10,2)' - ) - ), - ) ); - $this->assertEqualSets( array( $post_3, $post_4 ), wp_list_pluck( $query->posts, 'ID' ) ); - - $query = new ES_WP_Query( array( - 'meta_query' => array( - array( - 'key' => 'decimal_value', - 'value' => '0', - 'compare' => '<', - 'type' => 'DECIMAL(10,2)' - ) - ), - ) ); - $this->assertEqualSets( array( $post_1 ), wp_list_pluck( $query->posts, 'ID' ) ); - - $query = new ES_WP_Query( array( - 'meta_query' => array( - array( - 'key' => 'decimal_value', - 'value' => '0.3', - 'compare' => '<=', - 'type' => 'DECIMAL(10,2)' - ) - ), - - ) ); - $this->assertEqualSets( array( $post_1, $post_2, $post_3, $post_5 ), wp_list_pluck( $query->posts, 'ID' ) ); - - $query = new ES_WP_Query( array( - 'meta_query' => array( - array( - 'key' => 'decimal_value', - 'value' => array( 0.23409845, .31 ), - 'compare' => 'BETWEEN', - 'type' => 'DECIMAL(10, 10)' - ) - ), - ) ); - $this->assertEqualSets( array( $post_3 ), wp_list_pluck( $query->posts, 'ID' ) ); - - $query = new ES_WP_Query( array( - 'meta_query' => array( - array( - 'key' => 'decimal_value', - 'value' => array( 0.23409845, .31 ), - 'compare' => 'NOT BETWEEN', - 'type' => 'DECIMAL(10,10)' - ) - ), - ) ); - $this->assertEqualSets( array( $post_1, $post_2, $post_4, $post_5 ), wp_list_pluck( $query->posts, 'ID' ) ); - - $query = new ES_WP_Query( array( - 'meta_query' => array( - array( - 'key' => 'decimal_value', - 'value' => '.3', - 'compare' => 'LIKE', - 'type' => 'DECIMAL(10,2)' - ) - ), - ) ); - $this->assertEqualSets( array( $post_1, $post_3 ), wp_list_pluck( $query->posts, 'ID' ) ); - - $query = new ES_WP_Query( array( - 'meta_query' => array( - array( - 'key' => 'decimal_value', - 'value' => '.3', - 'compare' => 'NOT LIKE', - 'type' => 'DECIMAL(10,2)' - ) - ), - ) ); - $this->assertEqualSets( array( $post_2, $post_4, $post_5 ), wp_list_pluck( $query->posts, 'ID' ) ); - - $query = new ES_WP_Query( array( - 'orderby' => 'meta_value', - 'order' => 'DESC', - 'meta_key' => 'decimal_value', - 'meta_type' => 'DECIMAL(10, 2)' - ) ); - $this->assertEqualSets( array( $post_4, $post_3, $post_2, $post_5, $post_1 ), wp_list_pluck( $query->posts, 'ID' ) ); - - } function test_meta_query_decimal_ordering() { $post_1 = $this->factory->post->create(); @@ -396,176 +263,6 @@ function test_taxonomy_empty_or() { $this->assertEquals( 0 , count( $posts ) ); } - function test_meta_between_not_between() { - $post_id = $this->factory->post->create(); - add_post_meta( $post_id, 'time', 500 ); - $post_id2 = $this->factory->post->create(); - add_post_meta( $post_id2, 'time', 1001 ); - $post_id3 = $this->factory->post->create(); - add_post_meta( $post_id3, 'time', 0 ); - $post_id4 = $this->factory->post->create(); - add_post_meta( $post_id4, 'time', 1 ); - $post_id5 = $this->factory->post->create(); - add_post_meta( $post_id5, 'time', 1000 ); - - es_wp_query_index_test_data(); - - $args = array( - 'meta_key' => 'time', - 'meta_value' => array( 1, 1000 ), - 'meta_type' => 'numeric', - 'meta_compare' => 'NOT BETWEEN' - ); - - $query = new ES_WP_Query( $args ); - $this->assertEquals( 2, count ( $query->posts ) ); - foreach ( $query->posts as $post ) { - $this->assertInstanceOf( 'WP_Post', $post ); - $this->assertEquals( 'raw', $post->filter ); - } - $posts = wp_list_pluck( $query->posts, 'ID' ); - $this->assertEqualSets( array( $post_id2, $post_id3 ), $posts ); - - $args = array( - 'meta_key' => 'time', - 'meta_value' => array( 1, 1000 ), - 'meta_type' => 'numeric', - 'meta_compare' => 'BETWEEN' - ); - - $query = new ES_WP_Query( $args ); - $this->assertEquals( 3, count ( $query->posts ) ); - foreach ( $query->posts as $post ) { - $this->assertInstanceOf( 'WP_Post', $post ); - $this->assertEquals( 'raw', $post->filter ); - } - $posts = wp_list_pluck( $query->posts, 'ID' ); - $this->assertEqualSets( array( $post_id, $post_id4, $post_id5 ), $posts ); - } - - /** - * @ticket 16829 - */ - function test_meta_default_compare() { - // compare should default to IN when meta_value is an array - $post_id = $this->factory->post->create(); - add_post_meta( $post_id, 'foo', 'bar' ); - $post_id2 = $this->factory->post->create(); - add_post_meta( $post_id2, 'bar', 'baz' ); - $post_id3 = $this->factory->post->create(); - add_post_meta( $post_id3, 'foo', 'baz' ); - $post_id4 = $this->factory->post->create(); - add_post_meta( $post_id4, 'baz', 'bar' ); - $post_id5 = $this->factory->post->create(); - add_post_meta( $post_id5, 'foo', rand_str() ); - - es_wp_query_index_test_data(); - - $posts = es_get_posts( array( - 'meta_key' => 'foo', - 'meta_value' => array( 'bar', 'baz' ) - ) ); - - $this->assertEquals( 2, count( $posts ) ); - $posts = wp_list_pluck( $posts, 'ID' ); - $this->assertEqualSets( array( $post_id, $post_id3 ), $posts ); - - $posts = es_get_posts( array( - 'meta_key' => 'foo', - 'meta_value' => array( 'bar', 'baz' ), - 'meta_compare' => 'IN' - ) ); - - $this->assertEquals( 2, count( $posts ) ); - foreach ( $posts as $post ) { - $this->assertInstanceOf( 'WP_Post', $post ); - $this->assertEquals( 'raw', $post->filter ); - } - $posts = wp_list_pluck( $posts, 'ID' ); - $this->assertEqualSets( array( $post_id, $post_id3 ), $posts ); - } - - /** - * @ticket 17264 - */ - function test_duplicate_posts_when_no_key() { - $post_id = $this->factory->post->create(); - add_post_meta( $post_id, 'city', 'Lorem' ); - add_post_meta( $post_id, 'address', '123 Lorem St.' ); - $post_id2 = $this->factory->post->create(); - add_post_meta( $post_id2, 'city', 'Lorem' ); - $post_id3 = $this->factory->post->create(); - add_post_meta( $post_id3, 'city', 'Loren' ); - - es_wp_query_index_test_data(); - - $args = array( - 'meta_query' => array( - array( - 'value' => 'lorem', - 'compare' => 'LIKE' - ) - ) - ); - - $posts = es_get_posts( $args ); - $this->assertEquals( 2, count( $posts ) ); - foreach ( $posts as $post ) { - $this->assertInstanceOf( 'WP_Post', $post ); - $this->assertEquals( 'raw', $post->filter ); - } - $posts = wp_list_pluck( $posts, 'ID' ); - $this->assertEqualSets( array( $post_id, $post_id2 ), $posts ); - } - - /** - * @ticket 15292 - */ - function test_empty_meta_value() { - $post_id = $this->factory->post->create(); - add_post_meta( $post_id, 'foo', '0' ); - add_post_meta( $post_id, 'bar', 0 ); - $post_id2 = $this->factory->post->create(); - add_post_meta( $post_id2, 'foo', 1 ); - $post_id3 = $this->factory->post->create(); - add_post_meta( $post_id3, 'baz', 0 ); - $post_id4 = $this->factory->post->create(); - add_post_meta( $post_id4, 'baz', 0 ); - $post_id5 = $this->factory->post->create(); - add_post_meta( $post_id5, 'baz', 0 ); - add_post_meta( $post_id5, 'bar', '0' ); - $post_id6 = $this->factory->post->create(); - add_post_meta( $post_id6, 'baz', 0 ); - - es_wp_query_index_test_data(); - - $posts = es_get_posts( array( 'meta_key' => 'foo', 'meta_value' => '0' ) ); - $this->assertEquals( 1, count ( $posts ) ); - foreach ( $posts as $post ) { - $this->assertInstanceOf( 'WP_Post', $post ); - $this->assertEquals( 'raw', $post->filter ); - } - $this->assertEquals( $post_id, $posts[0]->ID ); - - $posts = es_get_posts( array( 'meta_key' => 'bar', 'meta_value' => '0' ) ); - $this->assertEquals( 2, count ( $posts ) ); - foreach ( $posts as $post ) { - $this->assertInstanceOf( 'WP_Post', $post ); - $this->assertEquals( 'raw', $post->filter ); - } - $posts = wp_list_pluck( $posts, 'ID' ); - $this->assertEqualSets( array( $post_id, $post_id5 ), $posts ); - - $posts = es_get_posts( array( 'meta_key' => 'bar', 'meta_value' => 0 ) ); - $this->assertEquals( 2, count ( $posts ) ); - foreach ( $posts as $post ) { - $this->assertInstanceOf( 'WP_Post', $post ); - $this->assertEquals( 'raw', $post->filter ); - } - $posts = wp_list_pluck( $posts, 'ID' ); - $this->assertEqualSets( array( $post_id, $post_id5 ), $posts ); - } - function test_taxonomy_include_children() { $cat_a = $this->factory->term->create( array( 'taxonomy' => 'category', 'name' => 'Australia' ) ); $cat_b = $this->factory->term->create( array( 'taxonomy' => 'category', 'name' => 'Sydney', 'parent' => $cat_a ) ); From eab372583a9f7134cb0ea20e54a2b697670f0ecb Mon Sep 17 00:00:00 2001 From: Matt Boynes Date: Sat, 27 Feb 2016 19:09:40 -0500 Subject: [PATCH 07/10] Revert changes to LIKE queries Unfortunately, we just can't have parity with MySQL on these --- class-es-wp-meta-query.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/class-es-wp-meta-query.php b/class-es-wp-meta-query.php index c2b23fc..de19dec 100644 --- a/class-es-wp-meta-query.php +++ b/class-es-wp-meta-query.php @@ -109,8 +109,11 @@ public function get_dsl( $es_query, $type ) { case 'LIKE' : case 'NOT LIKE' : - // The only problem here is that this is a case-sensitive search - $this_filter = array( 'query' => array( 'wildcard' => array( $es_query->meta_map( $meta_key ) => '*' . $meta_value . '*' ) ) ); + if ( '*' == $meta_key ) { + $this_filter = array( 'query' => $es_query->dsl_multi_match( $es_query->meta_map( $meta_key, 'analyzed' ), $meta_value ) ); + } else { + $this_filter = array( 'query' => $es_query->dsl_match( $es_query->meta_map( $meta_key, 'analyzed' ), $meta_value ) ); + } break; case 'BETWEEN' : From 433e584de0a772b8285d8c3863794f469b8baef1 Mon Sep 17 00:00:00 2001 From: Matt Boynes Date: Sat, 27 Feb 2016 19:35:10 -0500 Subject: [PATCH 08/10] Update readme and tests to reflect differences in LIKE queries --- README.md | 11 ++++++++++- tests/query/metaQuery.php | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 14f855f..82ca36d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A drop-in replacement for WP_Query to leverage Elasticsearch for complex queries ## Warning! -This plugin is currently in pre-alpha development, and as such, no part of it is guaranteed. It works (the unit tests prove that), but we won't be concerned about backwards compatibility until the first release. If you choose to use this, please pay close attention to the commit log to make sure we don't break anything you've implemented. +This plugin is currently in beta development, and as such, no part of it is guaranteed. It works (the unit tests prove that), but we won't be concerned about backwards compatibility until the first release. If you choose to use this, please pay close attention to the commit log to make sure we don't break anything you've implemented. ## Instructions for use @@ -45,6 +45,15 @@ In one regard, this is a safer way to use this library, because it will fall bac Regardless of which way you use the library, everything else about the object should work as per usual. +## Differences with WP_Query and Unsupported Features + +### Meta Queries + +* **Regexp comparisons are not supported.** The regular expression syntax is slightly different in Elasticsearch vs. PHP, so even if we tried to support them, it would result in a lot of unexpected behaviors. Furthermore, regular expressions are very resource-intensive in Elasticsearch, so you're probably better off just using WP_Query for these queries regardless. + * If you try to use a regexp query, ES_WP_Query will throw a `_doing_it_wrong()` notice. +* **LIKE comparisons are incongruous with MySQL.** In ES_WP_Query, LIKE-comparison meta queries will run a `match` query against the analyzed meta values. This will behave similar to a keyword search and will generally be more useful than a LIKE query in MySQL. However, there are notably differences with the MySQL implementation and ES_WP_Query will very likely produce different search results, so don't expect it to be a drop-in replacement. + + ## A note about WP_Query filters Since this library removes MySQL from most of the equation, the typical WP_Query filters (`posts_where`, `posts_join`, etc.) become irrelevant or -- in some extreme situations -- conflicting. diff --git a/tests/query/metaQuery.php b/tests/query/metaQuery.php index 5a7963c..ab525be 100644 --- a/tests/query/metaQuery.php +++ b/tests/query/metaQuery.php @@ -207,11 +207,16 @@ public function test_meta_query_single_query_compare_arithmetic_comparisons() { $this->assertEqualSets( $expected, $query->posts ); } + /** + * This has been altered from the core unit test. We're upcasing the meta + * value "BAR" and instead of searching LIKE "ba", we're searching LIKE + * "bar". See the README for more information about LIKE queries. + */ public function test_meta_query_single_query_compare_like() { $p1 = self::factory()->post->create(); $p2 = self::factory()->post->create(); - add_post_meta( $p1, 'foo', 'bar' ); + add_post_meta( $p1, 'foo', 'BAR' ); es_wp_query_index_test_data(); $query = new ES_WP_Query( array( @@ -221,7 +226,7 @@ public function test_meta_query_single_query_compare_like() { 'meta_query' => array( array( 'key' => 'foo', - 'value' => 'ba', + 'value' => 'bar', 'compare' => 'LIKE', ), ), @@ -231,13 +236,19 @@ public function test_meta_query_single_query_compare_like() { $this->assertEqualSets( $expected, $query->posts ); } + /** + * This has been altered from the core unit test. We're upcasing the meta + * values "BAR" and "RAB" and instead of searching NOT LIKE "ba", we're + * searching NOT LIKE "bar". See the README for more information about LIKE + * queries. + */ public function test_meta_query_single_query_compare_not_like() { $p1 = self::factory()->post->create(); $p2 = self::factory()->post->create(); $p3 = self::factory()->post->create(); - add_post_meta( $p1, 'foo', 'bar' ); - add_post_meta( $p2, 'foo', 'rab' ); + add_post_meta( $p1, 'foo', 'BAR' ); + add_post_meta( $p2, 'foo', 'RAB' ); es_wp_query_index_test_data(); $query = new ES_WP_Query( array( @@ -247,7 +258,7 @@ public function test_meta_query_single_query_compare_not_like() { 'meta_query' => array( array( 'key' => 'foo', - 'value' => 'ba', + 'value' => 'bar', 'compare' => 'NOT LIKE', ), ), @@ -799,6 +810,10 @@ public function test_meta_query_relation_or_compare_equals_and_in() { } /** + * This has been altered from the core unit test. We're pluralizing the meta + * value "shallots" and instead of searching LIKE "hall", we're searching + * LIKE shallot. See the README for more information about LIKE queries. + * * @ticket 24093 */ public function test_meta_query_relation_or_compare_equals_and_like() { @@ -806,7 +821,7 @@ public function test_meta_query_relation_or_compare_equals_and_like() { add_post_meta( $posts[0], 'color', 'orange' ); add_post_meta( $posts[1], 'color', 'blue' ); add_post_meta( $posts[1], 'vegetable', 'onion' ); - add_post_meta( $posts[2], 'vegetable', 'shallot' ); + add_post_meta( $posts[2], 'vegetable', 'shallots' ); es_wp_query_index_test_data(); $query = new ES_WP_Query( array( @@ -819,7 +834,7 @@ public function test_meta_query_relation_or_compare_equals_and_like() { ), array( 'key' => 'vegetable', - 'value' => 'hall', + 'value' => 'shallot', 'compare' => 'LIKE', ), ), @@ -1053,6 +1068,11 @@ public function test_meta_query_relation_and_compare_not_equals_not_in() { } /** + * This has been altered from the core unit test. We're pluralizing the meta + * value "shallots" and instead of searching NOT LIKE "hall", we're + * searching NOT LIKE shallot. See the README for more information about + * LIKE queries. + * * @ticket 24093 */ public function test_meta_query_relation_and_compare_not_equals_and_not_like() { @@ -1060,7 +1080,7 @@ public function test_meta_query_relation_and_compare_not_equals_and_not_like() { add_post_meta( $posts[0], 'color', 'orange' ); add_post_meta( $posts[1], 'color', 'blue' ); add_post_meta( $posts[1], 'vegetable', 'onion' ); - add_post_meta( $posts[2], 'vegetable', 'shallot' ); + add_post_meta( $posts[2], 'vegetable', 'shallots' ); add_post_meta( $posts[3], 'vegetable', 'banana' ); es_wp_query_index_test_data(); @@ -1074,7 +1094,7 @@ public function test_meta_query_relation_and_compare_not_equals_and_not_like() { ), array( 'key' => 'vegetable', - 'value' => 'hall', + 'value' => 'shallot', 'compare' => 'NOT LIKE', ), ), From f8bcf9cb4b830f535607a24b2cbc52e89bdedd43 Mon Sep 17 00:00:00 2001 From: Matt Boynes Date: Sun, 28 Feb 2016 10:34:12 -0500 Subject: [PATCH 09/10] Nesteded meta queries & improved parity with WP_Query --- class-es-wp-meta-query.php | 345 +++++++++++++++++++++++-------------- 1 file changed, 216 insertions(+), 129 deletions(-) diff --git a/class-es-wp-meta-query.php b/class-es-wp-meta-query.php index de19dec..1ca3c0b 100644 --- a/class-es-wp-meta-query.php +++ b/class-es-wp-meta-query.php @@ -5,6 +5,13 @@ */ class ES_WP_Meta_Query extends WP_Meta_Query { + /** + * Some object which extends ES_WP_Query_Wrapper. + * + * @var ES_WP_Query_Wrapper + */ + protected $es_query; + /** * Turns an array of meta query parameters into ES Query DSL * @@ -12,173 +19,253 @@ class ES_WP_Meta_Query extends WP_Meta_Query { * * @param object $es_query Any object which extends ES_WP_Query_Wrapper. * @param string $type Type of meta. Currently, only 'post' is supported. - * @return array array() + * @return array ES filters */ public function get_dsl( $es_query, $type ) { - global $wpdb; - + // Currently only 'post' is supported if ( 'post' != $type ) { return false; } - $queries = array(); - $filter = array(); + $this->es_query = $es_query; + + $filters = $this->get_dsl_clauses(); + + return apply_filters_ref_array( 'get_meta_dsl', array( $filters, $this->queries, $type, $this->es_query ) ); + } + + /** + * Generate ES Filter clauses to be appended to a main query. + * + * Called by the public {@see ES_WP_Meta_Query::get_dsl()}, this method + * is abstracted out to maintain parity with the other Query classes. + * + * @access protected + * + * @return array + */ + protected function get_dsl_clauses() { + /* + * $queries are passed by reference to + * `ES_WP_Meta_Query::get_dsl_for_query()` for recursion. To keep + * $this->queries unaltered, pass a copy. + */ + $queries = $this->queries; + return $this->get_dsl_for_query( $queries ); + } + + /** + * Generate ES filters for a single query array. + * + * If nested subqueries are found, this method recurses the tree to produce + * the properly nested DSL. + * + * @access protected + * + * @param array $query Query to parse, passed by reference. + * @return array Array containing nested ES filter clauses. + */ + protected function get_dsl_for_query( &$query ) { + $filters = array(); + + foreach ( $query as $key => &$clause ) { + if ( 'relation' === $key ) { + $relation = $query['relation']; + } elseif ( is_array( $clause ) ) { + if ( $this->is_first_order_clause( $clause ) ) { + // This is a first-order clause. + $filters[] = $this->get_dsl_for_clause( $clause, $query, $key ); + } else { + // This is a subquery, so we recurse. + $filters[] = $this->get_dsl_for_query( $clause ); + } + } + } + + // Filter to remove empties. + $filters = array_filter( $filters ); + $this->clauses = array_filter( $this->clauses ); + + if ( empty( $relation ) ) { + $relation = 'and'; + } + + if ( count( $filters ) > 1 ) { + $filters = array( strtolower( $relation ) => $filters ); + } elseif ( ! empty( $filters ) ) { + $filters = reset( $filters ); + } + + return $filters; + } + + /** + * Generate ES filter clauses for a first-order query clause. + * + * "First-order" means that it's an array with a 'key' or 'value'. + * + * @access public + * + * @param array $clause Query clause, passed by reference. + * @param array $query Parent query array. + * @param string $clause_key Optional. The array key used to name the + * clause in the original `$meta_query` + * parameters. If not provided, a key will be + * generated automatically. + * @return array ES filter clause component. + */ + public function get_dsl_for_clause( &$clause, $query, $clause_key = '' ) { + // Key must be a string, so fallback for clause keys is 'meta-clause'. + if ( is_int( $clause_key ) || ! $clause_key ) { + $clause_key = 'meta-clause'; + } + + // Ensure unique clause keys, so none are overwritten. + $iterator = 1; + $clause_key_base = $clause_key; + while ( isset( $this->clauses[ $clause_key ] ) ) { + $clause_key = $clause_key_base . '-' . $iterator; + $iterator++; + } // Split out 'exists' and 'not exists' queries. These may also be // queries missing a value or with an empty array as the value. - foreach ( $this->queries as $k => $q ) { + if ( isset( $clause['compare'] ) && ! empty( $clause['value'] ) ) { + if ( 'EXISTS' == strtoupper( $clause['compare'] ) ) { + $clause['compare'] = is_array( $clause['value'] ) ? 'IN' : '='; + } elseif ( 'NOT EXISTS' == strtoupper( $clause['compare'] ) ) { + unset( $clause['value'] ); + } + } - // WordPress 4.1 introduces a new structure for WP_Meta_Query:queries to support nested queries. - // the following protects against PHP warnings until support for nesting is added - if ( 'relation' === $k ) { - continue; + if ( ( isset( $clause['value'] ) && is_array( $clause['value'] ) && empty( $clause['value'] ) ) || ( ! array_key_exists( 'value', $clause ) && ! empty( $clause['key'] ) ) ) { + $this->clauses[ $clause_key ] =& $clause; + if ( isset( $clause['compare'] ) && 'NOT EXISTS' == strtoupper( $clause['compare'] ) ) { + return $this->es_query->dsl_missing( $this->es_query->meta_map( trim( $clause['key'] ) ) ); + } else { + return $this->es_query->dsl_exists( $this->es_query->meta_map( trim( $clause['key'] ) ) ); } + } - if ( isset( $q['compare'] ) && ! empty( $q['value'] ) ) { - if ( 'EXISTS' == strtoupper( $q['compare'] ) ) { - $q['compare'] = is_array( $q['value'] ) ? 'IN' : '='; - } elseif ( 'NOT EXISTS' == strtoupper( $q['compare'] ) ) { - unset( $q['value'] ); - } + $clause['key'] = isset( $clause['key'] ) ? trim( $clause['key'] ) : '*'; + + if ( array_key_exists( 'value', $clause ) && is_null( $clause['value'] ) ) { + $clause['value'] = ''; + } + + $clause['value'] = isset( $clause['value'] ) ? $clause['value'] : null; + + if ( isset( $clause['compare'] ) ) { + $clause['compare'] = strtoupper( $clause['compare'] ); + } else { + $clause['compare'] = is_array( $clause['value'] ) ? 'IN' : '='; + } + + if ( in_array( $clause['compare'], array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) { + if ( ! is_array( $clause['value'] ) ) { + $clause['value'] = preg_split( '/[,\s]+/', $clause['value'] ); } - if ( ( isset( $q['value'] ) && is_array( $q['value'] ) && empty( $q['value'] ) ) || ( ! array_key_exists( 'value', $q ) && ! empty( $q['key'] ) ) ) { - if ( isset( $q['compare'] ) && 'NOT EXISTS' == strtoupper( $q['compare'] ) ) { - $filter[] = $es_query->dsl_missing( $es_query->meta_map( trim( $q['key'] ) ) ); - } else { - $filter[] = $es_query->dsl_exists( $es_query->meta_map( trim( $q['key'] ) ) ); - } - } else { - $queries[ $k ] = $q; + if ( empty( $clause['value'] ) ) { + // This compare type requires an array of values. If we don't + // have one, we bail on this query. + return array(); } + } else { + $clause['value'] = trim( $clause['value'] ); } - foreach ( $queries as $k => $q ) { - $meta_key = isset( $q['key'] ) ? trim( $q['key'] ) : '*'; + // Store the clause in our flat array. + $this->clauses[ $clause_key ] =& $clause; - if ( array_key_exists( 'value', $q ) && is_null( $q['value'] ) ) - $q['value'] = ''; + if ( '*' == $clause['key'] && ! in_array( $clause['compare'], array( '=', '!=', 'LIKE', 'NOT LIKE' ) ) ) { + return apply_filters( 'es_meta_query_keyless_query', array(), $clause['value'], $clause['compare'], $this, $this->es_query ); + } - $meta_value = isset( $q['value'] ) ? $q['value'] : null; + $clause['type'] = $this->get_cast_for_type( isset( $clause['type'] ) ? $clause['type'] : '' ); - if ( isset( $q['compare'] ) ) - $meta_compare = strtoupper( $q['compare'] ); - else - $meta_compare = is_array( $meta_value ) ? 'IN' : '='; + // Allow adapters to normalize meta values (like `strtolower` if mapping to `raw_lc`) + $clause['value'] = apply_filters( 'es_meta_query_meta_value', $clause['value'], $clause['key'], $clause['compare'], $clause['type'] ); - if ( in_array( $meta_compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) { - if ( ! is_array( $meta_value ) ) { - $meta_value = preg_split( '/[,\s]+/', $meta_value ); + switch ( $clause['compare'] ) { + case '>' : + case '>=' : + case '<' : + case '<=' : + switch ( $clause['compare'] ) { + case '>' : $operator = 'gt'; break; + case '>=' : $operator = 'gte'; break; + case '<' : $operator = 'lt'; break; + case '<=' : $operator = 'lte'; break; } + $filter = $this->es_query->dsl_range( $this->es_query->meta_map( $clause['key'], $clause['type'] ), array( $operator => $clause['value'] ) ); + break; - if ( empty( $meta_value ) ) { - continue; + case 'LIKE' : + case 'NOT LIKE' : + if ( '*' == $clause['key'] ) { + $filter = array( 'query' => $this->es_query->dsl_multi_match( $this->es_query->meta_map( $clause['key'], 'analyzed' ), $clause['value'] ) ); + } else { + $filter = array( 'query' => $this->es_query->dsl_match( $this->es_query->meta_map( $clause['key'], 'analyzed' ), $clause['value'] ) ); } - } else { - $meta_value = trim( $meta_value ); - } + break; - if ( '*' == $meta_key && ! in_array( $meta_compare, array( '=', '!=', 'LIKE', 'NOT LIKE' ) ) ) { - $keyless_filter = apply_filters( 'es_meta_query_keyless_query', array(), $meta_value, $meta_compare, $this, $es_query ); - if ( ! empty( $keyless_filter ) ) { - $filter[] = $keyless_filter; + case 'BETWEEN' : + case 'NOT BETWEEN' : + // These may produce unexpected results depending on how your data is indexed. + $clause['value'] = array_slice( $clause['value'], 0, 2 ); + if ( 'DATETIME' == $clause['type'] && $date1 = strtotime( $clause['value'][0] ) && $date2 = strtotime( $clause['value'][1] ) ) { + $clause['value'] = array( $date1, $date2 ); + sort( $clause['value'] ); + $filter = $this->es_query->dsl_range( + $this->es_query->meta_map( $clause['key'], $clause['type'] ), + ES_WP_Date_Query::build_date_range( $clause['value'][0], '>=', $clause['value'][1], '<=' ) + ); } else { - // @todo: How should we handle errors like this? + natcasesort( $clause['value'] ); + $filter = $this->es_query->dsl_range( + $this->es_query->meta_map( $clause['key'], $clause['type'] ), + array( 'gte' => $clause['value'][0], 'lte' => $clause['value'][1] ) + ); } - continue; - } - - $meta_type = $this->get_cast_for_type( isset( $q['type'] ) ? $q['type'] : '' ); - - // Allow adapters to normalize meta values (like `strtolower` if mapping to `raw_lc`) - $meta_value = apply_filters( 'es_meta_query_meta_value', $meta_value, $meta_key, $meta_compare, $meta_type ); - - switch ( $meta_compare ) { - case '>' : - case '>=' : - case '<' : - case '<=' : - switch ( $meta_compare ) { - case '>' : $operator = 'gt'; break; - case '>=' : $operator = 'gte'; break; - case '<' : $operator = 'lt'; break; - case '<=' : $operator = 'lte'; break; - } - $this_filter = $es_query->dsl_range( $es_query->meta_map( $meta_key, $meta_type ), array( $operator => $meta_value ) ); - break; - - case 'LIKE' : - case 'NOT LIKE' : - if ( '*' == $meta_key ) { - $this_filter = array( 'query' => $es_query->dsl_multi_match( $es_query->meta_map( $meta_key, 'analyzed' ), $meta_value ) ); - } else { - $this_filter = array( 'query' => $es_query->dsl_match( $es_query->meta_map( $meta_key, 'analyzed' ), $meta_value ) ); - } - break; - - case 'BETWEEN' : - case 'NOT BETWEEN' : - // These may produce unexpected results depending on how your data is indexed. - $meta_value = array_slice( $meta_value, 0, 2 ); - if ( 'DATETIME' == $meta_type && $date1 = strtotime( $meta_value[0] ) && $date2 = strtotime( $meta_value[1] ) ) { - $meta_value = array( $date1, $date2 ); - sort( $meta_value ); - $this_filter = $es_query->dsl_range( - $es_query->meta_map( $meta_key, $meta_type ), - ES_WP_Date_Query::build_date_range( $meta_value[0], '>=', $meta_value[1], '<=' ) - ); - } else { - natcasesort( $meta_value ); - $this_filter = $es_query->dsl_range( - $es_query->meta_map( $meta_key, $meta_type ), - array( 'gte' => $meta_value[0], 'lte' => $meta_value[1] ) - ); - } - break; - - case 'REGEXP' : - case 'NOT REGEXP' : - case 'RLIKE' : - _doing_it_wrong( 'ES_WP_Query', __( 'ES_WP_Query does not support regular expression meta queries.', 'es-wp-query' ), '0.1' ); - break; - - default : - if ( '*' == $meta_key ) { - $this_filter = array( 'query' => $es_query->dsl_multi_match( $es_query->meta_map( $meta_key, $meta_type ), $meta_value ) ); - } else { - $this_filter = $es_query->dsl_terms( $es_query->meta_map( $meta_key, $meta_type ), $meta_value ); - } - break; + break; - } + case 'REGEXP' : + case 'NOT REGEXP' : + case 'RLIKE' : + _doing_it_wrong( 'ES_WP_Query', __( 'ES_WP_Query does not support regular expression meta queries.', 'es-wp-query' ), '0.1' ); + // Empty out $clause, since this will be disregarded. + $clause = array(); + return array(); + break; - if ( ! empty( $this_filter ) ) { - if ( in_array( $meta_compare, array( 'NOT IN', '!=', 'NOT BETWEEN', 'NOT LIKE' ) ) ) { - $filter[] = array( - 'and' => array( - $es_query->dsl_exists( $es_query->meta_map( trim( $q['key'] ) ) ), - array( 'not' => $this_filter ), - ), - ); + default : + if ( '*' == $clause['key'] ) { + $filter = array( 'query' => $this->es_query->dsl_multi_match( $this->es_query->meta_map( $clause['key'], $clause['type'] ), $clause['value'] ) ); } else { - $filter[] = $this_filter; + $filter = $this->es_query->dsl_terms( $this->es_query->meta_map( $clause['key'], $clause['type'] ), $clause['value'] ); } - } + break; } - $filter = array_filter( $filter ); - - if ( ! empty( $filter ) && count( $filter ) > 1 ) { - $filter = array( strtolower( $this->relation ) => $filter ); - } elseif ( ! empty( $filter ) ) { - $filter = reset( $filter ); + if ( ! empty( $filter ) ) { + // To maintain parity with WP_Query, if we're doing a negation + // query, we still only query posts where the meta key exists. + if ( in_array( $clause['compare'], array( 'NOT IN', '!=', 'NOT BETWEEN', 'NOT LIKE' ) ) ) { + return array( + 'and' => array( + $this->es_query->dsl_exists( $this->es_query->meta_map( $clause['key'] ) ), + array( 'not' => $filter ), + ), + ); + } else { + return $filter; + } } - return apply_filters_ref_array( 'get_meta_dsl', array( $filter, $queries, $type, $es_query ) ); } - /** * Get the ES mapping suffix for the given type. * From 56424063cff025b10f32c252e64b5a58fa2d0bc6 Mon Sep 17 00:00:00 2001 From: Matt Boynes Date: Mon, 29 Feb 2016 16:48:49 -0500 Subject: [PATCH 10/10] Use older factory syntax to test old wp versions --- tests/query/metaQuery.php | 204 +++++++++++++++++++------------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/tests/query/metaQuery.php b/tests/query/metaQuery.php index ab525be..54e37e2 100644 --- a/tests/query/metaQuery.php +++ b/tests/query/metaQuery.php @@ -6,9 +6,9 @@ */ class Tests_Query_MetaQuery extends WP_UnitTestCase { public function test_meta_query_no_key() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); - $p3 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); + $p3 = $this->factory->post->create(); add_post_meta( $p1, 'foo', 'bar' ); add_post_meta( $p2, 'oof', 'bar' ); @@ -31,9 +31,9 @@ public function test_meta_query_no_key() { } public function test_meta_query_no_value() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); - $p3 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); + $p3 = $this->factory->post->create(); add_post_meta( $p1, 'foo', 'bar' ); add_post_meta( $p2, 'oof', 'bar' ); @@ -56,8 +56,8 @@ public function test_meta_query_no_value() { } public function test_meta_query_single_query_compare_default() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); add_post_meta( $p1, 'foo', 'bar' ); es_wp_query_index_test_data(); @@ -79,8 +79,8 @@ public function test_meta_query_single_query_compare_default() { } public function test_meta_query_single_query_compare_equals() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); add_post_meta( $p1, 'foo', 'bar' ); es_wp_query_index_test_data(); @@ -103,9 +103,9 @@ public function test_meta_query_single_query_compare_equals() { } public function test_meta_query_single_query_compare_not_equals() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); - $p3 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); + $p3 = $this->factory->post->create(); add_post_meta( $p1, 'foo', 'bar' ); add_post_meta( $p2, 'foo', 'baz' ); @@ -129,9 +129,9 @@ public function test_meta_query_single_query_compare_not_equals() { } public function test_meta_query_single_query_compare_arithmetic_comparisons() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); - $p3 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); + $p3 = $this->factory->post->create(); add_post_meta( $p1, 'foo', '1' ); add_post_meta( $p2, 'foo', '2' ); @@ -213,8 +213,8 @@ public function test_meta_query_single_query_compare_arithmetic_comparisons() { * "bar". See the README for more information about LIKE queries. */ public function test_meta_query_single_query_compare_like() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); add_post_meta( $p1, 'foo', 'BAR' ); es_wp_query_index_test_data(); @@ -243,9 +243,9 @@ public function test_meta_query_single_query_compare_like() { * queries. */ public function test_meta_query_single_query_compare_not_like() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); - $p3 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); + $p3 = $this->factory->post->create(); add_post_meta( $p1, 'foo', 'BAR' ); add_post_meta( $p2, 'foo', 'RAB' ); @@ -269,9 +269,9 @@ public function test_meta_query_single_query_compare_not_like() { } public function test_meta_query_single_query_compare_between_not_between() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); - $p3 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); + $p3 = $this->factory->post->create(); add_post_meta( $p1, 'foo', '1' ); add_post_meta( $p2, 'foo', '10' ); @@ -317,8 +317,8 @@ public function test_meta_query_single_query_compare_between_not_between() { * @expectedIncorrectUsage ES_WP_Query */ public function test_meta_query_single_query_compare_regexp() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); add_post_meta( $p1, 'foo', 'bar' ); add_post_meta( $p2, 'foo', 'baz' ); @@ -342,8 +342,8 @@ public function test_meta_query_single_query_compare_regexp() { * @expectedIncorrectUsage ES_WP_Query */ public function test_meta_query_single_query_compare_rlike() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); add_post_meta( $p1, 'foo', 'bar' ); add_post_meta( $p2, 'foo', 'baz' ); @@ -368,8 +368,8 @@ public function test_meta_query_single_query_compare_rlike() { * @expectedIncorrectUsage ES_WP_Query */ public function test_meta_query_single_query_compare_not_regexp() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); add_post_meta( $p1, 'foo', 'bar' ); add_post_meta( $p2, 'foo', 'baz' ); @@ -390,9 +390,9 @@ public function test_meta_query_single_query_compare_not_regexp() { } public function test_meta_query_relation_default() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); - $p3 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); + $p3 = $this->factory->post->create(); add_post_meta( $p1, 'foo', 'foo value 1' ); add_post_meta( $p1, 'bar', 'bar value 1' ); @@ -421,18 +421,18 @@ public function test_meta_query_relation_default() { } public function test_meta_query_relation_or() { - $post_id = self::factory()->post->create(); + $post_id = $this->factory->post->create(); add_post_meta( $post_id, 'foo', rand_str() ); add_post_meta( $post_id, 'foo', rand_str() ); - $post_id2 = self::factory()->post->create(); + $post_id2 = $this->factory->post->create(); add_post_meta( $post_id2, 'bar', 'val2' ); - $post_id3 = self::factory()->post->create(); + $post_id3 = $this->factory->post->create(); add_post_meta( $post_id3, 'baz', rand_str() ); - $post_id4 = self::factory()->post->create(); + $post_id4 = $this->factory->post->create(); add_post_meta( $post_id4, 'froo', rand_str() ); - $post_id5 = self::factory()->post->create(); + $post_id5 = $this->factory->post->create(); add_post_meta( $post_id5, 'tango', 'val2' ); - $post_id6 = self::factory()->post->create(); + $post_id6 = $this->factory->post->create(); add_post_meta( $post_id6, 'bar', 'val1' ); es_wp_query_index_test_data(); @@ -463,22 +463,22 @@ public function test_meta_query_relation_or() { } public function test_meta_query_relation_and() { - $post_id = self::factory()->post->create(); + $post_id = $this->factory->post->create(); add_post_meta( $post_id, 'foo', rand_str() ); add_post_meta( $post_id, 'foo', rand_str() ); - $post_id2 = self::factory()->post->create(); + $post_id2 = $this->factory->post->create(); add_post_meta( $post_id2, 'bar', 'val2' ); add_post_meta( $post_id2, 'foo', rand_str() ); - $post_id3 = self::factory()->post->create(); + $post_id3 = $this->factory->post->create(); add_post_meta( $post_id3, 'baz', rand_str() ); - $post_id4 = self::factory()->post->create(); + $post_id4 = $this->factory->post->create(); add_post_meta( $post_id4, 'froo', rand_str() ); - $post_id5 = self::factory()->post->create(); + $post_id5 = $this->factory->post->create(); add_post_meta( $post_id5, 'tango', 'val2' ); - $post_id6 = self::factory()->post->create(); + $post_id6 = $this->factory->post->create(); add_post_meta( $post_id6, 'bar', 'val1' ); add_post_meta( $post_id6, 'foo', rand_str() ); - $post_id7 = self::factory()->post->create(); + $post_id7 = $this->factory->post->create(); add_post_meta( $post_id7, 'foo', rand_str() ); add_post_meta( $post_id7, 'froo', rand_str() ); add_post_meta( $post_id7, 'baz', rand_str() ); @@ -533,7 +533,7 @@ public function test_meta_query_relation_and() { * @ticket 30681 */ public function test_meta_query_compare_exists() { - $posts = self::factory()->post->create_many( 3 ); + $posts = $this->factory->post->create_many( 3 ); add_post_meta( $posts[0], 'foo', 'bar' ); add_post_meta( $posts[2], 'foo', 'baz' ); es_wp_query_index_test_data(); @@ -555,7 +555,7 @@ public function test_meta_query_compare_exists() { * @ticket 30681 */ public function test_meta_query_compare_exists_with_value_should_convert_to_equals() { - $posts = self::factory()->post->create_many( 3 ); + $posts = $this->factory->post->create_many( 3 ); add_post_meta( $posts[0], 'foo', 'bar' ); add_post_meta( $posts[2], 'foo', 'baz' ); es_wp_query_index_test_data(); @@ -578,7 +578,7 @@ public function test_meta_query_compare_exists_with_value_should_convert_to_equa * @ticket 30681 */ public function test_meta_query_compare_not_exists_should_ignore_value() { - $posts = self::factory()->post->create_many( 3 ); + $posts = $this->factory->post->create_many( 3 ); add_post_meta( $posts[0], 'foo', 'bar' ); add_post_meta( $posts[2], 'foo', 'baz' ); es_wp_query_index_test_data(); @@ -601,15 +601,15 @@ public function test_meta_query_compare_not_exists_should_ignore_value() { * @ticket 18158 */ public function test_meta_query_compare_not_exists() { - $post_id = self::factory()->post->create(); + $post_id = $this->factory->post->create(); add_post_meta( $post_id, 'foo', rand_str() ); - $post_id2 = self::factory()->post->create(); + $post_id2 = $this->factory->post->create(); add_post_meta( $post_id2, 'bar', rand_str() ); - $post_id3 = self::factory()->post->create(); + $post_id3 = $this->factory->post->create(); add_post_meta( $post_id3, 'bar', rand_str() ); - $post_id4 = self::factory()->post->create(); + $post_id4 = $this->factory->post->create(); add_post_meta( $post_id4, 'baz', rand_str() ); - $post_id5 = self::factory()->post->create(); + $post_id5 = $this->factory->post->create(); add_post_meta( $post_id5, 'foo', rand_str() ); es_wp_query_index_test_data(); @@ -674,7 +674,7 @@ public function test_meta_query_compare_not_exists() { * @ticket 29062 */ public function test_meta_query_compare_not_exists_with_another_condition_relation_or() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); update_post_meta( $posts[0], 'color', 'orange' ); update_post_meta( $posts[1], 'color', 'blue' ); update_post_meta( $posts[1], 'vegetable', 'onion' ); @@ -711,7 +711,7 @@ public function test_meta_query_compare_not_exists_with_another_condition_relati * @ticket 24093 */ public function test_meta_query_relation_or_compare_equals() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); add_post_meta( $posts[0], 'color', 'orange' ); add_post_meta( $posts[1], 'color', 'blue' ); add_post_meta( $posts[1], 'vegetable', 'onion' ); @@ -745,7 +745,7 @@ public function test_meta_query_relation_or_compare_equals() { * @ticket 24093 */ public function test_meta_query_relation_or_compare_equals_different_keys() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); add_post_meta( $posts[0], 'color', 'orange' ); add_post_meta( $posts[1], 'color', 'blue' ); add_post_meta( $posts[1], 'vegetable', 'onion' ); @@ -779,7 +779,7 @@ public function test_meta_query_relation_or_compare_equals_different_keys() { * @ticket 24093 */ public function test_meta_query_relation_or_compare_equals_and_in() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); add_post_meta( $posts[0], 'color', 'orange' ); add_post_meta( $posts[1], 'color', 'blue' ); add_post_meta( $posts[1], 'vegetable', 'onion' ); @@ -817,7 +817,7 @@ public function test_meta_query_relation_or_compare_equals_and_in() { * @ticket 24093 */ public function test_meta_query_relation_or_compare_equals_and_like() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); add_post_meta( $posts[0], 'color', 'orange' ); add_post_meta( $posts[1], 'color', 'blue' ); add_post_meta( $posts[1], 'vegetable', 'onion' ); @@ -851,7 +851,7 @@ public function test_meta_query_relation_or_compare_equals_and_like() { * @ticket 24093 */ public function test_meta_query_relation_or_compare_equals_and_between() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); add_post_meta( $posts[0], 'number_of_colors', '2' ); add_post_meta( $posts[1], 'number_of_colors', '5' ); add_post_meta( $posts[1], 'vegetable', 'onion' ); @@ -886,7 +886,7 @@ public function test_meta_query_relation_or_compare_equals_and_between() { * @ticket 24093 */ public function test_meta_query_relation_and_compare_in_same_keys() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); add_post_meta( $posts[0], 'color', 'orange' ); add_post_meta( $posts[1], 'color', 'blue' ); add_post_meta( $posts[1], 'vegetable', 'onion' ); @@ -922,7 +922,7 @@ public function test_meta_query_relation_and_compare_in_same_keys() { * @ticket 24093 */ public function test_meta_query_relation_and_compare_in_different_keys() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); add_post_meta( $posts[0], 'color', 'orange' ); add_post_meta( $posts[1], 'color', 'blue' ); add_post_meta( $posts[1], 'vegetable', 'onion' ); @@ -958,7 +958,7 @@ public function test_meta_query_relation_and_compare_in_different_keys() { * @ticket 24093 */ public function test_meta_query_relation_and_compare_not_equals() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); add_post_meta( $posts[0], 'color', 'orange' ); add_post_meta( $posts[1], 'color', 'blue' ); add_post_meta( $posts[1], 'vegetable', 'onion' ); @@ -993,7 +993,7 @@ public function test_meta_query_relation_and_compare_not_equals() { * @ticket 24093 */ public function test_meta_query_relation_and_compare_not_equals_different_keys() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); // !shallot, but orange. add_post_meta( $posts[0], 'color', 'orange' ); @@ -1036,7 +1036,7 @@ public function test_meta_query_relation_and_compare_not_equals_different_keys() * @ticket 24093 */ public function test_meta_query_relation_and_compare_not_equals_not_in() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); add_post_meta( $posts[0], 'color', 'orange' ); add_post_meta( $posts[1], 'color', 'blue' ); add_post_meta( $posts[1], 'vegetable', 'onion' ); @@ -1076,7 +1076,7 @@ public function test_meta_query_relation_and_compare_not_equals_not_in() { * @ticket 24093 */ public function test_meta_query_relation_and_compare_not_equals_and_not_like() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); add_post_meta( $posts[0], 'color', 'orange' ); add_post_meta( $posts[1], 'color', 'blue' ); add_post_meta( $posts[1], 'vegetable', 'onion' ); @@ -1111,10 +1111,10 @@ public function test_meta_query_relation_and_compare_not_equals_and_not_like() { * @ticket 23033 */ public function test_meta_query_decimal_results() { - $post_1 = self::factory()->post->create(); - $post_2 = self::factory()->post->create(); - $post_3 = self::factory()->post->create(); - $post_4 = self::factory()->post->create(); + $post_1 = $this->factory->post->create(); + $post_2 = $this->factory->post->create(); + $post_3 = $this->factory->post->create(); + $post_4 = $this->factory->post->create(); update_post_meta( $post_1, 'decimal_value', '-0.3' ); update_post_meta( $post_2, 'decimal_value', '0.23409844' ); @@ -1287,7 +1287,7 @@ public function test_meta_vars_should_be_converted_to_meta_query() { * @ticket 29604 */ public function test_meta_query_with_orderby_meta_value_relation_or() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); update_post_meta( $posts[0], 'foo', 5 ); update_post_meta( $posts[1], 'foo', 6 ); update_post_meta( $posts[2], 'foo', 4 ); @@ -1327,7 +1327,7 @@ public function test_meta_query_with_orderby_meta_value_relation_or() { * @ticket 29604 */ public function test_meta_query_with_orderby_meta_value_relation_and() { - $posts = self::factory()->post->create_many( 4 ); + $posts = $this->factory->post->create_many( 4 ); update_post_meta( $posts[0], 'foo', 5 ); update_post_meta( $posts[1], 'foo', 6 ); update_post_meta( $posts[2], 'foo', 4 ); @@ -1371,9 +1371,9 @@ public function test_meta_query_with_orderby_meta_value_relation_and() { * @ticket 29642 */ public function test_meta_query_nested() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); - $p3 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); + $p3 = $this->factory->post->create(); add_post_meta( $p1, 'foo', 'bar' ); add_post_meta( $p2, 'foo2', 'bar' ); @@ -1413,9 +1413,9 @@ public function test_meta_query_nested() { * @ticket 29642 */ public function test_meta_query_nested_two_levels_deep() { - $p1 = self::factory()->post->create(); - $p2 = self::factory()->post->create(); - $p3 = self::factory()->post->create(); + $p1 = $this->factory->post->create(); + $p2 = $this->factory->post->create(); + $p3 = $this->factory->post->create(); add_post_meta( $p1, 'foo', 'bar' ); add_post_meta( $p3, 'foo2', 'bar' ); @@ -1459,15 +1459,15 @@ public function test_meta_query_nested_two_levels_deep() { } public function test_meta_between_not_between() { - $post_id = self::factory()->post->create(); + $post_id = $this->factory->post->create(); add_post_meta( $post_id, 'time', 500 ); - $post_id2 = self::factory()->post->create(); + $post_id2 = $this->factory->post->create(); add_post_meta( $post_id2, 'time', 1001 ); - $post_id3 = self::factory()->post->create(); + $post_id3 = $this->factory->post->create(); add_post_meta( $post_id3, 'time', 0 ); - $post_id4 = self::factory()->post->create(); + $post_id4 = $this->factory->post->create(); add_post_meta( $post_id4, 'time', 1 ); - $post_id5 = self::factory()->post->create(); + $post_id5 = $this->factory->post->create(); add_post_meta( $post_id5, 'time', 1000 ); es_wp_query_index_test_data(); @@ -1509,15 +1509,15 @@ public function test_meta_between_not_between() { */ public function test_meta_default_compare() { // compare should default to IN when meta_value is an array - $post_id = self::factory()->post->create(); + $post_id = $this->factory->post->create(); add_post_meta( $post_id, 'foo', 'bar' ); - $post_id2 = self::factory()->post->create(); + $post_id2 = $this->factory->post->create(); add_post_meta( $post_id2, 'bar', 'baz' ); - $post_id3 = self::factory()->post->create(); + $post_id3 = $this->factory->post->create(); add_post_meta( $post_id3, 'foo', 'baz' ); - $post_id4 = self::factory()->post->create(); + $post_id4 = $this->factory->post->create(); add_post_meta( $post_id4, 'baz', 'bar' ); - $post_id5 = self::factory()->post->create(); + $post_id5 = $this->factory->post->create(); add_post_meta( $post_id5, 'foo', rand_str() ); es_wp_query_index_test_data(); @@ -1549,12 +1549,12 @@ public function test_meta_default_compare() { * @ticket 17264 */ public function test_duplicate_posts_when_no_key() { - $post_id = self::factory()->post->create(); + $post_id = $this->factory->post->create(); add_post_meta( $post_id, 'city', 'Lorem' ); add_post_meta( $post_id, 'address', '123 Lorem St.' ); - $post_id2 = self::factory()->post->create(); + $post_id2 = $this->factory->post->create(); add_post_meta( $post_id2, 'city', 'Lorem' ); - $post_id3 = self::factory()->post->create(); + $post_id3 = $this->factory->post->create(); add_post_meta( $post_id3, 'city', 'Loren' ); es_wp_query_index_test_data(); @@ -1581,19 +1581,19 @@ public function test_duplicate_posts_when_no_key() { * @ticket 15292 */ public function test_empty_meta_value() { - $post_id = self::factory()->post->create(); + $post_id = $this->factory->post->create(); add_post_meta( $post_id, 'foo', '0' ); add_post_meta( $post_id, 'bar', 0 ); - $post_id2 = self::factory()->post->create(); + $post_id2 = $this->factory->post->create(); add_post_meta( $post_id2, 'foo', 1 ); - $post_id3 = self::factory()->post->create(); + $post_id3 = $this->factory->post->create(); add_post_meta( $post_id3, 'baz', 0 ); - $post_id4 = self::factory()->post->create(); + $post_id4 = $this->factory->post->create(); add_post_meta( $post_id4, 'baz', 0 ); - $post_id5 = self::factory()->post->create(); + $post_id5 = $this->factory->post->create(); add_post_meta( $post_id5, 'baz', 0 ); add_post_meta( $post_id5, 'bar', '0' ); - $post_id6 = self::factory()->post->create(); + $post_id6 = $this->factory->post->create(); add_post_meta( $post_id6, 'baz', 0 ); es_wp_query_index_test_data(); @@ -1646,7 +1646,7 @@ public function test_empty_meta_value() { * @ticket 31045 */ public function test_orderby_clause_key() { - $posts = self::factory()->post->create_many( 3 ); + $posts = $this->factory->post->create_many( 3 ); add_post_meta( $posts[0], 'foo', 'aaa' ); add_post_meta( $posts[1], 'foo', 'zzz' ); add_post_meta( $posts[2], 'foo', 'jjj' ); @@ -1671,13 +1671,13 @@ public function test_orderby_clause_key() { * @ticket 31045 */ public function test_orderby_clause_key_as_secondary_sort() { - $p1 = self::factory()->post->create( array( + $p1 = $this->factory->post->create( array( 'post_date' => '2015-01-28 03:00:00', ) ); - $p2 = self::factory()->post->create( array( + $p2 = $this->factory->post->create( array( 'post_date' => '2015-01-28 05:00:00', ) ); - $p3 = self::factory()->post->create( array( + $p3 = $this->factory->post->create( array( 'post_date' => '2015-01-28 03:00:00', ) ); @@ -1707,7 +1707,7 @@ public function test_orderby_clause_key_as_secondary_sort() { * @ticket 31045 */ public function test_orderby_more_than_one_clause_key() { - $posts = self::factory()->post->create_many( 3 ); + $posts = $this->factory->post->create_many( 3 ); add_post_meta( $posts[0], 'foo', 'jjj' ); add_post_meta( $posts[1], 'foo', 'zzz' );