Reputation: 15
So what I basically want to do is create a new array of users from existing mongoose documents. I have a users array in my database. Each user has a attribute booksBorrowed which is also a array and I need to replace this with another object retrieved from a Book Model. I know that I can use populate function to do this. But in the booksBorrowed array I have some other values like Date and a boolean. So I can't use that function. Please help me out :). Thanks in advance.
router.get("/users",isAdmin, function(req,res){
User.find({}, function(err, users){
if (err){
console.log(err);
}
else {
var modifiedUsers = [];
for (const user of users) {
var booksBorrowed = [];
function async pushBook(book) {
await booksBorrowed.push(book)
}
if(user.booksBorrowed){
for (const book of user.booksBorrowed){
Book.findById(book[0], function(err, bookFound){
if(err){
console.log(err);
}
pushBook(bookFound);
});
};
}
console.log(booksBorrowed);
user.booksBorrowed = booksBorrowed;
modifiedUsers.push(user);
};
res.render("users", {users: modifiedUsers});
}
});
When I console.log(booksBorrowed) All I see is a list of empty arrays. Maybe the variable doesn't get updated or the process of pushing doesn't complete and the rest of the code runs.
Upvotes: 0
Views: 36
Reputation: 707318
There are a number of issues with your code. Primarily, it shows that you don't understand how await
works and then probably don't understand how it relates to promises. Here are some points:
await
only does something useful when you await
a promise that is linked to the asynchronous operation you're trying to wait on. So await booksBorrowed.push(book)
does nothing useful.await
and for control flow.modifiedUsers
array looks like maybe there's a problem because the way your code is written, it's the exact same array as users
since you add every single user to the modifiedUsers
array. If you meant for it to be only users who have borrowed a book, then you will need clarify that in your question and adjust the logic to actually do that.user.booksBorrowed
array to only be the first item in that array. So if there is more than one book in that array, it will never be used and your code will replace user.booksBorrowed
with only a single element array. This doesn't seem correct, but I don't know what logic you want this to be. I don't understand why you're replacing user.booksBorrowed
in the first place.Here's a rewritten version that addresses these first three issues:
router.get('/users', isAdmin, async function (req, res) {
try {
let users = await User.find({});
let modifiedUsers = [];
for (const user of users) {
let booksBorrowed = [];
if (user.booksBorrowed) {
for (const book of user.booksBorrowed) {
let bookFound = await Book.findById(book[0]);
booksBorrowed.push(bookFound);
}
}
user.booksBorrowed = booksBorrowed;
modifiedUsers.push(user);
}
res.render('users', { users: modifiedUsers });
} catch (e) {
// log error and send error status
console.log(e);
res.sendStatus(500);
}
});
Please, please read and learn about how promises work and how await
works with promises and how your database can use promises. You will need to know this to write good solid code. This is one example, but you need to learn the concepts yourself.
Upvotes: 1