MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Como atualizar um campo usando seu valor anterior no MongoDB/Mongoose


Você não pode consultar os valores do documento que deseja atualizar, portanto, precisará de uma consulta para recuperar o documento e outra para atualizá-lo. Parece que há uma solicitação de recurso para isso em OPEN estado desde 2016.

Se você tem uma coleção com documentos que se parecem com:
{ "_id" : ObjectId("590a4aa8ff1809c94801ecd0"), "name" : "bar" }

Usando o shell do MongoDB, você pode fazer algo assim:
db.test.find({ name: "bar" }).snapshot().forEach((doc) => {
    doc.name = "foo-" + doc.name;

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

O documento será atualizado conforme o esperado:
{ "_id" : ObjectId("590a4aa8ff1809c94801ecd0"), "name": "foo-bar" }

Observe o .snapshot() call. Isso garante que a consulta não retornará um documento várias vezes porque uma operação de gravação intermediária o move devido ao aumento no tamanho do documento.

Aplicando isso ao seu exemplo do Mongoose, conforme explicado em este exemplo 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 a pena mencionar que existe um $concat operador na estrutura de agregação, mas infelizmente você não pode usá-lo em uma update consulta.

De qualquer forma, dependendo do que você precisa fazer, você pode usar isso junto com o $out operador para salvar os resultados da agregação em uma nova coleção.

Com esse mesmo exemplo, você fará:
db.test.aggregate([{
    $match: { name: "bar" }
}, {
    $project: { name: { $concat: ["foo", "-", "$name"] }}
}, {
    $out: "prefixedTest"
}]);

E uma nova coleção prefixedTest será criado com documentos que se parecem com:
{ "_id" : ObjectId("XXX"), "name": "foo-bar" }

Apenas como referência, há outra pergunta interessante sobre esse mesmo tópico com algumas respostas que vale a pena ler:Atualizar o campo MongoDB usando o valor de outro campo