Pular para o conteúdo principal

Filtros de Dados

A filtragem de dados é uma operação fundamental para processar e analisar informações de forma eficiente. Esta seção aborda como aplicar filtros, criar condições complexas e otimizar o processamento de dados no n8n.

Visão Geral

Filtros permitem selecionar dados específicos baseados em critérios definidos, reduzindo o volume de informações processadas e melhorando a performance dos workflows. No n8n, você pode filtrar dados usando:

  • Filtros simples por valor
  • Condições complexas com operadores lógicos
  • Filtros baseados em expressões JavaScript
  • Filtros temporais para datas
  • Filtros de texto com regex

Tipos de Filtros

Filtros por Valor

Filtros básicos baseados em valores específicos:

// Filtrar por valor exato
const filtrarPorValor = (dados, campo, valor) => {
  return dados.filter(item => item[campo] === valor);
};

// Exemplo: Filtrar clientes ativos
const clientesAtivos = filtrarPorValor(clientes, 'status', 'ativo');

// Filtrar por múltiplos valores
const filtrarPorValores = (dados, campo, valores) => {
  return dados.filter(item => valores.includes(item[campo]));
};

// Exemplo: Filtrar por estados específicos
const estadosFiltrados = filtrarPorValores(clientes, 'estado', ['SP', 'RJ', 'MG']);

Filtros Numéricos

Filtros para valores numéricos com operadores de comparação:

// Filtrar por faixa de valores
const filtrarPorFaixa = (dados, campo, min, max) => {
  return dados.filter(item => {
    const valor = parseFloat(item[campo]);
    return valor >= min && valor <= max;
  });
};

// Exemplo: Filtrar produtos por preço
const produtosBaratos = filtrarPorFaixa(produtos, 'preco', 0, 100);
const produtosCaros = filtrarPorFaixa(produtos, 'preco', 500, 9999);

// Filtrar por valor mínimo
const filtrarMinimo = (dados, campo, valor) => {
  return dados.filter(item => parseFloat(item[campo]) >= valor);
};

// Exemplo: Filtrar vendas acima de R$ 1000
const vendasAltas = filtrarMinimo(vendas, 'valor', 1000);

Filtros de Texto

Filtros para processamento de strings e texto:

// Filtrar por texto contido
const filtrarPorTexto = (dados, campo, texto) => {
  return dados.filter(item => 
    item[campo].toLowerCase().includes(texto.toLowerCase())
  );
};

// Exemplo: Filtrar produtos por nome
const produtosEletronicos = filtrarPorTexto(produtos, 'nome', 'eletrônico');

// Filtrar por regex
const filtrarPorRegex = (dados, campo, padrao) => {
  const regex = new RegExp(padrao, 'i');
  return dados.filter(item => regex.test(item[campo]));
};

// Exemplo: Filtrar emails válidos
const emailsValidos = filtrarPorRegex(clientes, 'email', '^[^@]+@[^@]+\\.[^@]+$');

// Filtrar por início de texto
const filtrarPorInicio = (dados, campo, prefixo) => {
  return dados.filter(item => 
    item[campo].toLowerCase().startsWith(prefixo.toLowerCase())
  );
};

// Exemplo: Filtrar clientes por nome
const clientesJoao = filtrarPorInicio(clientes, 'nome', 'João');

Filtros Temporais

Filtros para datas e timestamps:

// Filtrar por período
const filtrarPorPeriodo = (dados, campo, inicio, fim) => {
  const dataInicio = new Date(inicio);
  const dataFim = new Date(fim);
  
  return dados.filter(item => {
    const data = new Date(item[campo]);
    return data >= dataInicio && data <= dataFim;
  });
};

// Exemplo: Filtrar vendas do último mês
const hoje = new Date();
const inicioMes = new Date(hoje.getFullYear(), hoje.getMonth(), 1);
const vendasMes = filtrarPorPeriodo(vendas, 'data', inicioMes, hoje);

// Filtrar por data específica
const filtrarPorData = (dados, campo, data) => {
  const dataFiltro = new Date(data);
  return dados.filter(item => {
    const itemData = new Date(item[campo]);
    return itemData.toDateString() === dataFiltro.toDateString();
  });
};

