Full-Text em outros bancos e ecossistema

Índices de texto no MongoDB

text indexes, $text/$search, pesos, idioma e limites do text search nativo vs Atlas Search.

Intermediário 42 min 32 pontos Leitura 0%

Nesta aula você vai

  • Criar text indexes compostos e consultar com $text e textScore
  • Configurar pesos e idioma default_language / language_override
  • Reconhecer limites do text search nativo e quando migrar para Atlas Search

Índices de texto no MongoDB

Objetivos

Nesta aula você vai:

  • Criar text indexes compostos e consultar com $text e textScore
  • Configurar pesos e idioma (default_language / language_override)
  • Reconhecer limites do text search nativo e quando migrar para Atlas Search

Introdução

MongoDB oferece text indexes nativos para busca lexical em campos string. É o caminho rápido em self-hosted e em clusters pequenos. Em escala e relevância avançada, o caminho industrial no ecossistema Atlas é Atlas Search (Apache Lucene). Esta aula cobre o nativo com precisão e delimita a fronteira.

Conteúdo

Criando um text index

Um único text index por coleção (pode cobrir vários campos):

db.artigos.createIndex(
  { titulo: 'text', corpo: 'text', tags: 'text' },
  {
    name: 'artigos_text',
    weights: { titulo: 10, tags: 5, corpo: 1 },
    default_language: 'portuguese',
    language_override: 'idioma',
  }
);
  • weights: importância relativa no score.
  • default_language: stemming/stopwords (ex.: portuguese, english, none).
  • language_override: campo no documento que redefine o idioma por doc.

Wildcard text index (todos os campos string) existe, mas é caro e pouco seletivo — evite em produção sem necessidade clara.

Consulta $text

db.artigos.find(
  { $text: { $search: 'sqlite fts5', $language: 'portuguese' } },
  { score: { $meta: 'textScore' }, titulo: 1, resumo: 1 }
).sort({ score: { $meta: 'textScore' } }).limit(20);

Operadores na string $search:

  • termos: cloudflare workers
  • frase: "full text"
  • negação: sqlite -mysql

Combine com filtros de igualdade/range no mesmo find (o planner usa o text index + outros predicados):

db.artigos.find({
  status: 'publicado',
  $text: { $search: 'd1 edge' },
});

Aggregation e textScore

db.artigos.aggregate([
  { $match: { $text: { $search: 'bm25 ranking' } } },
  { $addFields: { score: { $meta: 'textScore' } } },
  { $sort: { score: -1 } },
  { $limit: 20 },
  {
    $project: {
      titulo: 1,
      score: 1,
      trecho: { $substrCP: ['$corpo', 0, 160] },
    },
  },
]);

Não há snippet/highlight nativos equivalentes ao FTS5 — highlights ricos são território do Atlas Search (highlight nas opções de $search).

Limites do text search nativo

Capacidade Text index Atlas Search
Stemming básico / idioma Sim Sim (analyzers ricos)
Frases / negação Sim Sim
Fuzzy, autocomplete, facetas Limitado/não Sim
Highlight de trechos Manual Nativo
Relevância afinável (Lucene) Básica Avançada
Vários índices de busca 1 text index Múltiplos search indexes

Sinais para migrar: autocomplete preditivo, sinônimos, facetas, fuzzy, multi-índice, ou relevância que o textScore não entrega.

$search vs $text

  • $text: operador de query do text index nativo.
  • $search: stage de aggregation do Atlas Search (não disponível no MongoDB Community da mesma forma).

Não confunda os dois em documentação ou código.

Exemplos práticos

// Setup
db.produtos.createIndex(
  { nome: 'text', descricao: 'text' },
  { weights: { nome: 8, descricao: 1 }, default_language: 'portuguese' }
);

db.produtos.insertMany([
  { nome: 'Curso D1 FTS5', descricao: 'Full-text na edge', status: 'ativo' },
  { nome: 'MongoDB text index', descricao: 'Busca lexical nativa', status: 'ativo' },
]);

// Busca ranqueada
db.produtos
  .find(
    { status: 'ativo', $text: { $search: 'full-text edge' } },
    { score: { $meta: 'textScore' }, nome: 1 }
  )
  .sort({ score: { $meta: 'textScore' } });
// API Node (driver)
const results = await col
  .find(
    { $text: { $search: query } },
    { projection: { score: { $meta: 'textScore' }, titulo: 1 } }
  )
  .sort({ score: { $meta: 'textScore' } })
  .limit(20)
  .toArray();

Problemas e como resolver

Problema Causa Mitigação
Erro ao criar 2º text index Limite de um por coleção Unificar campos no mesmo índice
Score irrelevante Pesos/idioma errados Ajustar weights e default_language
Sem highlight Limitação nativa Substring manual ou Atlas Search
$search falha no Community Stage Atlas-only Usar $text ou Atlas

Resumo

Text indexes + $text + textScore resolvem busca lexical básica no MongoDB com pesos e idioma. Para autocomplete, fuzzy, facetas e highlights de produto, planeje Atlas Search (ou motor externo). Próxima aula: Cassandra e o padrão Solr/OpenSearch.