Join and aggregate

Hi, I am new to mongodb. Till now I have worked with SQL queries. I have the following 2 schemas, that should be joined and the following calculations to be done.

a { 
   academic_year:  { type:String} 
} 
b { 
       b1: {type:Number, default:0  },
      b2: {type:Number, default:0  },
      b3: [{  b3_1: {type:Number, default:0  },  b3_2: {type:Number, default:0  },  b3_3: {type:Number, default:0 }
              }]
       b4: {type:mongoose.Schema.ObjectId, 
    ref: 'a'}         
} 

Let's suppose we have below example
a { 
   academic_year: "2021-2022"
   _id:234lkjlk2342432
} 


b { 
       b1:1,
      b2: 2,
      b3: [
	  {  b3_1: 5,  b3_2: 4,  b3_3: 4, },
	  {  b3_1: 1,  b3_2: 4,  b3_3: 2 }
	  {  b3_1: 5,  b3_2: 1,  b3_3: 2 }
              ]
       b4: "234lkjlk2342432"        
}

the result to return would bebelow where bigtotal= b1+b2+ sum of total field

c{ 
 academic_year: "2021-2022",
 b1:1,
 b2: 2,
  b3: [
	  {  b3_1: 5,  b3_2: 4,  b3_3: 4,total:13  },
	  {  b3_1: 1,  b3_2: 4,  b3_3: 2 ,total:7},
	  {  b3_1: 5,  b3_2: 1,  b3_3: 2,total:8 }
              ],
			  
    BigTotal:31,
	
	
}

Hi @Genti_P and welcome to the MongoDB community forum!!

Based on the sample example and the expected response , the following aggregation query would be helpful.

[
  {
    '$lookup': {
      'from': 'a', 
      'localField': '_id', 
      'foreignField': '_id', 
      'as': 'c'
    }
  }, {
    '$addFields': {
      'academic_year': {
        '$arrayElemAt': [
          '$c', 0
        ]
      }
    }
  }, {
    '$addFields': {
      'academic_year': '$academic_year.academic_year'
    }
  }, {
    '$unset': [
      'c', 'b4'
    ]
  }, {
    '$addFields': {
      'bigtotal': {
        '$map': {
          'input': '$b3', 
          'as': 'obj', 
          'in': {
            'total': {
              '$add': [
                '$$obj.b3_1', '$$obj.b3_2', '$$obj.b3_3'
              ]
            }
          }
        }
      }
    }
  }, {
    '$addFields': {
      'b3': {
        '$zip': {
          'inputs': [
            '$b3', '$bigtotal'
          ]
        }
      }
    }
  }, {
    '$addFields': {
      'b3': {
        '$map': {
          'input': '$b3', 
          'in': {
            '$mergeObjects': '$$this'
          }
        }
      }
    }
  }, {
    '$addFields': {
      'bigtotal': {
        '$sum': [
          '$b1', '$b2', {
            '$sum': '$bigtotal.total'
          }
        ]
      }
    }
  }
]

The output for the above aggregation would look like:

[
  {
    _id: ObjectId("636cbcf1e1c238226bb5a421"),
    b1: 1,
    b2: 2,
    b3: [
      { b3_1: 5, b3_2: 4, b3_3: 4, total: 13 },
      { b3_1: 1, b3_2: 4, b3_3: 2, total: 7 },
      { b3_1: 5, b3_2: 1, b3_3: 2, total: 8 }
    ],
    academic_year: '2011-2022',
    bigtotal: 31
  }
]

However, please note the following recommendations:

  1. Depending on your use case, the aggregation works but may be difficult to maintain in the long term.
  2. The first four stages can be avoided if the field academic_year is stored in the document in collection b , thus shortening the aggregation pipeline by 50%
  3. Alternatively you may consider to do this processing in the application code since I think the aggregation output just adds extra information in the documents in collection b

Also, note that, the above aggregation is dependent on the sample example provided and was not optimised for performance by any means, I would recommend you to throughly test before applying it to the application for entire documents in collection.

Let us know if you have any further queries.

Best Regards
Aasawari

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.