// Filtrar por período relativo
const filtrarPeriodoRelativo = (dados, campo, dias) => {
  const hoje = new Date();
  const inicio = new Date(hoje.getTime() - (dias * 24 * 60 * 60 * 1000));
  
  return dados.filter(item => {
    const data = new Date(item[campo]);
    return data >= inicio && data <= hoje;
  });
};

// Exemplo: Filtrar registros dos últimos 7 dias
const registrosRecentes = filtrarPeriodoRelativo(registros, 'dataCriacao', 7);

Filtros Complexos

Filtros com Múltiplas Condições

Combine diferentes critérios usando operadores lógicos:

// Filtro AND (todas as condições devem ser verdadeiras)
const filtrarAND = (dados, condicoes) => {
  return dados.filter(item => {
    return condicoes.every(condicao => {
      const { campo, operador, valor } = condicao;
      
      switch (operador) {
        case '==':
          return item[campo] === valor;
        case '!=':
          return item[campo] !== valor;
        case '>':
          return parseFloat(item[campo]) > valor;
        case '<':
          return parseFloat(item[campo]) < valor;
        case '>=':
          return parseFloat(item[campo]) >= valor;
        case '<=':
          return parseFloat(item[campo]) <= valor;
        case 'contains':
          return item[campo].toLowerCase().includes(valor.toLowerCase());
        case 'startsWith':
          return item[campo].toLowerCase().startsWith(valor.toLowerCase());
        default:
          return false;
      }
    });
  });
};

// Exemplo: Filtrar clientes ativos de SP com valor > 1000
const clientesFiltrados = filtrarAND(clientes, [
  { campo: 'status', operador: '==', valor: 'ativo' },
  { campo: 'estado', operador: '==', valor: 'SP' },
  { campo: 'valor', operador: '>', valor: 1000 }
]);

// Filtro OR (pelo menos uma condição deve ser verdadeira)
const filtrarOR = (dados, condicoes) => {
  return dados.filter(item => {
    return condicoes.some(condicao => {
      const { campo, operador, valor } = condicao;
      
      switch (operador) {
        case '==':
          return item[campo] === valor;
        case '!=':
          return item[campo] !== valor;
        case '>':
          return parseFloat(item[campo]) > valor;
        case '<':
          return parseFloat(item[campo]) < valor;
        case 'contains':
          return item[campo].toLowerCase().includes(valor.toLowerCase());
        default:
          return false;
      }
    });
  });
};

// Exemplo: Filtrar clientes de SP ou RJ
const clientesSPouRJ = filtrarOR(clientes, [
  { campo: 'estado', operador: '==', valor: 'SP' },
  { campo: 'estado', operador: '==', valor: 'RJ' }
]);

Filtros Aninhados

Filtros para estruturas de dados complexas:

// Filtrar por propriedades aninhadas
const filtrarAninhado = (dados, caminho, valor) => {
  return dados.filter(item => {
    const valorAninhado = obterValorAninhado(item, caminho);
    return valorAninhado === valor;
  });
};

const obterValorAninhado = (objeto, caminho) => {
  return caminho.split('.').reduce((obj, prop) => obj?.[prop], objeto);
};

// Exemplo: Filtrar por cidade do endereço
const clientesSaoPaulo = filtrarAninhado(clientes, 'endereco.cidade', 'São Paulo');

// Filtrar arrays aninhados
const filtrarArrayAninhado = (dados, campoArray, criterio) => {
  return dados.filter(item => {
    const array = item[campoArray];
    if (!Array.isArray(array)) return false;
    
    return array.some(elemento => {
      return Object.entries(criterio).every(([campo, valor]) => 
        elemento[campo] === valor
      );
    });
  });
};

// Exemplo: Filtrar clientes que têm pedido com status "pendente"
const clientesComPedidoPendente = filtrarArrayAninhado(clientes, 'pedidos', {
  status: 'pendente'
});

Filtros Específicos para Dados Brasileiros

Filtros de CPF/CNPJ

// Filtrar por tipo de documento
const filtrarPorTipoDocumento = (dados, campo, tipo) => {
  return dados.filter(item => {
    const documento = item[campo].replace(/[^\d]/g, '');
    
    if (tipo === 'CPF') {
      return documento.length === 11;
    } else if (tipo === 'CNPJ') {
      return documento.length === 14;
    }
    
    return false;
  });
};

