Estrutura correta do metaquery na API REST v2 para filtrar por intervalo de datas

Hola,

No meu plugin personalizado que exibe coleções e itens do Tainacan via shortcodes com página de configurações, filtros dinâmicos e suporte multilíngue, qual é a estrutura correta do metaquery na API REST v2 para filtrar por intervalo de datas? Especificamente, como devo formatar os valores de data (texto, ISO, timestamp) e quais operadores de comparação são suportados para metadatos do tipo data, já que atualmente retorna resultados vazios mesmo quando existem itens dentro do intervalo especificado e os filtros funcionam corretamente no admin do Tainacan?

public function get_collection_items($collection_id, $page = 1, $per_per_page = 12, $filters = [], $search = '') {
    $filters_hash = md5(serialize($filters) . $search . $page . $per_page);
    $cache_key = 'mt_items_' . $collection_id . '_' . $filters_hash . '_' . $this->current_lang;
    $cached = $this->get_cached_data($cache_key, 'items');
    
    // Retorna dados em cache se disponíveis
    if ($cached !== false && !empty($cached['items'])) {
        return $cached;
    }
    
    $params = [
        'collection_id' => intval($collection_id), 
        'perpage' => $per_page, 
        'paged' => $page, 
        'status' => 'publish',
        'orderby' => 'date', 
        'order' => 'DESC'
    ];
    
    // DEBUG: Mostrar filtros recebidos do shortcode
    $date_min = $filters['date_min'] ?? '';
    $date_max = $filters['date_max'] ?? '';
    $this->log_debug("Filtros de data recebidos - Mín: $date_min, Máx: $date_max");
    
    // PROBLEMA PRINCIPAL: Esta seção retorna resultados vazios
    // quando filtros de data são aplicados
    $metaquery = [];
    $has_filters = false;
    
    if (!empty($date_min) || !empty($date_max)) {
        // Encontra os metadados de data da coleção
        $date_meta_ids = $this->find_date_metadatum_ids_advanced($collection_id);
        
        if (!empty($date_meta_ids)) {
            $primary_date_meta_id = $date_meta_ids[0];
            
            // TENTATIVA ATUAL (NÃO FUNCIONA)
            // PROVAVEL PROBLEMA: Formato ou operadores incorretos
            if (!empty($date_min)) {
                $metaquery[] = [
                    'key' => $primary_date_meta_id,
                    'value' => $date_min, // Ex: "1900" ou "1900-01-01"
                    'compare' => '>='     // Operador de comparação
                ];
                $has_filters = true;
            }
            
            if (!empty($date_max)) {
                $metaquery[] = [
                    'key' => $primary_date_meta_id,
                    'value' => $date_max, // Ex: "1950" ou "1950-12-31"
                    'compare' => '<='     // Operador de comparação
                ];
                $has_filters = true;
            }
            
            $this->log_debug("Aplicando filtros de data: $date_min - $date_max no metadado: $primary_date_meta_id");
        } else {
            $this->log_debug("AVISO: Nenhum metadado de data encontrado para a coleção $collection_id");
        }
    }
    
    // Adiciona metaquery aos parâmetros se houver filtros
    if ($has_filters) {
        $params['metaquery'] = $metaquery;
        $this->log_debug("Parâmetros com metaquery: " . json_encode($params));
    }
    
    // Faz a chamada para API do Tainacan
    $api_url = $this->get_api_url('items', $params);
    $response = $this->optimized_api_call($api_url);
    
    // PROCESSAMENTO DA RESPOSTA
    $response_body = wp_remote_retrieve_body($response);
    $data = json_decode($response_body, true) ?? [];
    
    // RESULTADO: Sempre vazio quando filtros de data são aplicados
    $result = [
        'items' => $data['items'] ?? [], // ← ARRAY VAZIO com filtros de data
        'total_pages' => wp_remote_retrieve_header($response, 'x-wp-totalpages') ?? 1,
        'total_items' => wp_remote_retrieve_header($response, 'x-wp-total') ?? 0 // ← ZERO com filtros
    ];
    
    // Log diagnóstico
    $this->log_debug("RESULTADO DOS FILTROS DE DATA - Itens: " . count($result['items']) . ", Total: " . $result['total_items']);
    
    // DEBUG: Verifica se a coleção tem itens sem filtros
    if ($result['total_items'] === 0 && (!empty($date_min) || !empty($date_max))) {
        $this->log_debug("🚨 ALERTA: Filtros de data retornaram 0 itens, mas a coleção pode ter itens");
        $this->perform_diagnostic($collection_id, $date_meta_ids, $date_min, $date_max);
    }
    
    return $result;
}

Exemplo de log do problema:

MT_DEBUG - Filtros de data recebidos - Mín: 1900, Máx: 1950
MT_DEBUG - Metadados de data encontrados: 4755, 4756, 4757
MT_DEBUG - Aplicando filtros de data: 1900 - 1950 no metadado: 4755
MT_DEBUG - Parâmetros com metaquery: {“collection_id”:4740,“metaquery”:[{“key”:“4755”,“value”:“1900”,“compare”:“>=”},{“key”:“4755”,“value”:“1950”,“compare”:“<=”}]}
MT_DEBUG - RESULTADO DOS FILTROS DE DATA - Itens: 0, Total: 0
MT_DEBUG - :police_car_light: ALERTA: Filtros de data retornaram 0 itens, mas a coleção pode ter itens

Metadados de data são encontrados corretamente. A query é montada e enviada para a API. A API retorna 200 OK mas com arrays vazios. O problema está na formatação ou estrutura do metaquery para filtros de data. Obrigado, JP

Oi @miramontes!

Só pra me ajudar a entender um pouco mais aqui, esta sua função get_api_url está chamando qual endpoint? O /wp-json/tainacan/v2/items? E neste caso você está querendo fazer um filtro por data ou por número? Porque se for data mesmo aí você precisaria passar elas no formato yyyy-mm-dd.

Uma boa maneira de visualizar como a API monta estas consultas é justamente criando filtros na interface e inspecionando as requisições de rede do navegador.

Por exemplo aqui está um filtro de data aplicado:

https://localhost/minhas-fotos/?metaquery[0][key]=57&metaquery[0][value][0]=1985-11-06&metaquery[0][value][1]=2025-11-12&metaquery[0][compare]=BETWEEN&metaquery[0][type]=DATE

Note como fica o array de metaqueries:

metaquery[0][key] = 57
metaquery[0][value][0] = 1985-11-06
metaquery[0][value][1] = 2025-11-12
metaquery[0][compare] = BETWEEN
metaquery[0][type] = DATE

Esta forma de mostrar o array é uma notação do WordPress. Podem ter outros filtros aplicados, por isso metaquery é um array. O operador BETWEEN é possível por conta do type ser DATE.

Você tem toda a razão! O formato yyyy-mm-dd era realmente a solução, mas o problema principal era que eu estava usando os metadatos errados (4755, 4756, 4757) que nem eram do tipo data. Seguindo sua sugestão de verificar a estrutura real, implementei uma busca por todos os metadatos da coleção e encontrei o correto: ID 4775 do tipo Tainacan\Metadata_Types\Date. Agora com as datas no formato 1900-01-01 a 1950-12-31 e usando o metadato certo, os filtros funcionam perfeitamente e retornam resultados! Muito obrigado pela paciência e pelas orientações precisas.

1 curtida

Este tópico foi fechado automaticamente 5 dias depois da última resposta. Novas respostas não são mais permitidas.