Reputation: 43116
I have a document from a mongoose find that I want to extend before JSON encoding and sending out as a response. If I try adding properties to the doc it is ignored. The properties don't appear in Object.getOwnPropertyNames(doc)
making a normal extend not possible. The strange thing is that JSON.parse(JSON.encode(doc))
works and returns an object with all of the correct properties. Is there a better way to do this?
Upvotes: 290
Views: 229983
Reputation: 486
I have been using the toObject
method on my document without success.
I needed to add the flattenMap
property to true
to finally have a POJO.
const data = document.data.toObject({ flattenMaps: true });
Upvotes: 1
Reputation: 5745
In some cases as @JohnnyHK suggested, you would want to get the Object as a Plain Javascript. as described in this Mongoose Documentation there is another alternative to query the data directly as object:
const docs = await Model.find().lean();
In addition if someone might want to conditionally turn to an object,it is also possible as an option
argument, see find() docs at the third parameter:
const toObject = true;
const docs = await Model.find({},null,{lean:toObject});
its available on the functions: find()
, findOne()
, findById()
, findOneAndUpdate()
, and findByIdAndUpdate()
.
it is also worth mentioning that the _id
attribute isn't a string object as if you would do JSON.parse(JSON.stringify(object))
but a ObjectId from mongoose types, so when comparing it to strings cast it to string before: String(object._id) === otherStringId
Upvotes: 40
Reputation: 686
The lean option tells Mongoose to skip hydrating the result documents. This makes queries faster and less memory intensive, but the result documents are plain old JavaScript objects (POJOs), not Mongoose documents.
const leanDoc = await MyModel.findOne().lean();
not necessary to use JSON.parse() method
Upvotes: 8
Reputation: 324
You can also stringify the object and then again parse to make the normal object. For example like:-
const obj = JSON.parse(JSON.stringify(mongoObj))
Upvotes: 7
Reputation: 6200
To get plain object from Mongoose document, I used _doc
property as follows
mongooseDoc._doc //returns plain json object
I tried with toObject
but it gave me functions,arguments and all other things which i don't need.
Upvotes: 9
Reputation: 28451
A better way of tackling an issue like this is using doc.toObject()
like this
doc.toObject({ getters: true })
other options include:
getters:
apply all getters (path and virtual getters)virtuals:
apply virtual getters (can override getters option)minimize:
remove empty objects (defaults to true)transform:
a transform function to apply to the resulting document before returningdepopulate:
depopulate any populated paths, replacing them with their original refs (defaults to false)versionKey:
whether to include the version key (defaults to true)so for example you can say
Model.findOne().exec((err, doc) => {
if (!err) {
doc.toObject({ getters: true })
console.log('doc _id:', doc._id)
}
})
and now it will work.
For reference, see: http://mongoosejs.com/docs/api.html#document_Document-toObject
Upvotes: 19
Reputation: 39679
Mongoose Model
s inherit from Document
s, which have a toObject()
method. I believe what you're looking for should be the result of doc.toObject()
.
http://mongoosejs.com/docs/api.html#document_Document-toObject
Upvotes: 410
Reputation: 312129
Another way to do this is to tell Mongoose that all you need is a plain JavaScript version of the returned doc by using lean()
in the query chain. That way Mongoose skips the step of creating the full model instance and you directly get a doc
you can modify:
MyModel.findOne().lean().exec(function(err, doc) {
doc.addedProperty = 'foobar';
res.json(doc);
});
Upvotes: 270
Reputation: 1147
the fast way if the property is not in the model :
document.set( key,value, { strict: false });
Upvotes: 30