varios valor update una modificar mas insertar inserta documentos documento crear consultas como comandos coleccion actualizar mongodb mongodb-java

valor - ¿Cómo actualizo parcialmente un objeto en MongoDB para que el nuevo objeto se superponga/fusione con el existente?



mongodb modificar documento (9)

Dado este documento guardado en MongoDB

{ _id : ..., some_key: { param1 : "val1", param2 : "val2", param3 : "val3" } }

Se debe guardar un objeto con nueva información sobre param2 y param3 del mundo exterior

var new_info = { param2 : "val2_new", param3 : "val3_new" };

Quiero fusionar / superponer los nuevos campos sobre el estado existente del objeto para que param1 no se elimine

Haciendo esto

db.collection.update( { _id:...} , { $set: { some_key : new_info } }

Llevará a que MongoDB esté haciendo exactamente lo que se le pidió y establece some_key a ese valor. reemplazando el anterior.

{ _id : ..., some_key: { param2 : "val2_new", param3 : "val3_new" } }

¿Cuál es la forma de que MongoDB actualice solo campos nuevos (sin indicarlos uno por uno explícitamente)? para obtener esto:

{ _id : ..., some_key: { param1 : "val1", param2 : "val2_new", param3 : "val3_new" } }

Estoy usando el cliente de Java, pero cualquier ejemplo será apreciado



La mejor solución es extraer propiedades del objeto y convertirlas en pares de valores-clave de notación de puntos planos. Podría usar, por ejemplo, esta biblioteca:

https://www.npmjs.com/package/mongo-dot-notation

Tiene la función .flatten que le permite cambiar el objeto en un conjunto plano de propiedades que podrían .flatten al modificador $ set, sin preocupaciones de que cualquier propiedad de su objeto DB existente sea eliminada / sobrescrita sin necesidad.

Tomado de documentos de mongo-dot-notation :

var person = { firstName: ''John'', lastName: ''Doe'', address: { city: ''NY'', street: ''Eighth Avenu'', number: 123 } }; var instructions = dot.flatten(person) console.log(instructions); /* { $set: { ''firstName'': ''John'', ''lastName'': ''Doe'', ''address.city'': ''NY'', ''address.street'': ''Eighth Avenu'', ''address.number'': 123 } } */

Y luego forma el selector perfecto - actualizará SÓLO las propiedades dadas. EDITAR: me gusta ser arqueólogo algunas veces;)


Lo resolví con mi propia función. Si desea actualizar el campo especificado en el documento, debe abordarlo con claridad.

Ejemplo:

{ _id : ..., some_key: { param1 : "val1", param2 : "val2", param3 : "val3" } }

Si solo desea actualizar param2, es incorrecto hacerlo:

db.collection.update( { _id:...} , { $set: { some_key : new_info } } //WRONG

Debes usar:

db.collection.update( { _id:...} , { $set: { some_key.param2 : new_info } }

Entonces escribí una función algo así:

function _update($id, $data, $options=array()){ $temp = array(); foreach($data as $key => $value) { $temp["some_key.".$key] = $value; } $collection->update( array(''_id'' => $id), array(''$set'' => $temp) ); } _update(''1'', array(''param2'' => ''some data''));



Parece que puede establecer isPartialObject que podría lograr lo que desea.


Puede usar la notación de puntos para acceder y establecer campos en el interior de los objetos, sin afectar las otras propiedades de esos objetos.

Dado el objeto que especificó arriba:

> db.test.insert({"id": "test_object", "some_key": {"param1": "val1", "param2": "val2", "param3": "val3"}}) WriteResult({ "nInserted" : 1 })

Podemos actualizar solo some_key.param2 y some_key.param3 :

> db.test.findAndModify({ ... query: {"id": "test_object"}, ... update: {"$set": {"some_key.param2": "val2_new", "some_key.param3": "val3_new"}}, ... new: true ... }) { "_id" : ObjectId("56476e04e5f19d86ece5b81d"), "id" : "test_object", "some_key" : { "param1" : "val1", "param2" : "val2_new", "param3" : "val3_new" } }

Puede profundizar tan profundo como desee. Esto también es útil para agregar nuevas propiedades a un objeto sin afectar las existentes.


Si entiendo la pregunta correctamente, quiere actualizar un documento con los contenidos de otro documento, pero solo los campos que aún no están presentes, e ignorar por completo los campos que ya están configurados (incluso a otro valor).

No hay forma de hacerlo en un solo comando.

Primero tiene que consultar el documento, descubrir qué es lo que quiere $set y luego actualizarlo (usando los valores anteriores como un filtro que hace juego para asegurarse de no obtener actualizaciones simultáneas).

Otra lectura de su pregunta sería que está satisfecho con $set , pero no desea establecer explícitamente todos los campos. ¿Cómo pasaría los datos?

Usted sabe que puede hacer lo siguiente:

db.collection.update( { _id:...} , { $set: someObjectWithNewData }


Tuve éxito haciéndolo de esta manera:

db.collection.update( { _id:...} , { $set: { ''key.another_key'' : new_info } } );

Tengo una función que maneja dinámicamente las actualizaciones de mi perfil

function update(prop, newVal) { const str = `profile.${prop}`; db.collection.update( { _id:...}, { $set: { [str]: newVal } } ); }

Nota: ''perfil'' es específico para mi implementación, es solo la cadena de la clave que desea modificar.


use $ set haga este proceso

.update({"_id": args.dashboardId, "viewData._id": widgetId}, {$set: {"viewData.$.widgetData": widgetDoc.widgetData}}) .exec() .then(dashboardDoc => { return { result: dashboardDoc }; });