Docs Menu
Docs Home
/ /

Operaciones de escritura masiva

En esta guía, aprenderá a usar PyMongo para realizar operaciones masivas. Estas operaciones reducen el número de llamadas al servidor al realizar múltiples operaciones de escritura en un solo método.

El Collection Las clases MongoClient y bulk_write() proporcionan un método bulk_write(). Al llamar a en una instancia Collection, se pueden realizar múltiples operaciones de escritura en una sola colección. Al llamar a bulk_write() en una instancia MongoClient, se pueden realizar escrituras masivas en múltiples espacios de nombres. En MongoDB, un espacio de nombres consta del nombre de la base de datos y el nombre de la colección en el formato <database>.<collection>.

Importante

Para realizar operaciones masivas en una instancia MongoClient, asegúrese de que su aplicación cumpla con los siguientes requisitos:

  • Utiliza PyMongo v4.9 o posterior

  • Se conecta a MongoDB Server v8.0 o posterior

Los ejemplos de esta guía utilizan las colecciones sample_restaurants.restaurants y sample_mflix.movies de la Conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, consulte Tutorial paraempezar a usar PyMongo.

Para cada operación de escritura que desee realizar, cree una instancia de una de las siguientes clases de operación:

  • InsertOne

  • UpdateOne

  • UpdateMany

  • ReplaceOne

  • DeleteOne

  • DeleteMany

Luego, pase una lista de estas instancias al método bulk_write().

Importante

Asegúrese de importar las clases de operación de escritura en su archivo de aplicación, como se muestra en el siguiente código:

from pymongo import InsertOne, UpdateOne, UpdateMany, ReplaceOne, DeleteOne, DeleteMany

Las siguientes secciones muestran cómo crear instancias de las clases anteriores, que puede utilizar para realizar operaciones de recopilación y de cliente en masa.

Para realizar una operación de inserción, cree una instancia de InsertOne y especifique el documento que desea insertar. Pase los siguientes argumentos de palabra clave al constructor InsertOne:

  • namespace: El espacio de nombres donde se insertará el documento. Este argumento es opcional si se realiza la operación masiva en una sola colección.

  • document:El documento a insertar.

El siguiente ejemplo crea una instancia de InsertOne:

operation = InsertOne(
namespace="sample_restaurants.restaurants",
document={
"name": "Mongo's Deli",
"cuisine": "Sandwiches",
"borough": "Manhattan",
"restaurant_id": "1234"
}
)

También puedes crear una instancia de InsertOne pasando una instancia de una clase personalizada al constructor. Esto proporciona mayor seguridad de tipos si usas una herramienta de verificación de tipos. La instancia que pases debe heredar de la clase TypedDict.

Nota

TypedDict en Python 3.7 y versiones anteriores

La clase TypedDict se encuentra en el módulo typing, el cual está disponible solo en Python 3.8 y versiones posteriores. Para usar la clase TypedDict en versiones anteriores de Python, instala el paquete typing_extensions.

El siguiente ejemplo construye una instancia InsertOne utilizando una clase personalizada para mayor seguridad de tipo:

class Restaurant (TypedDict):
name: str
cuisine: str
borough: str
restaurant_id: str
operation = pymongo.InsertOne(Restaurant(
name="Mongo's Deli", cuisine="Sandwiches", borough="Manhattan", restaurant_id="1234"))

Para insertar varios documentos, cree una instancia de InsertOne para cada documento.

Nota

El campo _id debe ser único

En una colección de MongoDB, cada documento debe contener un campo _id con un valor único.

Si se especifica un valor para el campo _id, debe asegurarse de que el valor sea único en la colección. De lo contrario, el controlador genera automáticamente un valor ObjectId único para el campo.

Recomendamos dejar que el controlador genere valores de _id automáticamente para garantizar la unicidad. Los valores duplicados de _id violan restricciones de índice único, lo que provoca que el controlador devuelva un error.

