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

MongoDB - $set para atualizar ou enviar o elemento Array


Na verdade, fazer o que parece que você diz que está fazendo não é uma operação singular, mas vou percorrer as partes necessárias para fazer isso ou cobrir outras situações possíveis.

O que você está procurando é, em parte, o $ posicional operador. Você precisa de parte da sua consulta para também "encontrar" o elemento da matriz que deseja.
db.products.update(
    { 
        "_id": ObjectId("536c55bf9c8fb24c21000095"),
        "recentviews.viewedby": "abc"
    },
    { 
        "$set": { 
            "recentviews.$.vieweddate": ISODate("2014-05-09T04:12:47.907Z")
        }
    }
)

Portanto, o $ representa a posição correspondente na matriz para que a parte de atualização saiba qual item da matriz atualizar. Você pode acessar campos individuais do documento na matriz ou apenas especificar o documento inteiro para atualizar nessa posição.
db.products.update(
    { 
        "_id": ObjectId("536c55bf9c8fb24c21000095"),
        "recentviews.viewedby": "abc"
    },
    { 
        "$set": { 
            "recentviews.$": {
                 "viewedby": "abc",
                 "vieweddate": ISODate("2014-05-09T04:12:47.907Z")
        }
    }
)

Se os campos não mudarem de fato e você quiser apenas inserir um novo elemento de array se o mesmo não existir, então você pode usar $addToSet
db.products.update(
    { 
        "_id": ObjectId("536c55bf9c8fb24c21000095"),
        "recentviews.viewedby": "abc"
    },
    { 
        $addToSet:{ 
            "recentviews": {
                 "viewedby": "abc",
                 "vieweddate": ISODate("2014-05-09T04:12:47.907Z")
        }
    }
)

No entanto, se você estiver apenas procurando por "empurrar" para uma matriz por um valor de chave singular, se isso não existir, precisará fazer mais manipulação manual, primeiro vendo se o elemento na matriz existe e, em seguida, fazendo o $push declaração onde não.

Você obtém ajuda dos métodos do mangusto para fazer isso, rastreando o número de documentos afetados pela atualização:
Product.update(
    { 
        "_id": ObjectId("536c55bf9c8fb24c21000095"),
        "recentviews.viewedby": "abc"
    },
    { 
        "$set": { 
            "recentviews.$": {
                 "viewedby": "abc",
                 "vieweddate": ISODate("2014-05-09T04:12:47.907Z")
        }
    },
    function(err,numAffected) {

        if (numAffected == 0) {
            // Document not updated so you can push onto the array
            Product.update(
                { 
                    "_id": ObjectId("536c55bf9c8fb24c21000095")
                },
                { 
                    "$push": { 
                        "recentviews": {
                            "viewedby": "abc",
                            "vieweddate": ISODate("2014-05-09T04:12:47.907Z")
                        }
                    }
                },
                function(err,numAffected) {

                }
            );
        }            

    }
);

A única palavra de cautela aqui é que há uma pequena mudança de implementação nas mensagens writeConcern do MongoDB 2.6 para versões anteriores. Não tendo certeza agora de como a API do mangusto realmente implementa o retorno do numAffected argumento no retorno de chamada a diferença pode significar algo.

Nas versões anteriores, mesmo que os dados enviados na atualização inicial correspondessem exatamente a um elemento existente e não houvesse nenhuma alteração real necessária, o valor "modificado" seria retornado como 1 mesmo que nada foi realmente atualizado.

A partir do MongoDB 2.6, a resposta de preocupação de gravação contém duas partes. Uma parte mostra o documento modificado e a outra mostra a correspondência. Portanto, embora a correspondência seja retornada pela parte da consulta que corresponde a um elemento existente, a contagem real do documento modificado retornaria como 0 se de fato não houvesse nenhuma mudança necessária.

Portanto, dependendo de como o número de retorno é realmente implementado no mangusto, pode ser mais seguro usar o $addToSet operador nessa atualização interna para garantir que, se o motivo dos zero documentos afetados não fosse apenas que o elemento exato já existia.