Visão geral
Mongoose é uma biblioteca de Modelagem de Dados de Objetos (ODM) para MongoDB. Você pode usar o Mongoose para ajudar na modelagem de dados, aplicação de esquemas, validação de modelos e manipulação geral de dados. Como o MongoDB tem um modelo de dados flexível que permite alterar e atualizar bancos de dados no futuro, não há esquemas rígidos. No entanto, o Mongoose impõe um esquema semirrígido desde o início, então você deve definir um esquema e modelo.
Schemas
Um esquema define a estrutura dos documentos da sua coleção. Um esquema Mongoose é mapeado diretamente para uma coleção MongoDB.
O exemplo a seguir cria um novo esquema denominado blog
:
const blog = new Schema({ title: String, slug: String, published: Boolean, author: String, content: String, tags: [String], comments: [{ user: String, content: String, votes: Number }] }, { timestamps: true });
Ao criar um esquema, você deve definir cada campo e seus tipos de dados. Os seguintes tipos são permitidos:
String
Número
Data
Buffer
Boolean
Misto
ObjectId
Array
Int32
Decimal128
Double
Map
Modelos
Os modelos pegam seu esquema e o aplicam a cada documento em sua coleção. Os modelos são responsáveis por todas as interações de documento , como operações de criação, leitura, atualização e exclusão (CRUD).
Dica
O primeiro argumento que você passa para o modelo é a forma singular do nome da sua coleção. O Mongoose altera automaticamente isso para o plural, transforma em minúsculas e usa isso para o nome da coleção de banco de dados .
O exemplo seguinte mostra como declarar um modelo denominado Blog
que utiliza o esquema blog
:
const Blog = mongoose.model('Blog', blog);
No exemplo anterior , Blog
se traduz na collection blogs
no MongoDB.
Tutorial
Neste tutorial, você executará as seguintes ações:
Configure seu ambiente para usar o Mongoose
Conecte-se ao MongoDB
Criar um esquema e modelo Mongoose
Inserir, atualizar, localizar e excluir dados
Campos do documento do projeto
Validar seus dados
Usar vários esquemas e middleware
Verifique os pré-requisitos
Antes de iniciar este tutorial, verifique se você tem os seguintes componentes preparados:
Uma conta do MongoDB Atlas com um cluster configurado. Para visualizar instruções, consulte o guia Introdução ao Atlas.
Node.js v16.20.1 ou mais tarde.
Configure seu ambiente
Este tutorial usa nodemon para executar o código localmente. Execute os seguintes comandos no seu terminal para inicializar seu projeto e instalar as dependências necessárias:
mkdir mongodb-mongoose cd mongodb-mongoose npm init -y npm i mongoose npm i -D nodemon
Abra seu projeto no editor de código de sua preferência. Este tutorial usa módulos ES em vez de CommonJS. Você deve adicionar o tipo module
para usar os módulos ES. Vá para o arquivo package.json
e adicione o seguinte código:
... "scripts": { "dev": "nodemon index.js" }, "type": "module", ...
Inicie seu aplicação com nodemon
executando o seguinte comando:
npm run dev
Observação
Quando você usa nodemon, o código é executado toda vez que você salva um arquivo.
Conecte-se ao MongoDB
No nível raiz do seu projeto, crie um arquivo denominado index.js
e adicione o seguinte código ao topo do arquivo:
import mongoose from 'mongoose'; mongoose.connect("<connection string>")
Substitua o placeholder <connection string>
pela string de conexão do MongoDB Atlas . Para mais informações sobre como localizar sua string de conexão, consulte o tutorial Connect to Your Cluster na documentação do Atlas.
Criar um esquema e um modelo
Antes de começar a adicionar e atualizar dados no MongoDB, você deve criar um esquema e um modelo.
Com o Mongoose, você cria um arquivo de modelo de esquema para cada esquema necessário. Primeiro, crie uma pasta chamada model
para colocar todos os seus arquivos de esquema e, em seguida, crie seu primeiro arquivo de esquema chamado Blog.js
. Abra este arquivo e adicione o seguinte código:
import mongoose from 'mongoose'; const { Schema, model } = mongoose; const blogSchema = new Schema({ title: String, slug: String, published: Boolean, author: String, content: String, tags: [String], comments: [{ user: String, content: String, votes: Number }] }, { timestamps: true }); const Blog = model('Blog', blogSchema); export default Blog;
Esse esquema habilita uma opção timestamps
, que adiciona campos createdAt
e updatedAt
gerenciados por mongoose ao esquema que são atualizados automaticamente. Para obter mais informações, consulte a página Registros de data e hora na documentação do Mongoose.
Realizar operações CRUD
Agora você tem seu primeiro modelo e esquema configurados e pode começar a inserir dados no banco de dados. As seções a seguir mostram como realizar operações CRUD usando o Mongoose.
Insert Data
Vá para index.js
e adicione a seguinte declaração de importação ao topo do seu arquivo:
import Blog from './model/Blog.js';
Adicione o seguinte código abaixo da linha que contém sua string de conexão:
// Creates a new blog post and inserts it into database const article = await Blog.create({ title: 'Awesome Post!', slug: 'awesome-post', published: true, content: 'This is the best post ever', tags: ['featured', 'announcement'], }); console.log('Created article:', article);
O código anterior usa o método create()
do Mongoose para instanciar o objeto que representa um artigo de blog e, em seguida, salvá-lo no banco de dados. Os registros do documento retornados no console, incluindo seu _id
. Anote este _id
para uso em etapas futuras.
Atualizar dados
Para atualizar dados, você pode editar diretamente o objeto local com o Mongoose. Em seguida, você pode usar o método save()
para escrever a atualização no banco de dados.
Adicione o seguinte código para atualizar o artigo inserido na seção anterior:
// Updates the title of the article article.title = "The Most Awesomest Post!!"; await article.save(); console.log('Updated Article:', article);
Updated Article: { title: 'The Most Awesomest Post!!', slug: 'awesome-post', published: true, content: 'This is the best post ever', tags: [ 'featured', 'announcement' ], _id: new ObjectId('...'), comments: [], __v: 0 }
Encontrar dados
Para localizar um documento específico, você pode usar o método Mongoose findById()
para consultar um documento especificando seu _id
.
Adicione o seguinte código ao seu arquivo index.js
para encontrar um artigo específico pelo _id
:
// Finds the article by its ID. Replace <object id> with the objectId of the article. const articleFound = await Blog.findById("<object id>").exec(); console.log('Found Article by ID:', articleFound);
Found Article by ID: { _id: new ObjectId('68261c9dae39e390341c367c'), title: 'The Most Awesomest Post!!', slug: 'awesome-post', published: true, content: 'This is the best post ever', tags: [ 'featured', 'announcement' ], comments: [], __v: 0 }
Observação
Por padrão, as queries do Mongoose retornam theables, que são objetos com algumas propriedades de uma JavaScript Promise. Você pode anexar o método exec()
a uma query para receber uma verdadeira JavaScript Promise. Para saber mais sobre como trabalhar com promessas no Mongoose, consulte o guia Promises na documentação do Mongoose.
Especifique campos do documento
Você pode usar o Mongoose para projeto somente os campos necessários. O seguinte código especifica para projeto somente os campos title
, slug
e content
.
Adicione o seguinte código ao seu arquivo index.js
, substituindo o espaço reservado <object
id>
pelo valor ObjectId
para o documento inserido anteriormente:
// Finds the article by its ID and projects only the title, slug, and content fields. // Replace <object id> with the objectId of the article. const articleProject = await Blog.findById("<object id>", "title slug content").exec(); console.log('Projected Article:', articleProject);
Projected Article: { _id: new ObjectId('...'), title: 'The Most Awesomest Post!!', slug: 'awesome-post', content: 'This is the best post ever' }
Excluir dados
O Mongoose utiliza os métodos deleteOne()
e deleteMany()
para excluir dados de uma coleção. Você pode especificar o campo do documento que deseja excluir e passar esse campo para o método escolhido.
Adicione o seguinte código ao seu arquivo index.js para excluir um artigo do banco de dados:
// Deletes one article with the slug "awesome-post". const blogOne = await Blog.deleteOne({ slug: "awesome-post" }); console.log('Deleted One Blog:', blogOne);
Deleted One Blog: { acknowledged: true, deletedCount: 1 }
Para excluir vários artigos, você pode adicionar o seguinte código:
// Deletes all articles with the slug "awesome-post". const blogMany = await Blog.deleteMany({ slug: "awesome-post" }); console.log('Deleted Many Blogs:', blogMany);
Deleted Many Blogs: { acknowledged: true, deletedCount: 4 }
Validar seus dados
Os artigos inseridos nas etapas anteriores não contêm os campos author
, dates
ou comments
, embora esses campos estejam incluídos no esquema. Isso ocorre porque, embora você tenha definido a estrutura do documento, não definiu quais campos são obrigatórios. Qualquer campo que não seja definido como obrigatório pode ser omitido.
No Mongoose, quando você inclui a validação em um campo, você deve passar um objeto como seu valor.
Observação
Os validadores são executados automaticamente nos métodos create()
e save()
. Você pode especificá-los para executá-los em métodos de atualização, como update()
e updateOne()
, definindo a opção runValidators
como true
. Para obter mais informações sobre validadores, consulte a página Validação na documentação do Mongoose.
Você pode usar vários métodos de validação com o Mongoose. Por exemplo, você pode definir required
como true em quaisquer campos que queira exigir. Você também pode validar o tipo e a formatação. No código a seguir, o campo slug
é definido como string
com minLength
de 4
. Isso significa que fornecer um slug
com menos de 4 caracteres resultará em um ValidationError
.
Para adicionar validação de dados e definir esses requisitos, atualize o esquema em Blog.js
conforme mostrado no exemplo a seguir :
const blogSchema = new Schema({ title: { type: String, required: true, }, slug: { type: String, required: true, minLength: 4, }, published: { type: Boolean, default: false, }, author: { type: String, required: true, }, content: String, tags: [String], comments: [{ user: String, content: String, votes: Number }] }, { timestamps: true });
Depois de adicionar essa validação, seu aplicação falhará. Adicione um campo author
à chamada create()
em seu arquivo index.js
para atender ao novo requisito de validação:
// Creates a new blog post and inserts it into database const article = await Blog.create({ title: 'Awesome Post!', slug: 'awesome-post', published: true, author: 'A.B. Cee', content: 'This is the best post ever', tags: ['featured', 'announcement'], });
Dica
Quando você usa esquemas com Mongoose, value: String
é o mesmo que value: {type: String}
.
Para obter mais informações, consulte a página Validação na documentação do Mongoose.
Introduzir vários esquemas
Em seguida, você pode adicionar mais complexidade ao seu campo author
criando um outro esquema e aninhando-o no esquema de blog.
Na pasta model
, crie um novo arquivo denominado User.js
. Adicione o seguinte código a este arquivo:
import mongoose from 'mongoose'; const {Schema, model} = mongoose; const userSchema = new Schema({ name: { type: String, required: true, }, email: { type: String, minLength: 10, required: true, lowercase: true }, }); const User = model('User', userSchema); export default User;
Para utilizar seu novo modelo de usuário para definir o campo author
no esquema do blog, atualize o arquivo Blog.js
com as seguintes alterações:
Adicione
SchemaTypes
à lista de propriedades extraídas da biblioteca Mongoose.Altere o campo
author
type
paraSchemaTypes.ObjectId
e adicione uma referência (ref
) ao modelo'User'
.
O seguinte código mostra essas atualizações:
const { Schema, SchemaTypes, model } = mongoose; ... // Inside Schema block: author: { type: SchemaTypes.ObjectId, ref: 'User', required: true, }, ...
Você pode reutilizar o mesmo modelo User
para o campo comment.user
alterando a definição blogSchema
:
... // Inside Schema block: comments: [{ user: { type: SchemaTypes.ObjectId, ref: 'User', required: true, }, ...
Para usar o novo modelo de usuário em seu aplicação, acesse o arquivo index.js
. Adicione o seguinte código ao topo do arquivo para importar o modelo de usuário:
import User from './model/User.js';
Como você adicionou a validação de campo ao esquema de blog, o código anterior para inserir, atualizar e excluir blogs e especificar campos para projeto, não passará na validação e o aplicação apresentará erro.
Crie um novo usuário adicionando a seguinte chamada create()
:
// Create a new user const user = await User.create({ name: 'Jess Garica', email: 'jgarcia@email.com', });
Atualize a chamada create()
existente com o seguinte código para criar um novo artigo que use o novo usuário como autor, conforme mostrado no código a seguir:
// Creates a new blog post that references the user as the author const articleAuthor = await Blog.create({ title: 'Awesome Post!', slug: 'Awesome-Post', author: user._id, content: 'This is the best post ever', tags: ['featured', 'announcement'], }); console.log('Article with Author:', articleAuthor);
Article with Author: { title: 'Awesome Post!', slug: 'awesome-post', published: false, author: new ObjectId('...'), content: 'This is the best post ever', tags: [ 'featured', 'announcement' ], _id: new ObjectId('...'), createdAt: 2025-05-15T18:05:23.780Z, comments: [], __v: 0 }
O código anterior adiciona uma coleção users
com a coleção blogs
no banco de dados MongoDB . Este código adiciona o campo author
exigido e define seu valor para user._id
.
Para adicionar os valores dos campos name
e email
ao campo author
do artigo, você pode anexar o método Mongoose populate()
à sua query do Blog. O método populate()
executará uma segunda query para o documento do usuário referenciado por user._id
.
Adicione o seguinte código ao index.js
para preencher estes dados:
// Populates the author field with user data const articlePopulate = await Blog.findOne({ title: "Awesome Post!" }).populate("author"); console.log('Article Populated:', articlePopulate);
Article Populated: { _id: new ObjectId('...'), title: 'Awesome Post!', slug: 'awesome-post', published: false, author: { _id: new ObjectId('...'), name: 'Jess Garica', email: 'jgarcia@email.com', __v: 0 }, content: 'This is the best post ever', tags: [ 'featured', 'announcement' ], createdAt: 2025-05-15T18:04:28.590Z, comments: [], __v: 0 }
Para obter mais informações, consulte o Document.populate() página da documentação da API Mongoose.
Adicionar middleware
No Mongoose, middleware são funções executadas antes ou durante a execução de funções assíncronas no nível do esquema.
Um exemplo de middleware é uma função que valida o campo email
de uma instância User
antes de salvar ou atualizar.
Este exemplo utiliza o pacote validator
. Você pode instalar o pacote validator
executando o seguinte comando:
npm install validator
Para adicionar essa função de middleware, adicione o seguinte código à declaração userSchema
em seu arquivo User.js
:
import validator from 'validator';
userSchema.pre('save', function (next) { const user = this; // Normalize email if (user.email) { user.email = user.email.trim().toLowerCase(); } // Validate email format if (!validator.isEmail(user.email)) { return next(new Error('Invalid email format')); } next(); });
Para ver o efeito dessa função, modifique o campo user.email
em seu arquivo index.js
para torná-lo um endereço de e-mail inválido:
const user = await User.create({ name: 'Jess Garica', email: 'jgarciaemail.com', });
Error: Invalid email format
Se você corrigir o endereço de e-mail, poderá ver que o erro não será gerado.
Além da função de middleware pre()
, o Mongoose também oferece uma função de middleware post()
. Para obter mais informações sobre middleware, consulte a página Middleware na documentação do Mongoose.
Próximos passos
Agora você tem um projeto de amostra que usa o Mongoose para executar operações CRUD em uma collection do MongoDB . A partir daqui, você pode optar por construir neste projeto com queries mais complexas ou validação de documento . As seções a seguir incluem alguns exemplos de recursos do Mongoose que você pode usar em seu aplicação.
Setters personalizados do Mongoose
Os setters personalizados modificam seus dados quando eles são salvos e podem ser implementados de forma semelhante aos validadores. O Mongoose fornece os seguintes configuradores personalizados:
lowercase
uppercase
trim
O exemplo a seguir coloca os caracteres no campo blog.slug
em minúsculas :
const blogSchema = new Schema({ ... slug: { type: String, required: true, minLength: 4, lowercase: true, }, ... });
Para obter mais informações, consulte a página SchemaStringOptions na documentação da API Mongoose.
Métodos de ajuda
O Mongoose inclui vários métodos assistente que são abstraídos dos métodos regulares do MongoDB . Nesta seção, você pode encontrar exemplos de alguns desses métodos. Esses métodos não são usados especificamente neste tutorial, mas são úteis para fazer referência ao começar a usar o Mongoose.
exists()
O método exists()
retorna null
ou o primeiro documento que corresponde à query fornecida. O seguinte é um exemplo de correspondência de um artigo com base no campo author
:
const blog = await Blog.exists({ author: 'Jess Garcia' }); console.log(blog);
Para obter mais informações, consulte o Model.exists() seção da documentação da API Mongoose.
where()
O método where()
permite encadear e criar query complexas.
O seguinte é um exemplo de executar uma operação de localizar utilizando findOne()
com um objeto de consulta simples e a consulta equivalente com o método where()
:
const blogFind = await Blog.findOne({ author: "Jess Garcia" }); console.log(blogFind); const blogWhere = await Blog.findOne().where("author").equals("Jess Garcia"); console.log(blogWhere);
Nesta implementação, a implementação do where()
começa com um findOne()
que informa ao Mongoose para tratá-la como uma query do findOne()
. Isso é importante porque, se você usar where()
sozinho (Blog.where(...)
), o Mongoose implicitamente o tratará como uma operação find()
.
Geralmente, o método where()
é usado para queries complexas que envolvem a criação de queries dinâmicas ou vários comparadores, ou quando o uso desse método melhora a legibilidade. Não há diferença de desempenho entre utilizar o método where()
ou uma query de objeto simples.
Para incluir projeção ao usar o método where()
, encadeie o método select()
após a query, conforme mostrado no exemplo a seguir:
const blog = await Blog.findOne().where("author").equals("Jess Garcia").select("title author"); console.log(blog);
Para obter mais informações, consulte as seguintes seções da documentação da API do Mongoose:
Recursos adicionais
Para saber mais sobre como usar o Mongoose com o MongoDB, consulte a documentação do Mongoose.
Para encontrar suporte ou contribuir para a comunidade MongoDB, consulte a página Comunidade de desenvolvedores do MongoDB.