Issue
I’m currently building a REST-Api with node.js express and can’t figure out how to update / add elements to the scores Array.
Here is one document from my MongoDB collection (how it should look):
My mongoose model:
const challengesSchema = new mongoose.Schema({
createdBy:{
type:String,
required: true
},
mapType:{
type:String,
required: true
},
time:{
type:Number,
required: true
},
numberOfMaps:{
type:String,
required: true
},
maps:{
type:Array,
required: true
},
pin:{
type: String,
required: true
},
takenBy:{
type: Array,
required: false
}
})
Basically I receive an id, which I can use to do Challenges.findById({challenge._id})
.
I figured out how to add an object to the takenBy Array
, like so:
Challenges.findOneAndUpdate(
{ _id: challenge._id },
{
$push: {
takenBy: user
}
}
);
How can I add an element (score, like “20”) to the scores array in the array ‘takenBy’ ?
Solution
You can push score and calculate the new TotalScore in one go using filtered positional operator $ like this.
router.put("/challenges/:id/:scoreId", async (req, res) => {
let score = req.body.score;
try {
let result = await Challenges.findByIdAndUpdate(
req.params.id,
{
$push: { "takenBy.$[inner].scores": score },
$inc: {
"takenBy.$[inner].TotalScore": score
}
},
{
arrayFilters: [{ "inner._id": req.params.scoreId }],
new: true
}
);
if (!result) return res.status(404);
res.send(result);
} catch (err) {
console.log(err);
res.status(500).send("Something went wrong");
}
});
Test:
Let’s have this existing document:
{
"_id" : ObjectId("5e08fe4c0bc1b932e8726a0f"),
"maps" : [ ],
"takenBy" : [
{
"_id" : "id1",
"TotalScore" : NumberInt(100),
"scores" : [
NumberInt(20),
NumberInt(60),
NumberInt(20)
]
},
{
"_id" : "id2",
"TotalScore" : NumberInt(30),
"scores" : [
NumberInt(10),
NumberInt(20)
]
}
],
"createdBy" : "5dfe0...",
"mapType" : "World",
"time" : NumberInt(2),
"numberOfMaps" : "2",
"pin" : "9558",
"__v" : NumberInt(0)
}
If we want to add a score of 50 to then id1, we send a PUT request (http://…./challenges/5e08fe4c0bc1b932e8726a0f/id1) with this body:
{
"score": 50
}
The result will be like this:
{
"_id" : ObjectId("5e08fe4c0bc1b932e8726a0f"),
"maps" : [ ],
"takenBy" : [
{
"_id" : "id1",
"TotalScore" : NumberInt(150),
"scores" : [
NumberInt(20),
NumberInt(60),
NumberInt(20),
NumberInt(50)
]
},
{
"_id" : "id2",
"TotalScore" : NumberInt(30),
"scores" : [
NumberInt(10),
NumberInt(20)
]
}
],
"createdBy" : "5dfe0...",
"mapType" : "World",
"time" : NumberInt(2),
"numberOfMaps" : "2",
"pin" : "9558",
"__v" : NumberInt(0)
}
As you see the score is added to the related item array, and it’s TotalScore is also incremented by 50 giving the TotalScore 150
Answered By – SuleymanSah
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0