I have an application with 2 models: Student, Book (see below). Whenever a book is added, I would like it to be appended to the books array of every student model. The updateMany function of Mongoose should by my understanding do that, although it never updates the array.
POST function to create a new book object based on given ISBN and append it to every books array of the student model:
if (req.isAuthenticated()) {
if (req.body.ISBN && req.body.dueDate) {
https.get('https://www.googleapis.com/books/v1/volumes?q=isbn:' + req.body.ISBN, function (hres) {
var body = "";
hres.on('data', function (chunk) {
body += chunk;
});
hres.on('end', function () {
var resp = JSON.parse(body);
const newBook = new book({
title: resp.items[0].volumeInfo.title,
length: resp.items[0].volumeInfo.pageCount,
author: resp.items[0].authors,
ISBN: req.body.ISBN,
finished: false,
dueDate: req.body.dueDate
});
newBook.save();
student.updateMany({},{$push: {books:newBook}})
});
});
res.redirect('/admin')
}
else {
res.redirect('/newBook');
}
}
else {
res.redirect('/Login')
}
Student model:
const mongoose = require('mongoose');
const bookSchema = require('./book').schema;
const studentSchema = new mongoose.Schema({
name:{
type: String,
required: true
},
books:{
type: [bookSchema]
}
});
module.exports = mongoose.model("student", studentSchema);
Book model:
const mongoose = require('mongoose');
const bookSchema = new mongoose.Schema({
title:{
type: String
},
length:{
type:Number
},
author:{
type:String
},
ISBN:{
type:String
},
finished:{
type:Boolean
},
dueDate:{
type:String
}
});
module.exports = mongoose.model("book", bookSchema);
2
Answers
student.updateMany({},{$push: {books:newBook}})
is the correct syntax but need theawait
word to properly works if you are using promises.If you want to use callBacks you need to add the
.exec()
at the end of the operation so you are telling mongoose to run that command.Using async await (wich i recommend)
remmer you need to run to add the async word on the higher function to be able to use await, on you code shoud be here
As mentioned by Fernando, your existing solution requires
await
keyword for proper execution. And to useawait
, you have to convert the existing function toasync
function. On top of that, it is also encouraged to useasync-await
instead of callback chains for better readability.Remark
Also note that, once you call
new book()
, mongoose will create new unique_id
. It means, if you call this function multiple times with the same ISBN, yourbooks
collection andbooks
array ofstudents
collection will end up containing the same books with same ISBN, but different_id
. So, one possible strategy is to have 2 functions, one which handles new book creation and the other one which handles book update, e.g. updatingdueDate
of existing book. Then, we may want to check for existing book in theaddNewBook
function prior to adding new book. Thus, function for adding new book could be written as follows