في هذا الدليل، سنبدأ العمل بإصدار Python من chDB.
سنبدأ بالاستعلام عن ملف JSON على S3، ثم سننشئ جدولًا في chDB استنادًا إلى ملف JSON، ونجري بعض الاستعلامات على البيانات.
وسنرى أيضًا كيفية جعل الاستعلامات تُرجع البيانات بتنسيقات مختلفة، بما في ذلك Apache Arrow وPandas، وفي النهاية سنتعلم كيفية الاستعلام عن Pandas DataFrames.
لننشئ أولًا بيئة افتراضية:
python -m venv .venv
source .venv/bin/activate
والآن سنقوم بتثبيت chDB.
تأكد من أن لديك الإصدار 2.0.3 أو أحدث:
pip install "chdb>=2.0.2"
والآن سنثبّت ipython:
سنستخدم ipython لتشغيل الأوامر الواردة في بقية هذا الدليل، ويمكنك تشغيله عبر تنفيذ:
سنستخدم أيضًا Pandas وApache Arrow في هذا الدليل، لذا فلنثبّت هاتين المكتبتين أيضًا:
pip install pandas pyarrow
الاستعلام عن ملف JSON في S3
لنلقِ الآن نظرة على كيفية الاستعلام عن ملف JSON مخزَّن في حاوية S3.
تحتوي مجموعة بيانات عدم الإعجاب على YouTube على أكثر من 4 مليارات صفّ من حالات عدم الإعجاب بمقاطع فيديو YouTube حتى عام 2021.
سنعمل على أحد ملفات JSON من مجموعة البيانات هذه.
استورِد chdb:
يمكننا كتابة الاستعلام التالي لوصف بنية أحد ملفات 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)"
يمكننا أيضًا عدّ عدد الصفوف في ذلك الملف:
chdb.query(
"""
SELECT count()
FROM s3(
's3://clickhouse-public-datasets/youtube/original/files/' ||
'youtubedislikes_20211127161229_18654868.1637897329_vid.json.zst',
'JSONLines'
)"""
)
يحتوي هذا الملف على أكثر قليلًا من 300,000 سجل.
لا يدعم chdb حتى الآن تمرير معلمات الاستعلام، لكن يمكننا استخراج المسار وتمريره باستخدام 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')
"""
)
لا بأس في فعل ذلك باستخدام المتغيرات المعرّفة في برنامجك، لكن لا تفعله مع المُدخلات التي يقدّمها المستخدم، وإلا فسيصبح استعلامك عرضة لحقن SQL.
تنسيق الإخراج الافتراضي هو CSV، لكن يمكن تغييره باستخدام المعلَمة output_format.
يدعم chDB تنسيقات بيانات ClickHouse، بالإضافة إلى بعض التنسيقات الخاصة به، بما في ذلك DataFrame، الذي يعيد Pandas DataFrame:
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 35307
أو إذا أردنا الحصول على جدول Apache 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]]
بعد ذلك، لنرَ كيفية إنشاء جدول في chDB.
نحتاج إلى استخدام واجهة برمجة تطبيقات مختلفة لهذا الغرض، لذا لنستوردها أولًا:
from chdb import session as chs
بعد ذلك، سنهيّئ جلسة.
إذا أردنا الاحتفاظ بالجلسة على القرص، فعلينا تحديد اسم دليل.
إذا تركناه فارغًا، فستكون قاعدة البيانات في الذاكرة وستُفقد بمجرد إنهاء عملية Python.
sess = chs.Session("gettingStarted.chdb")
بعد ذلك، سننشئ قاعدة بيانات:
sess.query("CREATE DATABASE IF NOT EXISTS youtube")
يمكننا الآن إنشاء جدول dislikes استنادًا إلى المخطط الوارد في ملف JSON، باستخدام أسلوب CREATE...EMPTY AS.
سنستخدم الإعداد schema_inference_make_columns_nullable حتى لا تُجعل جميع أنواع الأعمدة 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
"""
)
يمكننا بعد ذلك استخدام جملة DESCRIBE لاستعراض المخطط:
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"
بعد ذلك، لنقم بتعبئة ذلك الجدول بالبيانات:
sess.query(f"""
INSERT INTO youtube.dislikes
SELECT *
FROM s3('{path}','JSONLines')
SETTINGS schema_inference_make_columns_nullable=0
"""
)
يمكننا أيضًا تنفيذ هاتين الخطوتين معًا دفعةً واحدة باستخدام أسلوب CREATE...AS.
لنُنشئ جدولًا آخر باستخدام هذا الأسلوب:
sess.query(f"""
CREATE TABLE youtube.dislikes2
ORDER BY fetch_date
AS
SELECT *
FROM s3('{path}','JSONLines')
SETTINGS schema_inference_make_columns_nullable=0
"""
)
أخيرًا، لنُجرِ استعلامًا على الجدول:
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 49489
لنفترض أننا أضفنا بعد ذلك عمودًا إضافيًا إلى DataFrame لحساب نسبة الإعجابات إلى مرات عدم الإعجاب.
يمكننا كتابة التعليمة البرمجية التالية:
df["likeDislikeRatio"] = df["likeCount"] / df["dislikeCount"]
الاستعلام عن Pandas DataFrame
يمكننا بعد ذلك الاستعلام عن DataFrame هذا من خلال 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.051021
يمكنك أيضًا الاطلاع على مزيد من المعلومات حول الاستعلام عن Pandas DataFrames في دليل المطورين للاستعلام عن Pandas DataFrames.
نأمل أن يكون هذا الدليل قد قدّم لك فكرة واضحة وجيدة عن chDB.
للتعرّف أكثر على كيفية استخدامه، راجع أدلة المطورين التالية: