Saltar al contenido

Mongoose buscar/actualizar subdocumento

Este tutorial ha sido aprobado por expertos así se garantiza la exactitud de nuestro tutorial.

Solución:

Entonces, como observa, el valor predeterminado en mongoose es que cuando “incrusta” datos en un array así obtienes un _id valor para cada array entrada como parte de sus propias propiedades de subdocumento. En realidad, puede usar este valor para determinar el índice del elemento que desea actualizar. La forma MongoDB de hacer esto es el posicional $ variable de operador, que mantiene la posición “emparejada” en el array:

Folder.findOneAndUpdate(
     "_id": folderId, "permissions._id": permission._id ,
     
        "$set": 
            "permissions.$": permission
        
    ,
    function(err,doc) 

    
);

Que .findOneAndUpdate() método devolverá el documento modificado o, de lo contrario, puede usar .update() como método si no necesita que le devuelvan el documento. Las partes principales están “coincidiendo” con el elemento de la array para actualizar e “identificar” que coinciden con el posicional $ como se mencionó anteriormente.

Entonces, por supuesto, estás usando el $set operador para que solamente los elementos que especifique en realidad se envían “por cable” al servidor. Puede llevar esto más lejos con la “notación de puntos” y simplemente especificar los elementos que realmente desea actualizar. Como en:

Folder.findOneAndUpdate(
     "_id": folderId, "permissions._id": permission._id ,
     
        "$set": 
            "permissions.$.role": permission.role
        
    ,
    function(err,doc) 

    
);

Así que esta es la flexibilidad que ofrece MongoDB, donde puede ser muy “objetivo” en la forma en que realmente actualiza un documento.

Sin embargo, lo que esto hace es “pasar por alto” cualquier lógica que pueda haber incorporado en su esquema de “mangosta”, como “validación” u otros “ganchos de pre-guardado”. Esto se debe a que la forma “óptima” es una “característica” de MongoDB y cómo está diseñada. Mongoose en sí trata de ser un envoltorio de “conveniencia” sobre esta lógica. Pero si está preparado para tomar el control usted mismo, entonces las actualizaciones se pueden realizar de la manera más óptima.

Entonces, cuando sea posible, mantenga sus datos “incrustados” y no use modelos referenciados. Permite la actualización atómica de los elementos “principal” y “secundario” en actualizaciones simples en las que no necesita preocuparse por la concurrencia. Probablemente sea una de las razones por las que debería haber seleccionado MongoDB en primer lugar.

Para validar los subdocumentos al actualizar en Mongoose, debe ‘cargarlo’ como un objeto de esquema, y ​​luego Mongoose activará automáticamente la validación y los enlaces.

const userSchema = new mongoose.Schema(
  // ...
  addresses: [addressSchema],
);

si tienes un array de subdocumentos, puede obtener el deseado con el id() método proporcionado por Mongoose. Luego puede actualizar sus campos individualmente, o si desea actualizar varios campos a la vez, use el set() método.

User.findById(userId)
  .then((user) => 
    const address = user.addresses.id(addressId); // returns a matching subdocument
    address.set(req.body); // updates the address while keeping its schema       
    // address.zipCode = req.body.zipCode; // individual fields can be set directly

    return user.save(); // saves document with subdocuments and triggers validation
  )
  .then((user) => 
    res.send( user );
  )
  .catch(e => res.status(400).send(e));

Tenga en cuenta que en realidad no necesita el userId para encontrar el documento de usuario, puede obtenerlo buscando el que tiene un subdocumento de dirección que coincide addressId como sigue:

User.findOne(
  'addresses._id': addressId,
)
// .then() ... the same as the example above

Recuerda que en MongoDB se guarda el subdocumento solamente cuando se guarda el documento principal.

Lea más sobre el tema en la documentación oficial.

Si no desea una recopilación separada, simplemente inserte el esquema de permisos en el esquema de carpetas.

var folderSchema = new Schema(
    name:  type: string ,
    permissions: [ 
        role:  type: String ,
        create_folders:  type: Boolean ,
        create_contents:  type: Boolean 
     ]
);

Si necesita colecciones separadas, este es el mejor enfoque:

Podrías tener un modelo de Permiso:

var mongoose = require('mongoose');
var PermissionSchema = new Schema(
  role:  type: String ,
  create_folders:  type: Boolean ,
  create_contents:  type: Boolean 
);

module.exports = mongoose.model('Permission', PermissionSchema);

Y un modelo de Carpeta con una referencia al documento de permiso. Puede hacer referencia a otro esquema como este:

var mongoose = require('mongoose');
var FolderSchema = new Schema(
  name:  type: string ,
  permissions: [  type: mongoose.Schema.Types.ObjectId, ref: 'Permission'  ]
);

module.exports = mongoose.model('Folder', FolderSchema);

y luego llamar Folder.findOne().populate('permissions') para pedirle a mangosta que complete los permisos de campo.

Ahora, lo siguiente:

savePermission: function (folderId, permission, callback) 
    Folder.findOne( _id: folderId ).populate('permissions').exec(function (err, data) 
        var perm = _.findWhere(data.permissions,  _id: permission._id );                

        _.extend(perm, permission);

        data.markModified("permissions");
        data.save(callback);
    );

los perm El campo no estará indefinido (si el permiso._id está realmente en los permisos array), ya que ha sido poblado por Mongoose.

Recuerda algo, que tienes la capacidad de aclarar si te fue útil.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *