Definition:
The $project
stage allows you to reshape
documents in the pipeline. This stage can be used to:
select
orexclude
fields from the documents.rename
an existing fields.create new fields
that contain values based on existing fields.transform
ormodify
the values of existing fields.
Syntax:
$project : { <field1>: <1>, <field2>: <0>, <newField>: <expression>}
1
: field will be included in the resulted document.0
: field will not be included (excluded).expression
: an expression that specifies how to reshape the document.$
: the dollar sign can be used in theexpression
part toreference
the value of an existing field as we will see in the examples.
Examples:
(1) To include or exclude specific fields from documents:
(1-1)
db.collection.aggregate([
{ $project: { _id: 0, name: 1, age: 1 } }
])
This will only include
the name
and age
fields in the output, while excluding
the _id
field.
(1-2)
db.collection.aggregate([
{ $project: { _id: 0, age: 0 } }
])
This will only execlude
the _id_
and age
fields in the output, while including
all other fields like name
, email
, ..etc.
(1-3)
The following query is not valid
and will produce an error
:
db.collection.aggregate([
{ $project: { _id: 0, name: 1, age: 0 } }
])
Importnat note to consider when include or exclude specific fields. MongoDB doesn't support include fields and exclude specific fields at the same time except the _id
field.
Trying to exclude
the age
field while including other fields in the same $project
stage is not allowed in MongoDB's
aggregation framework.
If you want to exclude
the age
field, you would need to remove it from the inclusion list like this:
db.users.aggregate([
{ $project: { _id: 0, name: 1 } }
])
(2) To rename an existing field in a document:
Suppose you have a collection of documents with a field called fname
and you want to rename it to firstName
. You can use the following $project
stage to rename the field:
db.collection.aggregate([
{
$project: {
firstName: "$fname",
fname: 0
}
}
])
In this example, the $project
stage creates a new field called firstName
and assigns it the value of the fname
field. the dollar sign $
is used to reference
the fname
field.
The fname
field is then excluded from the output by setting its value to 0
.
Another example, if you have a document with a nested field called address.city
, you can use the following $project
stage to rename the city
field to town
:
db.collection.aggregate([
{
$project: {
"address.town": "$address.city",
"address.city": 0
}
}
])
Note that you can also rename multiple fields - not just one field - using a single $project
stage and you also don't have to exclude the field to be renamed from the result.
(3) To create new fields that contain values based on existing fields:
Consider a collection of products that has fields such as name
, price
, and quantity
. You might want to create a new field called totalValue
that contains the total value of each product based on its price
and quantity
.
You can use the $multiply
expression to calculate this value and create a new field using the $project
stage as shown below:
db.products.aggregate([
{
$project: {
name: 1,
price: 1,
quantity: 1,
totalValue: { $multiply: ["$price", "$quantity"] }
}
}
])
In this example, the $multiply
expression multiplies the values of the price and quantity fields for each document, and the result is stored in a new field called totalValue
.
Another example, if you have a document that contain name
and age
of the user and you want to add a new field that indicates the year in which the person was born:
db.collection.aggregate([
{ $project: { name: 1, age: 1, birthYear: { $subtract: [2023, "$age"] } } }
])
This will create a new field called birthYear
that contains the calculated value of subtracting the age
field from the current year
(2023).
(4) To transform the values of an existing field :
Let's say you have a collection of documents that contain a field called price
and you want to transform the values of this field by multiplying them by a certain factor.
You can use the $multiply
operator in the $project
stage to achieve this:
db.collection.aggregate([
{ $project: { _id: 0, price: { $multiply: ["$price", 1.1] } } }
])
In this example, the $multiply
operator multiplies the value of the price
field in each document by 1.1, effectively increasing the price of each item by 10%
.
Here's another example that uses the $toUpper
operator to transform the values of a field called name
to uppercase:
db.collection.aggregate([
{ $project: { _id: 0, name: { $toUpper: "$name" } } }
])
Definition:
The $addFields
stage is equivalent to the $project
stage. The only difference is that $project
stage only includes fields that are explicitly specified in the stage, while $addFields
automatically includes all existing fields in the document and adds new fields.
We can say that $addFields
is like a shorthand for $project
that includes all existing fields in addition to the newly created fields.
Syntax:
{ $addFields: { <newField>: <expression>, ... } }
//all other existing fields will automatically included
If the name of the new field is the same as an existing field name (including _id
), $addFields
overwrites the existing value of that field with the value of the specified expression.
Examples:
(1) Consider a collection of products that has fields such as name
, price
, and quantity
. You want to add a new field called total
to each document that represents the total value of the sale (i.e., quantity
* price
).
db.sales.aggregate([
{
$addFields: {
total: { $multiply: [ "$quantity", "$price" ] }
}
}
])
After running this pipeline, the output documents will include the original fields as well as the new total field:
[
{ "_id": 1, "name": "A", "quantity": 2, "price": 1.50, "total": 3.00 }
{ "_id": 2, "name": "B", "quantity": 3, "price": 0.75, "total": 2.25 }
{ "_id": 3, "name": "c", "quantity": 4, "price": 0.50, "total": 2.00 }
]
(2) Suppose you have a collection of blog posts, where each document includes an _id
field and other fields like title
and author
. You want to replace the _id
field with a new field called postId
, but keep all the other fields in the document.
db.posts.aggregate([
{
$addFields: {
postId: "$_id",
_id: 0
}
}
])
In this pipeline, the $addFields
stage creates a new field called postId
and assigns it the value of the existing _id
field. Then it sets the _id
field to 0
, effectively removing it from the output.
After running this pipeline, the output documents will look like that:
[
{ "title": "First Post", "author": "Ahmed", "postId": 1 }
{ "title": "Second Post", "author": "Omnia", "postId": 2 }
{ "title": "Third Post", "author": "Mohamed", "postId": 3 }
]
Definition:
The $set
act the same as $addFields
stage. It was introduced in MongoDB 4.2
Syntax:
{ $set: { <newField>: <expression>, ... } }
Examples:
Consider the following documents in a collection called vehicles
:
[
{ "_id": 1, "type": "car", "specs": { "doors": 4, "wheels": 4 } },
{ "_id": 2, "type": "motorcycle", "specs": { "doors": 0, "wheels": 2 } },
{ "_id": 3, "type": "jet ski" }
]
To add a new field fuel_type
to the embedded document specs:
db.vehicles.aggregate( [
{ $set: { "specs.fuel_type": "unleaded" } }
] )
The operation returns the following results:
[
{ "_id": 1, "type": "car", "specs": { "doors": 4, "wheels": 4, "fuel_type": "unleaded" } },
{ "_id": 2, "type": "motorcycle", "specs": { "doors": 0, "wheels": 2, "fuel_type": "unleaded" } },
{ "_id": 3, "type": "jet ski", "specs": {"fuel_type": "unleaded"} }
]
The $addFields
stage will produce the same result as we did here with the $set
stage.
Definition:
The $unset
stage is used to exclude
fields from documents in a collection.
Syntax:
The $unset
stage has the two following syntax:
-
To remove a single field :
{ $unset: "<field>" }
-
To remove multiple fields :
{ $unset: [ "<field1>", "<field2>", ... ] }
The $unset
is an alias for the $project
stage that excludes fields:
{ $project: { "<field1>": 0, "<field2>": 0, ... } }
Examples:
Consider the following documents in a collection called books
:
[
{
"_id" : 1,
"title": "Antelope Antics",
"isbn": "0001122223334",
"author": { "last":"An", "first": "Auntie" },
"copies": [
{ "warehouse": "A", "qty": 5 },
{ "warehouse": "B", "qty": 15 }
]
},
{
"_id" : 2,
"title": "Bees Babble",
"isbn": "999999999333",
"author": { "last":"Bumble", "first": "Bee" },
"copies": [
{ "warehouse": "A", "qty": 2 },
{ "warehouse": "B", "qty": 5 }
]
}
]
To remove multiple fields:
db.books.aggregate([
{ $unset: [ "isbn", "author.first", "copies.warehouse" ] }
])
The previous operation outputs the following documents:
{
"_id": 1,
"title": "Antelope Antics",
"author": { "last": "An" },
"copies": [
{ "qty": 5 },
{ "qty": 15 }
]
}
{
"_id": 2,
"title": "Bees Babble",
"author": { "last": "Bumble" },
"copies": [
{ "qty": 2 },
{ "qty": 5 }
]
}
βοΈ How To Query Array Fields in MongoDB Documents
βοΈ How To Add and Remove Array Elements in MongoDB Documents
βοΈ How To Update Array Elements in MongoDB Documents
π΄οΈ Linkedin: Dragon Slayer π²
π Articles: All Articles written by D.S