Docs Menu
Docs Home
/ /

db.collection.findAndModify() (método mongosh)

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:

C#Java SyncNode.jsPyMongoCC++GoJava RSKotlin CoroutineKotlin SyncPHPMongoidRubyRustScala

Importante

Método obsoleto de mongosh

Usar findOneAndUpdate(), findOneAndDelete() o en su findOneAndReplace() lugar.

db.collection.findAndModify(document)

Actualiza y devuelve un único documento. Por defecto, el documento devuelto no incluye las modificaciones realizadas durante la actualización. Para devolver el documento con las modificaciones realizadas en la actualización, utilice la opción new.

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.

Modificado en la versión 5.0.

El método findAndModify() tiene la siguiente forma:

db.collection.findAndModify({
query: <document>,
sort: <document>,
remove: <boolean>,
update: <document or aggregation pipeline>,
new: <boolean>,
fields: <document>,
upsert: <boolean>,
bypassDocumentValidation: <boolean>,
writeConcern: <document>,
maxTimeMS: <integer>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
let: <document> // Added in MongoDB 5.0
});

El método db.collection.findAndModify() toma un parámetro de documento con los siguientes campos de documento incrustado:

Parameter
Tipo
Descripción

query

Documento

Opcional. Los criterios de selección para la modificación. El campo query emplea los mismos selectores de query que se utilizan en el método db.collection.find(). Aunque el query puede coincidir con varios documentos, db.collection.findAndModify() solo seleccionará un documento para modificar.

Si no se especifica, el valor es por defecto un documento vacío.

Si el argumento del query no es un documento, la operación arroja un error.

sort

Documento

Opcional. Determina qué documento actualiza la Operación si el query selecciona varios documentos. db.collection.findAndModify() actualiza el primer documento en el orden de clasificación especificado por este argumento.

Si el argumento de orden no es un documento, la operación genera un error.

MongoDB no almacena documentos en una colección en un orden específico. Al ordenar en un campo que contiene valores duplicados, los documentos que contienen esos valores pueden ser devueltos en cualquier orden.

La operación $sort no es un "ordenamiento estable", lo que significa que no se garantiza que los documentos con claves de ordenamiento equivalentes permanezcan en el mismo orden relativo en la salida y en la entrada.

Si el campo especificado en los criterios de ordenación no existe en dos documentos, entonces el valor por el cual se ordenan es el mismo. Los dos documentos pueden ser devueltos en cualquier orden.

Si se desea un orden de clasificación coherente, se debe incluir al menos un campo en la clasificación que contenga valores únicos. La forma más sencilla de garantizar esto es incluir el campo _id en la query de ordenación.

Consultar coherencia de ordenación para obtener más información.

remove

booleano

Debe especificar el campo remove o el campo update. Remueve el documento especificado en el campo query. Configúrelo en true para remover el documento seleccionado . El valor por defecto es false.

update

documento o arreglo

Debe especificar el campo remove o el campo update. Realiza una actualización del documento seleccionado.

new

booleano

Opcional. Cuando true, devuelve el documento actualizado, en lugar del original. El valor por defecto es false.

fields

Documento

Opcional. Un subconjunto de campos que se deben devolver. El documento fields especifica la inclusión de un campo con 1, como en: fields: { <field1>: 1, <field2>: 1, ... }.

Si el argumento fields no es un documento, la operación arroja un error.

Para obtener más información sobre la proyección, consulta Proyección de fields.

upsert

booleano

Opcional. Se utiliza en conjunto con el campo update.

Cuando true, findAndModify() ya sea:

  • Crea un nuevo documento si no hay documentos que coincidan con query. Para más detalles, consulta comportamiento de inserción.

  • Actualiza un solo documento que coincida con query.

Para evitar múltiples inserciones, asegúrese de que los campos de query estén indexados de forma única. Consulte Inserción con un índice único para ver un ejemplo.

Se establece por defecto en false, lo que no inserta un nuevo documento cuando no se encuentra ninguna coincidencia.

