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.
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
$textetextScore - 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.