Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mongoose Model.update() - only update provided values

I have the following schema:

const wordSchema = mongoose.Schema({
  author: {type: String, index: true, default: 'unknown'},
  quote: String,
  source: {type: String, default: 'unknown', index: true},
  rating: {type: Number, default: 0},
  createdAt: {type: Date, default: Date.now},
  updatedAt: {type: Date, default: Date.now},
});

And the following PUT route in my express app:

// Route to update a quote in the DB
app.put('/words/:id', function(req, res) {
  const quote = new Word({
    _id: req.params.id,
    author: req.body.author,
    quote: req.body.quote,
    source: req.body.source,
    rating: req.body.rating,
    updatedAt: Date.now(),
  });
  Word.update(quote, function(err, raw) {
    if (err) {
      res.send(err);
    }
    res.send(raw);
  });
});

Now when I send the PUT request, if the parameters set with a default value are not provided, they will be filled with the default values from the Schema. How do I update only the provided values?

Thanks for the help.

like image 447
Miha Šušteršič Avatar asked Nov 07 '16 13:11

Miha Šušteršič


People also ask

How do I use Findone update?

As the name implies, findOneAndUpdate() finds the first document that matches a given filter , applies an update , and returns the document. By default, findOneAndUpdate() returns the document as it was before update was applied. You should set the new option to true to return the document after update was applied.

What does $Set do in Mongoose?

The $set operator replaces the value of a field with the specified value. The $set operator expression has the following form: { $set: { <field1>: <value1>, ... } } To specify a <field> in an embedded document or in an array, use dot notation.

What is Mongoose model ()?

A Mongoose model is a wrapper on the Mongoose schema. A Mongoose schema defines the structure of the document, default values, validators, etc., whereas a Mongoose model provides an interface to the database for creating, querying, updating, deleting records, etc.

Can I set default value in Mongoose schema?

You can also set the default schema option to a function. Mongoose will execute that function and use the return value as the default.


2 Answers

Don't create a new Word instance for the update, update takes conditions and doc object parameters that let you separately identify the document to update and provide its updated values:

app.put('/words/:id', function(req, res) {
  const doc = {
    author: req.body.author,
    quote: req.body.quote,
    source: req.body.source,
    rating: req.body.rating,
    updatedAt: Date.now(),
  });
  Word.update({_id: req.params.id}, doc, function(err, raw) {
    if (err) {
      res.send(err);
    }
    res.send(raw);
  });
});
like image 152
JohnnyHK Avatar answered Sep 18 '22 23:09

JohnnyHK


You can try using the Model.findByIdAndUpdate() method where all top level update keys which are not atomic operation names are treated as set operations and defaults/setters are never executed. You can use lodash's _.assign() method to set the updatedAt field:

// Route to update a quote in the DB
app.put('/words/:id', function(req, res) {
    const update = _.assign({ "updatedAt": new Date() }, req.body);
    Word.findByIdAndUpdate(req.params.id, update, function(err, raw) {
        if (err) {
            res.send(err);
        }
        res.send(raw);
    });
});
like image 21
chridam Avatar answered Sep 20 '22 23:09

chridam