Chaining Mongoose Aggregate

I am using Model.aggregate() to return selected fields from a selected document in MongoDb using Mongoose.

Here are my models (they’re simple don’t worry):

const exerciseSchema = new mongoose.Schema({
  id: String,
  description: String,
  duration: Number,
  date: {type: Date,
         default: new Date()}
})
const userSchema = new mongoose.Schema({
  username: { type: String,
          required: true,
          unique: true},
  exercise: [exerciseSchema]
})

What I’m trying to do is return the user with some fields from the associated exercise array. I would like the date to be returned in a format “YYYY-MM-DD”, but I can’t figure out how to include it in my query:

app.get(`/api/exercise/log/:userId`, async(req, res) => {
  let user = await User.aggregate([ 
    { $match : {_id: mongoose.Types.ObjectId(req.params.userId) }},
    { $project: { username: 1, 
                  exercise: { description: 1,
                              duration: 1,
                              date: 1
                             }
                  }
    }
  ], (err, user) => {
    if (err) { console.log(err.message);
               return res.send(`User id: ${req.params.userId} not found!`)
              };
     user[0].count = user[0].exercise.length;
     res.status(200).send(user[0]);
  })
});

Is there a way I can format the date field somehow before it is returned? I know there is a way ! But I cannot find it.

Also , would not say I was clear on why user is returned as an array - I guess it is because I am not searching in a “find one” type style so the query sets up an array. If anyone has advice about that (since I wonder if this is a sub optimal approach?) pleaes help!

Before the above line, you could use the map method to create a new array of user[0].exercise using map and change the date to the format you want be creating a new Data object based on the mongodb date and then accessing the month, day, and year using the various Date object methods. You will need to padding the values with an extra 0 to achieve your desired date format.

Hey thanks Randell! OK, that’s a workaround… but is there really no way to have it just come out correctly formatted? Am I dreaming :slight_smile: Also … can you do something like… chain together 2 $project operations so that you can have one inclusive and one exclusive? Maybe I should not worry about it and focus on end result here !

In your schema, instead of assigning new Date() for the default value, you could go ahead and store it in the format you want (using similar date methods I described above). If however the user has the option to add a date manually, you would need to control the values allowed on the front-end and the back-end to make sure they keep the format.

The bottom line is you would need to store the value in the format you want to return, but that is very limiting in case you wanted to be able to query on date ranges.