Al crear una aplicación de misión crítica, es importante prepararse para eventos inesperados que puedan ocurrir en producción. Esto incluye queries lentas inesperadas, índices faltantes o un aumento brusco de la carga de trabajo.
MongoDB Atlas le ayuda a crear una aplicación resiliente al equiparle con funciones listas para usar que le permiten prepararse proactivamente y responder de forma reactiva ante cualquier situación. Para crear una aplicación resiliente, le recomendamos configurar su implementación de MongoDB con las siguientes prácticas recomendadas de resiliencia de clúster y de aplicación y del lado del cliente.
Resiliencia del clúster
Para mejorar la resiliencia de su clúster, actualice su clúster a MongoDB 8.0. MongoDB 8.0 introduce las siguientes mejoras de rendimiento y nuevas funcionalidades relacionadas con la resiliencia:
Filtros de rechazo de operaciones para mitigar de forma reactiva las consultas costosas
Tiempos de espera a nivel de clúster para protección proactiva contra operaciones de lectura costosas
Mejor aislamiento de la carga de trabajo con el comando moveCollection
Gestión de memoria mejorada
Para ejecutar su aplicación de forma segura en producción, es importante asegurarse de que la utilización de memoria permita un margen de maniobra. Si un nodo se queda sin memoria disponible, puede verse afectado por el Linux Out of Memory Killer, que termina el proceso mongod.
MongoDB 8.0 utiliza un TCMalloc actualizado para todas las implementaciones de forma automática, lo que reduce el crecimiento promedio de la fragmentación de memoria con el tiempo. Esta menor fragmentación mejora la estabilidad operativa durante picos de carga y se traduce en una utilización de memoria mejorada en general.
Filtros de rechazo de operaciones
Una operación intensiva en recursos no intencionada puede causar problemas en producción si no se gestiona a tiempo.
MongoDB 8.0 te permite minimizar el impacto de estas operaciones utilizando filtros de rechazo de operaciones. Los filtros de rechazo de operación te permiten configurar MongoDB para rechazar las query hasta que vuelvas a habilitar las query con esa forma del query.
En otras palabras, una vez que identifiques una query lenta, no necesitas esperar a que los equipos de aplicaciones arreglen sus queries para contener el impacto de la query lenta. En su lugar, una vez que detectes un query de bajo rendimiento en tu perfilador del query, Panel de rendimiento en tiempo real o en los registros de query, puedes establecer un filtro de rechazo en esa forma del query. MongoDB luego impide que nuevas instancias de esa forma del query entrante se ejecuten. Una vez que corrijas la query, puedes volver a habilitar la forma del query.
Debes utilizar un filtro de rechazo de operaciones si deseas:
Contenga el impacto de las consultas lentas rápidamente mientras se está trabajando en la solución.
Prioriza cargas de trabajo más importantes durante tiempos de sobrecarga rechazando queries menos importantes.
Dale tiempo al clúster para recuperarse si está cerca del máximo uso de recursos.
Identifique y rechace consultas lentas en la interfaz de usuario de Atlas
Para usar un filtro de rechazo de operaciones en la Interfaz de Usuario de Atlas:
En Atlas, ve a la página Clusters de tu proyecto.
Si aún no se muestra, seleccione la organización que contiene su proyecto deseado en el menú Organizations de la barra de navegación.
Si aún no aparece, selecciona el proyecto deseado en el menú Projects de la barra de navegación.
En la barra lateral, haz clic en Clusters en la sección Database.
La página de clústeres se muestra.
Ve a el perfilador del query para el clúster especificado dentro del Proyecto actual.
Haz clic en el nombre del clúster para abrir la barra lateral Cluster.
Haz clic en Query Insights en la barra lateral de Cluster.
Haz clic en la pestaña Query Profiler.
Rechaza las operaciones de una forma del query específica.
Usa setQuerySettings en tu método db.adminCommand() para pasar el queryShapeHash, que especifica la forma del query que deseas rechazar.
Nota
Debes tener el rol de atlasAdmin para usar setQuerySettings.
Para ver un ejemplo, consulte Bloquear queries lentas con filtros de rechazo de operaciones.
Supervisa tus consultas después de un rechazo o expiración
Puedes supervisar cómo se ejecutan tus queries posteriormente en Métricas en la barra lateral del clúster:
En Atlas, ve a la página Clusters de tu proyecto.
Si aún no se muestra, seleccione la organización que contiene su proyecto deseado en el menú Organizations de la barra de navegación.
Si aún no aparece, selecciona el proyecto deseado en el menú Projects de la barra de navegación.
En la barra lateral, haz clic en Clusters en la sección Database.
La página de clústeres se muestra.
Tiempos de espera a nivel de clúster para operaciones de lectura
Es importante asegurarse de que su proceso de desarrollo considere cuidadosamente la eficiencia de las queries antes de que lleguen a producción. Las excepciones pueden ocurrir siempre, pero tener una mitigación proactiva contra queries ineficientes puede ayudar a evitar problemas de rendimiento del clúster.
Con MongoDB 8.0, puedes proteger tus consultas de operaciones no indexadas con el defaultMaxTimeMS del lado del servidor que ingresa al clúster. Si una operación excede este tiempo de espera, MongoDB cancela la operación para evitar que las consultas se ejecuten durante demasiado tiempo y consuman recursos. Esto te permite:
Traslada la responsabilidad de establecer límites de tiempo de los equipos de aplicaciones individuales a los equipos enfocados en bases de datos.
Minimiza el impacto de un escaneo de colección si a la query le falta un índice.
Ten una última ronda de mitigación contra operaciones costosas que lleguen a producción.
Si tienes queries que requieren un tiempo de espera diferente, como las queries de análisis, puedes sobrescribirlas configurando el tiempo de espera a nivel de operación con el método maxTimeMS.
Establezca el tiempo de espera por defecto para las operaciones de lectura en la API de administración de Atlas
Para establecer el parámetro defaultMaxTimeMS a través de la API de Administración de Atlas, consulta Actualizar opciones avanzadas de configuración para un clúster.
Establecer El Tiempo De Espera por defecto Para Las Operaciones De Lectura En La Interfaz De Usuario De Atlas
Para establecer el parámetro defaultMaxTimeMS en la interfaz de usuario de Atlas:
En Atlas, ve a la página Clusters de tu proyecto.
Si aún no se muestra, seleccione la organización que contiene su proyecto deseado en el menú Organizations de la barra de navegación.
Si aún no aparece, selecciona el proyecto deseado en el menú Projects de la barra de navegación.
En la barra lateral, haz clic en Clusters en la sección Database.
La página de clústeres se muestra.
Navegue a sus opciones de configuración.
Si tienes un clúster existente, navega a la página Editar clúster.
Si está creando un nuevo clúster, en la lista desplegable Select a version, seleccione MongoDB 8.0.
Haga clic en Additional Settings.
Desplázate hacia abajo y haz clic en More Configuration Options.
Para ver el comportamiento de las operaciones finalizadas,consulte "Supervisar las consultas tras el rechazo o el tiempo de espera". Para obtener más información, consulte defaultMaxTimeMS y "Establecer el tiempo de espera predeterminado para las operaciones de lectura".
Aísla el impacto de colecciones ocupadas no fragmentadas
Particionado permite escalar tu clúster horizontalmente. Con MongoDB, puedes fragmentar algunas colecciones, mientras permites que otras colecciones en el mismo clúster permanezcan sin fragmentar. Cuando se crea una nueva base de datos, la partición del clúster con la menor cantidad de datos se selecciona como partición primaria de esa base de datos por defecto. Todas las colecciones no particionadas de esa base de datos se encuentran en esa partición primaria por defecto. Esto puede causar un aumento del tráfico en la partición primaria a medida que aumenta la carga de trabajo, especialmente si el crecimiento de la carga de trabajo se centra en las colecciones no particionadas de la partición primaria.
Para distribuir mejor esta carga de trabajo, MongoDB 8.0 permite mover una colección no particionada a otras particiones desde la partición primaria mediante el comando moveCollection. Esto permite ubicar colecciones activas y ocupadas en particiones con un menor uso esperado de recursos. Con esto, puedes:
Optimiza el rendimiento en cargas de trabajo más grandes y complejas.
Logra un mejor uso de recursos.
Distribuye la fecha de manera más uniforme entre las particiones.
Recomendamos aislar tu colección en las siguientes circunstancias:
Si tu partición primaria experimenta una carga de trabajo significativa debido a la presencia de varias colecciones no particionadas de alto rendimiento.
Se anticipa que una colección sin particiones experimentará un crecimiento futuro, que podría convertirse en un cuello de botella para otras colecciones.
Estás ejecutando un diseño de implementación de una colección por clúster y deseas aislar a esos clientes según la prioridad o cargas de trabajo.
Tus particiones tienen más datos de lo proporcional debido a la cantidad de colecciones no fragmentadas ubicadas en ellos.
Para aprender a mover una colección no particionada con mongosh, consulta Mover una colección.
Mejores prácticas de aplicaciones y del lado del cliente
Puedes configurar las funcionalidades de tus implementaciones de MongoDB y de las librerías del driver para crear una aplicación resistente que pueda soportar interrupciones del servicio de red y eventos de failover. Para escribir un código de aplicación que aproveche al máximo las capacidades siempre activas de MongoDB Atlas, debes realizar las siguientes tareas:
Utilice una
majoritypreocupación de escritura y una preocupación de lectura que tenga sentido para su aplicación.Manejar errores en su aplicación.
Instale las Librerías de clientes más recientes
Instale las últimas Librerías de clientes para su lenguaje desde Librerías de clientes de MongoDB. Las librerías cliente conectan y transmiten consultas desde tu aplicación a tu base de datos. Utilizar las últimas Librerías de clientes permite acceder a las últimas funcionalidades de MongoDB.
Luego, en tu aplicación, importa la dependencia:
Si usas Maven, añade lo siguiente a tu lista de dependencias pom.xml:
<dependencies> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-driver-sync</artifactId> <version>4.0.1</version> </dependency> </dependencies>
Si está utilizando Gradle, añada lo siguiente a su lista de dependencias build.gradle:
dependencies { compile 'org.mongodb:mongodb-driver-sync:4.0.1' }
// Latest 'mongodb' version installed with npm const MongoClient = require('mongodb').MongoClient;
# Install the latest 'pymongo' version with pip and # import MongoClient from the package to establish a connection. from pymongo import MongoClient
Cadenas de conexión
Nota
Atlas proporciona una cadena de conexión preconfigurada. Para conocer los pasos para copiarla, consulte Cadenas de conexión proporcionadas por Atlas.
Utiliza una cadena de conexión que especifique todos los nodos en tu clúster de Atlas para conectar tu aplicación a tu base de datos. Si tu clúster realiza una elección de set de réplicas y se elige un nuevo primario, una cadena de conexión que especifica todos los nodos de su clúster detecta el nuevo primario sin lógica de la aplicación.
Puedes especificar todos los nodos de tu clúster usando cualquiera de las siguientes opciones:
el Formato de Conexión DNS lista de nodos iniciales (recomendado con Atlas).
La cadena de conexión también puede especificar opciones, especialmente retryWrites y writeConcern.
Atlas puede generar una cadena de conexión SRV optimizada para clústeres particionados utilizando los balanceadores de carga del servicio de nodos privados. Cuando se usa una cadena de conexión optimizada, Atlas limita el número de conexiones por mongos entre la aplicación y el clúster particionado. Las conexiones limitadas por mongos mejoran el rendimiento durante los picos en el número de conexiones.
Para obtener más información sobre las cadenas de conexión optimizadas para clústeres fragmentados detrás de un nodo privado, consulta ¿Cómo puedo optimizar el rendimiento de la conexión para clústeres fragmentados con nodos privados?
Cadenas de conexión proporcionadas por Atlas
Si copias tu cadena de conexión desde la interfaz de tu clúster de Atlas, la cadena de conexión está preconfigurada para tu clúster, utiliza el formato de lista de semillas DNS y la inclusión de las opciones recomendadas de retryWrites y w (nivel de confirmación de escritura (write concern)) para obtener resiliencia.
Para copiar tu URI de la cadena de conexión de Atlas:
En Atlas, ve a la página Clusters de tu proyecto.
Si aún no se muestra, seleccione la organización que contiene su proyecto deseado en el menú Organizations de la barra de navegación.
Si aún no aparece, selecciona el proyecto deseado en el menú Projects de la barra de navegación.
En la barra lateral, haz clic en Clusters en la sección Database.
La página de clústeres se muestra.
Copia el URI de la cadena de conexión.
Copia la cadena de conexión o el ejemplo completo del controlador en el código de tu aplicación. Debes proporcionar credenciales de usuario de base de datos.
Nota
Esta guía utiliza autenticación SCRAM a través de una cadena de conexión. Para aprender sobre el uso de los certificados X.509 para autenticarse, consulta X.509.
Utiliza tu cadena de conexión para crear un cliente de MongoDB en la aplicación:
// Copy the connection string provided by Atlas String uri = <your Atlas connection string>; // Instantiate the MongoDB client with the URI MongoClient client = MongoClients.create(uri);
// Copy the connection string provided by Atlas const uri = <your Atlas connection string>; // Instantiate the MongoDB client with the URI const client = new MongoClient(uri);
# Copy the connection string provided by Atlas uri = <your Atlas connection string> # Pass your connection string URI to the MongoClient constructor client = MongoClient(uri)
Escrituras y lecturas reintentables
Nota
MongoDB vuelve a intentar tanto los guardados como las lecturas una vez por defecto.
Escrituras reintentables
Utiliza escrituras reintentables para reintentar ciertas operaciones de escritura una sola vez si fallan. Si copiaste tu cadena de conexión desde Atlas, incluye "retryWrites=true". Si proporcionas tu propia cadena de conexión, incluye "retryWrites=true" como un parámetro de consulta.
Reintentar grabaciones exactamente una vez es la mejor estrategia para manejar errores de red transitorios y elecciones de sets de réplicas en las que la aplicación temporalmente no puede encontrar un nodo primario sano. Si el reintento tiene éxito, la operación en su totalidad tiene éxito y no se devuelve ningún error. Si la operación falla, es probable que sea debido a:
Un error de red persistente
Un comando inválido
Cuando una operación falla, su aplicación debe gestionar el error por sí misma.
Lecturas reintentables
Las operaciones de lectura se reintentan automáticamente una sola vez si fallan. No se requiere configuración adicional para reintentar las lecturas.
Guardar y nivel de consistencia de lectura
Puedes ajustar la coherencia y la disponibilidad de tu aplicación utilizando niveles de confirmación de escritura (write concern) y niveles de consistencia de lectura. Preocupaciones más estrictas implican que las operaciones de la base de datos esperen garantías de coherencia de datos más fuertes, mientras que el alivio de los requisitos de coherencia proporciona una mayor disponibilidad.
Ejemplo
Si su aplicación gestiona saldos monetarios, la coherencia es sumamente importante. Puedes usar las preocupaciones de escritura y el nivel de consistencia de lectura de majority para asegurarte de nunca leer datos obsoletos o datos que puedan ser revertidos.
Alternativamente, si tu aplicación registra datos de temperatura de cientos de sensores cada segundo, es posible que no te preocupe si lees datos que no incluyen las lecturas más recientes. Puedes relajar los requisitos de coherencia y proporcionar acceso más rápido a esos datos.
Nivel de confirmación de escritura
Puede configurar el nivel de confirmación de escritura (write concern) de su set de réplicas de Atlas a través del URI de cadena de conexión. Usa un majority nivel de confirmación de escritura (write concern) para garantizar que tus datos se escriban correctamente en tu base de datos y se conserven. Esta es la opción por defecto recomendada y suficiente para la mayoría de los casos de uso. Si copiaste tu cadena de conexión de Atlas, incluye "w=majority".
Cuando use un nivel de confirmación de escritura (write concern) que requiera confirmación, como majority, también puede especificar un límite máximo de tiempo para que las escrituras alcancen ese nivel de confirmación:
El parámetro de la cadena de conexión wtimeoutMS para todas las escrituras, o
La opción wtimeout para una única operación de guardar.
El que utilices o no un límite de tiempo y el valor que utilices depende del contexto de tu aplicación.
Importante
Si no especificas un límite de tiempo para las escrituras y el nivel de confirmación de escritura (write concern) es inalcanzable, la operación de escritura se mantendrá en espera indefinidamente.
readConcern
Se puede configurar el nivel de consistencia de lectura del set de réplicas de Atlas a través de la URI de cadena de conexión. La nivel de consistencia de lectura ideal depende de los requisitos de tu aplicación, pero el valor por defecto es suficiente para la mayoría de los casos de uso. No se requiere ningún parámetro de cadena de conexión para usar los niveles de consistencia de lectura por defecto.
Especificar un nivel de consistencia de lectura puede mejorar las garantías en torno a los datos que su aplicación recibe de Atlas.
Nota
La combinación específica de write concern y nivel de consistencia de lectura que utiliza tu aplicación afecta las garantías de orden de las operaciones. Esto se denomina coherencia causal. Para obtener más información sobre las garantías de la coherencia causal, consulta Coherencia causal y nivel de confirmación de escritura (write concern).
Error Handling
Los comandos no válidos, las interrupciones de red y los errores de red que no se gestionan mediante escrituras reintentables generan errores. Consulte la documentación de la API de su controlador para obtener más información sobre los errores.
Por ejemplo, si una aplicación intenta insertar un documento que contiene un valor _id que ya se utiliza en la colección de la base de datos, tu driver devuelve un error que incluye:
Unable to insert due to an error: com.mongodb.MongoWriteException: E11000 duplicate key error collection: <db>.<collection> ...
{ "name": : "MongoError", "message": "E11000 duplicate key error collection on: <db>.<collection> ... ", ... }
pymongo.errors.DuplicateKeyError: E11000 duplicate key error collection: <db>.<collection> ...
Sin una gestión adecuada de errores, un error podría evitar que tu aplicación realice el procesamiento de solicitudes hasta que se reinicie.
Tu aplicación debe gestionar errores sin fallos ni efectos secundarios. En el ejemplo anterior de una aplicación que inserta un _id duplicado en una colección, esa aplicación podría gestionar los errores de la siguiente manera:
// Declare a logger instance from java.util.logging.Logger private static final Logger LOGGER = ... ... try { InsertOneResult result = collection.insertOne(new Document() .append("_id", 1) .append("body", "I'm a goofball trying to insert a duplicate _id")); // Everything is OK LOGGER.info("Inserted document id: " + result.getInsertedId()); // Refer to the API documentation for specific exceptions to catch } catch (MongoException me) { // Report the error LOGGER.severe("Failed due to an error: " + me); }
... collection.insertOne({ _id: 1, body: "I'm a goofball trying to insert a duplicate _id" }) .then(result => { response.sendStatus(200) // send "OK" message to the client }, err => { response.sendStatus(400); // send "Bad Request" message to the client });
... try: collection.insert_one({ "_id": 1, "body": "I'm a goofball trying to insert a duplicate _id" }) return {"message": "User successfully added!"} except pymongo.errors.DuplicateKeyError as e: print ("The insert operation failed:", e)
La operación de inserción en este ejemplo arroja un error de "clave duplicada" la segunda vez que se invoca porque el campo _id debe ser único. Se detecta el error, se notifica al cliente y la aplicación sigue funcionando. Sin embargo, la operación de inserción falla y depende de ti decidir si mostrar un mensaje al usuario, reintentar la operación o hacer otra cosa.
Siempre se deben registrar los errores. Las estrategias comunes para el procesamiento adicional de errores incluyen:
Devuelva el error al cliente con un mensaje de error. Esta es una buena estrategia cuando no puedes resolver el error y necesitas informar a un usuario de que no se puede completar una acción.
Escribe en una base de datos de copias de seguridad. Esta es una buena estrategia cuando no puedes resolver el error pero no quieres arriesgarte a perder los datos de la solicitud.
Reintente la operación más allá del único reintento predeterminado. Esta es una buena estrategia cuando puede resolver la causa de un error mediante programación y luego reintentarla.
Debe seleccionar las mejores estrategias para el contexto de su aplicación.
Ejemplo
En el ejemplo de un error de clave duplicada, debe registrar el error pero no volver a intentar la operación porque nunca tendrá éxito. En su lugar, puedes guardar en una base de datos alternativa y revisar el contenido de esa base de datos en un momento posterior para garantizar que no se pierda ninguna información. El usuario no necesita hacer nada más y los datos están registrados, por lo que puedes optar por no enviar un mensaje de error al cliente.
Planificación para errores de red
Devolver un error puede ser un comportamiento deseable cuando una operación pueda quedar colgada indefinidamente e impedir que tu aplicación ejecute nuevas operaciones. Puedes usar el método maxTimeMS para establecer un límite de tiempo en operaciones individuales, devolviendo un error para que tu aplicación lo gestione si se excede ese límite de tiempo.
El límite de tiempo que se establezca para cada operación depende del contexto de esa operación.
Ejemplo
Si tu aplicación lee y muestra información de producto sencilla desde una colección inventory, puedes tener la confianza razonable de que esas operaciones de lectura solo toman un momento. Una query que se ejecuta inusualmente durante mucho tiempo es un buen indicador de que hay un problema de red persistente. Configurar maxTimeMS en esa operación a 5000, o 5 segundos, significa que tu aplicación recibe retroalimentación tan pronto como estés seguro de que hay un problema de red.
Prueba de conmutación por error
En el espíritu de pruebas de caos, Atlas realizará elecciones de set de réplicas automáticamente para tareas de mantenimiento periódicas y ciertos cambios de configuración.
Para comprobar si tu aplicación es resiliente a las elecciones del set de réplicas, prueba el proceso de failover simulando un evento de failover.
Aplicación de ejemplo resiliente
La aplicación de ejemplo reúne las siguientes recomendaciones para garantizar la resiliencia frente a interrupciones del servicio de red y eventos de conmutación por error:
Utilice la cadena de conexión proporcionada por Atlas con escrituras reintentables, nivel de confirmación de escritura de mayoría y nivel de consistencia de lectura por defecto.
Especificar un límite de operation time con el método maxTimeMS. Para obtener instrucciones sobre cómo configurar
maxTimeMS, consulta tu documentación del driver.Gestione errores por claves duplicadas y "timeouts".
La aplicación es una API HTTP que permite a los clientes crear o listar registros de usuarios. Expone un endpoint que acepta solicitudes GET y POST http://localhost:3000:
Método | Endpoint | Descripción |
|---|---|---|
|
| Obtiene una lista de nombres de usuario de una colección |
|
| Requiere un |
Nota
1 // File: App.java 2 3 import java.util.Map; 4 import java.util.logging.Logger; 5 6 import org.bson.Document; 7 import org.json.JSONArray; 8 9 import com.mongodb.MongoException; 10 import com.mongodb.client.MongoClient; 11 import com.mongodb.client.MongoClients; 12 import com.mongodb.client.MongoCollection; 13 import com.mongodb.client.MongoDatabase; 14 15 import fi.iki.elonen.NanoHTTPD; 16 17 public class App extends NanoHTTPD { 18 private static final Logger LOGGER = Logger.getLogger(App.class.getName()); 19 20 static int port = 3000; 21 static MongoClient client = null; 22 23 public App() throws Exception { 24 super(port); 25 26 // Replace the uri string with your MongoDB deployment's connection string 27 String uri = "<atlas-connection-string>"; 28 client = MongoClients.create(uri); 29 30 start(NanoHTTPD.SOCKET_READ_TIMEOUT, false); 31 LOGGER.info("\nStarted the server: http://localhost:" + port + "/ \n"); 32 } 33 34 public static void main(String[] args) { 35 try { 36 new App(); 37 } catch (Exception e) { 38 LOGGER.severe("Couldn't start server:\n" + e); 39 } 40 } 41 42 43 public Response serve(IHTTPSession session) { 44 StringBuilder msg = new StringBuilder(); 45 Map<String, String> params = session.getParms(); 46 47 Method reqMethod = session.getMethod(); 48 String uri = session.getUri(); 49 50 if (Method.GET == reqMethod) { 51 if (uri.equals("/")) { 52 msg.append("Welcome to my API!"); 53 } else if (uri.equals("/users")) { 54 msg.append(listUsers(client)); 55 } else { 56 msg.append("Unrecognized URI: ").append(uri); 57 } 58 } else if (Method.POST == reqMethod) { 59 try { 60 String name = params.get("name"); 61 if (name == null) { 62 throw new Exception("Unable to process POST request: 'name' parameter required"); 63 } else { 64 insertUser(client, name); 65 msg.append("User successfully added!"); 66 } 67 } catch (Exception e) { 68 msg.append(e); 69 } 70 } 71 72 return newFixedLengthResponse(msg.toString()); 73 } 74 75 static String listUsers(MongoClient client) { 76 MongoDatabase database = client.getDatabase("test"); 77 MongoCollection<Document> collection = database.getCollection("users"); 78 79 final JSONArray jsonResults = new JSONArray(); 80 collection.find().forEach((result) -> jsonResults.put(result.toJson())); 81 82 return jsonResults.toString(); 83 } 84 85 static String insertUser(MongoClient client, String name) throws MongoException { 86 MongoDatabase database = client.getDatabase("test"); 87 MongoCollection<Document> collection = database.getCollection("users"); 88 89 collection.insertOne(new Document().append("name", name)); 90 return "Successfully inserted user: " + name; 91 } 92 }
Nota
La siguiente aplicación de servidor utiliza Express, que debes agregar como una dependencia a tu proyecto antes de poder ejecutarlo.
1 const express = require('express'); 2 const bodyParser = require('body-parser'); 3 4 // Use the latest client libraries by installing & importing them 5 const MongoClient = require('mongodb').MongoClient; 6 7 const app = express(); 8 app.use(bodyParser.json()); 9 app.use(bodyParser.urlencoded({ extended: true })); 10 11 const uri = "mongodb+srv://<db_username>:<db_password>@cluster0-111xx.mongodb.net/test?retryWrites=true&w=majority"; 12 13 const client = new MongoClient(uri); 14 15 // ----- API routes ----- // 16 app.get('/', (req, res) => res.send('Welcome to my API!')); 17 18 app.get('/users', (req, res) => { 19 const collection = client.db("test").collection("users"); 20 21 collection 22 .find({}) 23 .maxTimeMS(5000) 24 .toArray((err, data) => { 25 if (err) { 26 res.send("The request has timed out. Please check your connection and try again."); 27 } 28 return res.json(data); 29 }); 30 }); 31 32 app.post('/users', (req, res) => { 33 const collection = client.db("test").collection("users"); 34 collection.insertOne({ name: req.body.name }) 35 .then(result => { 36 res.send("User successfully added!"); 37 }, err => { 38 res.send("An application error has occurred. Please try again."); 39 }) 40 }); 41 // ----- End of API routes ----- // 42 43 app.listen(3000, () => { 44 console.log(`Listening on port 3000.`); 45 client.connect(err => { 46 if (err) { 47 console.log("Not connected: ", err); 48 process.exit(0); 49 } 50 console.log('Connected.'); 51 }); 52 });
Nota
La siguiente aplicación web utiliza FastAPI. Para crear una nueva aplicación, se debe usar la estructura del archivo de muestra de FastAPI.
1 # File: main.py 2 3 from fastapi import FastAPI, Body, Request, Response, HTTPException, status 4 from fastapi.encoders import jsonable_encoder 5 6 from typing import List 7 from models import User 8 9 import pymongo 10 from pymongo import MongoClient 11 from pymongo import errors 12 13 # Replace the uri string with your |service| connection string 14 uri = "<atlas-connection-string>" 15 db = "test" 16 17 app = FastAPI() 18 19 20 def startup_db_client(): 21 app.mongodb_client = MongoClient(uri) 22 app.database = app.mongodb_client[db] 23 24 25 def shutdown_db_client(): 26 app.mongodb_client.close() 27 28 ##### API ROUTES ##### 29 30 def list_users(request: Request): 31 try: 32 users = list(request.app.database["users"].find().max_time_ms(5000)) 33 return users 34 except pymongo.errors.ExecutionTimeout: 35 raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="The request has timed out. Please check your connection and try again.") 36 37 38 def new_user(request: Request, user: User = Body(...)): 39 user = jsonable_encoder(user) 40 try: 41 new_user = request.app.database["users"].insert_one(user) 42 return {"message":"User successfully added!"} 43 except pymongo.errors.DuplicateKeyError: 44 raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Could not create user due to existing '_id' value in the collection. Try again with a different '_id' value.")