WordPress meta_query [ULTIMATE GUIDE]

WordPress Meta Query

WordPress has a powerful metadata system and database structure that gives developers great flexibility when adding various kinds of custom data. Many of the most popular plugins like Advanced Custom Fields or WooCommerce rely on it.

In this article, I’d like to show you how to work with WordPress meta queries in order to be able to fetch data from the database in all sorts of ways.

Query Posts By Meta Value

Let’s assume that you have posts that only want to show on a particular page that has the ID of 1 and that this data is stored in the wp_postmeta with meta key show_on_page. In order to query only the posts that we want to show on the page with ID of 1, we can use the following query:

<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_key' => 'show_on_page',
    'meta_value' => 1 // ID of the page
]);

$posts = $query->get_posts();

As you can see. we need to use the ‘meta_key’ parameter to tell the WP_Query which meta field to query by, and the ‘meta_value’ parameter is used to provide ID of the page that we want the posts to be shown on.

Now let’s assume that we want to get posts that are not supposed to be displayed on a page with ID 1. The query that we would use is the following:

<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_key' => 'show_on_page',
    'meta_value' => 1, // ID of the page
    'meta_compare' => '!='
]);

$posts = $query->get_posts();

This time we’ve used the ‘meta_compare’ => ‘!=’ to indicate that the ID of the page should be different than 1.

There is also another way to rewrite the queries above and get the same result. Here is how you can rewrite the first query:

<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_query' => [
        'key' => 'show_on_page',
        'value' => 1 // ID of the page
    ]
]);

$posts = $query->get_posts();

And this is how you could rewrite the second query:

<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_query' => [
        'key' => 'show_on_page',
        'value' => 1, // ID of the page
        'compare' => '!='
    ]
]);

$posts = $query->get_posts();

Instead of using ‘meta_’ parameters, we’re using the ‘meta_query’ option with an array of parameters to use for the meta query.

Query Posts By Multiple Meta Values

Now, that we know how to get posts by a meta field, we can take a look at a more complex example. Let’s assume that we want to get the posts that will be displayed on pages with 1, 2, or 3:

<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_query' => [
        'key' => 'show_on_page',
        'value' => [1, 2, 3], // IDs of the pages
        'compare' => 'IN'
    ]
]);

$posts = $query->get_posts();

You can spot 2 differences with our previous query:

  • we are using an array of values for the ‘value’ parameter to provide an array of page IDs
  • we are using the ‘compare’ => ‘IN’ parameter, that makes our query check if the meta value is one of the items in the array of page IDs ([1, 2, 3])

If you need to get the posts that are not supposed to be displayed on these pages, you could use alter your query like this:

<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_query' => [
        'key' => 'show_on_page',
        'value' => [1, 2, 3], // IDs of the pages
        'compare' => 'NOT IN'
    ]
]);

$posts = $query->get_posts();

The only difference is that we’re providing ‘NOT IN’ as a value for the ‘compare’ parameter which makes the query get the posts whose meta value isn’t included in the [1, 2, 3] array of page IDs.

Meta Query Comparison Operators

We’ve already seen how the “!=”, “IN”, and “NOT IN” comparison operators work, but that’s not all of them.
Let’s explore other operators and start with the numeric ones:

  • = (equal to)
  • != (not equal to)
  • > (greater than)
  • >= (greater or equal to)
  • < (less than)
  • <= (less or equal to)

Now, let’s try to get all the posts that should be displayed on a page with an ID less than or equal to 2:

<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_query' => [
        'key' => 'show_on_page',
        'value' => 2, // ID of the page
        'compare' => '<=',
        'type' => 'numeric'
    ]
]);

$posts = $query->get_posts();

A similar operation can be done with date meta fields. Let’s assume that we have a list of posts that we only want to be displayed after a certain date and that we have a custom field called “display_after”. In order to get the posts that can be displayed after a specific date (21st of November, 2021), here is how we can do it:

<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_query' => [
        'key' => 'display_after',
        'value' => '2021-11-21',
        'compare' => '>',
        'type' => 'DATE'
    ]
]);

$posts = $query->get_posts();

Other comparison operators include:

  • LIKE. Let’s get all the posts where the event_city meta field has with “Los”, which would match values like “Los Angeles”, “Leon de los Aldama”, “Los Mochis”, and so on:
<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_query' => [
        'key' => 'event_city',
        'value' => 'Los',
        'compare' => 'LIKE',
    ]
]);

$posts = $query->get_posts();
  • NOT LIKE. If we needed to fetch the posts with the event_city value that doesn’t contain “Los”, we would simply need to use the “NOT LIKE” operator:
<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_query' => [
        'key' => 'event_city',
        'value' => 'Los',
        'compare' => 'NOT LIKE',
    ]
]);

$posts = $query->get_posts();
  • BETWEEN. Here is how we can fetch the posts that have the “event_date” date is between 2 dates:
<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_query' => [
        'key' => 'event_date',
        'value' => ['2020-11-21', '2021-11-21'],
        'compare' => 'BETWEEN',
    ]
]);

