Is it possible to use variables defined in the $project phase in that same phase?
For example, I have this aggregation pipeline:
pipeline = [
  { '$match': {} },
  {
    '$group': {
      '_id': '$_id',
      'n': { '$first': 'n' }
    }
  },
  {
    '$project': {
      'name': 1,
      'n': 1,
      'revenue': { '$multiply': ['$n', 2] },
      'cost': { '$multiply': ['$revenue', 0.25] }
    }
  }
]
I'd like to use the $revenue variable (that I defined in $project) in the same $project stage to compute the value of cost, but this does not work.
Is there any way I can do this easily and efficiently? I thought about doing several projections but I would need to project many variables (~25 variables) every time I need to compute one additional variable, and I have a bunch of variables to compute that are depending on each other (~5 variables), and my code would probably look bad since there would be a lot of projecting of the same variables. How should I go about this?
No, but you can nest projection operators as a work-around:
pipeline = [{   
    '$match': {}
},
{
    '$group': {
        '_id': '$_id',
        'n': {'$first': 'n'}
},
{
    '$project': {
        'name': 1,
        'n': 1,
        'revenue': {'$multiply': ['$n', 2]},
        'cost': {'$multiply': [{'$multiply': ['$n', 2]}, 0.25]}
    }
}]
Which in this case you could simplify to:
pipeline = [{   
    '$match': {}
},
{
    '$group': {
        '_id': '$_id',
        'n': {'$first': 'n'}
},
{
    '$project': {
        'name': 1,
        'n': 1,
        'revenue': {'$multiply': ['$n', 2]},
        'cost': {'$multiply': ['$n', 2, 0.25]}
    }
}]
                        Just landed here while searching for the same issue. My current solution is adding more $project stages and always take all other fields. For your example it would look like this:
pipeline = [{   
    '$match': {}
},
{
    '$group': {
        '_id': '$_id',
        'n': {'$first': 'n'}
},
{
    '$project': {
        'name': 1,
        'n': 1,
        'revenue': {'$multiply': ['$n', 2]}
    }
},
{
    '$project': {
        'name': 1,
        'n': 1,
        'revenue': 1,
        'cost': {'$multiply': ['$revenue', 0.25]}
    }
}]
I did not find any better solution yet if you want to keep all previous computed fields, without reusing expressions several times.
Starting in Mongo 3.4, you can use a series of $addFields stages rather than verbose $project stages.
This way, you can keep on projecting additional fields, some of which can re-use fields previously computed:
// { name: "a", n: 3 }
// { name: "b", n: 5 }
db.collection.aggregate([
  { $addFields: { revenue: { $multiply: ["$n", 2] } } },
  { $addFields: { cost: { $multiply: ["$revenue", 0.25] } } } // re-use "revenue"
])
// { name: "a", n: 3, revenue: 6,  cost: 1.5 }
// { name: "b", n: 5, revenue: 10, cost: 2.5 }
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With