How to get customise array of object in aggegrate query project using mongoose

Viewed 21

I am new to mongoose and aggregate function. I have following collection in a document.

[
    {
        course_type: 1,
        sessions:[
            {
                start_at: "10/01/2020",
                end_at: "11/01/2020"
            },
            {
                start_at: "10/02/2020",
                end_at: "11/02/2020"
            },
            {
                start_at: "10/03/2020",
                end_at: "11/03/2020"
            }
        ]
    },
    {
        course_type: 2,
        sessions:[
            {
                start_at: "20/01/2021",
                end_at: "21/01/2021"
            },
            {
                start_at: "20/02/2021",
                end_at: "21/02/2021"
            }
        ]
    }
]

Is it possible to have start_at of first session and end_at of last session if the course_type is 1. And if the course type is 2 then sessions must be unwind. Is the following output is possible -

[
    {
        course_type: 1,
        start_at: "10/01/2020",
        end_at: "11/03/2020"
    }
    {
        course_type: 2,
        start_at: "20/01/2021",
        end_at: "21/01/2021"
    },
    {
        course_type: 2,
        start_at: "20/02/2021",
        end_at: "21/02/2021"
    }
]

Is this possible to do in $project of any other option is there. I have tried to do it with $arrayElemAt, but didn't get the expected output

1 Answers

You can use $arrayElemAt as you mentioned to access specific positions of an array like so:

db.collection.aggregate([
  {
    "$addFields": {
      firstSession: {
        "$arrayElemAt": [
          "$sessions",
          0
        ]
      },
      lastSession: {
        "$arrayElemAt": [
          "$sessions",
          {
            "$subtract": [
              {
                $size: "$sessions"
              },
              1
            ]
          }
        ]
      }
    }
  },
  {
    $project: {
      course_type: 1,
      start_at: "$firstSession.start_at",
      end_at: "$lastSession.end_at"
    }
  }
])

Mongo Playground

---------- EDIT ------------

This is considering the other condition you request which is to preserve the original sessions only of type:2:

db.collection.aggregate([
  {
    $facet: {
      type1: [
        {
          $match: {
            course_type: 1
          }
        },
        {
          "$addFields": {
            firstSession: {
              "$arrayElemAt": [
                "$sessions",
                0
              ]
            },
            lastSession: {
              "$arrayElemAt": [
                "$sessions",
                {
                  "$subtract": [
                    {
                      $size: "$sessions"
                    },
                    1
                  ]
                }
              ]
            }
          }
        },
        {
          $project: {
            course_type: 1,
            start_at: "$firstSession.start_at",
            end_at: "$lastSession.end_at"
          }
        }
      ],
      type2: [
        {
          $match: {
            course_type: 2
          }
        },
        {
          $unwind: "$sessions"
        },
        {
          $project: {
            course_type: 1,
            start_at: "$sessions.start_at",
            end_at: "$sessions.end_at"
          }
        }
      ]
    }
  },
  {
    "$addFields": {
      merged: {
        "$concatArrays": [
          "$type1",
          "$type2"
        ]
      }
    }
  },
  {
    $unwind: "$merged"
  },
  {
    "$replaceRoot": {
      "newRoot": "$merged"
    }
  }
])

Mongo Playground

Related