← Stack web // stack web · back end · banco de dados

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 é o mongosh, a janela de terminal onde você digita comando. Quem não sobe o mongod não conecta o mongosh em lugar nenhum. Por padrão o servidor escuta só em 127.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 um ObjectId ú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 _id de 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.

  1. 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-org

      Em outra versão do Ubuntu, troque noble pelo 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) e focal (20.04). Baixamos o índice desses três caminhos em 15/08/2026 e os três trazem o pacote mongodb-org. Os apelidos mais novos não trazem: plucky e questing respondem 404, e resolute (Ubuntu 26.04) responde 200 com um pacote só no índice, o mongodb-database-tools, sem mongodb-org e sem mongodb-mongosh. Quem está numa Ubuntu mais nova que a 24.04 aponta a linha do repositório para noble ou 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 mongosh junto.
      brew tap mongodb/brew
      brew update
      brew install mongodb-community@8.3
    • Windows: baixe o instalador .msi no Download Center e siga o assistente. Marque Install MongoD as a Service pra ele subir sozinho. Esse instalador não inclui o mongosh, então instale o cliente à parte pela página de instalação do mongosh.
  2. Suba o servidor. No Linux com systemd:

    sudo systemctl start mongod
    sudo systemctl status mongod

    No macOS, rodando como serviço do Homebrew:

    brew services start mongodb-community@8.3

    No Windows, o serviço já está de pé se você marcou a opção durante a instalação.

  3. Abra o cliente. Sem argumento nenhum:

    mongosh

    Isso equivale a mongosh "mongodb://localhost:27017", porque 27017 é a porta padrão. Na linha Connecting 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 como test>.

    Antes do prompt, o mongosh imprime 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.

  4. Escolha o banco.

    use loja

    O prompt vira loja>. Em disco ainda não existe banco nenhum, e ele nasce na primeira gravação.

  5. Grave o primeiro produto. Dois campos, e mais nada.

    db.produto.insertOne({ nome: "teclado", preco: 120 })

    A resposta vem com acknowledged: true e um insertedId com o ObjectId que o servidor acabou de criar pra você.

  6. 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 mongosh troca o prompt por | enquanto as chaves seguem abertas, e roda o comando quando você fecha o parêntese na última linha.

  7. Confira o que existe no banco.

    show collections
    db.produto.countDocuments()
  8. 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 } })
  9. Saia, volte e leia de novo.

    exit
    mongosh
    use loja
    db.produto.find()
A prova de que funcionou. O 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

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.