Para actualizar un documento, cree una instancia de UpdateOne y pase los siguientes argumentos:

  • namespace: El espacio de nombres donde se realizará la actualización. Este argumento es opcional si se realiza la operación masiva en una sola colección.

  • filter:El filtro de consulta que especifica los criterios utilizados para buscar coincidencias en los documentos de su colección.

  • update: La actualización que desea realizar. Para obtener más información sobre las operaciones de actualización, consulte la guía Operadores de actualización de campos en el manual del MongoDB Server.

UpdateOne actualiza el primer documento que coincide con su filtro de consulta.

El siguiente ejemplo crea una instancia de UpdateOne:

operation = UpdateOne(
namespace="sample_restaurants.restaurants",
filter={ "name": "Mongo's Deli" },
update={ "$set": { "cuisine": "Sandwiches and Salads" }}
)

Para actualizar varios documentos, cree una instancia de UpdateMany y pase los mismos argumentos. UpdateMany actualiza todos los documentos que coinciden con su filtro de consulta.

El siguiente ejemplo crea una instancia de UpdateMany:

operation = UpdateMany(
namespace="sample_restaurants.restaurants",
filter={ "name": "Mongo's Deli" },
update={ "$set": { "cuisine": "Sandwiches and Salads" }}
)

Una operación de reemplazo elimina todos los campos y valores de un documento específico y los reemplaza por otros nuevos. Para realizar una operación de reemplazo, cree una instancia de ReplaceOne y pase los siguientes argumentos:

  • namespace: El espacio de nombres donde se realizará la operación de reemplazo. Este argumento es opcional si se realiza la operación masiva en una sola colección.

  • filter:El filtro de consulta que especifica los criterios utilizados para encontrar el documento a reemplazar.

  • replacement:El documento que incluye los nuevos campos y valores que desea almacenar en el documento correspondiente.

El siguiente ejemplo crea una instancia de ReplaceOne:

operation = ReplaceOne(
namespace="sample_restaurants.restaurants",
filter={ "restaurant_id": "1234" },
replacement={
"name": "Mongo's Pizza",
"cuisine": "Pizza",
"borough": "Brooklyn",
"restaurant_id": "5678"
}
)

También puedes crear una instancia de ReplaceOne pasando una instancia de una clase personalizada al constructor. Esto proporciona mayor seguridad de tipos si usas una herramienta de verificación de tipos. La instancia que pases debe heredar de la clase TypedDict.

Nota

TypedDict en Python 3.7 y versiones anteriores

La clase TypedDict se encuentra en el módulo typing, el cual está disponible solo en Python 3.8 y versiones posteriores. Para usar la clase TypedDict en versiones anteriores de Python, instala el paquete typing_extensions.

El siguiente ejemplo construye una instancia ReplaceOne utilizando una clase personalizada para mayor seguridad de tipo:

class Restaurant (TypedDict):
name: str
cuisine: str
borough: str
restaurant_id: str
operation = pymongo.ReplaceOne(
{ "restaurant_id": "1234" },
Restaurant(name="Mongo's Pizza", cuisine="Pizza", borough="Brooklyn", restaurant_id="5678")
)

Para reemplazar varios documentos, debe crear una instancia de ReplaceOne para cada documento.

Tip

Herramientas de verificación de tipos

Para aprender más sobre las herramientas de verificación de tipos disponibles para Python, échale un vistazo a Verificadores de tipos en la página de herramientas.

Para eliminar un documento, cree una instancia de DeleteOne y pase los siguientes argumentos:

  • namespace: El espacio de nombres donde se eliminará el documento. Este argumento es opcional si se realiza la operación masiva en una sola colección.

  • filter:El filtro de consulta que especifica los criterios utilizados para encontrar el documento que se va a eliminar.

DeleteOne elimina sólo el primer documento que coincide con su filtro de consulta.

El siguiente ejemplo crea una instancia de DeleteOne:

operation = DeleteOne(
namespace="sample_restaurants.restaurants",
filter={ "restaurant_id": "5678" }
)

Para eliminar varios documentos, cree una instancia de DeleteMany y pase un espacio de nombres y un filtro de consulta que especifique el documento que desea eliminar. DeleteMany elimina todos los documentos que coinciden con su filtro de consulta.

