Criando uma aplicação CRUD em Mongoose com Node.js
Vamos examinar como realizar as operações básicas de dados em Mongoose.
Criando Documentos
Em tópicos anteriores, descrevemos de forma geral como criar e adicionar objetos no Mongoose. Especificamente, podemos chamar o método save()
no objeto do modelo:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema({
name: String,
age: Number,
});
const User = mongoose.model("User", userSchema);
async function main() {
await mongoose.connect("mongodb://127.0.0.1:27017/usersdb");
const tom = new User({ name: "Tom", age: 34 });
// adicionando objeto ao banco de dados
await tom.save();
console.log(tom);
}
main()
.catch(console.log)
.finally(async () => await mongoose.disconnect());
Além desse método, também podemos usar o método User.create()
:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema({
name: String,
age: Number,
});
const User = mongoose.model("User", userSchema);
async function main() {
await mongoose.connect("mongodb://127.0.0.1:27017/usersdb");
// adicionando objeto ao banco de dados
const user = await User.create({ name: "Sam", age: 28 });
console.log(user);
}
main()
.catch(console.log)
.finally(async () => await mongoose.disconnect());
O método User.create()
recebe o objeto a ser salvo como parâmetro e retorna o objeto salvo.
Obtendo Dados
Para obter dados, podemos usar uma série de métodos:
find
: retorna todos os objetos que correspondem ao critério de filtro.findById
: retorna um objeto pelo valor do campo_id
.findOne
: retorna um objeto que corresponde ao critério de filtro.
O método find()
aceita como primeiro parâmetro o critério de filtro e, como segundo parâmetro, uma função de callback para os documentos obtidos do banco de dados:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema({ name: String, age: Number });
const User = mongoose.model("User", userSchema);
async function main() {
await mongoose.connect("mongodb://127.0.0.1:27017/usersdb");
// obtendo todos os objetos do banco de dados
const users = await User.find({});
console.log(users);
}
main()
.catch(console.log)
.finally(async () => await mongoose.disconnect());
Se o critério de filtro for um objeto vazio ({})
, todos os objetos serão retornados:
[
{
_id: "6377c17b71c0bd75cec4d488",
name: "Bill",
age: 41,
__v: 0,
},
{
_id: "6377c7a46fa33e19ac7a7c41",
name: "Tom",
age: 34,
__v: 0,
},
{
_id: "6377ce352461051cdc78252a",
name: "Sam",
age: 28,
__v: 0,
},
];
Vamos alterar o código para obter apenas os usuários cujo nome seja "Tom":
const users = await User.find({ name: "Tom" });
O método findOne()
funciona de maneira semelhante ao método find, mas retorna um único objeto:
const user = await User.findOne({ name: "Bill" });
E o método findById()
retorna o documento com um identificador específico:
const id = "6377c7a46fa33e19ac7a7c41";
const user = await User.findById(id);
Removendo Dados
Para remoção, usamos os métodos deleteOne()
(remove um objeto) e deleteMany()
(remove todos os objetos que correspondem ao critério). Esses métodos aceitam um critério de filtro dos documentos a serem removidos. Por exemplo, vamos remover todos os usuários com idade igual a 41:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema({ name: String, age: Number });
const User = mongoose.model("User", userSchema);
async function main() {
await mongoose.connect("mongodb://127.0.0.1:27017/usersdb");
// removendo todos os objetos do banco de dados com age=41
const result = await User.deleteMany({ age: 41 });
console.log(result);
}
main()
.catch(console.log)
.finally(async () => await mongoose.disconnect());
O método User.deleteMany()
retorna um objeto contendo informações sobre a operação de remoção:
{ "acknowledged": true, "deletedCount": 1 }
O método deleteOne()
para remover um único documento é semelhante:
const result = await User.deleteOne({ name: "Tom" });
console.log(result); // { "acknowledged": true, "deletedCount": 1 }
Para remover um único documento, também podemos usar o método findOneAndDelete()
:
const user = await User.findOneAndDelete({ name: "Sam" });
console.log(user);
Esse método retorna o documento removido:
{ "_id": "6377bca2d16bfca92631cc10", "name": "Sam", "age": 28 }
A versão específica desse método para remoção pelo campo _id
é o método findByIdAndDelete()
:
const id = "6377c72806fb915eb6621ffd";
const user = await User.findByIdAndDelete(id);
console.log(user);
Atualizando Dados
Para atualizar dados no modelo, utilizamos os métodos updateOne()
e updateMany()
. O primeiro método atualiza um documento que corresponde ao critério, enquanto o segundo atualiza todos os documentos que correspondem ao critério de seleção:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema({ name: String, age: Number });
const User = mongoose.model("User", userSchema);
async function main() {
await mongoose.connect("mongodb://127.0.0.1:27017/usersdb");
// Alterando o valor do campo name de "Tom" para "Tom Smith" em todos os documentos
const result = await User.updateOne({ name: "Tom" }, { name: "Tom Smith" });
console.log(result);
}
main()
.catch(console.log)
.finally(async () => await mongoose.disconnect());
O primeiro parâmetro do método é o critério de filtro. Nesse caso, encontramos todos os usuários com nome "Tom". O segundo parâmetro descreve as alterações a serem feitas. Aqui, estamos mudando o nome para "Tom Smith". O método retorna o resultado da operação de atualização:
{ "acknowledged": true, "modifiedCount": 1, "upsertedId": null, "upsertedCount": 0, "matchedCount": 1 }
O método updateMany
funciona de maneira semelhante.
Atualizando pelo ID
Frequentemente, usamos a filtro pelo _id
para atualizações. Para isso, podemos usar o método findByIdAndUpdate()
:
const id = "6377ce352461051cdc78252a";
const user = await User.findByIdAndUpdate(id, { name: "Sam", age: 25 });
console.log(user);
O primeiro parâmetro é o valor do campo _id
do documento a ser atualizado, e o segundo é um conjunto de novos valores para os campos do objeto. O resultado do método é o documento atualizado:
{
"_id": "6377ce352461051cdc78252a",
"name": "Sam",
"age": 28,
"__v": 0
}
Por padrão, é retornado o estado antigo do documento. Se precisarmos do documento no estado atualizado, passamos um terceiro parâmetro ao método findByIdAndUpdate
, com {new: true}
(com valor false
, a cópia antiga é retornada):
const id = "6377ce352461051cdc78252a";
const user = await User.findByIdAndUpdate(id, { name: "Mike", age: 21 }, { new: true });
console.log("Objeto atualizado", user);
Se precisamos atualizar e retornar o documento atualizado não apenas pelo ID, mas por qualquer critério, podemos usar o método findOneAndUpdate
:
const user = await User.findOneAndUpdate({ name: "Mike" }, { name: "Alex", age: 24 }, { new: true });
console.log("Objeto atualizado", user);
O primeiro parâmetro representa o critério de seleção. O segundo parâmetro representa os valores atualizados do documento. O terceiro parâmetro indica que queremos retornar a versão do documento após a atualização, {new: true}
. O resultado do método é o documento atualizado.