I'm trying to update a specific field in a subdocument based on its Id and the Id of the parent document. I'm new to this so I may be misunderstanding the mongoDb documentation but as far as I can tell findOneAndUpdate should be working. I've also tried just update, updateOne, as well as findByIdAndUpdate. Nothing I've tried has successfully updated my object.
Im trying to update the rating value in a particular object in the savedBeers array.
Here is my model:
{
"_id": {
"$oid": "5c97cf50cc81525a75eb6c19"
},
"email": "[email protected]",
"password": "$2b$10$6ixbu2Ka.Zj0eE5kF21MLO6CiMblgu4D6IHiC7Ta52o.cZFMNw1Mm",
"__v": 0,
"savedBeers": [
{
"id": 2,
"comment": null,
"rating": 0
},
{
"id": 4,
"comment": null,
"rating": 0
}
]
}
Frontend:
function addRating(beerId, ratingValue){
let userId= localStorage.userId
console.log(beerId, userId, ratingValue);
$.ajax({
type: "PUT",
url: `/user/${userId}/${beerId}/${ratingValue}`,
success: addRatingSuccess,
error: addRatingError
});
function addRatingSuccess(response) {
console.log("added", response);
}
function addRatingError() {
console.log("error");
}
}
Backend userController.js:
addRating:(req,res)=>{
console.log(req.params);
req.params.beerId = parseInt(req.params.beerId)
req.params.ratingValue = parseInt(req.params.ratingValue)
db.User.findOneAndUpdate(
{_id: ObjectId(req.params.userId), "savedBeers.id": req.params.beerId },
{ $set: { 'savedBeers.$.rating' : req.params.ratingValue } },
{new:true})
.exec(function (err, doc){
if (err){
console.log(err);
res.json({
"error": err
})
} else {
console.log(doc);
res.json({
doc
})
}
})
}
This is the response I get in the front end:
added
{doc: {…}}
doc:
email: "[email protected]"
savedBeers: Array(2)
0: {id: 2, comment: null, rating: 0}
1: {id: 4, comment: null, rating: 0}
length: 2
__proto__: Array(0)
__v: 0
_id: "5c97cf50cc81525a75eb6c19"
__proto__: Object
__proto__: Object
And the backend:
{ userId: '5c97cf50cc81525a75eb6c19', beerId: 4, ratingValue: 3 }
{ savedBeers:
[ { id: 2, comment: null, rating: 0 },
{ id: 4, comment: null, rating: 0 } ],
_id: 5c97cf50cc81525a75eb6c19,
email: '[email protected]',
__v: 0 }
Thanks so much for taking the time. Please let me know if there is any other information that would be helpful.
findByIdAndUpdate()since that only accepts an_idvalue only. You wantfindOneAndUpdate()instead and you also typically wantnew: truewith either. Will not reopen since the linked answer is indeed the answer, it's just that you are still doing things wrong. Read answers and linked documentation again.db.your_collection.update( { _id: ObjectId("your_objectid"), "Statuses.Type": 1 }, { $set: { "Statuses.$.Timestamp": "new timestamp" } } )looks pretty mush the same as this:db.User.findOneAndUpdate( {_id: ObjectId(req.params.userId), "savedBeers.id": req.params.beerId }, { $set: { 'savedBeers.$.rating' : req.params.ratingValue } }, { new:true})}n: 0. That means nothing matched. You are using the plain node driver so things likefindByIdAndUpdateare not even valid."savedBeers.id": parseIntr(req.params.beerId)- That is you problem all along as yout needparseInt(). Just as important as theObjectId()where that is used and for the same reasonreq.paramsare "strings"** so you need to cast them. What was throwing me was your usage offindByIdAndUpdate()in the question, which is a mongoose method and not part of this driver. Mongoose has schema definitions that "autocast" values in query predicates to the expected type. For anything else you do it manually.