Laboratório: busca de e-commerce com SQLite, D1 e Workers

Modelando o catálogo e o conjunto de dados semente

Schema de produtos, carga de dados de exemplo e critérios de qualidade do corpus de busca.

Intermediário 40 min 30 pontos Leitura 0%

Nesta aula você vai

  • Definir schema relacional de produtos adequado a FTS5
  • Carregar um seed de ~15–20 produtos fictícios com diversidade linguística
  • Validar o corpus para plurais, acentos e termos compostos

Modelando o catálogo e o conjunto de dados semente

Objetivos

Nesta aula você vai:

  • Definir schema relacional de produtos adequado a FTS5
  • Carregar um seed de ~15–20 produtos fictícios com diversidade linguística
  • Validar o corpus para plurais, acentos e termos compostos

Introdução

Antes de criar a tabela virtual FTS5, o laboratório precisa de uma tabela canônica e de um corpus de teste que exercite os casos reais de busca em e-commerce brasileiro: acentos (furadeira vs furacão), plurais, nomes compostos (chave de fenda) e categorias misturadas (ferramentas, livros, gadgets).

Sem um seed deliberado, você só valida o caminho feliz — e o índice “funciona” sem revelar lacunas de tokenização.

Conteúdo

Schema da tabela products

Preço em centavos evita REAL e arredondamento flutuante. tags fica como texto (lista separada por espaço ou vírgula) para entrar no índice FTS junto com nome e descrição.

CREATE TABLE IF NOT EXISTS products (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  description TEXT NOT NULL,
  category TEXT NOT NULL,
  tags TEXT NOT NULL DEFAULT '',
  price_cents INTEGER NOT NULL CHECK (price_cents >= 0)
);

CREATE INDEX IF NOT EXISTS idx_products_category ON products(category);

Campos que entrarão no FTS5 (próxima aula): name, description, category, tags. O preço permanece só na tabela relacional — útil para filtros pós-MATCH, não para tokenização.

Seed: produtos fictícios brasileiros

Nomes e descrições originais para o laboratório (não copie de demos externas). Diversifique categorias e ortografia:

INSERT INTO products (name, description, category, tags, price_cents) VALUES
(
  'Furadeira Percussiva Nordkraft 650W',
  'Furadeira com percussão para alvenaria e madeira. Inclui maleta e jogo de brocas de 3 a 10 mm.',
  'ferramentas',
  'furadeira percussao broca obra',
  28990
),
(
  'Chave de Fenda Isolada VoltSafe 1000V',
  'Chave de fenda com cabo isolado para trabalho elétrico até 1000 V. Ponta magnética.',
  'ferramentas',
  'chave fenda isolada eletrica',
  4590
),
(
  'Serra Circular Compacta SerraMundi 1400W',
  'Serra circular portátil com guia paralela e disco de 7 1/4 polegadas para cortes retos em madeira.',
  'ferramentas',
  'serra circular madeira corte',
  51990
),
(
  'Alicate Universal GripMax Pro',
  'Alicate universal com cabo emborrachado e corte lateral. Ideal para instalação elétrica residencial.',
  'ferramentas',
  'alicate universal eletrica',
  3290
),
(
  'Nível a Laser LinhaCruz LX-2',
  'Nível a laser com projeção de cruz em 360 graus. Autonivelamento e suporte magnético.',
  'ferramentas',
  'nivel laser obra medicao',
  18990
),
(
  'Livro: Algoritmos na Prática com Grafos',
  'Guia intermediário de grafos, caminhos mínimos e aplicações em roteamento. Exemplos em pseudocódigo.',
  'livros',
  'algoritmos grafos programacao',
  8990
),
(
  'Livro: SQL Moderno para Relatórios',
  'Consultas analíticas, window functions e boas práticas de modelagem para dashboards.',
  'livros',
  'sql analytics relatorios',
  7490
),
(
  'Livro: Redes Sem Fio Explicadas',
  'Introdução a Wi-Fi, interferência e planejamento de cobertura em ambientes urbanos.',
  'livros',
  'redes wifi wireless',
  6790
),
(
  'Livro: Design de APIs REST Estáveis',
  'Versionamento, idempotência e contratos JSON para times que evoluem microsserviços.',
  'livros',
  'api rest design backend',
  8190
),
(
  'Fone Bluetooth Auricular Névoa SoundPod',
  'Fones intra-auriculares com cancelamento passivo e até 28 horas de bateria com case.',
  'gadgets',
  'fone bluetooth audio',
  15990
),
(
  'Carregador Portátil PowerFolha 20000mAh',
  'Power bank com duas saídas USB-A e uma USB-C PD 18 W. Indicador LED de carga.',
  'gadgets',
  'carregador powerbank usb-c',
  12990
),
(
  'Webcam Full HD OrbitCam 1080p',
  'Webcam com microfone estéreo, clip universal e correção automática de luz para videochamadas.',
  'gadgets',
  'webcam video reuniao',
  21990
),
(
  'Teclado Mecânico Compacto TeclaVento 75%',
  'Teclado mecânico 75% com switches táteis, layout ABNT2 e iluminação RGB por tecla.',
  'gadgets',
  'teclado mecanico abnt2',
  34990
),
(
  'Mouse Ergonômico Vertical MãoLivre V2',
  'Mouse vertical sem fio com sensor óptico de 1600 DPI e receptor USB nano.',
  'gadgets',
  'mouse ergonomico semfio',
  18990
),
(
  'Luminária de Mesa LED BrilhoCalmo',
  'Luminária com temperatura de cor ajustável e braço articulado para leitura e home office.',
  'gadgets',
  'luminaria led escritorio',
  9990
),
(
  'Multímetro Digital PrecisãoAmp 600V',
  'Multímetro para tensão, corrente e continuidade. Display backlight e sondas reforçadas.',
  'ferramentas',
  'multimetro eletrica medicao',
  11290
),
(
  'Livro: Observabilidade com OpenTelemetry',
  'Traces, métricas e logs correlacionados em sistemas distribuídos. Casos em português.',
  'livros',
  'observabilidade opentelemetry tracing',
  9290
),
(
  'Hub USB-C MaréDock 7 em 1',
  'Hub com HDMI 4K, leitor SD, duas USB-A e PD passthrough para notebooks finos.',
  'gadgets',
  'hub usb-c hdmi dock',
  24990
);

