Estoy tratando de averiguar cómo actualizar un valor de objeto específico que se encuentra dentro de una matriz de objetos. Probablemente me falta la respuesta o no puedo implementar la respuesta correctamente, pero agradecería algo de ayuda ya que estoy tratando de resolverlo desde hace algún tiempo.
Tengo una base de datos de Mongo llamada todoListDB, dentro hay una colección llamada listas. Cada documento dentro de las listas es una sola lista de tareas pendientes. Cada documento tiene un nombre de lista y una matriz de elementos. Cada elemento de la matriz es una sola tarea. Cada objeto de tarea tiene un nombre y un valor marcado. Me gustaría poder actualizar el valor marcado de 0 a 1.
Aquí hay parte del código con ejemplos de lo que he intentado.
// 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); } });He podido resolver mi propia pregunta. El truco parece ser que tienes que usar filtros de matriz.
// 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); } });