bypassDocumentValidation

booleano

Opcional. Le permite a db.collection.findAndModify() omitir la validación de esquema durante la operación. Esto permite actualizar documentos que no cumplen con los requisitos de validación.

writeConcern

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.

maxTimeMS

non-negative integer

Opcional.

Especifica un límite de tiempo en milisegundos. Si no especifica un valor para maxTimeMS, las operaciones no agotarán el tiempo de espera. Un valor de 0 especifica explícitamente el comportamiento por defecto sin límites.

MongoDB finaliza las operaciones que exceden su límite de tiempo asignado utilizando el mismo mecanismo que db.killOp(). MongoDB solo termina una operación en uno de sus puntos de interrupción designados.

collation

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:

collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}

Al especificar la intercalación, el campo locale es obligatorio; todos los demás campos de intercalación son opcionales. Para las descripciones de los campos, consulta Documento de intercalación.

Si no se especifica la intercalación, pero la colección tiene una intercalación por defecto (ver db.createCollection()), la operación utiliza la intercalación especificada para la colección.

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.

arrayFilters

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 $[<identifier>] para definir un identificador, al que luego puedes hacer referencia en los documentos de filtro de arreglo. No puedes tener un documento de filtro de arreglo para un identificador si dicho identificador no está incluido en el documento de actualización.

El <identifier> debe comenzar con una letra minúscula y contener solo caracteres alfanuméricos.

Puedes incluir el mismo identificador varias veces en el documento de actualización; sin embargo, para cada identificador distinto ($[identifier]) en el documento de actualización, debes especificar exactamente un documento de filtro de arreglo correspondiente. Es decir, no puedes especificar múltiples documentos de filtro de arreglo para el mismo identificador. Por ejemplo, si la instrucción de actualizar incluye el identificador x (posiblemente varias veces), no puedes especificar lo siguiente para arrayFilters que incluya dos documentos de filtro separados para x:

// INVALID
[
{ "x.a": { $gt: 85 } },
{ "x.b": { $gt: 80 } }
]

Sin embargo, se pueden especificar condiciones compuestas sobre el mismo identificador en un único documento de filtro, como en los siguientes ejemplos:

