Este tutorial está pensado como una introducción al trabajo con PyMongoArrow. Se asume que el lector está familiarizado con los conceptos básicos. Conceptos dePyMongo y MongoDB.
Instalar PyMongoArrow
Tip
Compatibilidad
Para obtener información sobre la compatibilidad con PyMongo, PyArrow y su sistema operativo, consulte la página de Compatibilidad.
Puedes instalar PyMongoArrow de tres maneras:
Pepita
Conda
De la fuente
Instalar con Pip
Recomendamos usar pip para instalar PyMongoArrow en todas las plataformas. PyMongoArrow está disponible en PyPI.
python -m pip install pymongoarrow
Para obtener una versión específica de Pymongo:
python -m pip install pymongoarrow==1.12.0
Para actualizar usando pip:
python -m pip install --upgrade pymongoarrow
Importante
Si la instalación falla debido a un error, como por ejemplo ValueError: Could
not find "libbson-1.0" librarySignifica que pip no encontró una rueda adecuada para tu plataforma. Recomendamos asegurarte de tener pip >= 20.3 instalado. Para actualizar pip, ejecuta el siguiente comando de shell:
$ python -m pip install --upgrade pip
Luego puedes intentar reinstalar pymongoarrow.
Actualmente distribuimos ruedas para macOS, Windows y Linux en arquitecturas x86_64.
Para probar la instalación, ejecute el siguiente código en la consola de Python. Si PyMongoArrow está instalado correctamente, no verá ningún error ni excepción.
import pymongoarrow as pma
Instala con Conda
PyMongoArrow está disponible para conda usuarios ejecutando el siguiente comando de shell:
$ conda install --channel conda-forge pymongoarrow
Para probar la instalación, ejecute el siguiente código en la consola de Python. Si PyMongoArrow está instalado correctamente, no verá ningún error ni excepción.
import pymongoarrow as pma
Instalar desde la fuente
Si no puede usar las opciones anteriores para instalar pymongoarrow en su sistema, puede instalarlo desde el código fuente. Para saber cómo, consulte la Guía de Contribución.
Dependencies
La instalación desde el código fuente en Linux requiere las siguientes dependencias:
Versión GCC 12 o posterior
CMake
pkg-config
Para usar PyMongoArrow con una función de PyMongo que requiere una dependencia opcional, debe configurar la dependencia como una opción cuando instale PyMongo.
Nota
Para obtener más información sobre las dependencias opcionales de PyMongo, consulte Dependencias en la documentación de PyMongo.
Por ejemplo, para usar PyMongoArrow con cifrado de nivel de campo del lado del cliente, debe instalar PyMongo con la opción encryption además de instalar PyMongoArrow:
python -m pip install 'pymongo[encryption]' pymongoarrow
Las aplicaciones que utilizan las API de PyMongoArrow que devuelven conjuntos de resultados de consultas como instancias pandas.DataFrame, como ~pymongoarrow.api.find_pandas_all(), también deben tener pandas instalado:
python -m pip install pandas
Para probar la instalación, ejecute el siguiente código en la consola de Python. Si PyMongoArrow está instalado correctamente, no verá ningún error ni excepción.
import pymongoarrow as pma
Instale MongoDB
Este tutorial asume que una instancia de MongoDB se ejecuta en el host y puerto predeterminados. Después de descargar e instalar MongoDB, puede iniciarlo como se muestra en el siguiente ejemplo de código:
$ mongod
Insertar datos de muestra
Ejecuta el siguiente código para insertar datos de muestra en tu clúster:
from datetime import datetime from pymongo import MongoClient client = MongoClient() client.db.data.insert_many([ {'_id': 1, 'amount': 21, 'last_updated': datetime(2020, 12, 10, 1, 3, 1), 'account': {'name': 'Customer1', 'account_number': 1}, 'txns': ['A']}, {'_id': 2, 'amount': 16, 'last_updated': datetime(2020, 7, 23, 6, 7, 11), 'account': {'name': 'Customer2', 'account_number': 2}, 'txns': ['A', 'B']}, {'_id': 3, 'amount': 3, 'last_updated': datetime(2021, 3, 10, 18, 43, 9), 'account': {'name': 'Customer3', 'account_number': 3}, 'txns': ['A', 'B', 'C']}, {'_id': 4, 'amount': 0, 'last_updated': datetime(2021, 2, 25, 3, 50, 31), 'account': {'name': 'Customer4', 'account_number': 4}, 'txns': ['A', 'B', 'C', 'D']}])
Definir el esquema
PyMongoArrow se basa en un esquema de datos para ordenar los conjuntos de resultados de las consultas en formato tabular. Si no proporciona este esquema, PyMongoArrow lo infiere a partir de los datos. Puede definir el esquema creando un objeto Schema y asignando los nombres de campo a especificadores de tipo, como se muestra en el siguiente ejemplo:
from pymongoarrow.api import Schema schema = Schema({'_id': int, 'amount': float, 'last_updated': datetime})
MongoDB utiliza documentos incrustados para representar datos anidados. PyMongoArrow ofrece compatibilidad de primera clase con estos documentos:
schema = Schema({'_id': int, 'amount': float, 'account': { 'name': str, 'account_number': int}})
PyMongoArrow también admite listas y listas anidadas:
from pyarrow import list_, string schema = Schema({'txns': list_(string())}) polars_df = client.db.data.find_polars_all({'amount': {'$gt': 0}}, schema=schema)
Tip
PyMongoArrow incluye múltiples identificadores de tipo permitidos para cada tipo BSON compatible. Para obtener una lista completa de estos tipos de datos y sus identificadores de tipo asociados, consulte Tipos de datos.
Operaciones de búsqueda
El siguiente ejemplo de código muestra cómo cargar todos los registros que tienen un valor distinto de cero para el campo amount como un objeto pandas.DataFrame:
df = client.db.data.find_pandas_all({'amount': {'$gt': 0}}, schema=schema)
También puede cargar el mismo conjunto de resultados como una instancia pyarrow.Table:
arrow_table = client.db.data.find_arrow_all({'amount': {'$gt': 0}}, schema=schema)
O como ejemplo polars.DataFrame:
df = client.db.data.find_polars_all({'amount': {'$gt': 0}}, schema=schema)
O como un objeto NumPy arrays:
ndarrays = client.db.data.find_numpy_all({'amount': {'$gt': 0}}, schema=schema)
Al utilizar NumPy, el valor de retorno es un diccionario donde las claves son nombres de campo y los valores son las instancias numpy.ndarray correspondientes.
Nota
En todos los ejemplos anteriores, puede omitir el esquema como se muestra en el siguiente ejemplo:
arrow_table = client.db.data.find_arrow_all({'amount': {'$gt': 0}})
Si omite el esquema, PyMongoArrow intenta aplicar automáticamente un esquema basado en los datos contenidos en el primer lote.
Operaciones agregadas
Ejecutar una operación de agregación es similar a ejecutar una operación de búsqueda, pero se necesita una secuencia de operaciones para realizarla.
El siguiente es un ejemplo simple del método aggregate_pandas_all() que genera un nuevo marco de datos en el que todos los valores _id se agrupan y se suman sus valores amount:
df = client.db.data.aggregate_pandas_all([{'$group': {'_id': None, 'total_amount': { '$sum': '$amount' }}}])
También puede ejecutar operaciones de agregación en documentos incrustados. El siguiente ejemplo desenrolla los valores del campo anidado txn, cuenta el número de cada valor y devuelve los resultados como una lista de objetos NumPy ndarray, ordenados descendentemente:
pipeline = [{'$unwind': '$txns'}, {'$group': {'_id': '$txns', 'count': {'$sum': 1}}}, {'$sort': {"count": -1}}] ndarrays = client.db.data.aggregate_numpy_all(pipeline)
Tip
Para obtener más información sobre los pipelines de agregación, consulte la documentación del servidor MongoDB.
Escribir en MongoDB
Puede utilizar el método write() para escribir objetos de los siguientes tipos en MongoDB:
Flecha
TablePandas
DataFrameNumPy
ndarrayPolars
DataFrame
from pymongoarrow.api import write from pymongo import MongoClient coll = MongoClient().db.my_collection write(coll, df) write(coll, arrow_table) write(coll, ndarrays)
Nota
Las matrices NumPy se especifican como dict[str, ndarray].
Ignore Empty Values
El método write() acepta opcionalmente un parámetro booleano exclude_none. Si se establece este parámetro en True, el controlador no escribe valores vacíos en la base de datos. Si se establece este parámetro en False o se deja en blanco, el controlador escribe None por cada campo vacío.
El código del siguiente ejemplo escribe una flecha Table en MongoDB dos veces. Uno de los valores del campo 'b' se establece en None.
La primera llamada al método write() omite el parámetro exclude_none, por lo que el valor predeterminado es False. Todos los valores en Table, incluido None, se escriben en la base de datos. La segunda llamada al método write() establece exclude_none en True, por lo que se ignora el valor vacío en el campo 'b'.
data_a = [1, 2, 3] data_b = [1, None, 3] data = Table.from_pydict( { "a": data_a, "b": data_b, }, ) coll.drop() write(coll, data) col_data = list(coll.find({})) coll.drop() write(coll, data, exclude_none=True) col_data_exclude_none = list(coll.find({})) print(col_data) print(col_data_exclude_none)
{'_id': ObjectId('...'), 'a': 1, 'b': 1} {'_id': ObjectId('...'), 'a': 2, 'b': None} {'_id': ObjectId('...'), 'a': 3, 'b': 3} {'_id': ObjectId('...'), 'a': 1, 'b': 1} {'_id': ObjectId('...'), 'a': 2} {'_id': ObjectId('...'), 'a': 3, 'b': 3}
Escribir en otros formatos
Una vez cargados los conjuntos de resultados, puedes escribirlos en cualquier formato que admita el paquete.
Por ejemplo, para escribir la tabla referenciada por la variable arrow_table en un archivo Parquet llamado example.parquet, ejecute el siguiente código:
import pyarrow.parquet as pq pq.write_table(arrow_table, 'example.parquet')
Pandas también admite la escritura de instancias DataFrame en una variedad de formatos, incluidos CSV y HDF. Para guardar el marco de datos referenciado por la variable df en un archivo CSV llamado out.csv, ejecute el siguiente código:
df.to_csv('out.csv', index=False)
La API de Polars es una mezcla de los dos ejemplos anteriores:
import polars as pl df = pl.DataFrame({"foo": [1, 2, 3, 4, 5]}) df.write_parquet('example.parquet')
Nota
Los datos anidados son compatibles para las operaciones de lectura y escritura en parquet, pero no son bien soportados por Arrow o Pandas para operaciones de lectura y escritura en CSV.
Ampliación de PyMongo
El módulo pymongoarrow.monkey proporciona una interfaz para parchear PyMongo en su lugar y agregar la funcionalidad de PyMongoArrow directamente a las instancias Collection:
from pymongoarrow.monkey import patch_all patch_all()
Después de ejecutar el método monkey.patch_all(), las nuevas instancias de la clase Collection contendrán las API de PyMongoArrow; por ejemplo, el método pymongoarrow.api.find_pandas_all().
Nota
También puede usar cualquiera de las API de PyMongoArrow importándolas desde el módulo pymongoarrow.api. Si lo hace, debe pasar la instancia de Collection donde se ejecutará la operación como primer argumento al llamar al método de la API.
Solución de problemas
¿Por qué obtengo un undefined symbol error al instalar PyMongoArrow desde la fuente?
PyMongoArrow genera este error cuando la versión 12 o posterior de GCC no está instalada en su entorno Linux. Si experimenta este error, asegúrese de tener instalada la versión 12 o posterior de GCC.
¿Por qué ModuleNotFoundError: No module named 'polars' obtengo al usar PyMongoArrow?
PyMongoArrow genera este error cuando una aplicación intenta usar una API de PyMongoArrow que devuelve conjuntos de resultados de consultas como una instancia polars.DataFrame sin tener polars instalado en el entorno de Python. Dado que polars no depende directamente de PyMongoArrow, no se instala automáticamente al instalar pymongoarrow. Debe instalar polars por separado con el siguiente comando de shell:
python -m pip install polars