3

I need to remove certain fields from the JSON response. I've used the toJSON() method for doing this. Here is the code of my modal method for it.

    User.methods.toJSON = function () {
      let obj = this.toObject()
    
      delete obj.resetPasswordToken
      delete obj.resetPasswordExpire
      delete obj.otp
      delete obj.otpExpire
      return obj
    }

The above code is working fine but when I populate the User modal with my Media model it doesn't remove the fields that I deleted from the JSON response.

    const allMedia = await Media.find({}).populate({
      path: 'uploadedBy', // this is the user document 
    })

This is the code I wrote for populating the user model with the media model. But the problem is User gets populated with Media but it doesn't ignore the fields that I deleted from toJSON() method.

    {
        "name": null,
        "sizes": [],
        "isPrivate": false,
        "_id": "61d6d1a1fcaf7337f6f186de",
        "path": "http://192.168.1.7:2121/uploads/2022/1/7b37e2bc-b313-4b08-abd6-101e99c36527.png",
        "uploadedBy": {
            "firstName": "abc",
            "lastName": "abc",
            "role": "ADMIN",
            "resetPasswordToken": "77bda3f7794d305d7771fc23d932e1e9922df02c71b02c3564ad46b22ceac27e",
            "resetPasswordExpire": "1640954443294",
            "otp": null,
            "otpExpire": null,
            "_id": "61ceea9ce989f2d986fa9c5c",
            "userName": "abc",
            "email": "abc@gmail.com",
            "createdAt": "2021-12-31T11:33:48.066Z",
            "updatedAt": "2021-12-31T13:08:36.245Z"
        },
        "createdAt": "2022-01-06T11:25:21.839Z",
        "updatedAt": "2022-01-06T11:25:21.839Z"
    }

If anyone can help, it would be appreciated.

Thanks in advance,

NeNaD
  • 18,172
  • 8
  • 47
  • 89
Nik Lakhani
  • 207
  • 1
  • 10
  • Apparently you do not assign the result from the function with the deleted properties to a new variable so you end up with the unmodified object ... – R2D2 Jan 10 '22 at 14:59
  • I agree, @R2D2. But I don't know any way of returning the modified objects. – Nik Lakhani Jan 11 '22 at 03:37
  • Though, I can make a middleware or a helper function to be called before returning the object. But I am looking for a better approach if there is any. @R2D2 – Nik Lakhani Jan 11 '22 at 03:39

2 Answers2

1

You can define pre hook for each query for Media schema.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const schema = new Schema(...);

schema.pre('find', function () {
  this.populate('uploadedBy');
  this.select('-resetPasswordToken -resetPasswordExpire -otp -otpExpire');
});

You can add new pre hooks for other queries, just like for the find.

You can find more details here.

NeNaD
  • 18,172
  • 8
  • 47
  • 89
0

here is an example using Aggregation

const allMedia = await Media.aggragate([
  $lookup: {
    from: 'uploadedBy',
    localField: 'uploadedBy',
    foreignField: '_id',
    // your variable
    as: 'uploadedBy',
  },
  {
    $project: {
//removing the field you want to remove by attibuting a Zero
      resetPasswordToken:0,
      resetPasswordExpire: 0,
      otp:0,
      otpExpire:0
      // select the field you want to display 
      fieldYouWantoToDisplay: 1,
    },
  },
])
Anas Ben Yaiche
  • 225
  • 3
  • 7
  • This will remove the fields but I don't want to remove it for all the queries and that is the reason I've removed it globally from toJSON method. I've to repeat it for all queries If I do it using "aggregate" or "populate". – Nik Lakhani Jan 18 '22 at 11:08