Automattic / mongoose

MongoDB object modeling designed to work in an asynchronous environment.
https://mongoosejs.com
MIT License
26.95k stars 3.84k forks source link

Using lean for save? #1723

Closed imrefazekas closed 9 years ago

imrefazekas commented 11 years ago

I would like to use lean option as for save. The callback of save returns also a mongoose document and not a JS object which I want to change using a lean-like call.

Using lean for queries and toObject in saves' callback functions seems like a confusion to me.

Any ideas?

nadeesha commented 11 years ago

If you don't want to use lean, then your best bet is to form a new object from the returned Mongoose object

Person.findOne({
    _id: req.user.id
}, function(err, result) {
    if (err)
        return next(err);

    return (200, {
        id: result._id,
        spouse: result.spouse,
        children: result.children
    });
});
imrefazekas commented 11 years ago

Maybe my post was not clear, sorry. I would like to use the lean but on saving operations as well. The callbacks of the save functions like "save" or "update" return with schema object and I cannot use lean to have a pure JS object. This is my problem. I would like to use lean for save and update as well.

refack commented 11 years ago

@imrefazekas, Save, Update, Create, and Remove are not "queries", so they don't take the .lean() directive as is. You could use the .toObject() method on the returned object to get it without the schema:

p.save(function (err, returned) {
  var leanObject = returned.toObject(); // has many options: http://mongoosejs.com/docs/api.html#document_Document-toObject
  assert.equal(leanObject.schema, null);
});
ORESoftware commented 8 years ago

hummity hums...save() should have a lean option?

vkarpov15 commented 8 years ago

How would you imagine save() and lean working together? AFAIK that doesn't make sense.

ORESoftware commented 8 years ago

ummm, it's a been a few days but currently it's like so

user.save(function(err,user){

      //user is full-fledged etc
});

with lean option, it would/could be

user.save({
  lean:true
},function(err,user){

      //user is *not* full-fledged etc
});

isn't that right?

vkarpov15 commented 8 years ago

@ORESoftware nope, because the 2nd parameter in the callback to save is the exact same document. Mongoose doesn't ask the database for the newly updated doc. For instance,

user.save(function(err, _user){
  user === _user; // true
});
ORESoftware commented 8 years ago

oh ok got it :) my bad

peterpeterparker commented 7 years ago

for the record, the solution provided above by @refack still work like a charm in 2017

alex-dixon commented 7 years ago

@peterpeterparker I disagree and think this is still an issue for users who want data to be returned from all database operations instead of Mongoose instances.

peterpeterparker commented 7 years ago

@alex-dixon I was just pointing out that the solution of @refack for the save operation is still valid and functional in 2017, nothing more, nothing less ;)

alex-dixon commented 7 years ago

@peterpeterparker You're right. Sorry. Shouldn't have directed that toward you.

peterpeterparker commented 7 years ago

@alex-dixon no worries

ORESoftware commented 7 years ago

should we use lean() with Model.create()?

vkarpov15 commented 7 years ago

Never because you can't use lean() with Model.create() :p

ORESoftware commented 7 years ago

got it :)

billouboq commented 3 years ago

@vkarpov15 Hi, out of curiosity why can"t we add lean on Model.create ? If it's not possible, can we create a new method that will create a document, return the new created document and be leaned ?

Edit : I can just use findOneAndUpdate with upsert true for this, but does it fail if schema is not correct ?

vkarpov15 commented 3 years ago

@billouboq because using lean with Model.create() doesn't make much sense: create() instantiates a new document and inserts it into MongoDB. Whereas lean just skips creating a document and gives you back a POJO form of existing documents in the database.

If you want to use create() to create a new doc with schema validation, but then get a POJO back, you can just do await Model.create(doc).then(doc => doc.toObject())

billouboq commented 3 years ago

For perf reasons it can happen a lot that we need to create a doc and have created document back, all of this with mongoose schéma validation but still returning a simple doc instead of a mongoose one, so toObject is not an option for us :/

vkarpov15 commented 3 years ago

You can try Model.validate() followed by insertOne(): https://mongoosejs.com/docs/api/model.html#model_Model.validate . That will validate a raw object against your schema and then insert it into MongoDB. Try that out and see if the perf benefit is worth it. lean() is primarily useful because find() can return a lot of documents, so lean() can reduce the memory overhead. Unless you have very complex documents or a lot of documents, I doubt the perf improvement of avoiding create() would be significant relative to a network round trip.

billouboq commented 3 years ago

Nice explanation, thanks for the tips ! :)