El siguiente ejemplo crea una instancia de DeleteMany:

operation = DeleteMany(
namespace="sample_restaurants.restaurants",
filter={ "name": "Mongo's Deli" }
)

Después de definir una instancia de clase para cada operación que desee realizar, pase una lista de estas instancias al método bulk_write(). Llame al método bulk_write() en una instancia Collection para escribir en una sola colección o en una instancia MongoClient para escribir en varios espacios de nombres.

Si alguna de las operaciones de escritura llamadas en un Collection falla, PyMongo genera un BulkWriteError y no realiza ninguna operación adicional. BulkWriteError proporciona un atributo details que incluye la operación que falló y detalles sobre la excepción.

Si alguna de las operaciones de escritura llamadas en un MongoClient falla, PyMongo genera un ClientBulkWriteException y no realiza ninguna operación adicional. ClientBulkWriteException proporciona un atributo error que incluye información sobre la excepción.

Nota

Cuando PyMongo ejecuta una operación masiva, utiliza el write_concern de la colección o cliente donde se ejecuta la operación. También puede configurar una preocupación de escritura para la operación al usar el método MongoClient.bulk_write(). El controlador informa todos los errores de preocupación de escritura después de intentar todas las operaciones, independientemente del orden de ejecución.

Para obtener más información sobre las preocupaciones de escritura, consulte Preocupación de escritura en el manual de MongoDB Server.

El siguiente ejemplo realiza múltiples operaciones de escritura en la colección restaurants utilizando el método bulk_write() en una instancia Collection. Seleccione el Synchronous o pestaña Asynchronous para ver el código correspondiente:

operations = [
InsertOne(
document={
"name": "Mongo's Deli",
"cuisine": "Sandwiches",
"borough": "Manhattan",
"restaurant_id": "1234"
}
),
InsertOne(
document={
"name": "Mongo's Deli",
"cuisine": "Sandwiches",
"borough": "Brooklyn",
"restaurant_id": "5678"
}
),
UpdateMany(
filter={ "name": "Mongo's Deli" },
update={ "$set": { "cuisine": "Sandwiches and Salads" }}
),
DeleteOne(
filter={ "restaurant_id": "1234" }
)
]
results = restaurants.bulk_write(operations)
print(results)
BulkWriteResult({'writeErrors': [], 'writeConcernErrors': [], 'nInserted': 2,
'nUpserted': 0, 'nMatched': 2, 'nModified': 2, 'nRemoved': 1, 'upserted': []},
acknowledged=True)
operations = [
InsertOne(
document={
"name": "Mongo's Deli",
"cuisine": "Sandwiches",
"borough": "Manhattan",
"restaurant_id": "1234"
}
),
InsertOne(
document={
"name": "Mongo's Deli",
"cuisine": "Sandwiches",
"borough": "Brooklyn",
"restaurant_id": "5678"
}
),
UpdateMany(
filter={ "name": "Mongo's Deli" },
update={ "$set": { "cuisine": "Sandwiches and Salads" }}
),
DeleteOne(
filter={ "restaurant_id": "1234" }
)
]
results = await restaurants.bulk_write(operations)
print(results)
BulkWriteResult({'writeErrors': [], 'writeConcernErrors': [], 'nInserted': 2,
'nUpserted': 0, 'nMatched': 2, 'nModified': 2, 'nRemoved': 1, 'upserted': []},
acknowledged=True)

El siguiente ejemplo realiza varias operaciones de escritura en los espacios de nombres sample_restaurants.restaurants y sample_mflix.movies mediante el método bulk_write() en una instancia MongoClient. Seleccione la pestaña Synchronous o Asynchronous para ver el código correspondiente:

