Languages: English • Meta Query 日本語 (Add your language)
WP_Meta_Query is a class defined in wp-includes/meta.php that generates the necessary SQL for meta-related queries. It was introduced in Version 3.2.0 and greatly improved the possibility to query posts by custom fields. In the WP core, it's used in the WP_Query and WP_User_Query classes, and since Version 3.5 in the WP_Comment_Query class. Unless you're writing a custom SQL query, you should look in the *Custom Field Parameters* section for the corresponding class.
The following arguments can be passed in a key=>value paired array.
The 'type' DATE works with the 'compare' value BETWEEN only if the date is stored at the format YYYY-MM-DD and tested with this format.
Note: The 'meta_key', 'meta_value', 'meta_type' and 'meta_compare' arguments will only work if you use the second method described below.
You generally have two options on how to initialize and use a new WP_Meta_Query object:
Passing an Array of query parameters to the constructor:
$meta_query_args = array( 'relation' => 'OR', // Optional, defaults to "AND" array( 'key' => '_my_custom_key', 'value' => 'Value I am looking for', 'compare' => '=' ) ); $meta_query = new WP_Meta_Query( $meta_query_args );
In this case, you pass an array of key/value pair arrays (which were described above in the meta_query argument).
You can optionally pass the `relation` key and set it to either OR or AND. It defines the relation, when there is more than one meta query (whether all of the conditions should be met, or at least one of them needs to be met).
Nested arrays can be used to construct complex queries. For example, where _my_custom_key = value OR (_my_custom_key_2 = value AND _my_custom_key_3 = value).
$meta_query_args = array( 'relation' => 'OR', // Optional, defaults to "AND" array( 'key' => '_my_custom_key', 'value' => 'Value I am looking for', 'compare' => '=' ), array( 'relation' => 'AND', array( 'key' => '_my_custom_key_2', 'value' => 'Value I am looking for 2', 'compare' => '=' ), array( 'key' => '_my_custom_key_3', 'value' => 'Value I am looking for 3', 'compare' => '=' ) ) ); $meta_query = new WP_Meta_Query( $meta_query_args );
Using the WP_Meta_Query::parse_query_vars( $query ) method: You can use this method, if you want to use the simple query args(`meta_key`, `meta_value`, `meta_type`, `meta_compare`), or if you are unsure of the presence of meta query parameters.
// $query_vars can have various contents, so an example is not added here, but you need to have it defined beforehand $meta_query = new WP_Meta_Query(); // Won't work with an array( 'relation', array( 'key' => '...' ) ) // as the parse_query_vars() method searches for the `meta_` prefix $meta_query->parse_query_vars( array( 'meta_key' => 'some_key', // etc. ) );
You can retrieve the generated SQL by using the following method.
$mq_sql = $meta_query->get_sql( $type, $primary_table, $primary_id_column, $context = null );
List of Arguments:
$wpdb->posts
, or the alias name if you are aliasing the table in your SQL queryOn failure(for instance - lacking any meta query parameters in the query array), this function will return `false`.
On success, it will return an array like this:
array( 'join' => $join_sql, 'where' => $where_sql )
With each key holding the SQL for the corresponding section.
Example: Single Meta Entry - Flat array
Query
// Note that this will produce a "key only" query // If you want a full one, add a meta_value and meta_compare array key/value pair $query_args = array( 'meta_key' => 'some_key_name', ); $meta_query = new WP_Meta_Query(); $meta_query->parse_query_vars( $query_args ); $mq = $meta_query->get_sql( 'post', $wpdb->posts, 'ID', null );
Result
array (size=2) 'join' => string ' INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)' (length=62) 'where' => string ' AND (wp_postmeta.meta_key = 'some_key' )' (length=40)
Example: Multiple Meta Entries - Multi dimensional array:
Query:
$query_args = array( 'meta_query' => array( 'relation' => 'OR', array( 'key' => 'foo_key', // 'value' => 'foo', // 'compare' => 'LIKE', ), array( 'key' => 'bar_key', ), ) ); $meta_query = new WP_Meta_Query(); $meta_query->parse_query_vars( $query_args ); $mq_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID', null );
Result:
'join' => string ' INNER JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id' (length=60) 'where' => string ' AND (wp_postmeta.meta_key = 'foo_key' OR wp_postmeta.meta_key = 'bar_key' )' (length=75)
Note: This example will not append a space to the join statement, so you have to do it manually to not crash your query. The same goes for the where statement.
If you're using the value and compare parts of the meta_query input argument array, then the query string will look something like the following:
'where' => string ' AND (wp_postmeta.meta_key = 'foo_key' OR (mt1.meta_key = 'bar_key' AND CAST(mt1.meta_value AS CHAR) LIKE '%foo%') )'
Keep in mind that mt1 is the alias of the meta table and the join clause will look something like this and therefore use the JOIN twice:
'join' => string ' INNER JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id)'
Use that in further queries or form inside your posts_clauses, posts_where or posts_join filter callbacks.
Named meta sub-queries are particularly useful when you wish to sort by multiple different meta keys. If you pass the name (key) of your meta sub-query to the orderby array, WordPress will use that sub-query as the orderby parameter. See this example below:
$q = new WP_Query( array( 'meta_query' => array( 'relation' => 'AND', 'state_clause' => array( 'key' => 'state', 'value' => 'Wisconsin', ), 'city_clause' => array( 'key' => 'city', 'compare' => 'EXISTS', ), ), 'orderby' => array( 'city_clause' => 'ASC', 'state_clause' => 'DESC', ), ) );
Props cybmeta on WPSE for this example.
WP_Meta_Query() is located in wp-includes/class-wp-meta-query.php
.