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:
Importante
Método obsoleto de mongosh
Usar findOneAndUpdate(), findOneAndDelete() o en su findOneAndReplace() lugar.
Definición
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
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 });
Parámetros
El método db.collection.findAndModify() toma un parámetro de documento con los siguientes campos de documento incrustado:
Parameter | Tipo | Descripción | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Documento | Opcional. Los criterios de selección para la modificación. El campo 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. | ||||||||||||||||||
| Documento | Opcional. Determina qué documento actualiza la Operación si el query selecciona varios documentos. 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 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 Consultar coherencia de ordenación para obtener más información. | ||||||||||||||||||
| booleano | Debe especificar el campo | ||||||||||||||||||
| documento o arreglo | Debe especificar el campo
| ||||||||||||||||||
| booleano | Opcional. Cuando | ||||||||||||||||||
| Documento | Opcional. Un subconjunto de campos que se deben devolver. El documento Si el argumento Para obtener más información sobre la proyección, consulta Proyección de | ||||||||||||||||||
| booleano | Opcional. Se utiliza en conjunto con el campo Cuando
Para evitar múltiples inserciones, asegúrese de que los campos de Se establece por defecto en | ||||||||||||||||||
| booleano | Opcional. Le permite a | ||||||||||||||||||
| 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. | ||||||||||||||||||
| non-negative integer | Opcional. Especifica un límite de tiempo en milisegundos. Si no especifica un valor para MongoDB finaliza las operaciones que exceden su límite de tiempo asignado utilizando el mismo mecanismo que | ||||||||||||||||||
| 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 obtener ejemplos, consulta Especificar
| ||||||||||||||||||
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: 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 ( Para usar una variable para los resultados del filtro, debes acceder a la variable dentro del operador Para un ejemplo completo usando Nuevo en la versión 5.0. |
Devolución de datos
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
newno está establecido o esfalse:el documento antes de la modificación si el query coincide con un documento;
de lo contrario,
null.
Si
newestrue:el documento actualizado si el query devuelve una coincidencia;
el documento insertado si
upsert: truey ningún documento coincide con el query;de lo contrario,
null.
Comportamiento
Rendimiento
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.
fields Proyección
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
find()y lafindAndModify()proyección 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.
La opción fields acepta un documento en la siguiente forma:
{ 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:
Inserción con un índice único
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
updateManyomultiesfalse.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 | ||||||
|---|---|---|---|---|---|---|---|---|
| | El campo | ||||||
| | La operación falla porque modifica el campo en el patrón de clave del índice único ( | ||||||
| | La operación falla porque los campos del predicado de igualdad ( |
Colecciones fragmentadas
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
queryoPuede 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
_iden 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
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 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.
Clave de fragmentación faltante
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:
Validación de esquema
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.
Comparaciones con el update método
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 unsortque 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ónnew.El método
updateOne()devuelve un objetoWriteResult()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.
Transacciones
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.
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.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.
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.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.
Errores de nivel de confirmación de escritura
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.
Ejemplos
Actualizar y devolver
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:
El
queryencuentra un documento en la colecciónpeopledonde el camponametiene el valorTom, el campostatetiene el valoractivey el camporatingtiene un valor degreater than10.sortordena los resultados del query en orden ascendente. Si varios documentos cumplen con la condiciónquery, el método seleccionará la modificación del primer documento según el orden de estesort.La actualización
incrementsincrementa el valor del camposcoreen 1.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:trueal método.Si ningún documento cumple con la condición
query, el método devuelvenull.
Inserción
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
Devolver nuevo documento
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" }
Ordenar y remover
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 }
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.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" }
Especifique arrayFilters para una operación de actualización de matriz
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 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 ] }
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 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 } ] }
Utiliza una canalización de agregación para actualizaciones
db.collection.findAndModify() 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.findAndModify( { query: { "_id" : 1 }, update: [ { $set: { "total" : { $sum: "$grades.grade" } } } ], // The $set stage is an alias for ``$addFields`` stage new: 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 }
Usar variables en let
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" } } )
Roles de usuario y actualizaciones de documentos
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:
Jamescon un rolBilling.Michellecon un rolProvider.
Realiza los siguientes pasos para crear los roles, los usuarios y la colección:
Crea los roles
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: [ ] } )
Inicia sesión como Michelle, quien tiene el rol Provider, y realiza una actualización:
Realizar actualización
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:
Intento de realizar una actualización
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.