I am trying to work out how to update a specific object value that sits inside an array of objects. I am probably missing the answer or am unable to implement the answer correctly, but some help would be appreciated since I am trying to work it out for some time now.
I have a Mongo data base called todoListDB, inside there is a collection called lists. Each document inside lists is a single todo list. Each document has a list name, and an item array. Each item in the array is a single task. Each task object has a name, and a checked value. I would like to be able to update the checked value from 0 to 1.
Here is some of the code with examples of what I have tried.
// todoListDB
// lists collection: each document is a singel todo list
// items: each array object has a task and a checkbox state value
// example of path structure
{todoListDB:{lists:{
// todo list
{_id: {mongoose_id}, name: "shool", items:[
{name: "do homework", checked: 0, _id:{mongoose_id}},
{name: "read book", checked: 0, _id:{mongoose_id}},
]},
// todo list
{_id: {mongoose_id}, name: "work", items:[
{name: "fix this", checked: 0, _id:{mongoose_id}},
{name: "fix that", checked: 0, _id:{mongoose_id}},
]}
}}}
// update checkbox value checked:
// from:
{name: "do homework", checked: 0, _id:{mongoose_id}}
// to:
{name: "do homework", checked: 1, _id:{mongoose_id}}
let listName = 'school';
// I can query the array items but can't change the value
List.findOne({name: listName}, async function(err, foundList){
if (!err){
let items = foundList.items;
for (let i = 0; i < items.length; ++i) {
await delayed(100);
// Working
console.log('CHECKED:', items[i].name, items[i].checked);
// Doesn't work, no errors and no changes to the checked value
items[i].checked = 1;
// Doesn't work, no errors and no changes to the checked value
foundList.updateOne({name:items[i].name},{checked:1});
}
}
});
// Doesn't work, no errors and no changes to the checked value
List.findByIdAndUpdate({_id : id}, {checked:1},{overwrite:true}, function(err, doc){
if (err){
console.log(err);
}
else{
console.log('UPDATED: ', doc)
}
});
// Doesn't work: bad value error
let update = {'$set':{'items.$.name': 'eat','items.$.checked':1}}
List.findOneAndUpdate({name:listName},update,function(err, foundList){
if (err){
console.log(err);
}
});
// Working code from tutorial to delete items from array, but can't figure out how to write/convert
// the "path" to the object value I want to change using $set
List.findOneAndUpdate({name:listName},{$pull:{items: {name:subjects[i]}}},function(err, foundList){
if (err){
console.log(err);
}
});
I have been able to solve my own question. The trick seems to be that you have to use array filters.
// Query document with name school //
let query = {name:'school'};
// Update found object in items arary, set object.checked value to 1 //
let update = {'$set':{'items.$[elem].checked':1}};
// Find in (items) array object to be updated with key value pair: name:do homework //
let arrayFilter = {arrayFilters:[{'elem.name':'do homework'}]};
List.findOneAndUpdate(query, update, arrayFilter,function(err, foundList){
if (err){
console.log(err);
}
});