MongoDB project Stage
The $project stage reshapes each document by including, excluding, renaming, or computing fields, giving you full control over what the pipeline outputs.
Including and Excluding Fields
At its simplest, $project works like a projection in find(): set a field to 1 to include it, or 0 to exclude it. By default, the _id field is included automatically unless you explicitly set it to 0. You generally cannot mix inclusion and exclusion in the same $project, with the sole exception of explicitly excluding _id alongside included fields.
Basic Inclusion Projection
db.users.aggregate([
{ $project: {
_id: 0,
name: 1,
email: 1
} }
])Renaming and Computing Fields
$project isn't limited to picking existing fields; you can assign any expression to a new field name. This lets you rename fields, perform arithmetic, concatenate strings, or reference nested paths, all within the same stage. Expressions use the same operator syntax found throughout the aggregation framework, prefixed with a dollar sign to reference field values.
Computing and Renaming Fields
db.orders.aggregate([
{ $project: {
_id: 0,
customer: "$customerName",
total: { $multiply: ["$price", "$quantity"] },
isLarge: { $gt: ["$quantity", 10] }
} }
])Here the output document has three new fields: customer is simply renamed from customerName, total is computed by multiplying price and quantity, and isLarge is a boolean computed from a comparison expression.
- Set a field to 1 to include it unchanged
- Set a field to 0 to exclude it
- Assign a string starting with $ to copy or rename another field's value
- Assign an expression object to compute a new value
- Use dot notation to reach into embedded subdocuments
Reshaping Nested Data
db.employees.aggregate([
{ $project: {
_id: 0,
fullName: { $concat: ["$firstName", " ", "$lastName"] },
city: "$address.city",
yearsEmployed: { $divide: [{ $subtract: ["$$NOW", "$hireDate"] }, 31536000000] }
} }
])