最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Cast plain object to mongoose document - Stack Overflow

programmeradmin4浏览0评论

UPDATE 1: 5 votes have been received, so I have submitted a feature request:

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 );

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 );
Share Improve this question edited Feb 5, 2019 at 21:40 Ryan Wheale asked Jun 12, 2014 at 17:29 Ryan WhealeRyan Wheale 28.4k10 gold badges86 silver badges102 bronze badges 2
  • Would it not be possible to update each individual document using the unique ID which is provided on the object in the collection? That way you wouldn't have to convert the object to the specific type, and just do an update Model.update({_id : id}, ...} – rxjmx Commented Mar 10, 2015 at 9:28
  • That's a direct to database transaction and bypasses the need for a document instance. The discussion here is about converting a plain JS object into a fully casted mongoose document so that I can do business logic things like call custom methods, trigger validation manually, etc... – Ryan Wheale Commented Mar 10, 2015 at 16:51
Add a comment  | 

2 Answers 2

Reset to default 14

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.

  1. If you are getting a response from REST service and say you have a User mongoose model

var User = mongoose.model('User');
var fields = res.body; //Response JSON
var newUser = new User(fields);
newUser.save(function(err,resource){
  console.log(resource);
});

  1. In other case say you have an array of user JSON objects from User.find() that you want to query or populate

var query  = User.find({});
query.exec(function(users){
  //mongoose deep-populate ref docs
  User.deeppopulate users 'email_id phone_number'.exec({
    //query through populated users objects
  });
});

MongoDB doesn't support Joins and Transfers. So for now you can't cast values to an object directly. Although you can work around it with forEach.

发布评论

评论列表(0)

  1. 暂无评论