Considere que tengo este documento en mi colección MongoDB, Workout:
{ _id: ObjectId("60383b491e2a11272c845749") <--- Workout ID user: ObjectId("5fc7d6b9bbd9473a24d3ab3e") <--- User ID exercises: [ { _id: ObjectId("...") <--- Exercise ID exerciseName: "Bench Press", sets: [ { _id: ObjectId("...") <--- Set ID }, { _id: ObjectId("...") <--- Set ID } ] } ] }El objeto Workout puede incluir muchos objetos de ejercicio en la matriz de ejercicios y cada objeto de ejercicio puede tener muchos objetos establecidos en la matriz de conjuntos. Estoy tratando de implementar una funcionalidad de eliminación para un determinado conjunto. Necesito recuperar el entrenamiento en el que está almacenado el conjunto que quiero eliminar. Tengo acceso a la ID del usuario (almacenada en un contexto), la ID del ejercicio y la ID del conjunto que quiero eliminar como parámetros para .findOne() función. Sin embargo, no estoy seguro de poder atravesar los diferentes niveles de matrices y objetos dentro del objeto de entrenamiento. Esto es lo que he probado:
const user = checkAuth(context) // Gets logged in user details (id, username) const exerciseID, setID // Both of these are passed in already and are set to the appropriate values const workoutLog = Workout.findOne({ user: user.id, exercises: { _id: exerciseID } });Esto devuelve una matriz vacía, pero espero el objeto de entrenamiento completo que contiene el conjunto que quiero eliminar. Me gustaría omitir el ID de ejercicio de los parámetros de esta función y solo usar el ID de conjunto, pero no estoy seguro de cómo atravesar la matriz de objetos para acceder a su valor. ¿Es esto posible o debería hacerlo de otra manera? Gracias.
Al comparar con una matriz, si especifica la consulta de esta manera:
{ exercises: { _id: exerciseID } } MongoDB intenta hacer una coincidencia exacta en el documento . Entonces, en este caso, MongoDB solo coincidiría con documentos en la matriz de exercises de la forma exacta { _id: ObjectId("...") } . Debido a que los documentos en los exercises tienen otros campos, esto nunca producirá una coincidencia, incluso si los _id son los mismos.
Lo que desea hacer en su lugar es consultar un campo de los documentos en la matriz . El documento de consulta completo se vería así:
{ user: user.id, "exercises._id": exerciseID }Puede realizar tanto la búsqueda como la actualización en un solo paso. Prueba esto:
db.Workout.updateOne( { "user": ObjectId("5fc7d6b9bbd9473a24d3ab3e"), }, { $pull: { "exercises.$[exercise].sets": { "_id": ObjectId("6039709fe0c7d52970d3fa30") // <--- Set ID } } }, { arrayFilters: [ { "exercise._id" : ObjectId("6039709fe0c7d52970d3fa2e") // <--- Exercise ID } ] } );