// Exemplo: Separar pessoas físicas e jurídicas
const pessoasFisicas = filtrarPorTipoDocumento(clientes, 'documento', 'CPF');
const pessoasJuridicas = filtrarPorTipoDocumento(clientes, 'documento', 'CNPJ');

// Filtrar por estado baseado no CPF
const filtrarPorEstadoCPF = (dados, campo, estado) => {
  const codigosEstado = {
    'SP': [1, 2, 3, 4, 5, 6, 7, 8, 9],
    'RJ': [20, 21, 22, 23, 24],
    'MG': [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
    'RS': [40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
  };
  
  const codigos = codigosEstado[estado] || [];
  
  return dados.filter(item => {
    const cpf = item[campo].replace(/[^\d]/g, '');
    const codigo = parseInt(cpf.substring(8, 10));
    return codigos.includes(codigo);
  });
};

Filtros de CEP

// Filtrar por região baseada no CEP
const filtrarPorRegiaoCEP = (dados, campo, regiao) => {
  const regioesCEP = {
    'Norte': ['69', '68', '67', '66', '65', '64', '63'],
    'Nordeste': ['59', '58', '57', '56', '55', '54', '53', '52', '51', '50', '49', '48', '47', '46', '45', '44', '43', '42', '41', '40'],
    'Centro-Oeste': ['79', '78', '77', '76', '75', '74', '73', '72', '71', '70'],
    'Sudeste': ['39', '38', '37', '36', '35', '34', '33', '32', '31', '30', '29', '28', '27', '26', '25', '24', '23', '22', '21', '20'],
    'Sul': ['99', '98', '97', '96', '95', '94', '93', '92', '91', '90', '89', '88', '87', '86', '85', '84', '83', '82', '81', '80']
  };
  
  const prefixos = regioesCEP[regiao] || [];
  
  return dados.filter(item => {
    const cep = item[campo].replace(/[^\d]/g, '');
    const prefixo = cep.substring(0, 2);
    return prefixos.includes(prefixo);
  });
};

// Exemplo: Filtrar clientes do Sudeste
const clientesSudeste = filtrarPorRegiaoCEP(clientes, 'endereco.cep', 'Sudeste');

Otimização de Filtros

Filtros em Lote

Processe grandes volumes de dados eficientemente:

// Filtrar em lotes para melhor performance
const filtrarEmLotes = (dados, filtro, tamanhoLote = 1000) => {
  const resultados = [];
  
  for (let i = 0; i < dados.length; i += tamanhoLote) {
    const lote = dados.slice(i, i + tamanhoLote);
    const loteFiltrado = lote.filter(filtro);
    resultados.push(...loteFiltrado);
  }
  
  return resultados;
};

// Exemplo: Filtrar grandes volumes de dados
const dadosGrandes = Array.from({length: 100000}, (_, i) => ({
  id: i,
  valor: Math.random() * 1000,
  status: Math.random() > 0.5 ? 'ativo' : 'inativo'
}));

const dadosFiltrados = filtrarEmLotes(dadosGrandes, item => 
  item.status === 'ativo' && item.valor > 500
);

Filtros com Cache

Use cache para filtros frequentemente aplicados:

// Cache de filtros
const cacheFiltros = new Map();

const filtrarComCache = (dados, criterios, chaveCache) => {
  // Verificar cache
  if (cacheFiltros.has(chaveCache)) {
    const { resultado, timestamp } = cacheFiltros.get(chaveCache);
    const agora = Date.now();
    
    // Cache válido por 5 minutos
    if (agora - timestamp < 5 * 60 * 1000) {
      return resultado;
    }
  }
  
  // Aplicar filtro
  const resultado = dados.filter(item => {
    return criterios.every(criterio => {
      const { campo, operador, valor } = criterio;
      
      switch (operador) {
        case '==':
          return item[campo] === valor;
        case '>':
          return parseFloat(item[campo]) > valor;
        case 'contains':
          return item[campo].toLowerCase().includes(valor.toLowerCase());
        default:
          return false;
      }
    });
  });
  
  // Salvar no cache
  cacheFiltros.set(chaveCache, {
    resultado,
    timestamp: Date.now()
  });
  
  return resultado;
};

// Exemplo: Filtrar com cache
const clientesAtivosSP = filtrarComCache(
  clientes,
  [
    { campo: 'status', operador: '==', valor: 'ativo' },
    { campo: 'estado', operador: '==', valor: 'SP' }
  ],
  'clientes_ativos_sp'
);

Filtros Avançados

Filtros Fuzzy

Filtros que toleram erros de digitação:

// Filtro fuzzy para texto
const filtrarFuzzy = (dados, campo, termo, tolerancia = 0.8) => {
  return dados.filter(item => {
    const valor = item[campo].toLowerCase();
    const termoBusca = termo.toLowerCase();
    
    // Calcular similaridade
    const similaridade = calcularSimilaridade(valor, termoBusca);
    return similaridade >= tolerancia;
  });
};

// Algoritmo de similaridade simples (Levenshtein)
const calcularSimilaridade = (str1, str2) => {
  const matrix = [];
  
  for (let i = 0; i <= str2.length; i++) {
    matrix[i] = [i];
  }
  
  for (let j = 0; j <= str1.length; j++) {
    matrix[0][j] = j;
  }
  
  for (let i = 1; i <= str2.length; i++) {
    for (let j = 1; j <= str1.length; j++) {
      if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
        matrix[i][j] = matrix[i - 1][j - 1];
      } else {
        matrix[i][j] = Math.min(
          matrix[i - 1][j - 1] + 1,
          matrix[i][j - 1] + 1,
          matrix[i - 1][j] + 1
        );
      }
    }
  }
  
  const distancia = matrix[str2.length][str1.length];
  const maxLength = Math.max(str1.length, str2.length);
  
  return 1 - (distancia / maxLength);
};

// Exemplo: Busca fuzzy por nome
const clientesJoao = filtrarFuzzy(clientes, 'nome', 'João', 0.7);

Filtros Temporais Avançados

// Filtrar por dia da semana
const filtrarPorDiaSemana = (dados, campo, dias) => {
  return dados.filter(item => {
    const data = new Date(item[campo]);
    const diaSemana = data.getDay(); // 0 = Domingo, 1 = Segunda, etc.
    return dias.includes(diaSemana);
  });
};

// Exemplo: Filtrar vendas de segunda a sexta
const vendasSemana = filtrarPorDiaSemana(vendas, 'data', [1, 2, 3, 4, 5]);

// Filtrar por horário
const filtrarPorHorario = (dados, campo, horaInicio, horaFim) => {
  return dados.filter(item => {
    const data = new Date(item[campo]);
    const hora = data.getHours();
    return hora >= horaInicio && hora <= horaFim;
  });
};

// Exemplo: Filtrar transações em horário comercial
const transacoesComerciais = filtrarPorHorario(transacoes, 'timestamp', 8, 18);

Workflows de Filtragem

Workflow: Filtro de Dados em Tempo Real

Workflow: Análise de Dados Filtrados

Boas Práticas

Performance

  • Aplique filtros cedo no pipeline de dados
  • Use índices para campos frequentemente filtrados
  • Processe em lotes para grandes volumes
  • Cache resultados de filtros complexos
  • Monitore performance de filtros

Manutenibilidade

  • Documente critérios de filtro
  • Use constantes para valores mágicos
  • Crie funções reutilizáveis para filtros comuns
  • Teste filtros com dados reais
  • Valide resultados de filtros

Flexibilidade

  • Torne filtros configuráveis via parâmetros
  • Suporte múltiplos formatos de entrada
  • Permita combinação de filtros
  • Forneça valores padrão para filtros opcionais
  • Implemente fallbacks para casos especiais

Recursos Adicionais

Ferramentas Úteis

  • Lodash: Biblioteca com funções de filtragem avançadas
  • Ramda: Biblioteca funcional para manipulação de dados
  • date-fns: Biblioteca para manipulação de datas
  • validator.js: Validação de dados

Padrões de Filtro

  • Builder Pattern: Construir filtros complexos
  • Strategy Pattern: Diferentes algoritmos de filtro
  • Chain of Responsibility: Pipeline de filtros
  • Observer Pattern: Notificações de mudanças

Próximo: Edição de Dados - Modifique e transforme dados