operations = [
InsertOne(
namespace="sample_mflix.movies",
document={
"title": "Minari",
"runtime": 217,
"genres": ["Drama", "Comedy"]
}
),
UpdateOne(
namespace="sample_mflix.movies",
filter={ "title": "Minari" },
update={ "$set": { "runtime": 117 }}
),
DeleteMany(
namespace="sample_restaurants.restaurants",
filter={ "cuisine": "French" }
)
]
results = client.bulk_write(operations)
print(results)
ClientBulkWriteResult({'anySuccessful': True, 'error': None, 'writeErrors': [],
'writeConcernErrors': [], 'nInserted': 1, 'nUpserted': 0, 'nMatched': 1,
'nModified': 1, 'nDeleted': 344, 'insertResults': {}, 'updateResults': {},
'deleteResults': {}}, acknowledged=True, verbose=False)
operations = [
InsertOne(
namespace="sample_mflix.movies",
document={
"title": "Minari",
"runtime": 217,
"genres": ["Drama", "Comedy"]
}
),
UpdateOne(
namespace="sample_mflix.movies",
filter={ "title": "Minari" },
update={ "$set": { "runtime": 117 }}
),
DeleteMany(
namespace="sample_restaurants.restaurants",
filter={ "cuisine": "French" }
)
]
results = await client.bulk_write(operations)
print(results)
ClientBulkWriteResult({'anySuccessful': True, 'error': None, 'writeErrors': [],
'writeConcernErrors': [], 'nInserted': 1, 'nUpserted': 0, 'nMatched': 1,
'nModified': 1, 'nDeleted': 344, 'insertResults': {}, 'updateResults': {},
'deleteResults': {}}, acknowledged=True, verbose=False)

El método bulk_write() acepta opcionalmente parámetros adicionales, que representan opciones que puede utilizar para configurar la operación de escritura masiva.

La siguiente tabla describe las opciones que puede pasar al método Collection.bulk_write():

Propiedad
Descripción

ordered

If True, the driver performs the write operations in the order provided. If an error occurs, the remaining operations are not attempted.

If False, the driver performs the operations in an arbitrary order and attempts to perform all operations.
Defaults to True.

bypass_document_validation

Specifies whether the operation bypasses document-level validation. For more information, see Schema Validation in the MongoDB Server manual.
Defaults to False.

session

An instance of ClientSession. For more information, see the API documentation.

comment

A comment to attach to the operation. For more information, see the delete command fields guide in the MongoDB Server manual.

let

A map of parameter names and values. Values must be constant or closed expressions that don't reference document fields. For more information, see the let statement in the MongoDB Server manual.

El siguiente ejemplo llama al bulk_write() método del ejemplo anterior de escritura masiva de colección, pero establece la ordered opción False en. Seleccione Synchronous Asynchronous la pestaña o para ver el código correspondiente:

results = restaurants.bulk_write(operations, ordered=False)
results = await restaurants.bulk_write(operations, ordered=False)

Si alguna de las operaciones de escritura en una escritura masiva desordenada falla, PyMongo informa los errores solo después de intentar todas las operaciones.

Nota

Las operaciones masivas desordenadas no garantizan el orden de ejecución. El orden puede variar según la forma en que se enumeran para optimizar el tiempo de ejecución.

La siguiente tabla describe las opciones que puede pasar al método MongoClient.bulk_write():

Propiedad
Descripción

session

An instance of ClientSession. For more information, see the API documentation.

ordered

If True, the driver performs the write operations in the order provided. If an error occurs, the remaining operations are not attempted.

If False, the driver performs the operations in an arbitrary order and attempts to perform all operations.
Defaults to True.

verbose_results

Specifies whether the operation returns detailed results for each successful operation.
Defaults to False.

bypass_document_validation

Specifies whether the operation bypasses document-level validation. For more information, see Schema Validation in the MongoDB Server manual.
Defaults to False.

comment

A comment to attach to the operation. For more information, see the delete command fields guide in the MongoDB Server manual.

let

A map of parameter names and values. Values must be constant or closed expressions that don't reference document fields. For more information, see the let statement in the MongoDB Server manual.

write_concern

Specifies the write concern to use for the bulk operation. For more information, see Write Concern in the MongoDB Server manual.

