WordPress meta query is very slow with EXISTS comparison

I need to get posts that do not have a certain meta key.

    function handle_empty_date_paid($query, $query_vars)
    {
        if (!empty($query_vars['not_paid'])) {
            $query['meta_query'][] = array(
                'key' => '_date_paid',
                'compare' => 'NOT EXISTS'
            );
        }
        return $query;
    }

and then

$posts = get_posts([
    'limit' => 30,
    'not_paid' => '1'
]);

This query is very slow. Is there any way to make it work? The comparison ‘=0’ doesn’t work in this case. The opposite query date_paid => ‘>0’ works fine and fast. I think the slow performance is caused by ‘not present’. Is there a way to change this?

#edit

it’s a bit fast

global $wpdb;
$rows = $wpdb->get_results("SELECT post_id FROM {$wpdb->prefix}postmeta WHERE meta_key = '_date_paid'");
$exclude = [];
foreach($rows as $row) {
   $exclude[] = $row->post_id;
}
$args['post__not_in'] = $exclude;

Leave a Comment