Dado este documento salvo no MongoDB
{
_id : ...,
some_key: {
param1 : "val1",
param2 : "val2",
param3 : "val3"
}
}
Um objeto com novas informações dentro param2
e param3
fora do mundo precisa ser salvo
var new_info = {
param2 : "val2_new",
param3 : "val3_new"
};
Desejo mesclar / sobrepor os novos campos sobre o estado existente do objeto para que o param1 não seja removido
Fazendo isso
db.collection.update( { _id:...} , { $set: { some_key : new_info } }
Isso levará o MongoDB a fazer exatamente o que foi solicitado e define some_key para esse valor. substituindo o antigo.
{
_id : ...,
some_key: {
param2 : "val2_new",
param3 : "val3_new"
}
}
Como é que o MongoDB atualiza apenas novos campos (sem declará-los um por um explicitamente)? para conseguir esta:
{
_id : ...,
some_key: {
param1 : "val1",
param2 : "val2_new",
param3 : "val3_new"
}
}
Estou usando o cliente Java, mas qualquer exemplo será apreciado
mongodb
mongodb-java
Eran Medan
fonte
fonte
Respostas:
Se entendi a pergunta corretamente, você deseja atualizar um documento com o conteúdo de outro documento, mas apenas os campos que ainda não estão presentes, e ignora completamente os campos que já estão definidos (mesmo que com outro valor).
Não há como fazer isso em um único comando.
Você deve consultar o documento primeiro, descobrir o que deseja
$set
e depois atualizá-lo (usando os valores antigos como um filtro correspondente para garantir que você não receba atualizações simultâneas).Outra leitura da sua pergunta seria a sua satisfação
$set
, mas não deseja definir explicitamente todos os campos. Como você passaria os dados então?Você sabe que pode fazer o seguinte:
fonte
db.collection.update( { _id:...} , { $set: someObjectWithNewData, { $multi: true } } )
Eu resolvi isso com minha própria função. Se você deseja atualizar o campo especificado no documento, precisa tratá-lo claramente.
Exemplo:
Se você deseja atualizar apenas o param2, é errado fazer:
Você deve usar:
Então, eu escrevi uma função algo como isso:
fonte
db.users.update( { _id: ObjectId("594dbc3186bb5c84442949b1") }, { $set: { resume: { url: "http://i.imgur.com/UFX0yXs.jpg" } } } )
Você pode usar a notação de ponto para acessar e definir campos profundamente nos objetos, sem afetar as outras propriedades desses objetos.
Dado o objeto que você especificou acima:
Podemos atualizar apenas
some_key.param2
esome_key.param3
:Você pode se aprofundar o quanto quiser. Isso também é útil para adicionar novas propriedades a um objeto sem afetar as existentes.
fonte
A melhor solução é extrair propriedades do objeto e torná-las pares de valor-chave de notação de ponto simples. Você pode usar, por exemplo, esta biblioteca:
https://www.npmjs.com/package/mongo-dot-notation
Tem
.flatten
função que permite alterar o objeto em um conjunto plano de propriedades que podem ser atribuídas ao modificador $ set, sem preocupações de que qualquer propriedade do seu objeto de banco de dados existente seja excluída / substituída sem necessidade.Extraído de
mongo-dot-notation
documentos:E então forma o seletor perfeito - ele atualizará SOMENTE as propriedades dadas. EDIT: Eu gosto de ser arqueólogo algumas vezes;)
fonte
O Mongo permite atualizar documentos aninhados usando uma
.
convenção. Veja: Atualizando documentos aninhados no mongodb . Aqui está outra pergunta do passado sobre uma atualização de mesclagem, como a que você está procurando, acredito: Atualização atômica do MongoDB via documento 'mesclado'fonte
Eu tive sucesso fazendo assim:
Eu tenho uma função que lida com minhas atualizações de perfil dinamicamente
Nota: 'profile' é específico da minha implementação, é apenas a string da chave que você deseja modificar.
fonte
Parece que você pode definir isPartialObject que pode realizar o que você deseja.
fonte
Se você tiver vários campos a serem atualizados
fonte
Iniciando
Mongo 4.2
,db.collection.update()
pode aceitar um pipeline de agregação, que permite o uso de operadores de agregação, como$addFields
, que gera todos os campos existentes nos documentos de entrada e nos campos adicionados recentemente:A primeira parte
{}
é a consulta de correspondência, filtrando quais documentos atualizar (neste caso, todos os documentos).A segunda parte
[{ $addFields: { some_key: new_info } }]
é o pipeline de agregação de atualização:$addFields
.$addFields
executa exatamente o que você precisa: atualizando o objeto para que o novo objeto se sobreponha / mescle com o existente:{ param2: "val2_new", param3: "val3_new" }
será mesclado ao existentesome_key
mantendo-separam1
intocado e adicione ou substitua ambosparam2
eparam3
.Não se esqueça
{ multi: true }
, caso contrário, apenas o primeiro documento correspondente será atualizado.fonte
para
Espero que esta ajuda!
fonte
Você pode preferir fazer um upsert, essa operação no MongoDB é utilizada para salvar o documento na coleção. Se o documento corresponder aos critérios de consulta, ele executará a operação de atualização, caso contrário, ele inserirá um novo documento na coleção.
algo semelhante como abaixo
fonte
use $ set faça este processo
fonte
Faça um objeto de atualização com os nomes das propriedades, incluindo o caminho de ponto necessário. ("somekey." + do exemplo do OP) e use isso para fazer a atualização.
fonte
Sim, a melhor maneira é converter a notação de objeto em uma representação simples de cadeia de valor-chave, conforme mencionado neste comentário: https://stackoverflow.com/a/39357531/2529199
Eu queria destacar um método alternativo usando esta biblioteca do NPM: https://www.npmjs.com/package/dot-object, que permite manipular objetos diferentes usando a notação de ponto.
Usei esse padrão para criar programaticamente uma propriedade de objeto aninhado ao aceitar o valor-chave como variável de função, da seguinte maneira:
Esse padrão me permite usar propriedades aninhadas e de nível único de forma intercambiável e inseri-las corretamente no Mongo.
Se você precisar brincar com objetos JS além do Mongo, especialmente no lado do cliente, mas tiver consistência ao trabalhar com o Mongo, esta biblioteca oferece mais opções do que o
mongo-dot-notation
módulo NPM mencionado anteriormente .PS: Eu originalmente queria mencionar isso como um comentário, mas aparentemente meu representante de S / O não é alto o suficiente para postar um comentário. Portanto, não tentando usar o comentário de SzybkiSasza, só queria destacar o fornecimento de um módulo alternativo.
fonte
eu tentei
findAndModify()
atualizar um campo específico em um objeto preexistente.https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/
fonte
Você deve pensar em atualizar o objeto de forma intercambiável e, em seguida, simplesmente armazenar o objeto com os campos atualizados. Algo como feito abaixo
fonte
Você precisa usar Documentos Incorporados (stringfy o objeto path)
E assim, em JavaScript, você pode usar o Spread Operator (...) para atualizar
fonte