Conte ~18 linhas: suficiente para exercitar consultas e ainda pequeno para inspecionar resultados à mão.

Critérios de qualidade do corpus para FTS

Antes de indexar, verifique:

  1. Plurais e variantes:brocas / broca, fones / fone, chaves implícitas em descrição vs tag singular.
  2. Acentos e diacríticos: Névoa, Precisão, MãoLivre — o tokenizer unicode61 com remove_diacritics deve permitir busca sem acento (nevoa, precisao).
  3. Termos compostos: chave de fenda, serra circular, power bank (em tags como powerbank) — teste frase ("chave de fenda") e tokens separados.
  4. Categorias mistas: pelo menos três famílias (ferramentas, livros, gadgets) para filtrar com JOIN + category = ? depois do MATCH.
  5. Ruído controlado: marcas inventadas (Nordkraft, SerraMundi) não devem “roubar” relevância de termos genéricos; use-as em testes de prefixo (Nord*).
  6. Tags alinhadas ao texto: tags reforçam sinônimos leves (percussao sem ç) sem contradizer a descrição.

Validação rápida do seed

SELECT category, COUNT(*) AS n FROM products GROUP BY category;

SELECT id, name
FROM products
WHERE name LIKE '%ção%' OR description LIKE '%ção%' OR name LIKE '%ã%';

SELECT id, name FROM products WHERE description LIKE '% de %';

Espere distribuição razoável por categoria, presença de diacríticos e várias frases compostas. Se tudo for ASCII sem compostos, o lab de FTS5 fica artificialmente fácil.

Exemplos práticos

Checklist mínimo antes da próxima aula:

[ ] products criada com CHECK em price_cents
[ ] 15–20 INSERTs executados sem erro
[ ] ≥3 categorias distintas
[ ] ≥5 produtos com acento ou cedilha
[ ] ≥3 descrições com expressão composta (prep. "de"/"a")
[ ] tags preenchidas (não vazias) na maioria das linhas

Consulta de sanidade:

SELECT COUNT(*) AS total,
       SUM(CASE WHEN tags = '' THEN 1 ELSE 0 END) AS sem_tags
FROM products;

Problemas e como resolver

Problema Causa Mitigação
Seed monolítico Só uma categoria Redistribuir nomes e tags
Busca sem acento falha depois Corpus só ASCII Incluir nomes acentuados de propósito
Frase nunca casa Só palavras soltas Escrever descrições com compostos reais
Preço inconsistente Misturar reais e centavos Padronizar price_cents

Resumo

O laboratório começa com products bem modelada e um seed deliberadamente diverso. Plurais, acentos e compostos não são “dados de enfeite”: são o material que prova se FTS5 e o tokenizer estão configurados corretamente. Na próxima aula, você cria a virtual table FTS5, triggers e consultas MATCH sobre esse catálogo.