Stages define what happens to the stream; expressions define what a value is: a field path, a literal, or a single-key document naming an operator whose value holds the arguments — { $multiply: ['$qty', '$price'] }. They nest without limit, and MongoDB 8.3 1,815 offers well over a hundred. Conditionals turn a pipeline into a report: $cond is a ternary, $switch a chain of cases with a default, and $ifNull returns the first non-null argument.
db.orders.aggregate([
{ $set: { total: { $sum: { $map: { input: '$items', as: 'i',
in: { $multiply: ['$$i.qty', '$$i.price'] } } } } } },
{ $project: {
size: { $cond: [{ $gte: ['$total', 400] }, 'large', 'small'] },
band: { $switch: { branches: [
{ case: { $eq: ['$status', 'canceled'] }, then: 'lost' },
{ case: { $gte: ['$total', 400] }, then: 'high' },
{ case: { $gte: ['$total', 200] }, then: 'mid' } ], default: 'low' } },
ship: { $ifNull: ['$shipping', 0] } } },
{ $limit: 4 }
])[
{ _id: 'o-1001', size: 'small', band: 'low', ship: 12 },
{ _id: 'o-1002', size: 'small', band: 'mid', ship: 20 },
{ _id: 'o-1003', size: 'small', band: 'mid', ship: 0 },
{ _id: 'o-1004', size: 'large', band: 'lost', ship: 25 }
]$switch stops at the first true case, so o-1004 is lost even though its total also clears the high threshold. Omit default and a document matching no branch raises an error instead of returning null — usually what you want while developing.
Three array operators replace most of the loops you would write in Node: $map transforms every element, $filter keeps those whose cond is true, and $reduce folds an array using $$value and $$this — on order o-1011, { $reduce: { input: '$items', initialValue: 0, in: { $add: ['$$value', '$$this.qty'] } } } yields 4.
Three system variables come up constantly. $$ROOT is the document as it entered the stage, so { $group: { _id: '$customerId', docs: { $push: '$$ROOT' } } } collects whole documents. $$NOW is the server time the aggregation started, identical for every document and so safer than a date computed in Node. $$REMOVE makes a field conditional: { $cond: [c, '$$REMOVE', '$channel'] } emits channel only when c is false, which no combination of 1 and 0 can express. Your own variables come from $let and from the as option of $map and $lookup.