Using WP_Query and Multiple Meta Keys

When it comes to searching the WordPress database, there’s probably no better API than WP_Query. That doesn’t mean it’s not without it’s limitations, though (only which will be improved over time, I’m sure).

For example, consider the case where you have two types of meta data that are completely unrelated and you need to run a search for both of them. Essentially, you have WP_Query and multiple meta keys that you need in order to search for information from this database.

In this specific case, I’m not talking about a single piece of meta data that has multiple keys and that would support and AND or and OR clause.

Instead, I’m talking about the idea of having multiple meta keys each of which are associated with a given post, but must all be searched in order to find the posts that have the data associated with it.

In more technical terms, I’m looking for the intersection of post IDs all of which share a common set of multiple, unrelated meta keys.

Confused? Me too. This is why it helps to draw stuff out in a notebook whenever you’re working on something, but I digress.

Instead, perhaps code is the better way to do.

WP_Query and Multiple Meta Keys

Let’s say that we have the following two meta keys (to keep it simple):

The type of account (be it public or private, for example) that is specified in the `$_POST` submission of the page.

Minimum and maximum values for which a given post can have associated with, say, its cost.

As far as I know (and more on this in a minute), we need to run two instances of WP_Query and then collect the post IDs into an array. From there, we’ll then find the intersection of the post IDs that match the following criteria.

With that said, here’s the first example of looking at the type of account:

In the above example, we’re pulling back all of the posts that have public or private selected somewhere in their meta data (even if it’s in a custom meta box). After that, we’re storing the results in an array and we’re making sure to filter our any duplicates that may exist. This last step is really just a safe guard.

Next, let’s say that we’re looking at another set of meta data, say, the minimum or maximum values that a post has associated with it in terms of cost. Furthermore, we want to make sure that all records retrieve fit between a set amount of data.

To keep things simple, we’ll assume all values are stored as numeric values (rather than, say, $1,000,000 we’ll just use 1000000).

Okay, so at this point we need yet another instance of WP_Query in order to search the posts, so we’ll set it up to do something like this:

Once you’ve reached this point, you should have two arrays. Each of the arrays are going to contain their own sets of posts IDs but there will be some common IDs to each array – that’s what we’re after.

Luckily, PHP makes it really easy to find the intersection of two arrays:

At this point, you have the results that match the two criteria above.

Two important things to note about this is that this can be done effectively using raw SQL and it may even be more efficient; however, I try to stick with the API whenever possible. Since that level is abstraction is provided for a reason, I try to stick with that reason.

Secondly, I’m not above saying that I may have missed something completely and this is not the right way to do this. If that’s the case, I’m open to any and all suggestions and am willing to mention it in an update to the post by linked to the proper comments.

Whatever the case, this is something that does work and is relatively straightforward in how to achieve it using WP_Query until a more elegant solution comes along.