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

Atualização simultânea de elementos de matriz que são documentos incorporados no MongoDB


O processo aqui é realmente bastante simples, varia apenas em onde você deseja "encontrar ou criar" os elementos no array.

Primeiro, supondo que os elementos de cada chave já estejam no lugar, o caso simples é consultar o elemento e atualizar com o índice retornado por meio do posicional $ operador:
db.collection.update(
   {
       "_id": docId, 
       "attrs": { "$elemMatch": { "key": "A1", "type": "T1" } }
   }
   { "$set": { "attrs.$.value": "20" }
)

Isso só modificará o elemento correspondente sem afetar os outros.

No segundo caso em que "localizar ou criar" é necessário e a chave específica pode não existir, você usa "duas" instruções de atualização. Mas a API de operações em massa permite que você faça isso em uma única solicitação ao servidor com uma única resposta:
var bulk = db.collection.initializeOrderedBulkOp();

// Try to update where exists
bulk.find({
    "_id": docId,
    "attrs": { "$elemMatch": { "key": "A1", "type": "T2" } }
}).updateOne({
    "$set": { "attrs.$.value": "30" }
});

// Try to add where does noes not exist
bulk.find({
    "_id": docId,
    "attrs": { "$not": { "$elemMatch": { "key": "A1", "type": "T2" } } }
}).updateOne({
    "$push": { "attrs": { "key": "A1", "type": "T2", "value": "30" } }
});

bulk.execute();

A lógica básica é que primeiro a tentativa de atualização é feita para corresponder um elemento com os valores necessários, exatamente como feito antes. A outra condição testa onde o elemento não é encontrado revertendo a lógica de correspondência com $not .

No caso em que o elemento da matriz não foi encontrado, um novo é válido para adição via $push .

Devo acrescentar que, como estamos procurando especificamente por correspondências negativas aqui, é sempre uma boa ideia corresponder ao "documento" que você pretende atualizar por algum identificador exclusivo, como o _id chave. Embora seja possível com atualizações "múltiplas", você precisa ter cuidado com o que está fazendo.

Portanto, no caso de executar o processo "localizar ou criar", o elemento que não foi correspondido é adicionado à matriz corretamente, sem interferir em outros elementos, também a atualização anterior para uma correspondência esperada é aplicada da mesma maneira:
{
    "_id" : ObjectId("55b570f339db998cde23369d"),
    "attrs" : [
            {
                    "key" : "A1",
                    "type" : "T1",
                    "value" : "20"
            },
            {
                    "key" : "A2",
                    "type" : "T2",
                    "value" : "14"
            },
            {
                    "key" : "A1",
                    "type" : "T2",
                    "value" : "30"
            }
    ]
}

Este é um padrão simples de seguir e, claro, as Operações em Massa aqui removem qualquer sobrecarga envolvida no envio e recebimento de várias solicitações de e para o servidor. Tudo isso funciona felizmente sem interferir em outros elementos que podem ou não existir.

Além disso, existem os benefícios extras de manter os dados em uma matriz para facilitar a consulta e a análise, conforme suportado pelos operadores padrão, sem a necessidade de reverter para o processamento do servidor JavaScript para percorrer os elementos.