El siguiente ejemplo llama al bulk_write() método del ejemplo anterior de escritura masiva de cliente, pero establece la verbose_results opción True en. Seleccione la Synchronous Asynchronous pestaña o para ver el código correspondiente:

results = client.bulk_write(operations, verbose_results=True)
ClientBulkWriteResult({'anySuccessful': True, 'error': None, 'writeErrors': [],
'writeConcernErrors': [], 'nInserted': 1, 'nUpserted': 0, 'nMatched': 1, 'nModified': 1,
'nDeleted': 344, 'insertResults': {0: InsertOneResult(ObjectId('...'),
acknowledged=True)}, 'updateResults': {1: UpdateResult({'ok': 1.0, 'idx': 1, 'n': 1,
'nModified': 1}, acknowledged=True)}, 'deleteResults': {2: DeleteResult({'ok': 1.0,
'idx': 2, 'n': 344}, acknowledged=True)}}, acknowledged=True, verbose=True)
results = await client.bulk_write(operations, verbose_results=True)
ClientBulkWriteResult({'anySuccessful': True, 'error': None, 'writeErrors': [],
'writeConcernErrors': [], 'nInserted': 1, 'nUpserted': 0, 'nMatched': 1, 'nModified': 1,
'nDeleted': 344, 'insertResults': {0: InsertOneResult(ObjectId('...'),
acknowledged=True)}, 'updateResults': {1: UpdateResult({'ok': 1.0, 'idx': 1, 'n': 1,
'nModified': 1}, acknowledged=True)}, 'deleteResults': {2: DeleteResult({'ok': 1.0,
'idx': 2, 'n': 344}, acknowledged=True)}}, acknowledged=True, verbose=True)

Esta sección describe el valor de retorno de los siguientes métodos de operación masiva:

El método Collection.bulk_write() devuelve un objeto BulkWriteResult. El objeto BulkWriteResult contiene las siguientes propiedades:

Propiedad
Descripción

acknowledged

Indicates if the server acknowledged the write operation.

bulk_api_result

The raw bulk API result returned by the server.

deleted_count

The number of documents deleted, if any.

inserted_count

The number of documents inserted, if any.

matched_count

The number of documents matched for an update, if applicable.

modified_count

The number of documents modified, if any.

upserted_count

The number of documents upserted, if any.

upserted_ids

A map of the operation's index to the _id of the upserted documents, if applicable.

El método MongoClient.bulk_write() devuelve un objeto ClientBulkWriteResult. El objeto ClientBulkWriteResult contiene las siguientes propiedades:

Propiedad
Descripción

acknowledged

Indicates if the server acknowledged the write operation.

bulk_api_result

The raw bulk API result returned by the server.

delete_results

A map of any successful delete operations and their results.

deleted_count

The number of documents deleted, if any.

has_verbose_results

Indicates whether the returned results are verbose.

insert_results

A map of any successful insert operations and their results.

inserted_count

The number of documents inserted, if any.

matched_count

The number of documents matched for an update, if applicable.

modified_count

The number of documents modified, if any.

update_results

A map of any successful update operations and their results.

upserted_count

The number of documents upserted, if any.

Si no se agrega una anotación de tipo para el objeto MongoClient, el verificador de tipos podría mostrar un error similar al siguiente:

from pymongo import MongoClient
client = MongoClient() # error: Need type annotation for "client"

La solución es anotar el objeto MongoClient como client: MongoClient o client: MongoClient[Dict[str, Any]].

Si especifica MongoClient como una sugerencia de tipo, pero no incluye los tipos de datos para el documento, las claves y los valores, su verificador de tipos podría mostrar un error similar al siguiente:

error: Dict entry 0 has incompatible type "str": "int";
expected "Mapping[str, Any]": "int"

La solución es agregar la siguiente sugerencia de tipo al objeto MongoClient:

client: MongoClient[Dict[str, Any]]

Para aprender a realizar operaciones de escritura individuales, consulte las siguientes guías:

Para obtener más información sobre cualquiera de los métodos o tipos discutidos en esta guía, consultar la siguiente documentación de la API:

Volver

Delete Documents