I created an object within my MongoDb database. The object has the following scheme:
var goalsSchema = new mongoose.Schema({
types: [String],
start: String,
end: String,
});
var userSchema = new mongoose.Schema({
name: String,
surname: String,
email: String,
goals: [goalsSchema],
});
When I insert the object, through router.post()
, everything works fine, But when I try to add a string inside the Types property, it doesn't work. The terminal tells me that everything worked, with code 200
, but in reality the database is not updated.
This is code inside index.js
:
const mongoose = require("mongoose");
mongoose
.connect("mongodb://127.0.0.1:27017/meditactive", {
useUnifiedTopology: true,
useNewUrlParser: true,
})
.then(() => console.log("Server connected"))
.catch((err) => console.log(err));
var db = mongoose.connection;
const goalsRouter = require("./routes/goals");
app.use(express.json());
app.use(mongoSanitize());
app.use("/api/goal", goalsRouter);
app.listen(3000);
while this is the one within routes/goals
:
const mongoose = require("mongoose");
router.post("/:id/goals/:idgoal/edit", (req, res) => {
const { id } = req.params;
const { idgoal } = req.params;
const goalInsert = req.body;
User.findById(id)
.then((user) => {
if (user) {
const goalToModify = user.goals.find(
(goal) => goal._id.toString() === idgoal
);
console.log(goalToModify);
if (goalToModify) {
goalToModify.types.push(goalInsert);
user.markModified("goals");
user
.save()
.then(() => {
res.status(200).json({ message: "Goals added" });
})
.catch((err) => {
res.status(500).json({ error: err });
});
} else {
res.status(500).json({ error: err });
}
}
})
.catch((err) => {
res.status(500).json({ error: err });
});
});
I make the request with Postman
, I send a string between double quotes, I receive the message: Goals added
but inside types I see an empty object and not my string
For this type of update you can use mongoose findOneAndUpdate()
method. I will give an example using async/await
as you seem to be heading for nested then
blocks which can cause issues as your application grows.
router.post("/:id/goals/:idgoal/edit", async (req, res) => { //< Note the use of async keyword
try { // Wrap in a try catch for cleaner error handling
const { id } = req.params;
const { idgoal } = req.params;
const goalInsert = req.body;
const user = await User.findOneAndUpdate( //< Note the use of await
{
_id: new mongoose.Types.ObjectId(id), //< Find user with this _id
"goals._id": new mongoose.Types.ObjectId(idgoal), // But also with this idgoal
},
{
$push: { //< Push in the goals.types array
"goals.$.types": goalInsert
}
}, {new: true} //< This option returns the updated document
);
console.log(user);
res.status(200).json({ message: "Goals added" });
} catch(err){
res.status(500).json({ error: err });
}
});
This uses $push to push the items to your types
array.
If however, you need the types
array to be a unique list of values in the array then you will need to use $addToSet instead like so.
const user = await User.findOneAndUpdate( //< Note the use of await
{
_id: new mongoose.Types.ObjectId(id), //< Find user with this _id
"goals._id": new mongoose.Types.ObjectId(idgoal), // But also with this idgoal
},
{
$addToSet: { //< Add unique value in the goals.types array
"goals.$.types": goalInsert
}
}, {new: true} //< This option returns the updated document
);