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/class-es-wp-meta-query.php b/class-es-wp-meta-query.php index 3ee697e..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,158 +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'] ) ) ); } + } + + $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( $q['compare'] ) && 'EXISTS' == strtoupper( substr( $q['compare'], -6 ) ) ) { - unset( $q['value'] ); + 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; - - 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( '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. * @@ -184,4 +286,4 @@ public function get_cast_for_type( $type = '' ) { } return ''; } -} \ No newline at end of file +} diff --git a/tests/query/metaQuery.php b/tests/query/metaQuery.php new file mode 100644 index 0000000..54e37e2 --- /dev/null +++ b/tests/query/metaQuery.php @@ -0,0 +1,1769 @@ +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' ); + 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 = $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' ); + 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 = $this->factory->post->create(); + $p2 = $this->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 = $this->factory->post->create(); + $p2 = $this->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 = $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' ); + 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 = $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' ); + 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 ); + } + + /** + * 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 = $this->factory->post->create(); + $p2 = $this->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' => 'LIKE', + ), + ), + ) ); + + $expected = array( $p1 ); + $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 = $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' ); + 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' => 'NOT LIKE', + ), + ), + ) ); + + $expected = array( $p2 ); + $this->assertEqualSets( $expected, $query->posts ); + } + + public function test_meta_query_single_query_compare_between_not_between() { + $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' ); + 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 ); + } + + /** + * @expectedIncorrectUsage ES_WP_Query + */ + public function test_meta_query_single_query_compare_regexp() { + $p1 = $this->factory->post->create(); + $p2 = $this->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', + ), + ), + ) ); + } + + /** + * @expectedIncorrectUsage ES_WP_Query + */ + public function test_meta_query_single_query_compare_rlike() { + $p1 = $this->factory->post->create(); + $p2 = $this->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( + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'foo', + 'value' => 'z$', + 'compare' => 'RLIKE', + ), + ), + ) ); + } + + /** + * @expectedIncorrectUsage ES_WP_Query + */ + public function test_meta_query_single_query_compare_not_regexp() { + $p1 = $this->factory->post->create(); + $p2 = $this->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', + ), + ), + ) ); + } + + public function test_meta_query_relation_default() { + $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' ); + 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 = $this->factory->post->create(); + add_post_meta( $post_id, 'foo', rand_str() ); + add_post_meta( $post_id, 'foo', rand_str() ); + $post_id2 = $this->factory->post->create(); + add_post_meta( $post_id2, 'bar', 'val2' ); + $post_id3 = $this->factory->post->create(); + add_post_meta( $post_id3, 'baz', rand_str() ); + $post_id4 = $this->factory->post->create(); + add_post_meta( $post_id4, 'froo', rand_str() ); + $post_id5 = $this->factory->post->create(); + add_post_meta( $post_id5, 'tango', 'val2' ); + $post_id6 = $this->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 = $this->factory->post->create(); + add_post_meta( $post_id, 'foo', rand_str() ); + add_post_meta( $post_id, 'foo', rand_str() ); + $post_id2 = $this->factory->post->create(); + add_post_meta( $post_id2, 'bar', 'val2' ); + add_post_meta( $post_id2, 'foo', rand_str() ); + $post_id3 = $this->factory->post->create(); + add_post_meta( $post_id3, 'baz', rand_str() ); + $post_id4 = $this->factory->post->create(); + add_post_meta( $post_id4, 'froo', rand_str() ); + $post_id5 = $this->factory->post->create(); + add_post_meta( $post_id5, 'tango', 'val2' ); + $post_id6 = $this->factory->post->create(); + add_post_meta( $post_id6, 'bar', 'val1' ); + add_post_meta( $post_id6, 'foo', rand_str() ); + $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() ); + 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 = $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(); + + $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 = $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(); + + $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 = $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(); + + $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 = $this->factory->post->create(); + add_post_meta( $post_id, 'foo', rand_str() ); + $post_id2 = $this->factory->post->create(); + add_post_meta( $post_id2, 'bar', rand_str() ); + $post_id3 = $this->factory->post->create(); + add_post_meta( $post_id3, 'bar', rand_str() ); + $post_id4 = $this->factory->post->create(); + add_post_meta( $post_id4, 'baz', rand_str() ); + $post_id5 = $this->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 = $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' ); + 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 = $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' ); + 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 = $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' ); + 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 = $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' ); + 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 ); + } + + /** + * 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() { + $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' ); + add_post_meta( $posts[2], 'vegetable', 'shallots' ); + 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' => '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 = $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' ); + 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 = $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' ); + 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 = $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' ); + 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 = $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' ); + 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 = $this->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 = $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' ); + 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 ); + } + + /** + * 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() { + $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' ); + add_post_meta( $posts[2], 'vegetable', 'shallots' ); + 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' => '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 = $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' ); + 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 = $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 ); + 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 = $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 ); + 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 = $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' ); + 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 = $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' ); + 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 = $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 + */ + public 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 + */ + public 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 + */ + public 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(); + + $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 = $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' ); + 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 = $this->factory->post->create( array( + 'post_date' => '2015-01-28 03:00:00', + ) ); + $p2 = $this->factory->post->create( array( + 'post_date' => '2015-01-28 05:00:00', + ) ); + $p3 = $this->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 = $this->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() ) ); + } +} diff --git a/tests/query/post.php b/tests/query/post.php index 7ef674d..8c47dd3 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(); @@ -395,175 +262,4 @@ function test_taxonomy_empty_or() { $posts = $query->get_posts(); $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 ); - } - } \ No newline at end of file