Object.assign() creates wierd properties when assigns mongoose doc
Asked Answered
S

4

7
MessageThread.findById(req.body._id)
      .populate({ path: "messages" })
      .exec((err, foundMessageThread) => {
        var filtered = foundMessageThread.messages.map(message=>{
          return Object.assign({}, message, {isRead: true});
        })
        console.log("filtered", filtered);

      });

console.log shows:

{ '$__':
 InternalCache {
   strictMode: true,
   selected: {},
   shardval: undefined,
   saveError: undefined,
   validationError: undefined,
   adhocPaths: undefined,
   removing: undefined,
   inserting: undefined,
   version: undefined,
   getters: {},
   _id: 5a4c7f2d8b49fc260c396f55,
   populate: undefined,
   populated: undefined,
   wasPopulated: true,
   scope: undefined,
   activePaths: [Object],
   pathsToScopes: {},
   ownerDocument: undefined,
   fullPath: undefined,
   emitter: [Object],
   '$options': true },
isNew: false,
errors: undefined,
_doc:
 { sentAt: 2018-01-03T06:58:53.188Z,
   isRead: false,
   _id: 5a4c7f2d8b49fc260c396f55,
   sender: 5a4b77767251b44cd870219f,
   reciever: 5a4b780a7251b44cd87021a1,
   text: 'qwe',
   __v: 0 },
'$init': true,
isRead: true },
......

it repeats many times. I suppose it (InternalCache { strictMode: true...) relates to message that is taken from foundMessageThread. And it reveals its metadata(in my term) while assigning. Because:

MessageThread.findById(req.body._id)
  .populate({ path: "messages" })
  .exec((err, foundMessageThread) => {
    var filtered = foundMessageThread.messages.map(message=>{
      console.log("message", message)
      return Object.assign({}, message, {isRead: true});
    })
    console.log("filtered", filtered);

  });

console.log shows

{ sentAt: 2018-01-03T06:58:53.188Z,
  isRead: false,
  _id: 5a4c7f2d8b49fc260c396f55,
  sender: 5a4b77767251b44cd870219f,
  reciever: 5a4b780a7251b44cd87021a1,
  text: 'qwe',
  __v: 0 },
....

My question:

  1. Is it normal behavior?
  2. If it is how to fix it? Because "metadata" prevents objects being assigned.

P.S. I've tried:

MessageThread.findById(req.body._id)
  .populate({ path: "messages" })
  .exec((err, foundMessageThread) => {
    var filtered = foundMessageThread.messages.map(message=>{
      return **Object.assign({}, message._doc, {isRead: true})**;
    })
    console.log("filtered", filtered);

  });
Sadiron answered 3/1, 2018 at 20:28 Comment(0)
E
12

This is a normal behaviour with mongoose. Objects returned by mongoose wrap the actual data, so as to add behaviours (methods) to it.

You can get to the actual data object by using toObject method, for eg, message.toObject().

However there are properties like __v, which are used by mongoose for house keeping purposes. If you don't want them, you can modify the toObject method like this

messageSchema.set('toObject', {
  versionKey: false,
  transform: (doc, ret) => {
    delete ret.__v;
    return ret;
  },
});
Evidently answered 3/1, 2018 at 20:39 Comment(2)
Thanks @AkshendraPratap. But why when I do Object.assign() it shows up, when I do console.log() it doesn't. For example, in the 3rd code above console.log("message") showed regular doc. but when I did Object.assign(), actual data pop out? ))Sadiron
On a very higher level, to print the object as string, console.log will use a toString() function. Mongoose provides a toString for its documents as helper. Which is basically retuning toObject. You can look at the code here, github.com/Automattic/mongoose/blob/…Evidently
W
4

You can also use .lean() method with mongoose request. This allows to get less cumbersome response and process it easyly:

try {
    const assets = await myModel.Assets
      .find({ isActive: true }, { __v: 0, _id: 0 })
      .lean()
      .exec()
    // do something
}
catch(error) {
  throw error
}
Wolof answered 15/2, 2020 at 8:16 Comment(0)
C
1

It appears that the _doc property of mongoose objects should be referenced if you want to either assign to or from those objects. In fact, I was unable to set additional properties in a normal manner like so mongoDoc.newProp = propValue;. It was not altering the original object.

For assignment, instead of:

Object.assign(mongoDoc, {a: 1, b: 2});

You'd want:

Object.assign(mongoDoc._doc, {a: 1, b: 2});

Or if you're assigning the mongoDoc properties to another object, you'd want

Object.assign({a: 1, b: 2}, mongoDoc._doc);

Chandigarh answered 28/7, 2018 at 7:50 Comment(1)
that works but it does not look like a clean way to me!Buttercup
M
0

// add .lean() in your query like below

const documents = await DocumentModel.find().lean();

// at debug now ,
// now you will get your result;
Mayotte answered 17/9, 2022 at 20:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.