// Example 1
[
{ $or: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
// Example 2
[
{ $and: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
// Example 3
[
{ "x.a": { $gt: 85 }, "x.b": { $gt: 80 } }
]

Para obtener ejemplos, consulta Especificar arrayFilters para operaciones de actualización de arreglos.

arrayFilters no está disponible para actualizaciones que utilizan un pipeline de agregación.

Documento

Opcional.

Especifica un documento que contiene una lista de variables. Esto le permite mejorar la legibilidad de los comandos al separar las variables del texto de la query.

La sintaxis del documento es:

{
<variable_name_1>: <expression_1>,
...,
<variable_name_n>: <expression_n>
}

La variable se establece en el valor devuelto por la expresión y no puede modificarse posteriormente.

Para acceder al valor de una variable en el comando, se debe usar el prefijo de doble signo de dólar ($$) junto con el nombre de la variable en la forma $$<variable_name>. Por ejemplo: $$targetTotal.

Para usar una variable para los resultados del filtro, debes acceder a la variable dentro del operador $expr.

Para un ejemplo completo usando let y variables, vea Uso de variables en let.

Nuevo en la versión 5.0.

Para las operaciones de remoción, si el query coincide con un documento, findAndModify() devuelve el documento eliminado. Si el query no coincide con un documento para remover, findAndModify() devuelve null.

Para las operaciones para actualizar, findAndModify() devuelve uno de los siguientes:

  • Si el parámetro new no está establecido o es false:

    • el documento antes de la modificación si el query coincide con un documento;

    • de lo contrario, null.

  • Si new es true:

    • el documento actualizado si el query devuelve una coincidencia;

    • el documento insertado si upsert: true y ningún documento coincide con el query;

    • de lo contrario, null.

Para las escrituras reintentables, el método findAndModify() 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 findAndModify() 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.

Importante

Consistencia del lenguaje

Como parte de hacer que la proyección de find() y findAndModify() sea coherente con la etapa de $project de agregación,

La opción fields acepta un documento en la siguiente forma:

{ field1: <value>, field2: <value> ... }
Proyección
Descripción

<field>: <1 or true>

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 true.

<field>: <0 or false>

Especifica la exclusión de un campo.

"<field>.$": <1 or true>

Utiliza el operador de proyección de arreglo $ para devolver el primer elemento que coincide con la condición de query en el campo de arreglo. Si especificas un entero distinto de cero para el valor de proyección, la operación trata el valor como true.

No disponible para las vistas.

<field>: <array projection>

Utiliza los operadores de proyección de arreglos ($elemMatch, $slice) para especificar los elementos del arreglo que se deben incluir.

No disponible para las vistas.

<field>: <aggregation expression>

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.

  • Si se especifica un literal no numérico, no booleano (como una cadena de caracteres, un arreglo o una expresión de operador) para el valor de proyección, el campo se proyecta con el nuevo valor, por ejemplo:

    • { field: [ 1, 2, 3, "$someExistingField" ] }

    • { field: "New String Value" }

    • { field: { status: "Active", total: { $sum: "$existingArray" } } }

  • Para proyectar un valor literal para un campo, utiliza la expresión de agregación $literal, por ejemplo:

    • { field: { $literal: 5 } }

    • { field: { $literal: true } }

    • { field: { $literal: { fieldWithValue0: 0, fieldWithValue1: 1 } } }

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> } }

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.

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 _id es el único campo que puedes excluir explícitamente.

  • En las proyecciones que excluyen explícitamente campos, el campo _id es el único campo que puedes incluir explícitamente; sin embargo, el campo _id se incluye por defecto.

Para obtener más información sobre la proyección, consulte también:

Los upserts pueden crear documentos duplicados, a menos que haya un índice único para evitar duplicados.

Considere un ejemplo en el que no existe ningún documento con el nombre Andy y varios clientes emiten el siguiente comando aproximadamente al mismo tiempo:

db.people.findAndModify(
{
query: { name: "Andy" },
update: { $inc: { score: 1 } },
upsert: true
}
)

Si todas las operaciones findOneAndUpdate() finalizan la fase del query antes de que cualquier cliente inserte datos correctamente, y no hay un índice único en el campo name, cada operación findOneAndUpdate() puede tener como resultado una inserción, lo que crea múltiples documentos con name: Andy.

Un índice único en el campo name asegura que solo se cree un documento. Con un índice único establecido, las múltiples operaciones findOneAndUpdate() ahora muestran el siguiente comportamiento:

  • Exactamente una findOneAndUpdate() operación insertará correctamente un nuevo documento.

  • Otras operaciones findOneAndUpdate() actualizan el documento recién insertado o fallan debido a una colisión de clave única.

    Para que otras operaciones findOneAndUpdate() puedan actualizar el documento recién insertado, se deben cumplir todas las condiciones siguientes:

    • La colección objetivo tiene un índice único que causaría un error de clave duplicada.

    • La operación de actualización no es updateMany o multi es false.

    • La condición de coincidencia de actualización es:

      • Un único predicado de igualdad. Por ejemplo { "fieldA" : "valueA" }

      • Un AND lógico de predicados de igualdad. Por ejemplo { "fieldA" : "valueA", "fieldB" : "valueB" }

    • Los campos del predicado de igualdad coinciden con los campos del patrón de clave del índice único.

    • La operación de actualización no modifica ningún campo en el patrón de clave de índice único.

La siguiente tabla muestra ejemplos de operaciones de upsert que, cuando ocurre una colisión de clave, se actualizan o fallan.

Patrón de clave de índice único
Operación de actualización
Resultado
{ name : 1 }
db.people.updateOne(
{ name: "Andy" },
{ $inc: { score: 1 } },
{ upsert: true }
)

El campo score del documento coincidente se incrementa en 1.

{ name : 1 }
db.people.updateOne(
{ name: { $ne: "Joe" } },
{ $set: { name: "Andy" } },
{ upsert: true }
)

La operación falla porque modifica el campo en el patrón de clave del índice único (name).

{ name : 1 }
db.people.updateOne(
{ name: "Andy", email: "andy@xyz.com" },
{ $set: { active: false } },
{ upsert: true }
)

La operación falla porque los campos del predicado de igualdad (name, email) no coinciden con el campo clave del índice (name).

Para usar findAndModify en una colección particionada:

  • Si solo apunta a una partición, puede usar una clave de partición parcial en el campo query o

  • Puede proporcionar una condición de igualdad en una clave de partición completa en el campo query.

  • A partir de la versión 7.1, no es necesario indicar la clave de partición ni el campo _id en la especificación de la query.

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

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 actualizar el valor de clave de partición existente con db.collection.findAndModify():

  • 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.

Los documentos en una colección particionada pueden carecer de los campos de clave de partición. Para utilizar db.collection.findAndModify() para establecer la clave de partición que falta en el 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:

El método db.collection.findAndModify() añade compatibilidad con la opción bypassDocumentValidation, que le permite omitir la validación de esquema al insertar o actualizar documentos en una colección con reglas de validación.

Al actualizar un documento, db.collection.findAndModify() y el método updateOne() operan de manera diferente:

  • Si varios documentos cumplen con los criterios de actualización, para db.collection.findAndModify(), puedes especificar un sort que proporcione cierto control sobre qué documento actualizar.

    updateOne() actualiza el primer documento que coincide.

  • Por defecto, db.collection.findAndModify() devuelve la versión premodificada del documento. Para obtener el documento actualizado, utiliza la opción new.

    El método updateOne() devuelve un objeto WriteResult() que contiene el estado de la operación.

    Para devolver el documento actualizado, utilice el método find(). Sin embargo, es posible que otras actualizaciones hayan modificado el documento entre su actualización y la recuperación del documento. Además, si la actualización modificó solo un documento, pero varios documentos coincidieron, necesitará usar lógica adicional para identificar el documento actualizado.

Al modificar un solo documento, tanto el método db.collection.findAndModify() como updateOne() actualizan el documento atómicamente. Consulte Atomicidad y transacciones para obtener más información sobre las interacciones y el orden de las operaciones de estos métodos.

db.collection.findAndModify() 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.

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.findAndModify() 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.

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.

Si una operación db.collection.findAndModify() encuentra y modifica correctamente un documento, la operación agrega una entrada en el oplog (registro de operaciones). Si la operación falla o no encuentra un documento para modificar, la operación no agrega una entrada en el oplog.

En versiones de MongoDB anteriores a 6.0, si el comando findAndModify se ejecuta en un clúster particionado, mongos descarta el documento writeConcernError si la respuesta de la partición contiene un error. En MongoDB 6.0 y versiones posteriores, mongos devuelve writeConcernError.

El siguiente método actualiza y devuelve un documento existente en la colección de personas en la que el documento coincide con los criterios del query:

db.people.findAndModify({
query: { name: "Tom", state: "active", rating: { $gt: 10 } },
sort: { rating: 1 },
update: { $inc: { score: 1 } }
})

Este método realiza las siguientes acciones:

  1. El query encuentra un documento en la colección people donde el campo name tiene el valor Tom, el campo state tiene el valor active y el campo rating tiene un valor de greater than 10.

  2. sort ordena los resultados del query en orden ascendente. Si varios documentos cumplen con la condición query, el método seleccionará la modificación del primer documento según el orden de este sort.

  3. La actualización increments incrementa el valor del campo score en 1.

  4. El método devuelve el documento original (es decir, previo a la modificación) seleccionado para esta actualización:

    {
    "_id" : ObjectId("50f1e2c99beb36a0f45c6453"),
    "name" : "Tom",
    "state" : "active",
    "rating" : 100,
    "score" : 5
    }

    Para devolver el documento actualizado, agregue la opción new:true al método.

    Si ningún documento cumple con la condición query, el método devuelve null.

El siguiente método incluye la opción upsert: true para la operación update con el fin de actualizar un documento coincidente o, si no existe ningún documento coincidente, crear un nuevo documento:

db.people.findAndModify({
query: { name: "Gus", state: "active", rating: 100 },
sort: { rating: 1 },
update: { $inc: { score: 1 } },
upsert: true
})

Si el método encuentra un documento coincidente, hace una actualización.

Si el método no encuentra un documento coincidente, el método crea un nuevo documento. Debido a que el método incluía la opción sort, devuelve un documento vacío { } como el documento original (previo a la modificación):

{ }

Si el método no incluye una opción sort, el método devuelve null.

null

El siguiente método incluye tanto la opción upsert: true como la opción new:true. El método actualiza un documento coincidente y devuelve el documento actualizado o, si no existe ningún documento coincidente, inserta un documento y devuelve el documento recién insertado en el campo value.

En el siguiente ejemplo, ningún documento de la colección people cumple con la condición query:

db.people.findAndModify({
query: { name: "Pascal", state: "active", rating: 25 },
sort: { rating: 1 },
update: { $inc: { score: 1 } },
upsert: true,
new: true
})

El método devuelve el documento recién insertado:

{
"_id" : ObjectId("50f49ad6444c11ac2448a5d6"),
"name" : "Pascal",
"rating" : 25,
"score" : 1,
"state" : "active"
}

Al incluir una especificación sort en el campo rating, el siguiente ejemplo remueve de la colección people un único documento que tiene el valor state de active y el rating más bajo entre los documentos coincidentes:

db.people.findAndModify(
{
query: { state: "active" },
sort: { rating: 1 },
remove: true
}
)

El método devuelve el documento borrado:

{
"_id" : ObjectId("52fba867ab5fdca1299674ad"),
"name" : "XYZ123",
"score" : 1,
"state" : "active",
"rating" : 3
}

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.findAndModify({
query: { category: "cafe", status: "a" },
sort: { category: 1 },
update: { $set: { status: "Updated" } },
collation: { locale: "fr", strength: 1 }
});

La operación devuelve el siguiente documento:

{ "_id" : 1, "category" : "café", "status" : "A" }

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.

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 actualizar todos los elementos que sean mayores o iguales a 100 en el arreglo grades, utiliza el operador posicional filtrado $[<identifier>] con la opción arrayFilters en el método db.collection.findAndModify():

db.students.findAndModify({
query: { grades: { $gte: 100 } },
update: { $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 ] }

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 actualizar el mean de todos los elementos en el arreglo grades donde la calificación es mayor o igual a 85.

db.students2.findAndModify({
query: { _id : 1 },
update: { $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 }
]
}

db.collection.findAndModify() puede aceptar un pipeline de agregación para la actualización. El pipeline puede constar de las siguientes etapas:

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.findAndModify( {
query: { "_id" : 1 },
update: [ { $set: { "total" : { $sum: "$grades.grade" } } } ], // The $set stage is an alias for ``$addFields`` stage
new: true
} )

Nota

El $set utilizado en el pipeline se refiere a la etapa de agregación $set y no al operador de actualización $set.

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
}

Nuevo en la versión 5.0.

Para definir variables a las que puedes acceder en otros lugares del comando, utiliza la opción let.

Nota

Para filtrar los resultados usando una variable, debes acceder a la variable dentro del operador $expr.

Cree una colección cakeFlavors:

db.cakeFlavors.insertMany( [
{ _id: 1, flavor: "chocolate" },
{ _id: 2, flavor: "strawberry" },
{ _id: 3, flavor: "cherry" }
] )

El siguiente ejemplo define una variable targetFlavor en let y utiliza la variable para cambiar el sabor del pastel de cereza a naranja:

db.cakeFlavors.findAndModify( {
query: {
$expr: { $eq: [ "$flavor", "$$targetFlavor" ] }
},
update: { flavor: "orange" },
let: { targetFlavor: "cherry" }
} )

A partir de MongoDB 7.0, puedes usar la nueva variable de sistema USER_ROLES para devolver los roles de usuario.

El ejemplo en esta sección muestra actualizaciones de campos en una colección que contiene información médica. El ejemplo lee los roles de usuario actuales de la variable de sistema USER_ROLES y solo realiza las actualizaciones si el usuario tiene un rol específico.

Para usar una variable del sistema, agrega $$ al inicio del nombre de la variable. Especifica la variable del sistema USER_ROLES como $$USER_ROLES.

El ejemplo crea a estos usuarios:

  • James con un rol Billing.

  • Michelle con un rol Provider.

Realiza los siguientes pasos para crear los roles, los usuarios y la colección:

1

Crea roles llamados Billing y Provider con los privilegios y recursos necesarios.

Ejecuta:

db.createRole( { role: "Billing", privileges: [ { resource: { db: "test",
collection: "medicalView" }, actions: [ "find" ] } ], roles: [ ] } )
db.createRole( { role: "Provider", privileges: [ { resource: { db: "test",
collection: "medicalView" }, actions: [ "find" ] } ], roles: [ ] } )
2

Crea usuarios llamados James y Michelle con los roles requeridos.

db.createUser( {
user: "James",
pwd: "js008",
roles: [
{ role: "Billing", db: "test" }
]
} )
db.createUser( {
user: "Michelle",
pwd: "me009",
roles: [
{ role: "Provider", db: "test" }
]
} )
3

Ejecuta:

db.medical.insertMany( [
{
_id: 0,
patientName: "Jack Jones",
diagnosisCode: "CAS 17",
creditCard: "1234-5678-9012-3456"
},
{
_id: 1,
patientName: "Mary Smith",
diagnosisCode: "ACH 01",
creditCard: "6541-7534-9637-3456"
}
] )

Inicia sesión como Michelle, quien tiene el rol Provider, y realiza una actualización:

1

Ejecuta:

db.auth( "Michelle", "me009" )
2

Ejecuta:

// Attempt to find and modify document
db.medical.findAndModify( {
query:
{ $and: [
{
// Only update the document for Mary Smith
patientName: { $eq: "Mary Smith" }
},
{
// User must have the Provider role to perform the update
$expr: { $ne: [ {
$setIntersection: [ [ "Provider" ], "$$USER_ROLES.role" ]
}, [] ] }
}
]
},
// Update document
update: {
patientName: "Mary Smith",
diagnosisCode: "ACH 03",
creditCard: "6541-7534-9637-3456"
}
} )

El ejemplo anterior utiliza $setIntersection para devolver documentos donde la intersección entre la string "Provider" y los roles de usuario de $$USER_ROLES.role no está vacía. Michelle tiene el rol Provider, por lo tanto, se realiza la actualización.

A continuación, inicia sesión como James, que no tiene el rol de Provider, e intenta volver a actualizar:

1

Ejecuta:

db.auth( "James", "js008" )
2

Ejecuta:

// Attempt to find and modify document
db.medical.findAndModify( {
query:
{ $and: [
{
// Only update the document for Mary Smith
patientName: { $eq: "Mary Smith" }
},
{
// User must have the Provider role to perform the update
$expr: { $ne: [ {
$setIntersection: [ [ "Provider" ], "$$USER_ROLES.role" ]
}, [] ] }
}
]
},
// Update document
update: {
patientName: "Mary Smith",
diagnosisCode: "ACH 03",
creditCard: "6541-7534-9637-3456"
}
} )

El ejemplo anterior no actualiza ningún documento.

Volver

db.colección.find

En esta página