In this post I assume that you already have basic knowledge how to work with WP_Query class in WordPress. Before I begin, I want to show you some very simple examples. The similar examples you can find in WordPress Codex.

As you know all the posts have the metadata you can populate in “Custom fields” metabox (the metabox by the way can be hidden). So, for example, if you want to get a post with meta key show_on_homepage and meta value on, you can do it the following way:

$rd_args = array(
	'meta_key' => 'show_on_homepage',
	'meta_value' => 'on'
); 
$rd_query = new WP_Query( $rd_args );

Otherwise, if you need to query all posts except the ones with this pair of meta key and value, you can use the following parameters:

$rd_args = array(
	'meta_key' => 'show_on_homepage',
	'meta_value' => 'on',
	'meta_compare' => '!='
); 
$rd_query = new WP_Query( $rd_args );

Do not forget that all examples in this post are simplified, so, some of WP_Query parameters are missing, e.g posts_per_page or post_type.

If you are interested in other meta_compare parameter values, please look at “compare” parameter description below, because both of them accept the same values.

This was very very simple examples, just an introdution. But this post is about meta_query parameter. This parameter allows us to create a really cool post filters and search scripts.

Query Posts by a Meta Value

The simple example below allows you to get all the posts with a specific custom field value. Let’s just get all the posts with custom field name “color” and custom field value white.

// the meta_key 'color' with the meta_value 'white'
$rd_args = array(
	'meta_query' => array(
		array(
			'key' => 'color',
			'value' => 'white'
		)
	)
); 
$rd_query = new WP_Query( $rd_args );

If you look at the post edit page (in admin area) in any post which matches the query, you will see the following in the “Custom Fields” section:

Meta Value

Let’s do the opposite thing – get all the posts except the ones with meta key “color” and meta value white:

$rd_args = array(
	'meta_query' => array(
		array(
			'key' => 'color',
			'value' => 'white',
			'compare' => '!='
		)
	)
); 
$rd_query = new WP_Query( $rd_args );

Get Posts by Multiple Meta Values

Now let’s get all the posts with white OR green “color” custom field value:

// custom field name is color and custom field value is 'white' OR 'green'
$rd_args = array(
	'meta_query' => array(
		array(
			'key' => 'color',
			'value' => array('white','green'),
			'compare' => 'IN'
		)
	)
); 
$rd_query = new WP_Query( $rd_args );

Get all the posts (products in online shop for example) except white products and green products:

$rd_args = array(
	'meta_query' => array(
		array(
			'key' => 'color',
			'value' => array('white','green'),
			'compare' => 'NOT IN'
		)
	)
); 
$rd_query = new WP_Query( $rd_args );

How to use “compare” in meta_query

As you can see in example below and in further examples too, there is a compare parameter in every of them. Now I would like to show which values it can accept and what do they mean.

  • = (or not set) Equal to,
  • != – Not equal to,
  • < – Less than,
  • <= – Less or equal to,
  • > – Greater than,
  • >= – Greater than or equal to, example:
// the product price in this example is 2000 or more than 2000:
$args = array(
	'meta_query' => array(
		array(
			'key' => 'price',
			'value' => 2000,
			'type' => 'numeric', // specify it for numeric values
			'compare' => '>='
		)
	)
);
  • LIKE – Allows to search in meta values for a specific string, in the example below the query returns all the posts where “first_name” name contains John, it can be also JohnnyJohnathansomethingJohnsomething:
$args = array(
	'meta_query' => array(
		array(
			'key' => 'first_name',
			'value' => 'John',
			'compare' => 'LIKE'
		)
	)
);
  • Two more things: first – it is not case sensitive, second – wildcard symbols @ are not necessary.
  • NOT LIKE – similar to LIKE just works in an opposite way – meta value mustn’t contain the given string.
  • IN – posts meta value must contain one of the values of the given array
  • NOT IN – meta values must not contain ANY of the values in the given array.
  • BETWEEN – post meta value should be between the given range of values, example:
// the product price is more than 2000 and less than 4000
$args = array(
	'meta_query' => array(
		array(
			'key' => 'price',
			'value' => array( 2000, 4000 ),
			'type' => 'numeric',
			'compare' => 'BETWEEN'
		)
	)
);
  • It can also work for dates
  • NOT BETWEEN – not in a given range.
  • EXISTS (WordPress >= 3.5) – If meta value of a specific meta key exists or empty / null.
$args = array(
	'meta_query' => array(
		array(
			'key' => 'misha_key',
			'compare' => 'EXISTS'
		)
	)
);
  • So, actually it checks if a meta key exists, you do not even have to pass any value with this parameter.
  • NOT EXISTS (WordPress >= 3.5) – if a given meta key doesn’t exist at all
  • REGEXP (WordPress >= 3.7) – it allows you to compare meta values with regular expression, example:
$args = array(
	'meta_query' => array(
		array(
			'key' => 'misha_key',
			'value' => '^[0-9]*$', // "misha_key" must be only numbers
			'compare' => 'REGEXP'
		)
	)
);
  • NOT REGEXP (WordPress >= 3.7) – Similar to REGEXP but meta values must not match your given regular expression
  • RLIKE (WordPress >= 3.7) – it is the synonym to REGEXP