'Facing problems to retrieve data using mongodb Pipeline method using Nodejs

I am facing some problems to crack this particular challenge where I would like to retrieve data from MongoDb using pipeline in Nodejs.

Here is the data from DB:

{
    "_id" : ObjectId("623ec44a6900ca5e3a88ece0"),
    "student_id" : ObjectId("5fca683c239e4e2693ee20e4"),
    "isSession" : true,
    "record_list" : [ 
        {
            "_id" : ObjectId("623ec4ae319ebd3d243adeb4"),
            "Name" : "Adam",
            "Type" : 1,
            "class_id" : "aa0a2311-5989-4a7b-855f-4c4b73ae6315",
            "isPresent" : true
        }, 
        {
            "_id" : ObjectId("623ec4ae319ebd3d243adeb5"),
            "Name" : "Jack",
            "Type" : 1,
            "class_id" : "fa54389b-4504-465b-9c6c-a386918b8d67",
            "isPresent" : true
        }
    ]
}

Here is the output that I expect:

{
    "_id" : ObjectId("623ec44a6900ca5e3a88ece0"),
    "student_id" : ObjectId("5fca683c239e4e2693ee20e4"),
    "isSession" : true,
    "record_list" : [ 
        {
            "_id" : ObjectId("623ec4ae319ebd3d243adeb5"),
            "Name" : "Jack",
            "Type" : 1,
            "class_id" : "fa54389b-4504-465b-9c6c-a386918b8d67",
            "isPresent" : true
        }
    ]
}

I am sending class_id and student_id from UI and based on that it should filter the data and return the entire collection based on these parameters.

controller.ts

let pipeline: any = await Builder.User.SchoolBuilder.studentMatchRecord(payload);

What I tried:

school.builder.ts

export const studentMatchRecord = (payload: any) => {
    let pipeline: any = [];
    pipeline.push({ $match: { student_id: Types.ObjectId(payload.studentId) } });
    pipeline.push(
        { "$unwind": "$record_list" },
        {
            "$group": {
                "record_list.class_id": payload.classId,
            }
        });
    pipeline.push({
      $project: {
        student_id: 1,
        isSession: 1,
        record_list: 1,
      },
    });
    return pipeline;
  };

and even this:

  export const studentMatchRecord = (payload: any) => {
    let pipeline: any = [];
    let filterConditions: any = { $match: { $and: [] } };
    let matchCriteria: any = { $match: { $and: [] } };
    matchCriteria.$match.$and.push({
      student_id: Types.ObjectId(payload.student_id),
    });
    if (payload.classId) {
      filterConditions.$match.$and.push({
        "record_list.class_id": payload.class_id,
      });
    }
    if (filterConditions.$match.$and.length > 0) {
      pipeline.push(filterConditions);
    }
    pipeline.push({
      $project: {
        student_id: 1,
        isSession: 1,
        record_list: 1,
      },
    });
    return pipeline;
  };

but none of the case is working here. Can you please highlight what am I doing wrong here? Cheers.



Solution 1:[1]

Option 1: find/$elemMatch:

db.collection.find({
  "student_id": ObjectId("5fca683c239e4e2693ee20e4")
},
{
 "record_list": {
   "$elemMatch": {
     "class_id": "aa0a2311-5989-4a7b-855f-4c4b73ae6315"
 }
},
 "isSession": 1,
 "student_id": 1
})

playground1

Option 2: aggregate/$filter

 db.collection.aggregate([
 {
   $match: {
    "student_id": ObjectId("5fca683c239e4e2693ee20e4")
   }
 },
 {
  "$addFields": {
    "record_list": {
      "$filter": {
        "input": "$record_list",
        "as": "rec",
        "cond": {
          $eq: [
            "$$rec.class_id",
            "fa54389b-4504-465b-9c6c-a386918b8d67"
          ]
        }
      }
    }
  }
 }
])

playground2

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1