WP_Query supports filtering posts by custom field values via the meta_query parameter. It covers simple equality checks and more complex comparisons — ranges, existence checks, multiple conditions combined with AND/OR.
Problem: How do you retrieve WordPress posts filtered by a custom field (post meta) value?
Solution: Pass a meta_query argument to WP_Query — it supports single-field lookups, multi-field combinations with AND/OR, and numeric comparisons.
Simple single-field query:
$query = new WP_Query( [
'post_type' => 'product',
'meta_query' => [
[
'key' => '_featured',
'value' => '1',
'compare' => '=',
],
],
] );
Multi-condition query (AND / OR):
$query = new WP_Query( [
'post_type' => 'event',
'meta_query' => [
'relation' => 'AND',
[
'key' => 'event_city',
'value' => 'Kyiv',
'compare' => '=',
],
[
'key' => 'event_date',
'value' => date( 'Y-m-d' ),
'compare' => '>=',
'type' => 'DATE',
],
],
] );
Check for key existence (any value set):
$query = new WP_Query( [
'post_type' => 'post',
'meta_query' => [
[
'key' => '_thumbnail_id',
'compare' => 'EXISTS',
],
],
] );
Available compare operators: =, !=, >, >=, <, <=, LIKE, NOT LIKE, IN, NOT IN, BETWEEN, NOT BETWEEN, EXISTS, NOT EXISTS.
NOTE: Meta queries hit wp_postmeta which has no index on meta_value by default. On large datasets, complex meta queries can be slow. Consider adding a composite index on (meta_key, meta_value) or storing frequently-queried flags as post data (taxonomy terms or custom columns) instead.