Python
Tutorial Python: Acceso a datos con MySQL, PyMongo y Pandas
Python: introducción a la conexión con bases de datos usando MySQL Connector y PyMongo. Aprende a integrar y analizar datos con Pandas.
Aprende Python GRATIS y certifícateIntroducción a la conexión con bases de datos en Python
La conexión a bases de datos es una tarea fundamental en el desarrollo de aplicaciones y en el análisis de datos con Python. Este lenguaje de programación ofrece diversas librerías y módulos que facilitan la interacción con diferentes sistemas de gestión de bases de datos, tanto relacionales como NoSQL.
El uso de bases de datos permite almacenar y gestionar grandes volúmenes de información estructurada de manera eficiente. Python, gracias a su amplia comunidad y ecosistema, proporciona herramientas como MySQL Connector para conectarse a bases de datos MySQL y PyMongo para interactuar con MongoDB, una de las bases de datos NoSQL más populares.
Integrar Python con bases de datos nos permite realizar operaciones de lectura y escritura de datos directamente desde nuestros programas, automatizar tareas, y procesar la información de forma más flexible. Por ejemplo, podemos extraer datos para analizarlos con librerías como Pandas, lo que facilita el análisis y visualización de la información almacenada.
Además, la capacidad de interactuar dinámicamente con bases de datos desde Python es esencial para el desarrollo de aplicaciones web, sistemas de información y herramientas de inteligencia empresarial. Esto nos permite actualizar y recuperar datos en tiempo real, mejorar la escalabilidad de nuestras aplicaciones y mantener la integridad de la información.
Es importante entender los conceptos básicos de la conexión a bases de datos, como la establecimiento de conexiones seguras, el manejo de transacciones y la prevención de inyecciones SQL. También es crucial conocer cómo manejar errores y excepciones que puedan surgir durante la comunicación con la base de datos.
En resumen, la conexión con bases de datos amplía las capacidades de Python y es una habilidad esencial para cualquier desarrollador o analista de datos. A lo largo de esta sección, exploraremos las herramientas y prácticas recomendadas para establecer conexiones eficientes y seguras con bases de datos utilizando Python.
Instalación y configuración de MySQL Connector para Python
Para conectar Python con una base de datos MySQL, es esencial instalar MySQL Connector/Python, el controlador oficial que permite interactuar con MySQL de manera eficiente y segura.
La instalación se realiza utilizando pip, el gestor de paquetes de Python. Ejecuta el siguiente comando en tu terminal para instalar la versión más reciente del conector:
pip install mysql-connector-python
Este comando descargará e instalará MySQL Connector/Python desde el repositorio oficial de PyPI. Es recomendable verificar que pip y Python estén actualizados para garantizar la compatibilidad.
Una vez instalado, puedes confirmar la instalación importando el módulo en un script de Python:
import mysql.connector
print('MySQL Connector/Python se ha instalado correctamente.')
Para establecer una conexión con tu base de datos MySQL, necesitas proporcionar los parámetros de conexión como el host, nombre de usuario, contraseña y nombre de la base de datos. Aquí tienes un ejemplo básico:
import mysql.connector
conexion = mysql.connector.connect(
host='localhost',
user='nombre_usuario',
password='tu_contraseña',
database='nombre_base_datos'
)
if conexion.is_connected():
print('Conexión exitosa a la base de datos.')
Es importante manejar las excepciones que puedan ocurrir durante la conexión para identificar y resolver problemas. Utiliza un bloque try-except
para capturar errores:
import mysql.connector
from mysql.connector import Error
try:
conexion = mysql.connector.connect(
host='localhost',
user='nombre_usuario',
password='tu_contraseña',
database='nombre_base_datos'
)
if conexion.is_connected():
info_servidor = conexion.get_server_info()
print(f'Conectado al servidor MySQL versión {info_servidor}')
except Error as error:
print(f'Error al conectar a MySQL: {error}')
finally:
if conexion.is_connected():
conexion.close()
print('La conexión a la base de datos ha sido cerrada.')
Para mejorar la seguridad, evita almacenar las credenciales directamente en el código. Una práctica recomendada es utilizar variables de entorno o un archivo de configuración externo:
import os
import mysql.connector
conexion = mysql.connector.connect(
host=os.environ.get('DB_HOST'),
user=os.environ.get('DB_USER'),
password=os.environ.get('DB_PASSWORD'),
database=os.environ.get('DB_NAME')
)
Si necesitas especificar opciones adicionales, como el puerto, el juego de caracteres o utilizar una conexión SSL, puedes agregar más argumentos al método connect
:
conexion = mysql.connector.connect(
host='localhost',
port=3306,
user='nombre_usuario',
password='tu_contraseña',
database='nombre_base_datos',
ssl_disabled=False,
charset='utf8mb4'
)
En aplicaciones que requieren alto rendimiento, es conveniente utilizar un pool de conexiones para reutilizar conexiones y mejorar la eficiencia:
from mysql.connector import pooling
configuracion = {
'host': 'localhost',
'user': 'nombre_usuario',
'password': 'tu_contraseña',
'database': 'nombre_base_datos'
}
pool = pooling.MySQLConnectionPool(
pool_name='pool_de_conexiones',
pool_size=5,
**configuracion
)
conexion = pool.get_connection()
if conexion.is_connected():
print('Conexión establecida a través del pool de conexiones.')
Es posible verificar las versiones tanto del conector como del servidor MySQL para asegurar la compatibilidad:
import mysql.connector
print(f'Versión de MySQL Connector/Python: {mysql.connector.__version__}')
cursor = conexion.cursor()
cursor.execute('SELECT VERSION()')
version_mysql = cursor.fetchone()
print(f'Versión del servidor MySQL: {version_mysql[0]}')
Familiarizarse con la documentación oficial de MySQL Connector/Python es fundamental para aprovechar todas sus funcionalidades y seguir las buenas prácticas en el manejo de conexiones y operaciones con la base de datos.
Conexión y ejecución de consultas SQL en MySQL desde Python
Una vez establecida la conexión con la base de datos MySQL, es fundamental saber cómo ejecutar consultas SQL desde Python utilizando MySQL Connector/Python. Esto permite interactuar con los datos almacenados, realizar operaciones CRUD (Crear, Leer, Actualizar y Borrar) y procesar la información según las necesidades de tu aplicación.
Para ejecutar consultas SQL, primero se debe crear un cursor a partir de la conexión establecida. El cursor es un objeto que permite enviar comandos a la base de datos y manejar los resultados. Puedes crear un cursor de la siguiente manera:
cursor = conexion.cursor()
Con el cursor creado, es posible ejecutar una consulta SQL utilizando el método execute
:
consulta_sql = "SELECT * FROM empleados"
cursor.execute(consulta_sql)
Para obtener los resultados de una consulta SELECT
, se utilizan métodos como fetchall
, fetchone
o fetchmany
. Por ejemplo, para obtener todos los registros:
resultados = cursor.fetchall()
for fila in resultados:
print(fila)
Cada fila devuelta es una tupla que representa un registro de la tabla. Es posible acceder a los campos individuales por posición:
for fila in resultados:
print(f"Nombre: {fila[1]}, Puesto: {fila[2]}")
Es una buena práctica utilizar consultas parametrizadas para prevenir inyecciones SQL y mejorar la seguridad. Las consultas parametrizadas utilizan marcadores de posición y una tupla con los valores:
consulta_parametrizada = "SELECT * FROM empleados WHERE departamento = %s"
parametros = ('Ventas',)
cursor.execute(consulta_parametrizada, parametros)
Para insertar datos en la base de datos, se utiliza una sentencia INSERT
:
insercion_sql = "INSERT INTO empleados (nombre, puesto, salario) VALUES (%s, %s, %s)"
valores = ('Ana Pérez', 'Analista', 35000)
cursor.execute(insercion_sql, valores)
conexion.commit()
Es importante llamar al método commit
de la conexión para guardar los cambios realizados en la base de datos. Sin este paso, las operaciones de inserción, actualización o eliminación no se verán reflejadas.
Para actualizar registros existentes, se emplea una sentencia UPDATE
:
actualizacion_sql = "UPDATE empleados SET salario = %s WHERE nombre = %s"
valores_actualizados = (38000, 'Ana Pérez')
cursor.execute(actualizacion_sql, valores_actualizados)
conexion.commit()
De manera similar, para eliminar registros, se utiliza DELETE
:
eliminar_sql = "DELETE FROM empleados WHERE nombre = %s"
nombre_empleado = ('Ana Pérez',)
cursor.execute(eliminar_sql, nombre_empleado)
conexion.commit()
Es recomendable manejar excepciones durante la ejecución de consultas para capturar y gestionar posibles errores:
from mysql.connector import Error
try:
cursor.execute("TU CONSULTA SQL")
except Error as e:
print(f"Ocurrió un error al ejecutar la consulta: {e}")
Al finalizar las operaciones, es esencial cerrar el cursor y la conexión para liberar recursos:
cursor.close()
conexion.close()
Para trabajar con múltiples registros o ejecutar varias consultas, es posible utilizar transacciones. Esto asegura que un conjunto de operaciones se realice de forma atómica:
try:
conexion.start_transaction()
cursor.execute("CONSULTA 1")
cursor.execute("CONSULTA 2")
conexion.commit()
except Error as e:
conexion.rollback()
print(f"Transacción fallida: {e}")
Además, para mejorar la legibilidad y mantenimiento del código, es posible emplear los context managers de Python utilizando la cláusula with
:
with conexion.cursor() as cursor:
cursor.execute("SELECT * FROM empleados")
resultados = cursor.fetchall()
for fila in resultados:
print(fila)
Este enfoque asegura que el cursor se cierre automáticamente al salir del bloque with
, incluso si ocurre una excepción.
En operaciones que requieren alta eficiencia, considerar el uso de operaciones por lotes para insertar o actualizar múltiples registros:
insercion_masiva = "INSERT INTO empleados (nombre, puesto, salario) VALUES (%s, %s, %s)"
valores = [
('Juan Gómez', 'Gerente', 50000),
('María López', 'Desarrolladora', 40000),
('Carlos Ruiz', 'Diseñador', 38000)
]
cursor.executemany(insercion_masiva, valores)
conexion.commit()
Para acceder a los resultados de forma más conveniente, es posible configurar el cursor para que devuelva los registros como diccionarios en lugar de tuplas:
cursor = conexion.cursor(dictionary=True)
cursor.execute("SELECT * FROM empleados")
resultados = cursor.fetchall()
for fila in resultados:
print(f"Nombre: {fila['nombre']}, Puesto: {fila['puesto']}")
Esto permite acceder a los campos por nombre, mejorando la claridad del código.
Finalmente, recuerda que es esencial seguir las buenas prácticas de seguridad al manejar datos sensibles y asegurarte de que las conexiones y consultas se gestionen de manera eficiente y segura.
Manipulación de resultados SQL con Pandas: carga y análisis de datos
La librería Pandas es una herramienta poderosa en Python para la manipulación y análisis de datos. Combinar las capacidades de Pandas con las de MySQL Connector permite cargar resultados de consultas SQL directamente en DataFrames, facilitando el procesamiento y análisis de la información obtenida de una base de datos MySQL.
Para comenzar, puedes utilizar la función read_sql
de Pandas para ejecutar una consulta SQL y cargar los datos resultantes en un DataFrame:
import pandas as pd
import mysql.connector
# Establecer conexión con MySQL
conexion = mysql.connector.connect(
host='localhost',
user='nombre_usuario',
password='tu_contraseña',
database='nombre_base_datos'
)
# Definir la consulta SQL
consulta = "SELECT * FROM empleados"
# Cargar los resultados en un DataFrame
df_empleados = pd.read_sql(consulta, con=conexion)
Con el DataFrame df_empleados creado, puedes aprovechar las funcionalidades de Pandas para realizar análisis exploratorios. Por ejemplo, obtener un resumen de los datos:
print(df_empleados.head())
print(df_empleados.describe())
La función head()
muestra las primeras filas del DataFrame, mientras que describe()
proporciona estadísticas descriptivas de las columnas numéricas, como la media y la desviación estándar.
Una vez que los datos están en un DataFrame, es sencillo realizar operaciones de filtrado, agrupación y ordenamiento. Por ejemplo, para filtrar empleados con salario superior a un valor específico:
salario_minimo = 30000
df_salarios_altos = df_empleados[df_empleados['salario'] > salario_minimo]
print(df_salarios_altos)
Para calcular el salario promedio por departamento, puedes utilizar el método groupby
:
salario_promedio_departamento = df_empleados.groupby('departamento')['salario'].mean()
print(salario_promedio_departamento)
La combinación de MySQL y Pandas facilita la realización de análisis más complejos. Por ejemplo, unir datos de múltiples tablas directamente en la consulta SQL o utilizando las funciones de Pandas:
# Unir tablas mediante una consulta SQL
consulta = """
SELECT e.nombre, e.salario, d.nombre AS departamento
FROM empleados e
JOIN departamentos d ON e.departamento_id = d.id
"""
df_empleados_departamentos = pd.read_sql(consulta, con=conexion)
Si prefieres unir DataFrames en Pandas, puedes cargar cada tabla por separado y luego utilizar merge
:
df_empleados = pd.read_sql('SELECT * FROM empleados', con=conexion)
df_departamentos = pd.read_sql('SELECT * FROM departamentos', con=conexion)
df_combinado = pd.merge(df_empleados, df_departamentos, left_on='departamento_id', right_on='id')
print(df_combinado.head())
Es importante manejar adecuadamente las fechas y los tipos de datos al cargar información desde MySQL. Pandas suele inferir los tipos, pero puedes especificarlos si es necesario:
df_empleados = pd.read_sql(consulta, con=conexion, parse_dates=['fecha_contratacion'])
Para mejorar el rendimiento al trabajar con grandes volúmenes de datos, puedes utilizar el parámetro chunksize
para leer los datos en porciones:
for chunk in pd.read_sql(consulta, con=conexion, chunksize=1000):
procesar(chunk) # Reemplaza 'procesar' con la función que maneja cada chunk
Al finalizar el análisis, es posible almacenar los resultados procesados en nuevos archivos o incluso escribirlos de vuelta a la base de datos. Por ejemplo, para exportar el DataFrame a un archivo CSV:
df_empleados.to_csv('empleados_procesados.csv', index=False)
Para realizar visualizaciones rápidas de los datos, Pandas se integra fácilmente con bibliotecas como Matplotlib y Seaborn:
import matplotlib.pyplot as plt
# Gráfico de barras del número de empleados por departamento
conteo_departamentos = df_empleados['departamento'].value_counts()
conteo_departamentos.plot(kind='bar')
plt.title('Número de empleados por departamento')
plt.xlabel('Departamento')
plt.ylabel('Cantidad')
plt.show()
Además, es posible detectar y manejar valores nulos o ausentes mediante las funciones de Pandas:
# Identificar columnas con valores nulos
nulos = df_empleados.isnull().sum()
print(nulos)
# Eliminar filas con valores nulos
df_empleados_limpio = df_empleados.dropna()
# Rellenar valores nulos con un valor específico
df_empleados['salario'].fillna(df_empleados['salario'].mean(), inplace=True)
Para asegurar que los datos están correctamente tipificados y optimizados en memoria, puedes convertir columnas a tipos más eficientes:
df_empleados['salario'] = df_empleados['salario'].astype('float32')
Si trabajas con datos categóricos, convertir columnas a tipo category puede mejorar el rendimiento:
df_empleados['departamento'] = df_empleados['departamento'].astype('category')
Finalmente, recuerda cerrar la conexión a la base de datos cuando hayas terminado de trabajar:
conexion.close()
La integración de MySQL y Pandas ofrece una solución robusta para el análisis de datos, permitiendo manipular grandes cantidades de información con eficiencia. Al aprovechar las funcionalidades de ambas herramientas, puedes realizar desde operaciones simples hasta análisis estadísticos complejos, todo dentro del entorno flexible que ofrece Python.
Configuración e instalación de PyMongo para conectarse a MongoDB
Para interactuar con MongoDB desde Python, se utiliza PyMongo, el controlador oficial proporcionado por MongoDB. PyMongo permite realizar operaciones de inserción, consulta, actualización y eliminación de documentos en bases de datos MongoDB de manera eficiente.
La instalación de PyMongo se realiza fácilmente a través de pip, el gestor de paquetes de Python. Para instalar la última versión disponible, ejecuta el siguiente comando en la terminal:
pip install pymongo
Este comando descarga e instala PyMongo desde el repositorio oficial de PyPI. Es recomendable asegurarse de que pip y Python estén actualizados para evitar problemas de compatibilidad.
Una vez instalado PyMongo, puedes verificar la instalación importando el módulo en un script de Python:
import pymongo
print('PyMongo se ha instalado correctamente.')
Para establecer una conexión con una base de datos MongoDB, se utiliza el objeto MongoClient proporcionado por PyMongo. Este objeto permite conectarse a un servidor MongoDB especificando la URI de conexión. A continuación, se muestra un ejemplo de cómo conectarse a un servidor MongoDB local:
from pymongo import MongoClient
cliente = MongoClient('mongodb://localhost:27017/')
# Acceder a una base de datos
db = cliente['nombre_base_datos']
# Confirmar la conexión listando las colecciones disponibles
colecciones = db.list_collection_names()
print(f'Colecciones en la base de datos: {colecciones}')
En este ejemplo, se crea un cliente que se conecta al servidor MongoDB en el puerto 27017, que es el puerto predeterminado. Luego se accede a la base de datos deseada reemplazando 'nombre_base_datos'
por el nombre correspondiente.
Si necesitas conectarte a un servidor MongoDB remoto o uno que requiere autenticación, debes proporcionar las credenciales y la dirección del servidor en la URI de conexión. Un ejemplo de conexión con autenticación es el siguiente:
from pymongo import MongoClient
usuario = 'tu_usuario'
contraseña = 'tu_contraseña'
host = 'direccion_servidor'
puerto = 27017
nombre_base_datos = 'nombre_base_datos'
uri_conexion = f'mongodb://{usuario}:{contraseña}@{host}:{puerto}/{nombre_base_datos}'
cliente = MongoClient(uri_conexion)
db = cliente[nombre_base_datos]
# Verificar la conexión
print(f'Se ha conectado a la base de datos {nombre_base_datos} en el servidor {host}.')
Es importante manejar las excepciones que puedan surgir al establecer la conexión. Puedes utilizar un bloque try-except
para capturar errores y gestionar situaciones inesperadas:
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure
try:
cliente = MongoClient(uri_conexion)
# Intentar obtener información del servidor
info_servidor = cliente.server_info()
print('Conexión exitosa a MongoDB.')
except ConnectionFailure as error:
print(f'Error al conectar a MongoDB: {error}')
Para mejorar la seguridad, es recomendable no incluir las credenciales directamente en el código fuente. Una práctica común es utilizar variables de entorno o un archivo de configuración externo para almacenar información sensible:
import os
from pymongo import MongoClient
usuario = os.environ.get('MONGO_USER')
contraseña = os.environ.get('MONGO_PASSWORD')
host = os.environ.get('MONGO_HOST')
puerto = os.environ.get('MONGO_PORT')
nombre_base_datos = os.environ.get('MONGO_DB')
uri_conexion = f'mongodb://{usuario}:{contraseña}@{host}:{puerto}/{nombre_base_datos}'
cliente = MongoClient(uri_conexion)
db = cliente[nombre_base_datos]
Si trabajas con MongoDB Atlas, que es el servicio de base de datos en la nube de MongoDB, la URI de conexión suele incluir parámetros adicionales y requiere el uso de TLS/SSL. Un ejemplo de conexión a MongoDB Atlas es:
from pymongo import MongoClient
uri_conexion = 'mongodb+srv://usuario:contraseña@cluster0.mongodb.net/nombre_base_datos?retryWrites=true&w=majority'
cliente = MongoClient(uri_conexion)
db = cliente['nombre_base_datos']
# Comprobar la conexión listando las colecciones
print(db.list_collection_names())
En este caso, la URI comienza con mongodb+srv://
, lo que indica que se está utilizando el Protocolo de Registro de Servicio (SRV) para simplificar la resolución de nombres de host.
Para configurar opciones adicionales, como el tiempo de espera de la conexión o el número máximo de conexiones en el pool, puedes proporcionar argumentos adicionales al crear el objeto MongoClient
:
cliente = MongoClient(
uri_conexion,
serverSelectionTimeoutMS=5000, # Tiempo máximo de espera en milisegundos
maxPoolSize=50 # Número máximo de conexiones en el pool
)
Es esencial manejar correctamente las colecciones y documentos una vez establecida la conexión. Para acceder a una colección específica, simplemente:
coleccion = db['nombre_coleccion']
Y para realizar una operación básica, como insertar un documento:
documento = {
'nombre': 'María García',
'edad': 30,
'profesión': 'Ingeniera'
}
resultado = coleccion.insert_one(documento)
print(f'Documento insertado con el _id: {resultado.inserted_id}')
Para asegurar que la conexión se cierre adecuadamente y los recursos se liberen, puedes utilizar un context manager con la cláusula with
:
from pymongo import MongoClient
with MongoClient(uri_conexion) as cliente:
db = cliente['nombre_base_datos']
# Realizar operaciones con la base de datos
colecciones = db.list_collection_names()
print(f'Colecciones disponibles: {colecciones}')
De esta manera, al salir del bloque with
, la conexión se cierra automáticamente.
Cuando trabajes en aplicaciones que requieren alta disponibilidad y distribución geográfica, es posible que necesites configurar replicación y establecer las preferencias de lectura y escritura. PyMongo permite especificar estas preferencias:
from pymongo import ReadPreference
cliente = MongoClient(
uri_conexion,
read_preference=ReadPreference.SECONDARY_PREFERRED
)
En entornos donde la seguridad es crítica, es importante habilitar el cifrado de datos en tránsito mediante SSL/TLS. Puedes configurar el uso de SSL al establecer la conexión:
cliente = MongoClient(
uri_conexion,
ssl=True,
ssl_cert_reqs='CERT_REQUIRED',
tlsCAFile='/ruta/al/certificado_CA.pem'
)
Asegúrate de tener los certificados necesarios y de que el servidor MongoDB esté configurado para aceptar conexiones seguras.
Para entornos que requieren el uso de autenticación SCRAM-SHA-256 u otros mecanismos avanzados, especifica el mecanismo de autenticación:
cliente = MongoClient(
host=host,
port=puerto,
username=usuario,
password=contraseña,
authSource='admin',
authMechanism='SCRAM-SHA-256'
)
Es recomendable consultar la documentación oficial de PyMongo para obtener detalles sobre todas las opciones de configuración disponibles y las mejores prácticas al conectarse a MongoDB.
Finalmente, al desarrollar aplicaciones robustas, considera implementar reconexión automática y manejo de errores para garantizar que tu aplicación funcione de manera continua incluso ante fallos temporales en la conexión:
from pymongo.errors import AutoReconnect
try:
# Operaciones con MongoDB
resultado = coleccion.find_one({'nombre': 'María García'})
print(resultado)
except AutoReconnect:
print('Reconectando a MongoDB...')
# Implementar lógica de reconexión o reintento
Al seguir estas prácticas y configurar correctamente PyMongo, podrás conectarte y trabajar con MongoDB de forma segura y eficiente, aprovechando todas las capacidades que ofrece esta base de datos NoSQL.
Consultas, inserciones y actualizaciones en MongoDB con PyMongo
Para interactuar con los datos en MongoDB utilizando PyMongo, es fundamental comprender cómo realizar consultas, inserciones y actualizaciones. Estas operaciones permiten gestionar de manera efectiva los documentos dentro de las colecciones de una base de datos MongoDB.
Para realizar una consulta que obtenga un único documento, se utiliza el método find_one()
:
resultado = coleccion.find_one({'nombre': 'Carlos'})
print(resultado)
En este ejemplo, se busca un documento donde el campo nombre sea igual a 'Carlos'. El método find_one()
devuelve el primer documento que coincida con el criterio de búsqueda.
Si se desea obtener múltiples documentos, se emplea el método find()
:
cursor = coleccion.find({'edad': {'$gte': 25}})
for documento in cursor:
print(documento)
Aquí, se recuperan todos los documentos donde la edad sea mayor o igual a 25. El operador $gte es un operador de comparación que significa "mayor o igual que".
Es posible utilizar una variedad de operadores de consulta para construir criterios más complejos:
- $lt: menor que
- $lte: menor o igual que
- $gt: mayor que
- $ne: no igual
- $in: contenido en un conjunto
- $nin: no contenido en un conjunto
Por ejemplo, para encontrar documentos donde el campo ciudad sea 'Madrid' o 'Barcelona':
cursor = coleccion.find({'ciudad': {'$in': ['Madrid', 'Barcelona']}})
for documento in cursor:
print(documento)
Para mejorar el rendimiento, es posible limitar el número de documentos devueltos utilizando limit()
:
cursor = coleccion.find().limit(10)
Y para ordenar los resultados, se utiliza sort()
:
cursor = coleccion.find().sort('apellido', 1) # 1 para ascendente, -1 para descendente
En cuanto a las inserciones, para añadir un único documento se utiliza insert_one()
:
nuevo_documento = {
'nombre': 'Ana',
'apellido': 'López',
'edad': 28,
'ciudad': 'Valencia'
}
resultado = coleccion.insert_one(nuevo_documento)
print(f'Documento insertado con _id: {resultado.inserted_id}')
El método insert_one()
devuelve un objeto que contiene el _id del documento insertado. Este identificador único se genera automáticamente si no se proporciona en el documento.
Para insertar múltiples documentos a la vez, se emplea insert_many()
:
nuevos_documentos = [
{'nombre': 'Luis', 'apellido': 'García', 'edad': 35, 'ciudad': 'Sevilla'},
{'nombre': 'Marta', 'apellido': 'Sánchez', 'edad': 22, 'ciudad': 'Bilbao'}
]
resultado = coleccion.insert_many(nuevos_documentos)
print(f'Documentos insertados con _ids: {resultado.inserted_ids}')
El método insert_many()
recibe una lista de diccionarios, donde cada diccionario representa un documento a insertar.
Para actualizar documentos existentes, se utilizan los métodos update_one()
y update_many()
. Con update_one()
, se actualiza el primer documento que coincida con el criterio:
filtro = {'nombre': 'Ana'}
nueva_info = {'$set': {'edad': 29}}
resultado = coleccion.update_one(filtro, nueva_info)
print(f'Documentos modificados: {resultado.modified_count}')
En este ejemplo, se busca el documento donde nombre es 'Ana' y se actualiza el campo edad a 29. El operador $set se utiliza para establecer nuevos valores en los campos especificados.
Si se desea actualizar todos los documentos que cumplan un criterio, se usa update_many()
:
filtro = {'ciudad': 'Valencia'}
nueva_info = {'$set': {'ciudad': 'València'}}
resultado = coleccion.update_many(filtro, nueva_info)
print(f'Documentos actualizados: {resultado.modified_count}')
Aquí, se actualizan todos los documentos donde la ciudad es 'Valencia', cambiando el valor del campo ciudad a 'València'.
Se pueden utilizar otros operadores de actualización para modificar documentos:
- $inc: incrementa un valor numérico
- $rename: renombra un campo
- $unset: elimina un campo
- $push: añade un elemento a un arreglo
- $pull: elimina un elemento de un arreglo
Por ejemplo, para incrementar la edad en 1 de todos los documentos:
resultado = coleccion.update_many({}, {'$inc': {'edad': 1}})
print(f'Documentos actualizados: {resultado.modified_count}')
Si es necesario reemplazar completamente un documento, se puede usar replace_one()
:
filtro = {'nombre': 'Luis'}
nuevo_documento = {'nombre': 'Luis', 'apellido': 'García', 'edad': 36, 'ciudad': 'Sevilla'}
resultado = coleccion.replace_one(filtro, nuevo_documento)
print(f'Documentos reemplazados: {resultado.modified_count}')
Es importante manejar posibles excepciones al realizar operaciones con la base de datos. PyMongo proporciona un conjunto de excepciones que se pueden capturar:
from pymongo.errors import PyMongoError
try:
resultado = coleccion.insert_one(nuevo_documento)
except PyMongoError as e:
print(f'Error al insertar el documento: {e}')
Para eliminar campos específicos de un documento, se utiliza el operador $unset:
filtro = {'nombre': 'Marta'}
operacion = {'$unset': {'ciudad': ''}}
resultado = coleccion.update_one(filtro, operacion)
print(f'Campos eliminados en documentos: {resultado.modified_count}')
En ocasiones, es útil upsertar (actualizar o insertar) un documento. Esto se logra pasando el parámetro upsert=True
en las operaciones de actualización:
filtro = {'nombre': 'Pedro'}
nueva_info = {'$set': {'edad': 40, 'ciudad': 'Granada'}}
resultado = coleccion.update_one(filtro, nueva_info, upsert=True)
if resultado.upserted_id:
print(f'Documento insertado con _id: {resultado.upserted_id}')
else:
print(f'Documentos actualizados: {resultado.modified_count}')
En este caso, si no existe un documento que cumpla el filtro, se insertará uno nuevo con los valores proporcionados.
Para aumentar la eficiencia al insertar grandes volúmenes de datos, es posible utilizar la opción ordered=False
en insert_many()
, lo que permite que las inserciones continúen aun si ocurre un error en alguno de los documentos:
nuevos_documentos = [
{'nombre': 'Laura', 'edad': 27},
{'nombre': 'José', 'edad': 'veintiocho'}, # Error: edad no es numérico
{'nombre': 'Elena', 'edad': 32}
]
try:
resultado = coleccion.insert_many(nuevos_documentos, ordered=False)
print(f'Documentos insertados con _ids: {resultado.inserted_ids}')
except PyMongoError as e:
print(f'Ocurrió un error durante la inserción: {e}')
Al realizar consultas, es posible proyectar solo ciertos campos utilizando el parámetro projection
:
cursor = coleccion.find({}, {'_id': 0, 'nombre': 1, 'edad': 1})
for documento in cursor:
print(documento)
En este ejemplo, se excluye el campo _id y se incluyen solo los campos nombre y edad.
Además, PyMongo soporta la ejecución de agregaciones más complejas utilizando el método aggregate()
, permitiendo operaciones avanzadas como agrupaciones y cálculos:
pipeline = [
{'$group': {'_id': '$ciudad', 'total': {'$sum': 1}}},
{'$sort': {'total': -1}}
]
resultado = coleccion.aggregate(pipeline)
for documento in resultado:
print(documento)
Esta agregación cuenta el número de documentos por ciudad y ordena el resultado de forma descendente según el total.
Para garantizar la integridad de las operaciones, es recomendable utilizar transacciones cuando se trabaja con MongoDB replica sets o sharded clusters. Sin embargo, esto requiere una configuración específica del servidor y el uso de sessions en PyMongo.
Finalmente, es esencial cerrar la conexión al terminar las operaciones:
cliente.close()
Al dominar las operaciones de consultas, inserciones y actualizaciones con PyMongo, se puede gestionar eficazmente la información en MongoDB desde Python, aprovechando la flexibilidad y escalabilidad que ofrece esta base de datos NoSQL.
Integración de datos de MySQL y MongoDB en DataFrames de Pandas
La capacidad de integrar datos provenientes de distintas fuentes es esencial para realizar análisis completos y obtener insights valiosos. En Python, es posible unir información de bases de datos MySQL y MongoDB en DataFrames de Pandas, lo que permite manipular y analizar los datos de forma unificada.
Para comenzar, es necesario cargar los datos de MySQL en un DataFrame de Pandas. Utilizando la conexión establecida con MySQL Connector, puedes ejecutar consultas SQL y leer los resultados directamente con read_sql()
:
import pandas as pd
import mysql.connector
# Conexión a MySQL
conexion_mysql = mysql.connector.connect(
host='localhost',
user='usuario_mysql',
password='contraseña_mysql',
database='base_datos_mysql'
)
# Consulta SQL
consulta_mysql = "SELECT * FROM empleados_mysql"
# Cargar datos de MySQL en DataFrame
df_mysql = pd.read_sql(consulta_mysql, con=conexion_mysql)
A continuación, se procede a importar los datos de MongoDB. Debido a que PyMongo no tiene una función nativa para cargar directamente en un DataFrame, se extraen los documentos y se crea el DataFrame manualmente:
from pymongo import MongoClient
# Conexión a MongoDB
cliente_mongo = MongoClient('mongodb://localhost:27017/')
db_mongo = cliente_mongo['base_datos_mongo']
coleccion = db_mongo['empleados_mongo']
# Obtener documentos de MongoDB
cursor = coleccion.find()
lista_documentos = list(cursor)
# Cargar datos de MongoDB en DataFrame
df_mongo = pd.DataFrame(lista_documentos)
Es posible que el DataFrame resultante contenga el campo _id, que es un objeto ObjectId de MongoDB. Para facilitar el manejo de datos, se puede convertir este campo a tipo string o descartarlo si no es necesario:
df_mongo['_id'] = df_mongo['_id'].astype(str)
# O eliminar el campo _id
df_mongo.drop(columns=['_id'], inplace=True)
Una vez que se tienen ambos DataFrames df_mysql y df_mongo, es posible integrarlos. Si las estructuras de los datos comparten campos en común, se pueden utilizar funciones como merge()
para realizar un join:
# Supongamos que ambos DataFrames tienen el campo 'empleado_id'
df_integrado = pd.merge(df_mysql, df_mongo, on='empleado_id', how='inner')
El método merge()
permite especificar el tipo de unión utilizando el parámetro how: 'inner'
, 'outer'
, 'left'
o 'right'
. Esto define cómo se combinan los registros de los DataFrames.
En caso de que los campos para unir tengan nombres diferentes, puedes utilizar los parámetros left_on y right_on:
df_integrado = pd.merge(df_mysql, df_mongo, left_on='id_mysql', right_on='id_mongo', how='inner')
Si los DataFrames tienen columnas que se solapan pero que representan datos distintos, es conveniente renombrarlas utilizando el método rename()
para evitar conflictos:
df_mysql.rename(columns={'nombre': 'nombre_mysql'}, inplace=True)
df_mongo.rename(columns={'nombre': 'nombre_mongo'}, inplace=True)
También es posible concatenar los DataFrames si contienen registros similares y se desea combinarlos verticalmente:
df_concatenado = pd.concat([df_mysql, df_mongo], ignore_index=True)
Al concatenar, es importante manejar los valores faltantes que pueden surgir debido a diferencias en los esquemas de los datos. Puedes utilizar funciones como fillna()
para rellenar estos valores:
df_concatenado.fillna({'campo_específico': valor_por_defecto}, inplace=True)
Para facilitar el análisis, puedes estandarizar los tipos de datos de las columnas relevantes. Por ejemplo, convertir fechas a formato datetime:
df_integrado['fecha_contratacion'] = pd.to_datetime(df_integrado['fecha_contratacion'])
Si necesitas realizar transformaciones más complejas, como normalizar textos o calcular nuevos campos derivados, puedes aplicar funciones sobre las columnas:
df_integrado['nombre_completo'] = df_integrado['nombre'] + ' ' + df_integrado['apellido']
En situaciones donde los datos de MySQL y MongoDB complementan la información de los empleados, puedes crear un DataFrame enriquecido combinando campos de ambas fuentes. Por ejemplo, si en MongoDB tienes información adicional sobre proyectos asignados:
# Unir información de proyectos desde MongoDB al DataFrame de MySQL
df_integrado = pd.merge(df_mysql, df_mongo[['empleado_id', 'proyectos']], on='empleado_id', how='left')
Es esencial manejar adecuadamente los valores nulos que puedan aparecer tras la integración, especialmente si algunos empleados no tienen información en ambas fuentes. Utiliza isna()
para detectar nulos y tomar acciones según sea necesario.
Para mejorar el rendimiento al trabajar con grandes volúmenes de datos, considera filtrar y seleccionar únicamente las columnas relevantes durante la extracción. En MySQL:
consulta_mysql = "SELECT empleado_id, nombre, apellido FROM empleados_mysql WHERE activo = 1"
df_mysql = pd.read_sql(consulta_mysql, con=conexion_mysql)
En MongoDB, puedes limitar los campos utilizando el parámetro projection
en find()
:
cursor = coleccion.find({}, {'empleado_id': 1, 'proyectos': 1, '_id': 0})
lista_documentos = list(cursor)
df_mongo = pd.DataFrame(lista_documentos)
Una vez integrada la información, puedes realizar análisis más profundos, como agrupar por departamentos e identificar tendencias:
# Agrupar por departamento y contar número de empleados
conteo_departamento = df_integrado.groupby('departamento')['empleado_id'].count()
print(conteo_departamento)
También puedes utilizar visualizaciones para representar los datos combinados. Por ejemplo, graficar el número de proyectos por empleado:
import matplotlib.pyplot as plt
df_integrado['num_proyectos'] = df_integrado['proyectos'].apply(lambda x: len(x) if isinstance(x, list) else 0)
df_integrado.plot(kind='bar', x='nombre_completo', y='num_proyectos')
plt.title('Número de proyectos por empleado')
plt.xlabel('Empleado')
plt.ylabel('Proyectos asignados')
plt.show()
Además, si trabajas con datos sensibles, es fundamental considerar temas de seguridad y cumplimiento normativo. Asegúrate de manejar adecuadamente la protección de datos personales y de seguir las políticas de la organización en cuanto al manejo y almacenamiento de información.
Finalmente, puedes exportar el DataFrame integrado a diversos formatos para su posterior uso o compartirlo con otros sistemas:
# Exportar a CSV
df_integrado.to_csv('datos_integrados.csv', index=False)
# Exportar a Excel
df_integrado.to_excel('datos_integrados.xlsx', index=False)
La integración de datos de MySQL y MongoDB en DataFrames de Pandas permite aprovechar las fortalezas de ambas bases de datos y realizar análisis más completos. Al dominar estas técnicas, puedes enriquecer tus proyectos con información diversa y tomar decisiones basadas en un conjunto de datos más amplio y unificado.
Exportación de resultados a formatos estructurados con Pandas SQL Output
La capacidad de exportar datos procesados a formatos estructurados es esencial en el análisis y gestión de información. Pandas ofrece diversas funciones que permiten escribir los datos de un DataFrame a múltiples formatos, facilitando la integración con otros sistemas y el almacenamiento eficiente de la información.
Para exportar un DataFrame a una base de datos SQL, se utiliza el método to_sql()
de Pandas, que permite escribir los datos directamente en una tabla de una base de datos relacional. Es necesario contar con una conexión establecida a la base de datos mediante un motor de SQLAlchemy:
from sqlalchemy import create_engine
import pandas as pd
# Crear un motor de conexión a MySQL
engine = create_engine('mysql+mysqlconnector://usuario:contraseña@localhost/nombre_base_datos')
# Supongamos que df_datos es el DataFrame a exportar
df_datos.to_sql(
name='nombre_tabla',
con=engine,
if_exists='replace', # Opciones: 'fail', 'replace', 'append'
index=False
)
En este ejemplo, el DataFrame df_datos
se escribe en la tabla nombre_tabla
de la base de datos MySQL especificada. El parámetro if_exists
controla el comportamiento si la tabla ya existe: 'fail'
generará un error, 'replace'
eliminará la tabla existente y creará una nueva, y 'append'
agregará los datos al final de la tabla existente.
Es posible controlar los tipos de datos en la base de datos especificando el parámetro dtype
:
import sqlalchemy.types as types
df_datos.to_sql(
name='nombre_tabla',
con=engine,
if_exists='append',
index=False,
dtype={
'columna_entero': types.Integer(),
'columna_texto': types.VARCHAR(length=255),
'columna_fecha': types.DateTime()
}
)
Esto asegura que los tipos de las columnas en la base de datos sean coherentes con los datos del DataFrame.
Para exportar un DataFrame a un archivo CSV, se utiliza el método to_csv()
:
df_datos.to_csv(
'datos_exportados.csv',
sep=';', # Separador de columnas
decimal=',', # Separador de decimales
index=False,
encoding='utf-8' # Codificación del archivo
)
Este método escribe el contenido del DataFrame en un archivo CSV llamado 'datos_exportados.csv'
. Los parámetros permiten especificar detalles como el separador de columnas y decimales, la inclusión o exclusión del índice, y la codificación del archivo para asegurar compatibilidad internacional.
La exportación a archivos Excel se realiza con el método to_excel()
:
df_datos.to_excel(
'datos_exportados.xlsx',
sheet_name='Hoja1',
index=False
)
Aquí, el DataFrame se exporta a un archivo Excel llamado 'datos_exportados.xlsx'
, y se especifica el nombre de la hoja de cálculo. Es importante tener en cuenta que para utilizar este método es necesario instalar el paquete openpyxl o xlsxwriter dependiendo del formato de Excel deseado:
pip install openpyxl
Para exportar a formatos JSON, se utiliza el método to_json()
:
df_datos.to_json(
'datos_exportados.json',
orient='records',
indent=4,
force_ascii=False
)
El parámetro orient
controla la forma en que se estructuran los datos en el archivo JSON. La opción 'records'
convierte cada fila del DataFrame en un objeto JSON. El parámetro indent
añade espacios en blanco para mejorar la legibilidad, y force_ascii=False
asegura que los caracteres no ASCII se manejen correctamente.
Si se requiere guardar los datos en formatos más eficientes para el manejo de grandes volúmenes de información, Pandas soporta la exportación a Parquet y Feather:
df_datos.to_parquet('datos_exportados.parquet')
df_datos.to_feather('datos_exportados.feather')
Estos formatos ofrecen ventajas en términos de velocidad y compresión, siendo ideales para aplicaciones de Big Data. Es necesario instalar las librerías correspondientes:
pip install pyarrow
Al trabajar con datos tabulares que requieren un almacenamiento rápido y acceso mediante índices, el formato HDF5 es una opción válida:
df_datos.to_hdf('datos_exportados.h5', key='df', mode='w')
Para utilizar este formato, es necesario instalar el paquete PyTables:
pip install tables
Es fundamental manejar adecuadamente los valores faltantes antes de exportar los datos, ya que diferentes formatos pueden interpretarlos de maneras distintas. Utiliza métodos como fillna()
para reemplazar valores nulos:
df_datos.fillna(0, inplace=True)
Cuando se exportan datos a una base de datos SQL, es importante considerar el rendimiento y la eficiencia. Para insertar grandes volúmenes de datos, se puede ajustar el parámetro chunksize
para enviar los datos en bloques:
df_datos.to_sql(
name='nombre_tabla',
con=engine,
if_exists='append',
index=False,
chunksize=1000
)
Esto divide el DataFrame en porciones de 1000 filas, reduciendo el consumo de memoria y permitiendo que la base de datos procese los datos de manera más eficiente.
Al exportar datos a MongoDB, aunque Pandas no ofrece un método directo, es posible convertir el DataFrame a una lista de diccionarios y utilizar PyMongo:
from pymongo import MongoClient
# Conexión a MongoDB
cliente = MongoClient('mongodb://localhost:27017/')
db = cliente['nombre_base_datos']
coleccion = db['nombre_coleccion']
# Convertir DataFrame a diccionarios y eliminar posibles NaN
registros = df_datos.fillna('').to_dict(orient='records')
# Insertar registros en MongoDB
resultado = coleccion.insert_many(registros)
print(f'Se han insertado {len(resultado.inserted_ids)} documentos en MongoDB.')
Es importante limpiar los datos antes de la inserción para evitar inconsistencias y asegurar que los campos están en el formato esperado por MongoDB.
Cuando se necesitan exportar datos a un archivo comprimido, Pandas soporta la escritura directa a formatos como ZIP o GZIP:
df_datos.to_csv('datos_comprimidos.csv.gz', index=False, compression='gzip')
Esto reduce el tamaño del archivo resultante y es útil para transportar o almacenar grandes conjuntos de datos.
Es posible personalizar el formato de fecha y hora al exportar datos. Por ejemplo, al exportar a CSV:
df_datos.to_csv(
'datos_exportados.csv',
date_format='%d/%m/%Y',
index=False
)
Esto asegura que las columnas de tipo fecha se escriban con el formato deseado.
En situaciones donde se requiere dividir los datos en múltiples archivos o hojas, como al exportar a Excel, se puede utilizar el objeto ExcelWriter
:
with pd.ExcelWriter('datos_múltiples_hojas.xlsx') as writer:
df_parte1.to_excel(writer, sheet_name='Hoja1', index=False)
df_parte2.to_excel(writer, sheet_name='Hoja2', index=False)
Esto permite escribir varios DataFrames en diferentes hojas del mismo archivo Excel.
Al exportar datos críticos, es recomendable verificar la integridad y consistencia de los datos exportados. Por ejemplo, después de escribir en una base de datos SQL, se puede realizar una consulta para comprobar que el número de filas coincide:
# Contar filas insertadas en la tabla
with engine.connect() as conexion:
resultado = conexion.execute('SELECT COUNT(*) FROM nombre_tabla')
filas_insertadas = resultado.scalar()
print(f'Se han insertado {filas_insertadas} filas en la tabla.')
En contextos de automatización, es posible programar la exportación de datos para que se realice periódicamente. Utiliza librerías como schedule o realiza scripts que se ejecuten mediante cron en sistemas Unix.
También es posible exportar datos a través de API o servicios web, convirtiendo el DataFrame a formato JSON y enviándolo mediante solicitudes HTTP:
import requests
# Convertir DataFrame a JSON
datos_json = df_datos.to_json(orient='records')
# Enviar datos a una API
url_api = 'https://api.ejemplo.com/endpoint'
cabeceras = {'Content-Type': 'application/json'}
respuesta = requests.post(url_api, data=datos_json, headers=cabeceras)
if respuesta.status_code == 200:
print('Datos enviados correctamente a la API.')
else:
print(f'Error al enviar datos: {respuesta.status_code}')
Es esencial manejar adecuadamente los errores y excepciones que puedan ocurrir durante la exportación, implementando bloques try-except
y registrando cualquier incidencia para su posterior análisis.
En resumen, Pandas proporciona herramientas versátiles para la exportación de datos, permitiendo que los resultados de los análisis sean almacenados y compartidos en formatos estandarizados y compatibles con una amplia variedad de sistemas y aplicaciones.
Ejercicios de esta lección Acceso a datos con MySQL, PyMongo y Pandas
Evalúa tus conocimientos de esta lección Acceso a datos con MySQL, PyMongo y Pandas con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Polimorfismo
Clases y objetos
Listas
Estructuras de control
Diccionarios
Importar módulos y paquetes
Módulo math
Operadores
OOP en python
Estructuras de control
Instalación de Python y creación de proyecto
Listas
Estructuras de control
Encapsulación
Clases y objetos
Encapsulación
Tipos de datos
Crear módulos y paquetes
Herencia de clases
Tuplas
Crear módulos y paquetes
Herencia
Módulo datetime
Excepciones
Operadores
Funciones lambda
Importar módulos y paquetes
Clases y objetos
Diccionarios
Módulo os
Listas
Conjuntos
Funciones lambda
Tuplas
Módulo json
Operadores
Variables
Tipos de datos
Diccionarios en Python
Conjuntos
Módulo math
Excepciones
Módulo csv
Gestor de tareas CRUD
Funciones Python
Módulo json
Tipos de datos
Módulo datetime
Herencia
Análisis de datos de ventas con Pandas
Funciones
Funciones Python
Variables
Módulo csv
Introducción a Python
Polimorfismo
Módulo os
Todas las lecciones de Python
Accede a todas las lecciones de Python y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Python
Introducción Y Entorno
Instalación Y Creación De Proyecto
Introducción Y Entorno
Tipos De Datos
Sintaxis
Variables
Sintaxis
Operadores
Sintaxis
Estructuras De Control
Sintaxis
Funciones
Sintaxis
Funciones Lambda
Programación Funcional
Clases Y Objetos
Programación Orientada A Objetos
Excepciones
Programación Orientada A Objetos
Encapsulación
Programación Orientada A Objetos
Herencia
Programación Orientada A Objetos
Polimorfismo
Programación Orientada A Objetos
Listas
Estructuras De Datos
Tuplas
Estructuras De Datos
Diccionarios
Estructuras De Datos
Conjuntos
Estructuras De Datos
Módulo Csv
Biblioteca Estándar
Módulo Json
Biblioteca Estándar
Módulo Datetime
Biblioteca Estándar
Módulo Math
Biblioteca Estándar
Módulo Os
Biblioteca Estándar
Importar Módulos Y Paquetes
Paquetes Y Módulos
Crear Módulos Y Paquetes
Paquetes Y Módulos
Instalación Beautiful Soup
Web Scraping
Sintaxis General De Beautiful Soup
Web Scraping
Tipos De Selectores
Web Scraping
Web Scraping De Html
Web Scraping
Web Scraping Para Ciencia De Datos
Web Scraping
Autenticación Y Acceso A Recursos Protegidos
Web Scraping
Combinación De Selenium Con Beautiful Soup
Web Scraping
Acceso A Datos Con Mysql, Pymongo Y Pandas
Acceso A Bases De Datos
Certificados de superación de Python
Supera todos los ejercicios de programación del curso de Python y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.
Objetivos de aprendizaje de esta lección
- Entender cómo funcionan las conexiones a bases de datos en Python.
- Instalar y configurar MySQL Connector para Python.
- Establecer conexiones seguras y manejar excepciones.
- Ejecución de consultas SQL desde Python.
- Manipular e integrar resultados con Pandas.
- Conectar a MongoDB usando PyMongo y manejar documentos.
- Realizar operaciones CRUD en MongoDB desde Python.