En esta guía, pondremos en marcha la variante de Python de chDB. Comenzaremos consultando un archivo JSON en S3, luego crearemos una tabla en chDB a partir de ese archivo JSON y haremos algunas consultas sobre los datos. También veremos cómo hacer que las consultas devuelvan datos en distintos formatos, incluidos Apache Arrow y Pandas, y, por último, aprenderemos a consultar DataFrames de Pandas.
Preparación
Primero, vamos a crear un entorno virtual:
python -m venv .venv
source .venv/bin/activateY ahora instalaremos chDB. Asegúrate de tener la versión 2.0.3 o posterior:
pip install "chdb>=2.0.2"Ahora vamos a instalar ipython:
pip install ipythonVamos a usar ipython para ejecutar los comandos del resto de la guía, que puedes abrir ejecutando:
ipythonEn esta guía también usaremos Pandas y Apache Arrow, así que instalemos esas bibliotecas también:
pip install pandas pyarrowConsulta de un archivo JSON en S3
Veamos ahora cómo consultar un archivo JSON almacenado en un bucket de S3. El conjunto de datos de dislikes de YouTube contiene más de 4 mil millones de filas sobre dislikes en videos de YouTube hasta 2021. Vamos a trabajar con uno de los archivos JSON de ese conjunto de datos.
Importa chdb:
import chdbPodemos ejecutar la siguiente consulta para describir la estructura de uno de los archivos JSON:
chdb.query(
"""
DESCRIBE s3(
's3://clickhouse-public-datasets/youtube/original/files/' ||
'youtubedislikes_20211127161229_18654868.1637897329_vid.json.zst',
'JSONLines'
)
SETTINGS describe_compact_output=1
"""
)"id","Nullable(String)"
"fetch_date","Nullable(String)"
"upload_date","Nullable(String)"
"title","Nullable(String)"
"uploader_id","Nullable(String)"
"uploader","Nullable(String)"
"uploader_sub_count","Nullable(Int64)"
"is_age_limit","Nullable(Bool)"
"view_count","Nullable(Int64)"
"like_count","Nullable(Int64)"
"dislike_count","Nullable(Int64)"
"is_crawlable","Nullable(Bool)"
"is_live_content","Nullable(Bool)"
"has_subtitles","Nullable(Bool)"
"is_ads_enabled","Nullable(Bool)"
"is_comments_enabled","Nullable(Bool)"
"description","Nullable(String)"
"rich_metadata","Array(Tuple(
call Nullable(String),
content Nullable(String),
subtitle Nullable(String),
title Nullable(String),
url Nullable(String)))"
"super_titles","Array(Tuple(
text Nullable(String),
url Nullable(String)))"
"uploader_badges","Nullable(String)"
"video_badges","Nullable(String)"También podemos contar el número de filas de ese archivo:
chdb.query(
"""
SELECT count()
FROM s3(
's3://clickhouse-public-datasets/youtube/original/files/' ||
'youtubedislikes_20211127161229_18654868.1637897329_vid.json.zst',
'JSONLines'
)"""
)336432Este archivo contiene poco más de 300.000 registros.
chdb todavía no admite parámetros de consulta, pero podemos extraer la ruta y pasarla mediante una f-string.
path = 's3://clickhouse-public-datasets/youtube/original/files/youtubedislikes_20211127161229_18654868.1637897329_vid.json.zst'chdb.query(
f"""
SELECT count()
FROM s3('{path}','JSONLines')
"""
)Configuración del formato de salida
El formato de salida predeterminado es CSV, pero podemos cambiarlo mediante el parámetro output_format.
chDB admite los formatos de datos de ClickHouse, así como algunos propios, incluido DataFrame, que devuelve un DataFrame de Pandas:
result = chdb.query(
f"""
SELECT is_ads_enabled, count()
FROM s3('{path}','JSONLines')
GROUP BY ALL
""",
output_format="DataFrame"
)
print(type(result))
print(result)<class 'pandas.core.frame.DataFrame'>
is_ads_enabled count()
0 False 301125
1 True 35307O bien, si queremos recuperar una tabla Arrow:
result = chdb.query(
f"""
SELECT is_live_content, count()
FROM s3('{path}','JSONLines')
GROUP BY ALL
""",
output_format="ArrowTable"
)
print(type(result))
print(result)<class 'pyarrow.lib.Table'>
pyarrow.Table
is_live_content: bool
count(): uint64 not null
----
is_live_content: [[false,true]]
count(): [[315746,20686]]Creación de una tabla a partir de un archivo JSON
A continuación, veamos cómo crear una tabla en chDB. Para ello, necesitamos usar una API diferente, así que primero importémosla:
from chdb import session as chsA continuación, inicializaremos una sesión. Si queremos que la sesión se guarde en disco, tenemos que indicar un nombre de directorio. Si lo dejamos en blanco, la sesión será temporal: chDB guarda sus datos en un directorio temporal en disco y los elimina cuando se cierra la sesión, por lo que los datos no persisten.
sess = chs.Session("gettingStarted.chdb")A continuación, crearemos una base de datos:
sess.query("CREATE DATABASE IF NOT EXISTS youtube")Ahora podemos crear una tabla dislikes a partir del esquema del archivo JSON, usando la técnica CREATE...EMPTY AS.
Usaremos la configuración schema_inference_make_columns_nullable para evitar que todos los tipos de columna se conviertan en Nullable.
sess.query(f"""
CREATE TABLE youtube.dislikes
ORDER BY fetch_date
EMPTY AS
SELECT *
FROM s3('{path}','JSONLines')
SETTINGS schema_inference_make_columns_nullable=0
"""
)A continuación, podemos usar la cláusula DESCRIBE para inspeccionar el esquema:
sess.query(f"""
DESCRIBE youtube.dislikes
SETTINGS describe_compact_output=1
"""
)"id","String"
"fetch_date","String"
"upload_date","String"
"title","String"
"uploader_id","String"
"uploader","String"
"uploader_sub_count","Int64"
"is_age_limit","Bool"
"view_count","Int64"
"like_count","Int64"
"dislike_count","Int64"
"is_crawlable","Bool"
"is_live_content","Bool"
"has_subtitles","Bool"
"is_ads_enabled","Bool"
"is_comments_enabled","Bool"
"description","String"
"rich_metadata","Array(Tuple(
call String,
content String,
subtitle String,
title String,
url String))"
"super_titles","Array(Tuple(
text String,
url String))"
"uploader_badges","String"
"video_badges","String"A continuación, vamos a poblar esa tabla:
sess.query(f"""
INSERT INTO youtube.dislikes
SELECT *
FROM s3('{path}','JSONLines')
SETTINGS schema_inference_make_columns_nullable=0
"""
)También podríamos hacer ambos pasos de una sola vez con la técnica CREATE...AS.
Vamos a crear otra tabla con esa técnica:
sess.query(f"""
CREATE TABLE youtube.dislikes2
ORDER BY fetch_date
AS
SELECT *
FROM s3('{path}','JSONLines')
SETTINGS schema_inference_make_columns_nullable=0
"""
)Consultar una tabla
Por último, consultemos la tabla:
df = sess.query("""
SELECT uploader, sum(view_count) AS viewCount, sum(like_count) AS likeCount, sum(dislike_count) AS dislikeCount
FROM youtube.dislikes
GROUP BY ALL
ORDER BY viewCount DESC
LIMIT 10
""",
"DataFrame"
)
df uploader viewCount likeCount dislikeCount
0 Jeremih 139066569 812602 37842
1 TheKillersMusic 109313116 529361 11931
2 LetsGoMartin- Canciones Infantiles 104747788 236615 141467
3 Xiaoying Cuisine 54458335 1031525 37049
4 Adri 47404537 279033 36583
5 Diana and Roma IND 43829341 182334 148740
6 ChuChuTV Tamil 39244854 244614 213772
7 Cheez-It 35342270 108 27
8 Anime Uz 33375618 1270673 60013
9 RC Cars OFF Road 31952962 101503 49489Supongamos que luego añadimos una columna adicional al DataFrame para calcular la proporción entre «me gusta» y «no me gusta». Podríamos escribir el siguiente código:
df["likeDislikeRatio"] = df["likeCount"] / df["dislikeCount"]Consultar un DataFrame de Pandas
A continuación, podemos consultar ese DataFrame con chDB:
chdb.query(
"""
SELECT uploader, likeDislikeRatio
FROM Python(df)
""",
output_format="DataFrame"
) uploader likeDislikeRatio
0 Jeremih 21.473548
1 TheKillersMusic 44.368536
2 LetsGoMartin- Canciones Infantiles 1.672581
3 Xiaoying Cuisine 27.842182
4 Adri 7.627395
5 Diana and Roma IND 1.225857
6 ChuChuTV Tamil 1.144275
7 Cheez-It 4.000000
8 Anime Uz 21.173296
9 RC Cars OFF Road 2.051021También puede obtener más información sobre cómo consultar DataFrames de Pandas en la guía para desarrolladores sobre consultas en DataFrames de Pandas.
Próximos pasos
Esperamos que esta guía te haya ofrecido una buena visión general de chDB. Para obtener más información sobre cómo usarlo, consulta las siguientes guías para desarrolladores: