Al desarrollar una aplicación crítica, es importante prepararse para imprevistos que puedan ocurrir en producción. Esto incluye consultas lentas inesperadas, índices faltantes o un aumento brusco del volumen 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 lo siguiente: Resiliencia del clúster y mejores prácticas de aplicaciones y del lado del cliente.
Resiliencia de clústeres
Para mejorar la resiliencia de su clúster, Actualice su clúster a MongoDB.8.0 MongoDB 8.0 presenta las siguientes mejoras de rendimiento y nuevas funciones 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 el uso de la memoria permita margen de maniobra. Si un nodo se queda sin memoria disponible, puede volverse vulnerable al "asesino de memoria insuficiente" de Linux, que termina el nodo.mongod proceso.
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 la producción si no se gestiona rápidamente.
MongoDB 8.0 permite minimizar el impacto de estas operaciones mediante filtros de rechazo de operaciones. Estos filtros permiten configurar MongoDB para que rechace la ejecución de consultas hasta que se vuelvan a habilitar las consultas con esa forma de consulta.
En otras palabras, una vez que se identifica una consulta lenta, no es necesario esperar a que los equipos de la aplicación corrijan sus consultas para contener su impacto. En cambio, si se detecta una consulta con bajo rendimiento en el Analizador de Consultas, el Panel de Rendimiento en Tiempo Real o los registros de consultas, se puede establecer un filtro de rechazo para esa forma de consulta. MongoDB impide entonces que se ejecuten nuevas instancias de esa forma de consulta entrante. Una vez corregida la consulta, se puede volver a habilitar.
Debe utilizar un filtro de rechazo de operaciones si desea:
Contenga rápidamente el impacto de las consultas lentas mientras se realiza la solución.
Priorice las cargas de trabajo más importantes durante los momentos de sobrecarga rechazando las consultas menos importantes.
Dale tiempo al clúster para recuperarse si está cerca de la utilización máxima de recursos.
Identificar y rechazar consultas lentas en la interfaz de usuario de Atlas
Para utilizar un filtro de rechazo de operaciones en la interfaz de usuario de Atlas:
En Atlas, vaya a la Clusters Página para su 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.
Vaya al Generador de perfiles de consultas para el clúster especificado dentro del proyecto actual.
Haga clic en View Monitoring para esa instancia en el panel del proyecto.
Haz clic en la pestaña Query Insights.
Haz clic en la pestaña Query Profiler.
Rechazar operaciones de una forma de consulta específica.
Utilice setQuerySettings en su método db.adminCommand() para queryShapeHash pasar, que especifica la forma de consulta que desea rechazar.
Nota
Debe tener el rol atlasAdmin para setQuerySettings usar.
Para ver un ejemplo, consulte Bloquear consultas lentas con filtros de rechazo de operaciones.
Supervise sus consultas después del rechazo o el tiempo de espera
Puede supervisar cómo se ejecutan sus consultas posteriormente en la pestaña Métricas:
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.
Seleccione Operation Throttling.
En MongoDB Metrics, haz clic en Operation Throttling.
Con esta métrica, el gráfico de MongoDB muestra lo siguiente:
Killed, que muestra la cantidad de operaciones de lectura que MongoDB elimina con el tiempo debido a que exceden el tiempo de espera predeterminado del clúster.
Rejected, que muestra la cantidad de operaciones que MongoDB rechaza a lo largo del tiempo porque la consulta coincide con el filtro de rechazo definido por el usuario.
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 puede proteger sus consultas de operaciones no indexadas con la defaultMaxTimeMS entrada del servidor al clúster. Si una operación excede este tiempo de espera, MongoDB la cancela para evitar que las consultas se ejecuten demasiado tiempo y ocupen recursos. Esto le permite:
Transfiera la responsabilidad de establecer tiempos de espera de los equipos de aplicaciones individuales a los equipos centrados en la base de datos.
Minimiza el impacto de un escaneo de colección si a la consulta le falta un índice.
Disponer de una mitigación de última ronda contra operaciones costosas que llegan a producción.
Si tiene consultas que requieren un tiempo de espera diferente, como consultas de análisis, puede anularlas configurando el tiempo de espera a nivel de operación con el método maxTimeMS.
Establecer el tiempo de espera predeterminado para las operaciones de lectura en la API de administración de Atlas
Para configurar el parámetro a través de la API de administración de Atlas, consulte Actualizar defaultMaxTimeMSopciones de configuración avanzadas para un clúster.
Establecer el tiempo de espera predeterminado para las operaciones de lectura en la interfaz de usuario de Atlas
Para configurar el parámetro en la interfaz de usuario de defaultMaxTimeMS 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 el menú desplegable Select a version, seleccione MongoDB 8.0.
Haga clic en Additional Settings.
Desplácese hacia abajo y haga 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ísle el impacto de las colecciones ocupadas y no fragmentadas
Lafragmentación permite escalar el clúster horizontalmente. Con MongoDB, se pueden fragmentar algunas colecciones, mientras que otras del mismo clúster permanecen sin fragmentar. Al crear una base de datos, el fragmento del clúster con la menor cantidad de datos se selecciona como el fragmento principal de forma predeterminada. Todas las colecciones sin fragmentar de esa base de datos residen en ese fragmento principal de forma predeterminada. Esto puede provocar un aumento del tráfico al fragmento principal a medida que aumenta la carga de trabajo, especialmente si este se centra en las colecciones sin fragmentar del fragmento principal.
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:
Optimice el rendimiento en cargas de trabajo más grandes y complejas.
Lograr una mejor utilización de los recursos.
Distribuye la fecha de manera más uniforme entre las particiones.
Recomendamos aislar su colección en las siguientes circunstancias:
Si su fragmento principal experimenta una carga de trabajo significativa debido a la presencia de múltiples colecciones no fragmentadas de alto rendimiento.
Se anticipa que una colección no fragmentada experimentará un crecimiento futuro, lo que podría convertirse en un cuello de botella para otras colecciones.
Está ejecutando un diseño de implementación de una colección por clúster y desea aislar a esos clientes en función de la prioridad o las cargas de trabajo.
Sus fragmentos tienen una cantidad de datos mayor que la proporcional debido a la cantidad de colecciones no fragmentadas que se encuentran en ellos.
Para aprender a mover una colección no particionada con mongosh, consulta Mover una colección.
Mejores prácticas para aplicaciones y clientes
Puede configurar las características de sus implementaciones de MongoDB y las bibliotecas de controladores para crear una aplicación resiliente que pueda soportar interrupciones de red y conmutaciones por error. Para escribir código de aplicación que aproveche al máximo las capacidades de disponibilidad continua de MongoDB Atlas, debe 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.
Instalar las últimas bibliotecas de cliente
Instale las bibliotecas cliente más recientes para su lenguaje desde MongoDB Client Libraries. Estas bibliotecas conectan y retransmiten consultas desde su aplicación a su base de datos. Usar las bibliotecas cliente más recientes habilita las funciones más recientes de MongoDB.
Luego, en su aplicación, importe la dependencia:
Si está utilizando Maven, agregue lo siguiente a su pom.xml lista de dependencias:
<dependencies> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-driver-sync</artifactId> <version>4.0.1</version> </dependency> </dependencies>
Si está utilizando Gradle, agregue lo siguiente a su build.gradle lista de dependencias:
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 copiar la cadena preconfigurada, consulte Cadenas de conexión proporcionadas por Atlas.
Utilice una cadena de conexión que especifique todos los nodos de su clúster Atlas para conectar su aplicación a su base de datos. Si su clúster realiza una elección de conjunto de réplicas y se elige un nuevo nodo principal, una cadena de conexión que especifique todos los nodos del clúster detectará el nuevo nodo principal sin lógica de aplicación.
Puede especificar todos los nodos de su clúster utilizando:
el formato de cadena de conexión estándar, o
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 un optimizado Cadena de conexiónSRV para clústeres fragmentados que utilizan los balanceadores de carga de su servicio de punto final privado. Al usar una cadena de conexión optimizada, Atlas limita el número de conexiones por mongos entre su aplicación y su clúster fragmentado. La limitación de conexiones por mongos mejora el rendimiento durante picos de conexión.
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 copia su cadena de conexión desde la interfaz de su clúster Atlas, la cadena de conexión está preconfigurada para su clúster, utiliza el formato de lista de semillas de DNS e incluye las opciones recomendadas retryWrites y w (preocupación de escritura) para resiliencia.
Para copiar la URI de su cadena de conexión desde 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.
Copiar la cadena de conexión URI.
Copie la cadena de conexión o el ejemplo completo del controlador en el código de su aplicación. Debe proporcionar las credenciales de usuario de la base de datos.
Nota
Esta guía utiliza la autenticación SCRAM mediante una cadena de conexión. Para obtener más información sobre el uso de509 certificados X. para la autenticación, consulte X..509
Utilice su cadena de conexión para crear una instancia de un cliente MongoDB en su 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 las escrituras como las lecturas una vez de forma predeterminada.
Escrituras reintentables
Utilice escrituras reintentables para reintentar ciertas operaciones de escritura una sola vez si fallan. Si copió su cadena de conexión de Atlas, esta "retryWrites=true" incluye. Si proporciona su propia cadena de conexión, incluya "retryWrites=true" como parámetro de consulta.
Reintentar la escritura una sola vez es la mejor estrategia para gestionar errores de red transitorios y elecciones de conjuntos de réplicas en los que la aplicación no puede encontrar temporalmente un nodo principal en buen estado. Si el reintento tiene éxito, la operación en su conjunto se completa correctamente y no se devuelve ningún error. Si la operación falla, probablemente se deba a:
Un error de red duradero
Un comando no vá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 vez si fallan. No se requiere configuración adicional para reintentar las lecturas.
Preocupación por escribir y leer
Puede ajustar la consistencia y la disponibilidad de su aplicación mediante preocupaciones de escritura y lectura. Unas preocupaciones más estrictas implican que las operaciones de la base de datos esperan garantías de consistencia de datos más sólidas, mientras que una mayor flexibilidad en los requisitos de consistencia proporciona una mayor disponibilidad.
Ejemplo
Si su aplicación gestiona saldos monetarios, la consistencia es fundamental. Puede usar las consultas de escritura y lectura majority para asegurarse de no leer datos obsoletos o susceptibles de reversión.
Por otro lado, si su aplicación registra datos de temperatura de cientos de sensores cada segundo, no debería preocuparse si lee datos que no incluyan las lecturas más recientes. Puede flexibilizar los requisitos de consistencia y proporcionar un acceso más rápido a esos datos.
Nivel de confirmación de escritura
Puede configurar el nivel de preocupación de escritura de su conjunto de réplicas de Atlas mediante el URI de la cadena de conexión. Use una majority preocupación de escritura para garantizar que sus datos se escriban correctamente en su base de datos y se conserven. Este es el valor predeterminado recomendado y suficiente para la mayoría de los casos de uso. Si copió su cadena de conexión de Atlas, esta "w=majority" incluye.
Cuando utiliza una preocupación de escritura que requiere reconocimiento, como majority, también puede especificar un límite de tiempo máximo para que las escrituras alcancen ese nivel de reconocimiento:
El parámetro de cadena de conexión wtimeoutMS para todas las escrituras, o
La opción wtimeout para una sola operación de escritura.
El uso o no de un límite de tiempo y el valor que utilice dependerán del contexto de su aplicación.
Importante
Si no especifica un límite de tiempo para las escrituras y el nivel de preocupación por la escritura es inalcanzable, la operación de escritura se bloqueará indefinidamente.
readConcern
Puede configurar el nivel de preocupación de lectura de su conjunto de réplicas de Atlas mediante el URI de la cadena de conexión. La preocupación de lectura ideal depende de los requisitos de su aplicación, pero el valor predeterminado 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 las preocupaciones de lectura predeterminadas.
Especificar una preocupación 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 problemas de escritura y lectura que utiliza su aplicación afecta las garantías de orden de operación. Esto se denomina consistencia causal. Para obtener más información sobre las garantías de consistencia causal, consulte Consistencia causal y Problemas de lectura y escritura.
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, su controlador 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 de errores adecuada, un error puede impedir que su aplicación procese solicitudes hasta que se reinicie.
Su aplicación debería gestionar los errores sin fallos ni efectos secundarios. En el ejemplo anterior, una aplicación que insertaba un duplicado _id en una colecció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 de este ejemplo genera un error de "clave duplicada" la segunda vez que se invoca, ya que el campo _id debe ser único. Se detecta el error, se notifica al cliente y la aplicación continúa ejecutándose. Sin embargo, la operación de inserción falla, y usted decide si mostrar un mensaje al usuario, reintentar la operación o realizar otra acción.
Siempre se deben registrar los errores. Las estrategias comunes para el procesamiento adicional de errores incluyen:
Devolver el error al cliente con un mensaje de error. Esta es una buena estrategia cuando no se puede resolver el error y se necesita informar al usuario que una acción no se puede completar.
Escribir en una base de datos de respaldo. Esta es una buena estrategia cuando no se puede resolver el error, pero no se quiere arriesgar 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 reintentar la operación, ya que no se ejecutará correctamente. En su lugar, puede escribir en una base de datos de respaldo y revisar su contenido posteriormente para garantizar que no se pierda información. El usuario no necesita hacer nada más y los datos se registran, por lo que puede optar por no enviar un mensaje de error al cliente.
Planificación para errores de red
Devolver un error puede ser una buena idea cuando una operación se quedaría bloqueada indefinidamente e impediría que la aplicación ejecute nuevas operaciones. Puede usar el método maxTimeMS para establecer un límite de tiempo para operaciones individuales y devolver un error que la aplicación deberá gestionar si se excede dicho límite.
El límite de tiempo que establezca para cada operación dependerá 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
Con el espíritu de las pruebas de caos, Atlas realizará elecciones de conjuntos de réplicas automáticamente para el mantenimiento periódico y ciertos cambios de configuración.
Para comprobar si su aplicación es resistente a las elecciones de conjuntos de réplicas, pruebeel proceso de conmutación por error simulando un evento de conmutación por error.
Ejemplo de aplicación resiliente
La aplicación de ejemplo reúne las siguientes recomendaciones para garantizar la resiliencia ante cortes de red y eventos de conmutación por error:
Utilice la cadena de conexión proporcionada por Atlas con escrituras reintentables, preocupación de escritura mayoritaria y preocupación de lectura predeterminada.
Especifique un límite de tiempo de operación con el método maxTimeMS. Para obtener instrucciones sobre cómo
maxTimeMSconfigurar, consulte la documentación específica de su controlador.Manejar errores de claves duplicadas y tiempos de espera.
La aplicación es una API HTTP que permite a los clientes crear o listar registros de usuarios. Expone un punto final 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 debe agregar a su proyecto como dependencia 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, utilice la estructura de archivo de ejemplo 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.")