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.
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.
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.
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.
You can also set the default schema option to a function. Mongoose will execute that function and use the return value as the default.
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);
});
});
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);
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With