MongoDB con controladores
Esta página documenta una mongosh . Para ver el método equivalente en un driver de MongoDB, se debe consultar la página correspondiente al lenguaje de programación:
Definición
db.collection.findOneAndUpdate( filter, update, options )Actualiza un único documento en función de los criterios
filterysort.Tip
Novedades en la 8.0 versión: El
updateOne()El método incluye unasortopción para actualizar el primer documento en un orden de clasificación especificado por el usuario.Devuelve: Devuelve el documento original por defecto. Devuelve el documento actualizado si returnNewDocument está configurado en trueo returnDocument está configurado enafter.
Compatibilidad
Este método está disponible en implementaciones alojadas en los siguientes entornos:
MongoDB Atlas: El servicio totalmente gestionado para implementaciones de MongoDB en la nube
Nota
Este comando es compatible con todos los clústeres de MongoDB Atlas. Para obtener información sobre el soporte de Atlas para todos los comandos, consulte Comandos no compatibles.
MongoDB Enterprise: La versión basada en suscripción y autogestionada de MongoDB
MongoDB Community: La versión de MongoDB con código fuente disponible, de uso gratuito y autogestionada.
Sintaxis
El método findOneAndUpdate() tiene la siguiente forma:
db.collection.findOneAndUpdate( <filter>, <update document or aggregation pipeline>, { writeConcern: <document>, projection: <document>, sort: <document>, maxTimeMS: <number>, upsert: <boolean>, returnDocument: <string>, returnNewDocument: <boolean>, collation: <document>, arrayFilters: [ <filterdocument1>, ... ] } )
Parámetros
El método findOneAndUpdate() toma los siguientes parámetros:
Parameter | Tipo | Descripción | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Documento | Los criterios de selección para actualizar. Los mismos selectores query que en el método Para actualizar el primer documento devuelto en la colección, especifique un documento vacío Si no se especifica, el valor es por defecto un documento vacío. Si el campo de query no es un documento, la operación devuelve un error. Si ningún documento coincide con | ||||||||||||||||||
| documento o arreglo | El documento de actualización o una pipeline de agregación.
| ||||||||||||||||||
| Documento | Opcional. Un documento que expresa el nivel de confirmación de escritura. Omite el uso del nivel de confirmación de escritura por defecto. No establezcas explícitamente el nivel de confirmación de escritura para la operación si se ejecuta en una transacción. Para usar el nivel de confirmación de escritura con transacciones, consulta Transacciones y nivel de confirmación de escritura. | ||||||||||||||||||
| Documento | Opcional. Un subconjunto de campos que se deben devolver. Para devolver todos los campos en el documento devuelto, omita este parámetro. Si el argumento de proyección no es un documento, la operación genera un error. | ||||||||||||||||||
| Documento | Opcional. Especifica un orden de clasificación para los documentos que coinciden con el Si el argumento de orden no es un documento, la operación genera un error. Consulte | ||||||||||||||||||
| Número | Opcional. Especifica un límite de tiempo en milisegundos dentro del cual debe completarse la operación. Genera un error si se supera el límite. | ||||||||||||||||||
| booleano | Opcional. Cuando
Para evitar múltiples upserts, asegúrate de que el/los campo(s) Se establece por defecto en | ||||||||||||||||||
| string | Opcional. A partir de
| ||||||||||||||||||
| booleano | Opcional. Cuando Se establece por defecto en | ||||||||||||||||||
| Documento | Opcional. Especifica la intercalación a utilizar para la operación. La intercalación permite a los usuarios especificar reglas propias del lenguaje para la comparación de strings, como reglas para el uso de mayúsculas y minúsculas y marcas de acento. La opción de intercalación tiene la siguiente sintaxis: Al especificar la intercalación, el campo Si no se especifica la intercalación, pero la colección tiene una intercalación por defecto (ver Si no se especifica ninguna intercalación para la colección o para las operaciones, MongoDB utiliza la comparación binaria simple usada en versiones anteriores para las comparaciones de strings. No puedes especificar varias intercalaciones para una operación. Por ejemplo, no puedes especificar diferentes intercalaciones por campo, o si realizas una búsqueda con un ordenamiento, no puedes usar una intercalación para la búsqueda y otra para el ordenamiento. | ||||||||||||||||||
| arreglo | Opcional. Un arreglo de documentos de filtro que determinan qué elementos del arreglo modificar para una operación de actualización en un campo de arreglo. En el documento de actualización, usa el operador posicional filtrado El Puedes incluir el mismo identificador varias veces en el documento de actualización; sin embargo, para cada identificador distinto ( Sin embargo, se pueden especificar condiciones compuestas sobre el mismo identificador en un único documento de filtro, como en los siguientes ejemplos: Para ver ejemplos, consulte Operaciones de actualización de arreglos con
|
Comportamiento
Rendimiento
Para las escrituras reintentables, el método findOneAndUpdate() debe copiar todo el documento en una colección paralela especial para cada nodo de un set de réplicas antes de realizar la actualización. Esto puede hacer que findOneAndUpdate() sea una operación costosa cuando se trata de documentos grandes o sets de réplicas grandes.
Nuevo en la versión 8.0: Para actualizar el primer documento en un orden definido por el usuario con un mejor rendimiento, utilice el método db.collection.updateOne() con la opción sort.
Coincidencia de documento
db.collection.findOneAndUpdate() actualiza el primer documento coincidente en la colección con el filter. Si ningún documento coincide con filter, no se actualizará ningún documento.
El parámetro sort puede utilizarse para seleccionar qué documento se actualiza.
Proyección
Importante
Consistencia del lenguaje
Como parte de hacer que la proyección de find() y findAndModify() sea coherente con la etapa de agregación de $project,
Las proyecciones
find()y lafindAndModify()pueden aceptar expresiones y sintaxis de agregación.MongoDB aplica restricciones adicionales con respecto a las proyecciones. Consulta restricciones de proyección para obtener más detalles.
El parámetro projection acepta un documento con el siguiente formato:
{ field1 : <value>, field2 : <value> ... }
Proyección | Descripción |
|---|---|
| Especifica la inclusión de un campo. Si especificas un entero distinto de cero para el valor de proyección, la operación trata el valor como |
| Especifica la exclusión de un campo. |
| |
| Utiliza los operadores de proyección de arreglos ( No disponible para las vistas. |
| Especifica el valor del campo proyectado. Con el uso de expresiones y sintaxis de agregación, incluido el uso de literales y variables de agregación, se pueden proyectar campos nuevos o proyectar campos existentes con valores nuevos.
|
Especificación de campo embebido
Para campos en documentos incrustados, puedes especificar el campo mediante:
notación de puntos, por ejemplo
"field.nestedfield": <value>formulario anidado, por ejemplo
{ field: { nestedfield: <value> } }
_id Proyección de campo
El campo _id se incluye por defecto en los documentos devueltos, a menos que especifiques explícitamente _id: 0 en la proyección para suprimir el campo.
Inclusión o exclusión
Una projection no puede contener ambas especificaciones de inclusión y exclusión, con la excepción del campo _id:
En las proyecciones que incluyen explícitamente campos, el campo
_ides el único campo que puedes excluir explícitamente.En las proyecciones que excluyen explícitamente campos, el campo
_ides el único campo que puedes incluir explícitamente; sin embargo, el campo_idse incluye por defecto.
Para obtener más información sobre la proyección, consulte también:
Colecciones fragmentadas
Es posible que a los documentos de una colección fragmentada les falten los campos de clave de fragmento. Para identificar un documento que no tenga la clave de fragmento, puede usar la null coincidencia de igualdad. Junto con otra condición de filtro (como en el _id campo). Por ejemplo:
{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key
Modificación de la clave de fragmentación
Puede actualizarse el valor de clave de partición de un documento a menos que el campo de clave de partición sea el campo _id inmutable.
Advertencia
Los documentos en colecciones particionadas pueden no tener los campos de clave de partición. Toma precauciones para evitar remover accidentalmente la clave de partición al cambiar el valor de clave de partición de un documento.
Para modificar el valor de clave de fragmentación existente con db.collection.findOneAndUpdate():
Debes ejecutar en un
mongos. No emitas la operación directamente en la partición.Usted debe ejecutar ya sea en una transacción o como una escritura reintentable.
Debe incluir un filtro de igualdad en la clave de partición completa.
Clave de fragmentación faltante
Los documentos en una colección particionada pueden carecer de los campos de la clave de partición. Para usar db.collection.findOneAndUpdate() a fin de establecer la clave de partición faltante del documento,
Debes ejecutar en un
mongos. No emitas la operación directamente en la partición.Debe ejecutar ya sea en una transacción o como una escritura reintentable si el nuevo valor de la clave de partición no es
null.Debe incluir un filtro de igualdad en la clave de partición completa.
Tip
Dado que un valor de clave faltante se devuelve como parte de una coincidencia exacta nula, para evitar actualizar una clave con valor nulo, incluya condiciones de query adicionales (como en el campo _id) según corresponda.
Véase también:
Transacciones
db.collection.findOneAndUpdate() puede usarse dentro de transacciones distribuidas.
Importante
En la mayoría de los casos, una transacción distribuida incurre en un costo de rendimiento mayor que las escrituras de documentos individuales, y la disponibilidad de transacciones distribuidas no debería ser un sustituto para un diseño de esquema efectivo. Para muchos casos, el modelo de datos desnormalizado (documento incrustado y matrices) seguirá siendo óptimo para tus datos y casos de uso. Es decir, en muchos casos, modelar tus datos de forma adecuada minimizará la necesidad de transacciones distribuidas.
Para consideraciones adicionales sobre el uso de transacciones (como el límite de tiempo de ejecución y el límite de tamaño del oplog), consulta también las consideraciones de producción.
Inserta dentro de transacciones
Puedes crear colecciones e índices dentro de una transacción distribuida si la transacción no es una transacción de escritura entre particiones.
db.collection.findOneAndUpdate() con upsert: true puede ejecutarse en una colección existente o en una colección inexistente. Si se ejecuta en una colección que es inexistente, la operación crea la colección.
Nivel de confirmación de escritura y transacciones
No establezcas explícitamente el nivel de confirmación de escritura para la operación si se ejecuta en una transacción. Para usar el nivel de confirmación de escritura con transacciones, consulta Transacciones y nivel de confirmación de escritura.
Entradas de OpLog
Si una operación db.collection.findOneAndUpdate() actualiza con éxito un documento, la operación añade una entrada en el OpLog (registro de operaciones). Si la operación falla o no encuentra un documento para actualizar, no se agrega una entrada en el oplog.
Ejemplos
Actualizar un documento
La colección grades contiene documentos similares a los siguientes:
{ _id: 6305, name : "A. MacDyver", "assignment" : 5, "points" : 24 }, { _id: 6308, name : "B. Batlock", "assignment" : 3, "points" : 22 }, { _id: 6312, name : "M. Tagnum", "assignment" : 5, "points" : 30 }, { _id: 6319, name : "R. Stiles", "assignment" : 2, "points" : 12 }, { _id: 6322, name : "A. MacDyver", "assignment" : 2, "points" : 14 }, { _id: 6234, name : "R. Stiles", "assignment" : 1, "points" : 10 }
La siguiente operación encuentra el primer documento donde name : R. Stiles e incrementa la puntuación en 5:
db.grades.findOneAndUpdate( { "name" : "R. Stiles" }, { $inc: { "points" : 5 } } )
La operación devuelve el documento original antes de la actualización:
{ _id: 6319, name: "R. Stiles", "assignment" : 2, "points" : 12 }
Si returnNewDocument fuera cierto, la operación devolvería el documento actualizado en su lugar.
Ordene y actualice un documento
La colección grades contiene documentos similares a los siguientes:
{ _id: 6305, name : "A. MacDyver", "assignment" : 5, "points" : 24 }, { _id: 6308, name : "B. Batlock", "assignment" : 3, "points" : 22 }, { _id: 6312, name : "M. Tagnum", "assignment" : 5, "points" : 30 }, { _id: 6319, name : "R. Stiles", "assignment" : 2, "points" : 12 }, { _id: 6322, name : "A. MacDyver", "assignment" : 2, "points" : 14 }, { _id: 6234, name : "R. Stiles", "assignment" : 1, "points" : 10 }
La siguiente operación actualiza un documento donde name : "A. MacDyver". La operación ordena los documentos coincidentes por points en orden ascendente para actualizar el documento coincidente con la menor cantidad de puntos.
db.grades.findOneAndUpdate( { "name" : "A. MacDyver" }, { $inc : { "points" : 5 } }, { sort : { "points" : 1 } } )
La operación devuelve el documento original antes de la actualización:
{ _id: 6322, name: "A. MacDyver", "assignment" : 2, "points" : 14 }
Proyección del documento devuelto
En la siguiente operación, se utiliza proyección para mostrar solo los campos _id, points y assignment en el documento devuelto:
db.grades.findOneAndUpdate( { "name" : "A. MacDyver" }, { $inc : { "points" : 5 } }, { sort : { "points" : 1 }, projection: { "assignment" : 1, "points" : 1 } } )
La operación devuelve el documento original con solo los campos especificados en el documento projection y el campo _id, ya que no se suprimió explícitamente (_id: 0) en el documento de proyección.
{ "_id" : 6322, "assignment" : 2, "points" : 14 }
Actualizar el documento con un límite de tiempo
En la siguiente operación, se establece un límite de tiempo de 5 ms para completar la actualización:
try { db.grades.findOneAndUpdate( { "name" : "A. MacDyver" }, { $inc : { "points" : 5 } }, { sort: { "points" : 1 }, maxTimeMS : 5 }; ); } catch(e){ print(e); }
Si la operación excede el límite de tiempo, devuelve:
Error: findAndModifyFailed failed: { "ok" : 0, "errmsg" : "operation exceeded time limit", "code" : 50 }
Actualización del documento con inserción
En la siguiente operación, se utiliza el campo upsert para insertar el documento para actualizar si nada coincide con filter:
try { db.grades.findOneAndUpdate( { "name" : "A.B. Abracus" }, { $set: { "name" : "A.B. Abracus", "assignment" : 5}, $inc : { "points" : 5 } }, { sort: { "points" : 1 }, upsert:true, returnNewDocument : true } ); } catch (e){ print(e); }
La operación devuelve lo siguiente:
{ "_id" : ObjectId("5789249f1c49e39a8adc479a"), "name" : "A.B. Abracus", "assignment" : 5, "points" : 5 }
Si returnNewDocument fuera falso, la operación devolvería null, ya que no hay un documento original para devolver.
Especificar la intercalación
La intercalación permite a los usuarios especificar reglas propias del lenguaje para la comparación de strings, como reglas para el uso de mayúsculas y minúsculas y marcas de acento.
Una colección myColl tiene los siguientes documentos:
{ _id: 1, category: "café", status: "A" } { _id: 2, category: "cafe", status: "a" } { _id: 3, category: "cafE", status: "a" }
La siguiente operación incluye la opción de intercalación:
db.myColl.findOneAndUpdate( { category: "cafe" }, { $set: { status: "Updated" } }, { collation: { locale: "fr", strength: 1 } } );
La operación devuelve el siguiente documento:
{ "_id" : 1, "category" : "café", "status" : "A" }
Operaciones de actualización de arreglos con arrayFilters
Nota
arrayFilters no está disponible para actualizaciones que utilizan un pipeline de agregación.
Al actualizar el campo de un arreglo, puede especificar arrayFilters que determinen qué elementos del arreglo actualizar.
Se deben actualizar los elementos que coinciden con los criterios arrayFilters
Nota
arrayFilters no está disponible para actualizaciones que utilizan un pipeline de agregación.
Cree una colección students con los siguientes documentos:
db.students.insertMany( [ { "_id" : 1, "grades" : [ 95, 92, 90 ] }, { "_id" : 2, "grades" : [ 98, 100, 102 ] }, { "_id" : 3, "grades" : [ 95, 110, 100 ] } ] )
Para modificar todos los elementos que sean mayores o iguales que 100 en el arreglo grades, utilizar el operador posicional filtrado $[<identifier>] con la opción arrayFilters en el método db.collection.findOneAndUpdate():
db.students.findOneAndUpdate( { grades: { $gte: 100 } }, { $set: { "grades.$[element]" : 100 } }, { arrayFilters: [ { "element": { $gte: 100 } } ] } )
La operación actualiza el campo grades de un único documento y, tras la operación, la colección contiene los siguientes documentos:
{ "_id" : 1, "grades" : [ 95, 92, 90 ] } { "_id" : 2, "grades" : [ 98, 100, 100 ] } { "_id" : 3, "grades" : [ 95, 110, 100 ] }
Actualiza elementos específicos de un arreglo de documentos
Nota
arrayFilters no está disponible para actualizaciones que utilizan un pipeline de agregación.
Cree una colección students2 con los siguientes documentos:
db.students2.insertMany( [ { "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" : 85, "std" : 6 } ] }, { "_id" : 2, "grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85, "std" : 4 } ] } ] )
La siguiente operación encuentra un documento donde el campo _id es igual a 1 y utiliza el operador posicional filtrado $[<identifier>] con el arrayFilters para modificar el mean de todos los elementos en el arreglo grades donde la calificación es mayor o igual a 85.
db.students2.findOneAndUpdate( { _id : 1 }, { $set: { "grades.$[elem].mean" : 100 } }, { arrayFilters: [ { "elem.grade": { $gte: 85 } } ] } )
La operación actualiza el campo grades de un único documento y, tras la operación, la colección contiene los siguientes documentos:
{ "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 100, "std" : 4 }, { "grade" : 85, "mean" : 100, "std" : 6 } ] } { "_id" : 2, "grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85, "std" : 4 } ] }
Utiliza una canalización de agregación para actualizaciones
db.collection.findOneAndUpdate() puede aceptar un pipeline de agregación para la actualización. El pipeline puede constar de las siguientes etapas:
$addFieldsy su alias$set$replaceRooty su alias$replaceWith
El uso de un pipeline de agregación permite una instrucción de actualización más expresiva, como expresar actualizaciones condicionales basadas en los valores actuales de los campos o actualizar un campo con el valor de otros campos.
Por ejemplo, cree una colección students2 con los siguientes documentos:
db.students2.insertMany( [ { "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" : 85, "std" : 6 } ] }, { "_id" : 2, "grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85, "std" : 4 } ] } ] )
La siguiente operación encuentra un documento donde el campo _id es igual a 1 y utiliza una canalización de agregación para calcular un nuevo campo total a partir del campo grades:
db.students2.findOneAndUpdate( { _id : 1 }, [ { $set: { "total" : { $sum: "$grades.grade" } } } ], // The $set stage is an alias for ``$addFields`` stage { returnNewDocument: true } )
Nota
La operación devuelve el documento actualizado:
{ "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" :85, "std" : 6 } ], "total" : 250 }