Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cast plain object to mongoose document

UPDATE 1: 5 votes have been received, so I have submitted a feature request: https://github.com/LearnBoost/mongoose/issues/2637

Please cast your +1 votes there to let the core team know you want this feature.


UPDATE 2: See answer below...


ORIGINAL POST:

Lets say I do a "lean" query on a collection OR receive some data from a REST service and I get an array of objects (not mongoose documents).

These objects already exist in the database, but I need to convert some/all of those objects to mongoose documents for individual editing/saving.

I have read through the source and there is a lot going on once mongoose has data from the database (populating, casting, initializing, etc), but there doesn't seem to be a method for 'exposing' this to the outside world.

I am using the following, but it just seems hacky ($data is a plain object):

// What other properties am I not setting?  Is this enough? var doc = new MyModel( $data ); doc.isNew = false;  // mimicking mongoose internals // "init" is called internally after a document is loaded from the database // This method is not documented, but seems like the most "proper" way to do this. var doc = new MyModel( undefined ); doc.init( $data ); 

UPDATE: After more searching I don't think there is a way to do this yet, and the first method above is your best bet (mongoose v3.8.8). If anybody else is interested in this, I will make a feature request for something like this (leave a comment or upvote please):

var doc = MyModel.hydrate( $data ); 
like image 437
Ryan Wheale Avatar asked Jun 12 '14 17:06

Ryan Wheale


1 Answers

Posting my own answer so this doesn't stay open:

Version 4 models (stable released on 2015-03-25) now exposes a hydrate() method. None of the fields will be marked as dirty initially, meaning a call to save() will do nothing until a field is mutated.

https://github.com/LearnBoost/mongoose/blob/41ea6010c4a84716aec7a5798c7c35ef21aa294f/lib/model.js#L1639-1657

It is very important to note that this is intended to be used to convert a plain JS object loaded from the database into a mongoose document. If you are receiving a document from a REST service or something like that, you should use findById() and update().

For those who live dangerously:

If you really want to update an existing document without touching the database, I suppose you could call hydrate(), mark fields as dirty, and then call save(). This is not too different than the method of setting doc.isNew = false; as I suggested in my original question. However, Valeri (from the mongoose team) suggested not doing this. It could cause validation errors and other edge case issues and generally isn't good practice. findById is really fast and will not be your bottleneck.

like image 74
Ryan Wheale Avatar answered Sep 19 '22 22:09

Ryan Wheale