$posts = $query->get_posts();
  • NOT BETWEEN. We can do a similar operation to get the posts where the “event_date” is not between the 2 dates:
<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_query' => [
        'key' => 'event_date',
        'value' => ['2020-11-21', '2021-11-21'],
        'compare' => 'NOT BETWEEN',
    ]
]);

$posts = $query->get_posts();
  • EXISTS. We can also get ONLY the posts that have an “event_date” meta value set:
<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_query' => [
        'key' => 'event_date',
        'compare' => 'EXISTS',
    ]
]);

$posts = $query->get_posts();
  • NOT EXISTS. Alternatively, we can also get ONLY the posts where “event_date” meta value doesn’t exist:
<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_query' => [
        'key' => 'event_date',
        'compare' => 'NOT EXISTS',
    ]
]);

$posts = $query->get_posts();
  • REGEXP. And last but not least, we can use the REGEXP operator to perform various kinds of regular expression checks. For example, if we needed to only get the posts where the “email_address” meta field started with “tom@”, we here is how we can do it:
<?php

$query = new WP_Query([
    'post_type' => 'post',
    'meta_query' => [
        'key' => 'email_address',
        'value' => '^tom@',
        'compare' => 'REGEXP',
    ]
]);

$posts = $query->get_posts();

How To Combine Meta Queries

One more handy way to use a meta query option is to combine the conditions in a meta query. You can use binary “OR” relation as well as the “AND” relation. Here is how it works:

<?php

$query = new WP_Query([
    'post_type' => 'event',
    'meta_query' => [
        'relation' => 'AND',
        [
            'key' => 'show_on_page',
            'value' => 1,
        ],
        [
            'relation' => 'OR',
            [
                'key' => 'event_city',
                'value' => 'Los',
                'compare' => 'LIKE'
            ],
            [
                'key' => 'event_city',
                'value' => 'San',
                'compare' => 'LIKE'
            ]
        ]
    ]
]);

$posts = $query->get_posts();

The query above will get all the posts with the type of event that have to be shown on the page with an ID of 1 AND these posts have to have the ‘event_city’ meta value that has either ‘Los’ OR ‘San’ in it.

For example, if you had 2 events that need to be shown on the homepage and one had the city of the event set as Los Angeles, and another had San Diego, both will be shown on the homepage.

How To Order Posts By Meta Fields

You can also use the meta values to sort the posts by. Let’s say you wanted to sort the events by the name of the city that they take place (‘event_city’) in alphabetical order. Here is how you can do it:

<?php

$query = new WP_Query([
    'post_type' => 'event',
    'order' => 'ASC',
    'orderby' => 'meta_value',
    'meta_key' => 'event_city'
]);

$posts = $query->get_posts();

Let’s say that your value is numeric for example and you want to sort the events from the highest priority to the lowest one (higher numbers mean higher priority in this example):

<?php

$query = new WP_Query([
    'post_type' => 'event',
    'order' => 'DESC',
    'orderby' => 'meta_value',
    'meta_type' => 'NUMERIC',
    'meta_key' => 'priority'
]);

$posts = $query->get_posts();

As you can see, we’ve used the ‘meta_type’ parameter to tell WordPress that the value needs to be sorted as a numeric value. Other data types that ‘meta_type’ supports are ‘BINARY’, ‘CHAR’, ‘DATE’, ‘DATETIME’, ‘DECIMAL’, ‘SIGNED’, ‘TIME’, ‘UNSIGNED’.

How To Order Posts By Multiple Meta Fields

Since WordPress 4.2, you can order posts by multiple meta values. Here is how we can get all the events ordered by the event city in alphabetical/ascending order and then by the most recent events:

<?php

$query = new WP_Query([
    'post_type' => 'event',
    'meta_query' => [
        'relationship' => 'AND',
        'city_clause' => [
            'key' => 'event_city',
            'compare' => 'EXISTS',
        ],
        'date_clause' => [
            'key' => 'date',
            'compare' => 'EXISTS',
            'type' => 'DATETIME'
        ]
    ],
    'orderby' => [
        'city_clause' => 'ASC',
        'date_clause' => 'DESC'
    ],
]);

$posts = $query->get_posts();

As you can see, we first have to define different meta clauses (date_clause, city_clause) and I’ve also set the compare parameter to ‘EXISTS’ as we need to make sure that the meta_key exits. Then, we can use those clauses in the ‘orderby’ parameter and define by which clause we want to order first and in what direction we need to order the posts (ASC or DESC).

Conclusion

As you can see, the WordPress meta query is quite powerful and you can use it to customize your WordPress site if you know how to use it. Don’t be afraid to experiment with it and you’ll master it in no time.

About The Author

Andriy Haydash

Andriy Haydash

Andriy Haydash is a WordPress Expert who helps people build and launch successful WordPress membership and e-learning websites.

Note: Not all of the articles are written directly by me.
Affiliate Disclaimer: Some links in the post may be my affiliate links

The Ultimate Managed Hosting Platform

Before YOU Leave...
Join My Newsletter

Get practical tips & tricks on how to start, grow and market your course/membership site.