Introduction
MongoDB is a popular NoSQL database, widely used for its flexibility and capacity to handle large volumes of data. In this article, we will explore four crucial operations in MongoDB: insert, find, update, and delete. We will also discuss the stages of an aggregate pipeline that offer powerful functionalities for data analysis and transformation.
MongoDB CRUD Operations
Create/Insert
To insert documents into a MongoDB collection, we use the command insertOne()
to add a single document or insertMany()
to add multiple documents.
insertOne
:
db.collection('users').insertOne({
name: "John Doe",
age: 30,
email: "john.doe@email.com"
});
insertMany
:
db.collection('users').insertMany([
{ name: "Ana Doe", age: 25, email: "ana.doe@email.com" },
{ name: "Carlos Mendes", age: 40, email: "carlos.mendes@email.com" }
]);
Read
To read documents, we use the command find(). The first argument is the filter, and the second argument is optional, allowing us to specify which fields will be returned in the query.
find
:
db.collection('users').find({ name: "John Doe" }, { name: 1, email: 1 });
Update
Update operations are performed using the methods updateOne() and updateMany(). You can also use operators like $set
, $inc
and $rename
, among others.
updateOne
:
db.collection('users').updateOne(
{ email: "john.doe@email.com" },
{ $set: { age: 31 } }
);
updateMany
:
const result = db.collection('users').updateMany(
{ age: { $gte: 30 } },
{ $inc: { age: 1 } }
);
Delete
To remove documents, we use the methods deleteOne()
and deleteMany()
.
deleteOne
:
db.collection('users').deleteOne({ email: "ana.doe@email.com" });
deleteMany
:
db.collection('users').deleteMany({ age: { $lt: 18 } });
Aggregate Pipeline
MongoDB offers an aggregation framework to perform more complex queries that can involve multiple stages linked in a pipeline. Here are some commonly used stages:
1. $match
Filters documents based on specified criteria.
db.collection('sales').aggregate([
{ $match: { status: "finished" } }
]);
2. $group
Groups documents based on a specific key, which can be a value of a field or a combination of fields. Operations performed inside a $group are called accumulators, some of which include $sum, $addToSet, and $first.
db.collection('sales').aggregate([
{
$group: {
_id: "$category",
totalSales: { $sum: "$value" },
sales: { $addToSet: '$$ROOT' }
}
}
]);
3. $project
Controls which fields are returned. In this stage, you choose which fields will appear and can add new columns with custom values, such as through multiplication. It is important to note that in this stage, you cannot have both projection 0 and 1 for the same field, except for the _id
.
db.collection('sales').aggregate([
{
$project: {
_id: 0,
category: 1,
priceWithTax: { $multiply: ["$price", 1.2] }
}
}
]);
4. $addFields
With this stage, you can add new fields or modify existing fields.
db.collection('sales').aggregate([
{
$addFields: {
priceWithTax: { $multiply: ["$price", 1.2] }
}
}
]);
5. $sort
Orders documents in ascending (1) or descending (-1) order.
db.collection('sales').aggregate([
{ $sort: { price: -1 } }
]);
6. $limit
and $skip
Control the pagination of results.
db.collection('sales').aggregate([
{ $sort: { price: -1 } },
{ $limit: 10 },
{ $skip: 20 }
]);
7. $unwind
The $unwind
operator decomposes an array field into individual documents, generating one document for each element in the array. For example, if your collection has 5 documents, and each document has an array field with 5 objects, the result will be 25 documents. Example in MongoDB Playground
db.collection('sales').aggregate([
{
"$unwind": {
"path": "$products",
"preserveNullAndEmptyArrays": true
}
}
]);
8. $switch
Allows returning results based on conditional evaluations.
db.collection('sales').aggregate([
{
"$project": {
"price_description": {
$switch: {
branches: [
{ case: { $gt: ["$price", 5] }, then: "greater than 5" },
{ case: { $lt: ["$price", 5] }, then: "less than 5" },
],
default: "unknown price"
}
}
}
}
]);
9. $map
, $filter
e $reduce
These are array manipulation operations, generally used inside $project or $addFields. Example in MongoDB Playground
db.collection('sales').aggregate([
{
"$project": {
products: {
"$map": {
"input": "$products",
"as": "product",
"in": {
"$concat": [
"$$product.name",
" - ",
{
"$toString": "$$product.price"
}
]
}
}
},
products_w_price_gte_10: {
"$filter": {
"input": "$products",
"as": "product",
"cond": {
"$gte": [
"$$product.price",
10
]
}
}
},
products_values: {
"$reduce": {
"input": "$products.price",
"initialValue": "",
"in": {
"$concat": [
"$$value",
{
"$cond": [
{
"$eq": [
"$$value",
""
]
},
"",
", "
]
},
{
"$toString": "$$this"
}
]
}
}
}
}
}
]);
10. $lookup
The $lookup
stage is used to search records in another collection based on a foreign key, similar to a JOIN in SQL. It can be used in a simple way by comparing two keys (localField
and foreignField
):
db.collection('sales').aggregate([
{
"$lookup": {
"from": "users",
"localField": "user_id",
"foreignField": "_id",
"as": "users"
}
}
]);
The $lookup
can also use additional comparison fields by utilizing let for variables and a specific pipeline. It is important to remember that if you use a pipeline inside a lookup, it is only possible to compare variables defined in let with the columns of the collection chosen using $expr
. Example in MongoDB Playground
db.collection('sales').aggregate([
{
"$lookup": {
"from": "users",
"let": { "userId": "$user_id" },
"pipeline": [
{
"$match": {
"$expr": {
"$and": [
{ "$eq": ["$user_id", "$$userId"] }
]
}
}
},
{
"$project": {
"_id": 0,
"email": 1
}
},
{
"$limit": 1
}
],
"as": "users"
}
}
]);
Top comments (0)