Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

Operaciones de escritura masiva

En esta guía, puedes aprender a utilizar PyMongo para realizar operaciones masivas. Las operaciones de actualización masiva reducen el número de llamadas al servidor realizando múltiples operaciones de guardar en un solo método.

La Collection y las clases MongoClient ambas proporcionan un método bulk_write(). Al llamar a bulk_write() en una instancia de Collection, puedes realizar múltiples operaciones de guardar en una sola colección. Al llamar a bulk_write() en una instancia MongoClient, puedes realizar escrituras en bloque en varios nombres de namespaces. En MongoDB, un namespace consiste en el 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 de 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 Comenzar con PyMongo tutorial.

Para cada operación de guardar que desees realizar, crea una instancia de una de las siguientes clases de operaciones:

  • InsertOne

  • UpdateOne

  • UpdateMany

  • ReplaceOne

  • DeleteOne

  • DeleteMany

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

Importante

Asegúrese de importar las clases de operaciones de escritura a 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 previas, que puedes utilizar para realizar operaciones masivas de colección y cliente.

Para realizar una operación de inserción, crea una instancia de InsertOne y especifica el documento que deseas insertar. Pasa los siguientes argumentos clave al constructor InsertOne:

  • namespace: El namespace en el que insertar el documento. Este argumento es opcional si 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 de 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 query que especifica los criterios usados para emparejar documentos en tu 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 el filtro de query.

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, crea una instancia de UpdateMany y pasa los mismos argumentos. UpdateMany actualiza todos los documentos que coincidan con su filtro de query.

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 remueve todos los campos y valores de un documento especificado y los reemplaza por otros nuevos. Para realizar una operación de reemplazo, crea una instancia de ReplaceOne y pasa los siguientes argumentos:

  • namespace: El espacio de nombres en el que llevar a cabo la operación de reemplazo. Este argumento es opcional si realiza la operación masiva en una sola colección.

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

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

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 de ReplaceOne usando 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 query que especifica los criterios utilizados para hacer coincidir el documento a eliminar.

DeleteOne elimina únicamente el primer documento que coincida con tu filtro de query.

El siguiente ejemplo crea una instancia de DeleteOne:

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

Para borrar varios documentos, crea una instancia de DeleteMany e introduce un namespace y un filtro de query que especifique el documento que deseas borrar. DeleteMany remueve todos los documentos que coinciden con tu filtro de query.

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 guardar 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 guardar activadas en una MongoClient falla, PyMongo arroja un ClientBulkWriteException y no realiza más operaciones. 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 en el que se ejecuta la operación. También puedes establecer un nivel de confirmación de escritura (write concern) para la operación cuando uses el método MongoClient.bulk_write(). El driver informa de todos los errores de nivel de confirmación de escritura (write concern) después de intentar todas las operaciones, independientemente del orden de ejecución.

Para obtener más información sobre nivel de confirmación de escritura (write concern), consulta nivel de confirmación de escritura (write concern) en el manual del servidor de MongoDB.

El siguiente ejemplo realiza múltiples operaciones de escritura en la colección restaurants utilizando el método bulk_write() en una instancia de Collection. Elija el Synchronous o la 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 múltiples operaciones de escritura en los espacios de nombres sample_restaurants.restaurants y sample_mflix.movies utilizando el método bulk_write() en una instancia de MongoClient. Selecciona 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 puedes 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 método bulk_write() del anterior Ejemplo de guardar masivo en la colección, pero establece la opción ordered en False. Selecciona la pestaña Synchronous o Asynchronous 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 guardar en una escritura masiva no ordenada falla, PyMongo informa los errores solo después de intentar todas las operaciones.

Nota

Las operaciones masivas no ordenadas no ofrecen garantías del orden de ejecución. El orden puede diferir de la manera en que los enumeras para optimizar el tiempo de ejecución.

La siguiente tabla describe las opciones que puedes 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 método bulk_write() desde el anterior Ejemplo de escritura masiva en el cliente, pero configura la opción verbose_results en True. Selecciona la pestaña Synchronous o Asynchronous 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 cómo realizar operaciones de guardar individuales, consulta los 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