sql >> Base de Datos >  >> NoSQL >> MongoDB

Cómo actualizar un campo usando su valor anterior en MongoDB/Mongoose

No puede hacer referencia a los valores del documento que desea actualizar, por lo que necesitará una consulta para recuperar el documento y otra para actualizarlo. Parece que hay una solicitud de función para eso en OPEN estado desde 2016.

Si tiene una colección con documentos que se parecen a:

{ "_id" : ObjectId("590a4aa8ff1809c94801ecd0"), "name" : "bar" }

Usando el shell de MongoDB, puede hacer algo como esto:

db.test.find({ name: "bar" }).snapshot().forEach((doc) => {
    doc.name = "foo-" + doc.name;

    db.test.save(doc);
});

El documento se actualizará como se esperaba:

{ "_id" : ObjectId("590a4aa8ff1809c94801ecd0"), "name": "foo-bar" }

Tenga en cuenta el .snapshot() llamada. Esto asegura que la consulta no devolverá un documento varias veces porque una operación de escritura intermedia lo mueve debido al crecimiento del tamaño del documento.

Aplicando esto a su ejemplo Mongoose, como se explica en este ejemplo oficial :

Cat.findById(1, (err, cat) => {
    if (err) return handleError(err);

    cat.name = cat.name + "bar";

    cat.save((err, updatedCat) => {
        if (err) return handleError(err);

        ...
    });
});

Vale la pena mencionar que hay un $concat operador en el marco de agregación, pero desafortunadamente no puede usarlo en una update consulta.

De todos modos, dependiendo de lo que necesite hacer, puede usarlo junto con $out operador para guardar los resultados de la agregación en una nueva colección.

Con ese mismo ejemplo, harás:

db.test.aggregate([{
    $match: { name: "bar" }
}, {
    $project: { name: { $concat: ["foo", "-", "$name"] }}
}, {
    $out: "prefixedTest"
}]);

Y una nueva colección prefixedTest se creará con documentos que se parecen a:

{ "_id" : ObjectId("XXX"), "name": "foo-bar" }

Solo como referencia, hay otra pregunta interesante sobre este mismo tema con algunas respuestas que vale la pena leer:Actualizar el campo MongoDB usando el valor de otro campo