Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
Realización de operaciones CRUD en Amazon DocumentDB con Java
En esta sección se describe cómo realizar la operación CRUD (crear, leer, actualizar, eliminar) en Amazon DocumentDB mediante controladores Java de MongoDB.
Temas
Crear e insertar documentos en una colección de DocumentDB
La inserción de documentos en Amazon DocumentDB le permite añadir nuevos datos a sus colecciones. Existen varias formas de realizar las inserciones, en función de sus necesidades y del volumen de datos con el que esté trabajando. El método más básico para insertar un documento individual en la colección esinsertOne()
. Para insertar varios documentos a la vez, puede utilizar el insertMany()
método, que le permite añadir una serie de documentos en una sola operación. Otro método para insertar muchos documentos en una colección de DocumentDB es. bulkWrite()
En esta guía, analizamos todos estos métodos para crear documentos en una colección de DocumentDB.
insertOne()
Empecemos por examinar cómo insertar un documento individual en una colección de Amazon DocumentDBB. La inserción de un único documento se realiza mediante el insertOne()
método. Este método toma un objeto BsonDocumentInsertOneResult
Document article = new Document() .append("restaurantId", "REST-21G145") .append("name", "Future-proofed Intelligent Bronze Hat") .append("cuisine", "International") .append("rating", new Document() .append("average", 1.8) .append("totalReviews", 267)) .append("features", Arrays.asList("Outdoor Seating", "Live Music")); try { InsertOneResult result = collection.insertOne(article); System.out.println("Inserted document with the following id: " + result.getInsertedId()); } catch (MongoWriteException e) { // Handle duplicate key or other write errors System.err.println("Failed to insert document: " + e.getMessage()); throw e; } catch (MongoException e) { // Handle other MongoDB errors System.err.println("MongoDB error: " + e.getMessage()); throw e; }
Cuando insertOne()
lo utilices, asegúrate de incluir una gestión de errores adecuada. Por ejemplo, en el código anterior, «restaurantId
» tiene un índice único y, por lo tanto, al volver a ejecutar este código, se generará lo siguienteMongoWriteException
:
Failed to insert document: Write operation error on server docdbCluster.docdb.amazonaws.com:27017.
Write error: WriteError{code=11000, message='E11000 duplicate key error collection: Restaurants index: restaurantId_1', details={}}.
InsertMany ()
Los métodos principales utilizados para insertar muchos documentos en una colección son insertMany () y. bulkWrite()
El insertMany()
método es la forma más sencilla de insertar varios documentos en una sola operación. Acepta una lista de documentos y los inserta en la colección. Este método es ideal cuando se inserta un lote de documentos nuevos que son independientes entre sí y no requieren ningún procesamiento especial ni operaciones mixtas. El siguiente código muestra la lectura de documentos JSON de un archivo y su inserción en la colección. La insertMany()
función devuelve un InsertManyResult
InsertManyResult
objeto que se puede utilizar para obtener todos IDs los documentos insertados.
// Read JSON file content String content = new String(Files.readAllBytes(Paths.get(jsonFileName))); JSONArray jsonArray = new JSONArray(content); // Convert JSON articles to Documents List < Document > restaurants = new ArrayList < > (); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); Document doc = Document.parse(jsonObject.toString()); restaurants.add(doc); } //insert documents in collection InsertManyResult result = collection.insertMany(restaurants); System.out.println("Count of inserted documents: " + result.getInsertedIds().size());
El bulkWrite()
método permite realizar múltiples operaciones de escritura (insertar, actualizar, eliminar) en un solo lote. Puede usarlo bulkWrite()
cuando necesite realizar diferentes tipos de operaciones en un solo lote, como insertar algunos documentos y actualizar otros. bulkWrite()
admiten dos tipos de escritura por lotes, ordenada y desordenada:
Operaciones ordenadas: (predeterminado) Amazon DocumentDB procesa las operaciones de escritura de forma secuencial y se detiene ante el primer error que detecta. Esto resulta útil cuando el orden de las operaciones es importante, por ejemplo, cuando las operaciones posteriores dependen de las anteriores. Sin embargo, las operaciones ordenadas suelen ser más lentas que las no ordenadas. En el caso de las operaciones ordenadas, debe abordarse el caso de que el lote se detenga ante el primer error, lo que podría dejar algunas operaciones sin procesar.
Operaciones desordenadas: permite a Amazon DocumentDB procesar las inserciones como una sola ejecución en la base de datos. Si se produce un error en un documento, la operación continúa con los demás documentos. Esto resulta especialmente útil cuando se insertan grandes cantidades de datos y se pueden tolerar algunos errores, como durante la migración de datos o las importaciones masivas, donde algunos documentos pueden fallar debido a la duplicación de claves. En el caso de operaciones desordenadas, debe abordar los escenarios de éxito parcial, en los que algunas operaciones se realizan correctamente y otras no.
Al trabajar con el bulkWrite()
método, se requieren algunas clases esenciales. En primer lugar, la WriteModel
InsertOneModel
UpdateOneModel
UpdateManyModel
DeleteOneModel
DeleteManyModel
La BulkWriteOptions
BulkWriteResult
Para la gestión de errores, la MongoBulkWriteException
BulkWriteError
bulkWrite()
método. El código también muestra cómo trabajar con BulkWriteResult
bulkWrite()
operación BulkWriteOptions
List < WriteModel < Document >> bulkOperations = new ArrayList < > (); // get list of 10 documents representing 10 restaurants List < Document > restaurantsToInsert = getSampleData(); for (Document doc: restaurantsToInsert) { bulkOperations.add(new InsertOneModel < > (doc)); } // Update operation bulkOperations.add(new UpdateOneModel < > ( new Document("restaurantId", "REST-Y2E9H5"), new Document("", new Document("stats.likes", 20)) .append("", new Document("rating.average", 4.5)))); // Delete operation bulkOperations.add(new DeleteOneModel < > (new Document("restaurantId", "REST-D2L431"))); // Perform bulkWrite operation try { BulkWriteOptions options = new BulkWriteOptions() .ordered(false); // Allow unordered inserts BulkWriteResult result = collection.bulkWrite(bulkOperations, options); System.out.println("Inserted: " + result.getInsertedCount()); System.out.println("Updated: " + result.getModifiedCount()); System.out.println("Deleted: " + result.getDeletedCount()); } catch (MongoBulkWriteException e) { System.err.println("Bulk write error occurred: " + e.getMessage()); // Log individual write errors for (BulkWriteError error: e.getWriteErrors()) { System.err.printf("Error at index %d: %s (Code: %d)%n", error.getIndex(), error.getMessage(), error.getCode()); // Log the problematic document Document errorDoc = new Document(error.getDetails()); if (errorDoc != null) { System.err.println("Problematic document: " + errorDoc); } } } catch (Exception e) { System.err.println("Error during bulkWrite: " + e.getMessage()); }
Escrituras reintentables
A diferencia de MongoDB, Amazon DocumentDB no admite escrituras reintentables. En consecuencia, debe implementar una lógica de reintento personalizada en sus aplicaciones, especialmente para solucionar problemas de red o la falta temporal de disponibilidad del servicio. Por lo general, una estrategia de reintentos bien implementada implica aumentar la demora entre los reintentos y limitar el número total de reintentos. Consulte Gestión de errores con lógica de reintento a continuación un ejemplo de código sobre cómo crear una lógica de reintentos con gestión de errores.
Lectura y recuperación de datos de una colección de DocumentDB
La consulta de documentos en Amazon DocumentDB gira en torno a varios componentes clave que permiten recuperar y manipular datos con precisión. El find()
find()
método, Filters
FindIterable
La Filters
clase es una clase de utilidad del controlador Java de MongoDB que proporciona una API fluida para crear filtros de consultas. Esta clase ofrece métodos de fábrica estáticos que crean instancias de Bson
objetos que representan diversas condiciones de consulta. Los métodos más utilizados son las comparaciones eq()
de igualdad, gt()
lt()
gte()
, y lte()
las comparaciones numéricas, and()
la combinación or()
de varias condiciones, in()
las pruebas nin()
de pertenencia a matrices y la coincidencia regex()
de patrones. La clase está diseñada para proteger los tipos y proporciona una mejor comprobación en tiempo de compilación en comparación con las consultas basadas en documentos sin procesar, lo que la convierte en el enfoque preferido para crear consultas de DocumentDB en aplicaciones Java. La gestión de errores es sólida, con claras excepciones en el caso de construcciones de filtros no válidas.
FindIterable
es una interfaz especializada diseñada para gestionar el resultado del find()
método. Proporciona un amplio conjunto de métodos para refinar y controlar la ejecución de consultas, y ofrece una API fluida para el encadenamiento de métodos. La interfaz incluye métodos esenciales de modificación de consultas, como limit()
restringir el número de documentos devueltos, skip()
paginar, sort()
ordenar los resultados, projection()
seleccionar campos específicos y hint()
seleccionar índices. Las operaciones de agrupar, omitir y limitar FindIterable
son herramientas esenciales de paginación y administración de datos que ayudan a controlar la forma en que se recuperan y procesan los documentos de la base de datos.
Batching (batchSize
) controla el número de documentos que DocumentDB devuelve al cliente en una única red de ida y vuelta. Al establecer un tamaño de lote, DocumentDB no devuelve todos los documentos coincidentes a la vez, sino que los devuelve en grupos del tamaño de lote especificado.
Omitir le permite desplazar el punto de partida de los resultados y, básicamente, le indica a DocumentDB que omita un número específico de documentos antes de empezar a devolver las coincidencias. Por ejemplo, skip(20)
omitirá los primeros 20 documentos coincidentes. Esto se suele utilizar en escenarios de paginación en los que se desean recuperar las siguientes páginas de resultados.
El límite restringe el número total de documentos que se pueden devolver a partir de una consulta. Si lo especificalimit(n)
, DocumentDB dejará de devolver documentos después de haber devuelto «n» documentos, incluso si hay más coincidencias en la base de datos.
FindIterable
admite patrones de iterador y cursor al recuperar documentos de Amazon DocumentDB. La ventaja de usarlo FindIterable
como iterador es que permite la carga diferida de los documentos y solo los recupera cuando la aplicación los solicita. Otra ventaja de usar el iterador es que no es responsable de mantener la conexión con el clúster y, por lo tanto, no es necesario cerrarla explícitamente.
FindIterable
también proporcionan soporte MongoCursor
MongoCursor
es una implementación específica del controlador Java de MongoDB que proporciona control sobre las operaciones de la base de datos y la administración de recursos. Implementa la AutoCloseable
interfaz, lo que permite una gestión explícita de los recursos mediante try-with-resources bloques, lo cual es crucial para cerrar correctamente las conexiones de las bases de datos y liberar los recursos del servidor. De forma predeterminada, el tiempo de espera del cursor es de 10 minutos y DocumentDB no le da la opción de cambiar este comportamiento de tiempo de espera. Cuando trabaje con datos agrupados, asegúrese de recuperar el siguiente lote de datos antes de que se agote el tiempo de espera del cursor. Una consideración clave al usarlo MongoCursor
es que requiere un cierre explícito para evitar fugas de recursos.
En esta sección, se presentan varios ejemplos defind()
, Filters
yFindIterable
.
El siguiente ejemplo de código muestra cómo find()
recuperar un único documento mediante su campo «RestaurantID»:
Document filter = new Document("restaurantId", "REST-21G145"); Document result = collection.find(filter).first();
Si bien su uso Filters
permite comprobar mejor los errores en el momento de la compilación, el controlador java también permite especificar un Bson
filtro directamente en el find()
método. El siguiente código de ejemplo pasa Bson
el documento afind()
:
result = collection.find(new Document("$and", Arrays.asList( new Document("rating.totalReviews", new Document("$gt", 1000)), new Document("priceRange", "$$"))))
El siguiente código de ejemplo muestra varios ejemplos del uso de la Filters
clase confind()
:
FindIterable < Document > results; // Exact match results = collection.find(Filters.eq("name", "Thai Curry Palace")); // Not equal results = collection.find(Filters.ne("cuisine", "Thai")); // find an element in an array results = collection.find(Filters.in("features", Arrays.asList("Private Dining"))); // Greater than results = collection.find(Filters.gt("rating.average", 3.5)); // Between (inclusive) results = collection.find(Filters.and( Filters.gte("rating.totalReviews", 100), Filters.lte("rating.totalReviews", 200))); // AND results = collection.find(Filters.and( Filters.eq("cuisine", "Thai"), Filters.gt("rating.average", 4.5))); // OR results = collection.find(Filters.or( Filters.eq("cuisine", "Thai"), Filters.eq("cuisine", "American"))); // All document where the Field exists results = collection.find(Filters.exists("michelin")); // Regex results = collection.find(Filters.regex("name", Pattern.compile("Curry", Pattern.CASE_INSENSITIVE))); // Find all document where the array contain the list of value regardless of its order results = collection.find(Filters.all("features", Arrays.asList("Private Dining", "Parking"))); // Array size results = collection.find(Filters.size("features", 4));
El siguiente ejemplo muestra cómo encadenar las operaciones de sort()
skip()
,limit()
, y batchSize()
sobre un FindIterable
objeto. El orden en que se proporcionen estas operaciones influirá en el rendimiento de la consulta. Como práctica recomendada, el orden de estas operaciones debe ser sort()
projection()
,skip()
, limit()
ybatchSize()
.
FindIterable < Document > results = collection.find(Filters.gt("rating.totalReviews", 1000)) // Sorting .sort(Sorts.orderBy( Sorts.descending("address.city"), Sorts.ascending("cuisine"))) // Field selection .projection(Projections.fields( Projections.include("name", "cuisine", "priceRange"), Projections.excludeId())) // Pagination .skip(20) .limit(10) .batchSize(2);
El siguiente código de ejemplo muestra la creación de un iterador enFindIterable
. Utiliza la forEach
construcción de Java para recorrer el conjunto de resultados.
collection.find(Filters.eq("cuisine", "American")).forEach(doc -> System.out.println(doc.toJson()));
En el último ejemplo find()
de código, muestra cómo usarlo cursor()
para la recuperación de documentos. Crea el cursor en el bloque de prueba, lo que garantiza que el cursor se cierre cuando el código salga del bloque de prueba.
try (MongoCursor < Document > cursor = collection.find(Filters.eq("cuisine", "American")) .batchSize(25) .cursor()) { while (cursor.hasNext()) { Document doc = cursor.next(); System.out.println(doc.toJson()); } } // Cursor automatically closed
Actualización de documentos existentes en una colección de DocumentDB
Amazon DocumentDB proporciona mecanismos flexibles y eficaces para modificar los documentos existentes e insertar otros nuevos cuando no existen. El controlador Java de MongoDB ofrece varios métodos de actualizaciónupdateOne()
: para actualizaciones de un solo documentoupdateMany()
, para actualizaciones de varios documentos replaceOne()
y para la sustitución completa de documentos. Además de estos tres métodos, Updates
UpdateOptions
UpdateResult
La Updates
clase del controlador Java de MongoDB es una clase de utilidad que proporciona métodos de fábrica estáticos para crear operadores de actualización. Sirve como el generador principal para crear operaciones de actualización de forma legible y segura. Métodos básicos como set()
unset()
, y inc()
permiten la modificación directa de los documentos. El poder de esta clase se hace evidente cuando se combinan varias operaciones mediante el Updates.combine()
método que permite ejecutar varias operaciones de actualización de forma atómica, lo que garantiza la coherencia de los datos.
UpdateOptions
es una potente clase de configuración del controlador Java de MongoDB que proporciona capacidades de personalización esenciales para las operaciones de actualización de documentos. Dos aspectos importantes de esta clase son la compatibilidad con filtros de matriz y upsert para las operaciones de actualización. La función upsert, habilitada mediante esta funciónupsert(true)
, permite crear nuevos documentos cuando no se encuentra ningún documento coincidente durante una operación de actualización. De este arrayFilters()
modo, la operación de actualización puede actualizar con precisión los elementos de la matriz que cumplan criterios específicos.
UpdateResult
en MongoDB, el controlador Java proporciona el mecanismo de retroalimentación que detalla el resultado de una operación de actualización. Esta clase agrupa tres métricas clave: el número de documentos que cumplen los criterios de actualización (matchedCount
), el número de documentos realmente modificados (modifiedCount
) y la información sobre cualquier documento alterado (). upsertedId
Comprender estas métricas es esencial para gestionar correctamente los errores, verificar las operaciones de actualización y mantener la coherencia de los datos en las aplicaciones.
Actualice y sustituya un único documento
En DocumentDB, la actualización de un solo documento se puede realizar mediante el método updateOne (). Este método utiliza un parámetro de filtro, normalmente proporcionado por la Filters
clase, para identificar el documento que se va a actualizar, un parámetro Updat
e que determina qué campos se van a actualizar y un UpdateOptions
parámetro opcional para establecer diferentes opciones de actualización. El uso del updateOne()
método solo actualizará el primer documento que coincida con los criterios de selección. El siguiente código de ejemplo actualiza un solo campo de un documento:
collection.updateOne(Filters.eq("restaurantId", "REST-Y2E9H5"), Updates.set("name", "Amazing Japanese sushi"));
Para actualizar varios campos de un documento, utilícelo updateOne()
con, Update.combine()
como se muestra en el siguiente ejemplo. En este ejemplo también se muestra cómo agregar un elemento a una matriz del documento.
List<Bson> updates = new ArrayList<>(); // Basic field updates updates.add(Updates.set("name", "Shanghai Best")); // Array operations updates.add(Updates.addEachToSet("features", Arrays.asList("Live Music"))); // Counter updates updates.add(Updates.inc("rating.totalReviews", 10)); // Combine all updates Bson combinedUpdates = Updates.combine(updates); // Execute automic update with one call collection.updateOne(Filters.eq("restaurantId","REST-1J83NH"), combinedUpdates);
El siguiente ejemplo de código muestra cómo actualizar un documento de la base de datos. Si el documento especificado no existe, la operación lo insertará automáticamente como un documento nuevo. Este código también muestra cómo utilizar las métricas disponibles a través del UpdateResult
objeto.
Bson filter = Filters.eq("restaurantId", "REST-0Y9GL0"); Bson update = Updates.set("cuisine", "Indian"); // Upsert operation UpdateOptions options = new UpdateOptions().upsert(true); UpdateResult result = collection.updateOne(filter, update, options); if (result.getUpsertedId() != null) { System.out.println("Inserted document with _id: " + result.getUpsertedId()); } else { System.out.println("Updated " + result.getModifiedCount() + " document(s)"); }
El siguiente ejemplo de código muestra cómo reemplazar completamente un documento existente por uno nuevo mediante el replaceOne()
método, en lugar de actualizar campos individuales. El replaceOne()
método sobrescribe todo el documento y conserva únicamente el _id
campo del original. Si varios documentos coinciden con los criterios del filtro, solo se reemplaza el primer documento encontrado.
Document newDocument = new Document() .append("restaurantId", "REST-0Y9GL0") .append("name", "Bhiryani Adda") .append("cuisine", "Indian") .append("rating", new Document() .append("average", 4.8) .append("totalReviews", 267)) .append("features", Arrays.asList("Outdoor Seating", "Live Music")); UpdateResult result = collection.replaceOne( Filters.eq("restaurantId", "REST-0Y9GL0"), newDocument); System.out.printf("Modified %d document%n", result.getModifiedCount());
Actualice varios documentos
Hay dos formas de actualizar varios documentos de una colección simultáneamente. Puede usar el updateMany()
método o usar el UpdateManyModel
bulkWrite()
método. El updateMany()
método utiliza un parámetro de filtro para seleccionar los documentos que se van a actualizar, el Update
parámetro para identificar los campos que se van a actualizar y un UpdateOptions
parámetro opcional para especificar las opciones de actualización.
El siguiente código de ejemplo demuestra el uso del updateMany()
método:
Bson filter = Filters.and( Filters.in("features", Arrays.asList("Private Dining")), Filters.eq("cuisine", "Thai")); UpdateResult result1 = collection.updateMany(filter, Updates.set("priceRange", "$$$"));
El siguiente código de ejemplo demuestra que el bulkWrite()
método utiliza la misma actualización:
BulkWriteOptions options = new BulkWriteOptions().ordered(false); List < WriteModel < Document >> updates = new ArrayList < > (); Bson filter = Filters.and( Filters.in("features", Arrays.asList("Private Dining")), Filters.eq("cuisine", "Indian")); Bson updateField = Updates.set("priceRange", "$$$"); updates.add(new UpdateManyModel < > (filter, updateField)); BulkWriteResult result = collection.bulkWrite(updates, options); System.out.printf("Modified %d document%n", result.getModifiedCount());
Eliminar documentos de una colección de DocumentDB
El controlador deleteOne()
Java de MongoDB permite eliminar un solo documento deleteMany()
y eliminar varios documentos que coincidan con criterios específicos. Al igual que la actualización, la operación de eliminación también se puede utilizar con el bulkWrite()
método. Ambos deleteOne()
deleteMany()
devuelven un DeleteResult
deleteMany()
para eliminar varios documentos:
Bson filter = Filters.and( Filters.eq("cuisine", "Thai"), Filters.lt("rating.totalReviews", 50)); DeleteResult result = collection.deleteMany(filter); System.out.printf("Deleted %d document%n", result.getDeletedCount());
Gestión de errores con lógica de reintento
Una estrategia sólida de gestión de errores para Amazon DocumentDB debería incluir la categorización de los errores en reintentables (como tiempos de espera de la red o problemas de conexión) y no reintentables (como errores de autenticación o consultas no válidas). En el caso de los errores de operación debidos a errores que se deban volver a intentar, se debe implementar un intervalo de tiempo entre cada reintento, así como un máximo de reintentos. Las operaciones CRUD deben realizarse en un bloque de try-catch que capture MongoException
int MAX_RETRIES = 3; int INITIAL_DELAY_MS = 1000; int retryCount = 0; while (true) { try { crud_operation(); //perform crud that will throw MongoException or one of its subclass break; } catch (MongoException e) { if (retryCount < MAX_RETRIES) { retryCount++; long delayMs = INITIAL_DELAY_MS * (long) Math.pow(2, retryCount - 1); try { TimeUnit.MILLISECONDS.sleep(delayMs); } catch (InterruptedException t) { Thread.currentThread().interrupt(); throw new RuntimeException("Retry interrupted", t); } continue; } else throw new RuntimeException("Crud operation failed", e); } }