MongoDB: primeiro documento, primeiro find
O dado precisa continuar existindo depois que o programa fecha, e é aí que entra o banco. O MongoDB guarda cada registro como um documento, no mesmo formato que o seu código já usa, e dois documentos da mesma coleção podem ter campos diferentes. Esta página existe pra você ver isso acontecer na tela.
O que o MongoDB resolve
Pense num cadastro de produto de loja. O teclado tem nome e preço. O monitor tem nome, preço, tamanho de tela, uma lista de etiquetas e um fornecedor com nome e cidade. Num banco de tabela você declara todas essas colunas antes, deixa quase todas vazias na linha do teclado, e cria uma segunda tabela só pro fornecedor.
Depois chega o produto que ninguém previu, com dois campos novos, e a tabela precisa mudar de forma pra caber ele. O MongoDB tira esse atrito do caminho: cada produto vira um documento com os campos que aquele produto tem, e a lista de etiquetas e o fornecedor moram dentro do próprio registro. A documentação oficial resume assim: por padrão, os documentos de uma coleção não compartilham esquema, e os campos e os tipos podem variar de um documento pro outro.
Os conceitos que você precisa antes da primeira linha
- Servidor e cliente. O servidor é o
mongod, que fica rodando em segundo plano e cuida dos arquivos em disco. O cliente é omongosh, a janela de terminal onde você digita comando. Quem não sobe omongodnão conecta omongoshem lugar nenhum. Por padrão o servidor escuta só em127.0.0.1, então nada disso fica exposto na rede. - Documento. O registro do MongoDB. Um conjunto de campos e valores, gravado num formato binário chamado BSON. Um valor pode ser texto, número, array, ou outro documento inteiro. É por isso que o fornecedor cabe dentro do produto sem precisar de outra coleção.
- Coleção e banco. A coleção guarda documentos e faz o papel que a tabela faz no banco relacional. O banco guarda coleções. Nenhum dos dois precisa ser criado antes: a documentação diz que, se a coleção não existe, o MongoDB cria ela na primeira vez que você grava dado nela.
- O campo
_id. Todo documento tem um. Ele identifica o documento dentro da coleção e não pode repetir. Se você não mandar um_id, o servidor cria o campo e põe umObjectIdúnico ali dentro. Você quase nunca vai digitar esse valor na mão. - Esquema flexível com validação opcional. Aceitar formatos diferentes é o comportamento padrão, e não uma obrigação. Você pode ligar regras de validação na coleção, e a partir daí o próprio banco recusa a gravação que não seguir a regra.
O banco por dentro: documentos, coleções e consultas por filtro
Aqui o dado não mora em tabela: mora em documentos, estruturas de campos e valores com a cara de um JSON, agrupados em coleções. Um documento pode ter lista dentro, objeto dentro de objeto, e dois documentos da mesma coleção podem ter campos diferentes.
- Tipos dentro do documento: texto, número, booleano, data, lista, objeto aninhado e o
ObjectId, o identificador que o banco gera no campo_idde todo documento. - Sem esquema imposto não é sem modelagem: o banco aceita qualquer formato, então a disciplina do formato passa a ser sua. A decisão central é embutir ou referenciar: o endereço dentro do cliente (junto, rápido de ler) ou em documento próprio apontado por id (normalizado, como no relacional).
- A consulta é um documento-filtro: você descreve o que procura na mesma forma do dado.
{ cidade: "Recife" }casa por igualdade, e operadores com cifrão refinam:{ saldo: { $gt: 100 } }é "maior que".
// no mongosh
db.clientes.insertOne({
nome: "Ana",
saldo: 150,
contatos: { email: "ana@exemplo.com" }, // objeto aninhado
tags: ["vip", "recife"] // lista no documento
});
db.clientes.find({ saldo: { $gt: 100 } }); // filtro com operador
db.clientes.updateOne(
{ nome: "Ana" },
{ $inc: { saldo: -50 } } // altera sem reescrever
);
Compare com o SQL da página do MySQL: são as mesmas quatro operações, com o filtro escrito como dado em vez de sentença. Entender os dois modelos é o que te deixa escolher, e a escolha é o assunto do estudo de SQL vs NoSQL.
Hello world: dois formatos na mesma coleção
O roteiro abaixo usa o servidor rodando na sua máquina e o mongosh, o cliente de linha de comando oficial. Nada de Compass, nada de painel na nuvem. A ideia é ver o banco sem intermediário.
-
Instale o MongoDB Community Server e o mongosh. A página oficial é Install MongoDB Community Edition.
- Ubuntu 24.04: os quatro comandos do manual, nesta ordem.
sudo apt install gnupg curl curl -fsSL https://pgp.mongodb.com/server-8.0.asc | \ sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg \ --dearmor echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.3 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-8.3.list sudo apt update sudo apt install -y mongodb-orgEm outra versão do Ubuntu, troque
noblepelo apelido da sua, e repare que a lista de apelidos aceitos é curta. Para a série 8.3 o repositório oficial publica três:noble(24.04),jammy(22.04) efocal(20.04). Baixamos o índice desses três caminhos em 15/08/2026 e os três trazem o pacotemongodb-org. Os apelidos mais novos não trazem:pluckyequestingrespondem 404, eresolute(Ubuntu 26.04) responde 200 com um pacote só no índice, omongodb-database-tools, semmongodb-orge semmongodb-mongosh. Quem está numa Ubuntu mais nova que a 24.04 aponta a linha do repositório paranobleou instala pelo tarball do Download Center. No Debian a linha do repositório é outra, e o manual traz ela na aba do Debian. - macOS: a instalação oficial é por Homebrew, e ela já traz o
mongoshjunto.brew tap mongodb/brew brew update brew install mongodb-community@8.3 - Windows: baixe o instalador
.msino Download Center e siga o assistente. Marque Install MongoD as a Service pra ele subir sozinho. Esse instalador não inclui omongosh, então instale o cliente à parte pela página de instalação do mongosh.
- Ubuntu 24.04: os quatro comandos do manual, nesta ordem.
-
Suba o servidor. No Linux com systemd:
sudo systemctl start mongod sudo systemctl status mongodNo macOS, rodando como serviço do Homebrew:
brew services start mongodb-community@8.3No Windows, o serviço já está de pé se você marcou a opção durante a instalação.
-
Abra o cliente. Sem argumento nenhum:
mongoshIsso equivale a
mongosh "mongodb://localhost:27017", porque 27017 é a porta padrão. Na linhaConnecting to:o shell escreve o endereço já resolvido,mongodb://127.0.0.1:27017, com alguns parâmetros de conexão colados no fim. Deu certo quando aparece o prompt do banco atual, algo comotest>.Antes do prompt, o
mongoshimprime um bloco de avisos de inicialização do servidor entre duas linhas de tracinhos. Num servidor recém-instalado e sem senha, o aviso que sempre aparece éAccess control is not enabled for the database, e ele vem acompanhado de recados sobre sistema de arquivos, alocador de memória e swappiness. São avisos, e o prompt aparece logo abaixo deles. -
Escolha o banco.
use lojaO prompt vira
loja>. Em disco ainda não existe banco nenhum, e ele nasce na primeira gravação. -
Grave o primeiro produto. Dois campos, e mais nada.
db.produto.insertOne({ nome: "teclado", preco: 120 })A resposta vem com
acknowledged: truee uminsertedIdcom oObjectIdque o servidor acabou de criar pra você. -
Grave o segundo produto, com outro formato. Três campos a mais, um deles array e outro um documento inteiro.
db.produto.insertOne({ nome: "monitor", preco: 890, polegadas: 27, etiquetas: ["IPS", "27 polegadas"], fornecedor: { nome: "ACME", cidade: "Araraquara" } })Digitando ou colando esse bloco em várias linhas, o
mongoshtroca o prompt por|enquanto as chaves seguem abertas, e roda o comando quando você fecha o parêntese na última linha. -
Confira o que existe no banco.
show collections db.produto.countDocuments() -
Leia a coleção inteira.
db.produto.find()Agora leia com filtro, pedindo só o que custa mais de 500:
db.produto.find({ preco: { $gt: 500 } }) -
Saia, volte e leia de novo.
exitmongosh use loja db.produto.find()
find() sem filtro tem que imprimir dois documentos com formatos diferentes, um embaixo do outro. O teclado sai com três campos (_id, nome, preco) e o monitor sai com seis, com as etiquetas entre colchetes e o fornecedor entre chaves, aninhado dentro do produto. Nenhum dos dois ganhou campo vazio pra ficar igual ao outro, e nenhum comando reclamou de coluna que não existe. Os dois trazem um _id com um ObjectId que você nunca digitou, e o countDocuments() responde 2. O find() com filtro devolve só o monitor. Depois de sair e voltar, a mesma leitura repete os mesmos dois documentos, porque quem guardou foi o servidor e o cliente que você fechou era só a janela. Se voltar vazio, você está em outro banco: digite db pra ver em qual você caiu e refaça o use loja.Uma coisa pra reparar antes de sair
O find() devolve um cursor, e o mongosh percorre esse cursor sozinho até mostrar os 20 primeiros documentos. Com dois documentos você nem percebe. Numa coleção grande, o shell mostra os 20 e espera você digitar it pra continuar. Quem não sabe disso conta 20 linhas na tela e acha que a coleção tem 20 registros.
O que o MongoDB não é
MongoDB não é um banco sem esquema. Essa é a confusão que mais atrapalha quem chega vindo do SQL. O que o manual chama de modelo flexível é o padrão da coleção, que aceita documentos de formatos diferentes. O esquema continua existindo, e ele mora no seu código: alguma parte do programa espera preco como número e vai quebrar no dia em que alguém gravar "890" como texto.
O próprio MongoDB oferece o remédio. A validação de esquema deixa você declarar regra de campo e de tipo na coleção, e a partir dali o servidor recusa por padrão qualquer inserção ou atualização que produza documento inválido. Quem começa um projeto sério liga isso cedo.
A mesma confusão vira a frase "MongoDB não tem transação". Operação em um documento é atômica desde sempre, e a documentação diz que o banco suporta transação em várias operações, coleções, bancos, documentos e shards. A ressalva é de topologia: a transação é recurso de replica set e de cluster shardado, então o servidor único que você acabou de instalar aqui roda sem ela.
Fontes
- MongoDB Manual, "Databases and Collections", de onde saem a criação da coleção na primeira gravação e a frase de que, por padrão, os documentos de uma coleção não compartilham esquema. Conferida em 15/08/2026.
- MongoDB Manual,
db.collection.insertOne(), origem do formato da resposta comacknowledgedeinsertedId, e da regra doObjectIdgerado quando o documento chega sem_id. Conferida em 15/08/2026. - MongoDB Manual,
db.collection.find(), onde estão o cursor, os 20 documentos que omongoshmostra sozinho e oitpra continuar. Conferida em 15/08/2026. - MongoDB Manual, "Query Documents" e operador
$gt, modelo do filtro usado no passo 8. Conferidas em 15/08/2026. - MongoDB Manual, "Schema Validation", origem do trecho sobre o modelo flexível e sobre a recusa padrão de documento inválido. Conferida em 15/08/2026.
- MongoDB Manual, "Transactions", de onde vêm a atomicidade do documento único, o suporte a transação em várias coleções e a exigência de replica set ou cluster shardado. Conferida em 15/08/2026.
- MongoDB Manual, "Install MongoDB Community Edition", origem literal dos comandos de instalação do Ubuntu e do macOS, do passo do instalador no Windows e do
systemctl start mongod. Em 15/08/2026 a página trazia a série 8.3 como release atual do Community. Conferida em 15/08/2026. - mongosh, "Connect to a Deployment" e "Run Commands", de onde vêm o
mongoshsem argumento apontando pramongodb://localhost:27017, ousee oexit. Conferidas em 15/08/2026.
Rodamos este roteiro em 15/08/2026, numa Ubuntu 26.04 sem acesso de root, com os tarballs oficiais do Download Center: MongoDB Community Server 8.3.8 (mongodb-linux-x86_64-ubuntu2404-8.3.8.tgz) e mongosh 2.10.0. Como o systemctl do passo 2 pede root, subimos o servidor pelo binário, com mongod --dbpath dbpath --port 27099, e conectamos com mongosh --port 27099. Antes disso rodamos o mongosh sem argumento, como manda o passo 3, e ele confirmou a porta padrão ao responder MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017. Os comandos dos passos 4 a 9 saíram desta página sem nenhuma edição. O use loja respondeu switched to db loja, os dois insertOne responderam acknowledged: true com insertedId: ObjectId('6a8042c7b4f95495f6ba4007') e ObjectId('6a8042c8b4f95495f6ba4008'), o show collections respondeu produto e o countDocuments() respondeu 2. O find() sem filtro imprimiu o teclado com três campos e o monitor com seis, incluindo etiquetas: [ 'IPS', '27 polegadas' ] e fornecedor: { nome: 'ACME', cidade: 'Araraquara' } aninhado dentro do produto. O find() com $gt: 500 devolveu só o monitor. Fechado o shell e aberto outro, a mesma leitura repetiu os dois documentos e o mesmo 2. O passo 1, de instalação por apt, foi conferido pelo índice do repositório oficial em vez de executado, porque a máquina não tem root, e foi de lá que saiu o aviso sobre os apelidos de Ubuntu.
Para continuar
A comparação que mais ensina é com quem resolve o mesmo problema pelo caminho da tabela. PostgreSQL cobra tipo e restrição na hora de gravar, e MySQL é o que você mais vai encontrar em vaga e em hospedagem barata. Rode o hello world dos três e repare no que cada um exige antes de aceitar a primeira linha. Os três estão no mapa da stack web, junto com as linguagens que vão conversar com eles.
O curso desta trilha está em preparação. A lista paga menos.
Os tutoriais daqui continuam gratuitos. O que está a caminho é um curso pago que transforma esse mapa em formação guiada, na ordem certa e com projeto. Deixe seu e-mail: você recebe os estudos novos gratuitos e, no lançamento, o desconto de quem entrou na lista primeiro.