Reputation: 555
I am working on my first request that would add a subdocument to a document in MongoDB and I'm struggling with it. My database is a collection of users, and each user has an array of words they working on learning to translate in the application I am building. I am currently having two issues
when I make a request in postman to add a new word to my user's array of words, I add a new object that has ID, but none of the other property value pairs that I have in the word sub-model, and in the request(greek, english, success, timestamp).
my command prompt gives me the following errors
(node:8320) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3) (node:8320) UnhandledPromiseRejectionWarning: ValidationError: user validation failed: words.0.greek: Path
greek
is required., words.0.english: Pathenglish
is required., words.0.success: Pathsuccess
is required., words.0.timeStamp: PathtimeStamp
is required.
The second error is confusing because in my mind it should be word.greek and words.english to get the value from the each word object. However, it adds a 0 between the object and its property/value pair.
My mongoose model for the subdocument is as follows
const wordSchema = new Schema({
greek: {
type: String,
required: true,
trim: true,
minlength: 1,
index: { unique: true, sparse: true },
},
english: {
type: String,
required: true,
minlength: 1
},
success: {
type: Number,
required: true
},
timeStamp: {
type: Date,
required: true
},
});
This is my request to add the word to the User's array of words.
router.post("/update/:id",(req, res) =>{
console.log(req.body.greek)
var greek = req.body.greek;
var english = req.body.english;
var success = req.body.success;
var timeStamp = req.body.timeStamp
var newWord = {
greek: greek,
english: english,
success: success,
timeStamp: timeStamp
}
User.findById(req.params.id)
.then((user) => {
user.words.push(newWord);
user.save()
res.status(200).json(user)
.catch((err) => {res.status(400).json(err)})
})
.catch((err) => {res.status(400).json("Error: "+err)})
});
Any help would be greatly appreciated! I've done some googling on adding subdocuments to a document, but I still haven't found the solution.
Upvotes: 0
Views: 69
Reputation: 2387
one thing I see is user.save()
will return a promise, which you do not handle, hence the document will not be save. maybe consider:
User.findById(req.params.id)
.then(async (user) => {
user.words.push(newWord);
await user.save()
res.status(200).json(user)
.catch((err) => {res.status(400).json(err)})
})
.catch((err) => {res.status(400).json("Error: "+err)})
Upvotes: 1
Reputation: 678
Instead of fetching and then updating the document you can directly update the document in one DB call.
router.post("/update/:id",(req, res) =>{
console.log(req.body.greek)
var greek = req.body.greek;
var english = req.body.english;
var success = req.body.success;
var timeStamp = req.body.timeStamp
var newWord = {
greek: greek,
english: english,
success: success,
timeStamp: timeStamp
}
User.findOneAndUpdate({ _id: req.params.id }, {
$push: {
words: newWord
}
})
.then((user) => {
if(!user){
return res.status(404).json({
message: 'Not User matches given ID'
});
}
res.status(200).json(user);
})
.catch((err) => {res.status(400).json("Error: "+err)})
});
Upvotes: 2