تتيح لك ميزة نقاط نهاية واجهة برمجة تطبيقات الاستعلام إنشاء نقطة نهاية API مباشرةً من أي استعلام SQL محفوظ في وحدة تحكم ClickHouse Cloud. وستتمكن من الوصول إلى نقاط نهاية API عبر HTTP لتنفيذ استعلاماتك المحفوظة دون الحاجة إلى الاتصال بخدمة ClickHouse Cloud الخاصة بك باستخدام برنامج تشغيل أصلي.
المتطلبات المسبقة
قبل المتابعة، تأكد من توفر ما يلي لديك:
- مفتاح API بالأذونات المناسبة
- دور Admin في Console
يمكنك اتباع هذا الدليل لإنشاء مفتاح API إذا لم يكن لديك مفتاح بعد.
أنشئ استعلامًا محفوظًا
إذا كان لديك استعلام محفوظ، فيمكنك تخطي هذه الخطوة.
افتح علامة تبويب استعلام جديدة. لأغراض العرض التوضيحي، سنستخدم youtube dataset، التي تحتوي على نحو 4.5 مليار سجل. اتبع الخطوات الواردة في قسم "Create table" لإنشاء الجدول على خدمة Cloud الخاصة بك وإدراج البيانات فيه.
كمثال على استعلام، سنعرض أفضل 10 uploaders حسب متوسط عدد المشاهدات لكل فيديو، ضمن query parameter باسم year يُدخله المستخدم.
WITH sum(view_count) AS view_sum,
round(view_sum / num_uploads, 2) AS per_upload
SELECT
uploader,
count() AS num_uploads,
formatReadableQuantity(view_sum) AS total_views,
formatReadableQuantity(per_upload) AS views_per_video
FROM
youtube
WHERE
toYear(upload_date) = {year: UInt16}
GROUP BY uploader
ORDER BY per_upload desc
LIMIT 10لاحظ أن هذا الاستعلام يحتوي على parameter (year) مميز في المقتطف أعلاه.
يمكنك تحديد معلمات الاستعلام باستخدام { } مع نوع الـ parameter.
يكتشف محرر الاستعلام في SQL Console تلقائيًا تعبيرات query parameter في ClickHouse ويوفّر حقل إدخال لكل parameter.
لنشغّل هذا الاستعلام سريعًا للتأكد من أنه يعمل، وذلك بتحديد السنة 2010 في مربع إدخال متغيرات الاستعلام على الجانب الأيمن من محرر SQL:

بعد ذلك، احفظ الاستعلام:

يمكن العثور على مزيد من الوثائق حول استعلام محفوظ في قسم "Saving a query".
تهيئة نقطة النهاية لواجهة برمجة تطبيقات الاستعلام
يمكن تهيئة نقاط نهاية واجهة برمجة تطبيقات الاستعلام مباشرةً من عرض الاستعلام بالنقر على الزر Share ثم اختيار API Endpoint.
سيُطلب منك تحديد مفاتيح API التي يجب أن تتمكن من الوصول إلى نقطة النهاية:

بعد اختيار مفتاح API، سيُطلب منك:
- تحديد دور قاعدة البيانات الذي سيُستخدم لتشغيل الاستعلام (
Full accessأوRead onlyأوCreate a custom role) - تحديد النطاقات المسموح بها لمشاركة الموارد عبر المصادر المختلفة (CORS)
بعد اختيار هذه الخيارات، سيتم provision نقطة النهاية لواجهة برمجة تطبيقات الاستعلام تلقائيًا.
سيُعرض مثال لأمر curl حتى تتمكن من إرسال طلب اختبار:

يرد أمر curl المعروض في الواجهة أدناه للتيسير:
curl -H "Content-Type: application/json" -s --user '<key_id>:<key_secret>' '<API-endpoint>?format=JSONEachRow¶m_year=<value>'معاملات واجهة برمجة تطبيقات الاستعلام
يمكن تحديد معلمات الاستعلام في الاستعلام باستخدام الصياغة {parameter_name: type}. سيجري اكتشاف هذه المعاملات تلقائيًا، وستتضمن حمولة طلب المثال كائن queryVariables يمكنك من خلاله تمرير هذه المعاملات.
الاختبار والمراقبة
بمجرد إنشاء نقطة النهاية لواجهة برمجة تطبيقات الاستعلام، يمكنك اختباره باستخدام curl أو أي HTTP client آخر:

بعد إرسال أول طلب، من المفترض أن يظهر زر جديد مباشرةً إلى يمين الزر Share. سيؤدي النقر عليه إلى فتح flyout يحتوي على بيانات المراقبة الخاصة بالاستعلام:

تفاصيل التنفيذ
تُنفِّذ نقطة النهاية هذه الاستعلامات على نقاط نهاية واجهة برمجة تطبيقات الاستعلام المحفوظة لديك. وهي تدعم إصدارات متعددة، وتنسيقات استجابة مرنة، واستعلامات ذات معلمات، واستجابات متدفقة اختيارية (الإصدار 2 فقط).
نقطة النهاية:
GET /query-endpoints/{queryEndpointId}/run
POST /query-endpoints/{queryEndpointId}/runأساليب HTTP
| الأسلوب | حالة الاستخدام | المعلمات |
|---|---|---|
| GET | استعلامات بسيطة مع معلمات | مرّر متغيرات الاستعلام عبر معلمات URL (?param_name=value) |
| POST | استعلامات معقدة أو عند استخدام محتوى الطلب | مرّر متغيرات الاستعلام في محتوى الطلب (الكائن queryVariables) |
متى تستخدم GET:
- استعلامات بسيطة من دون بيانات متداخلة معقدة
- يمكن ترميز المعلمات بسهولة في URL
- يستفيد التخزين المؤقت من دلالات HTTP GET
متى تستخدم POST:
- متغيرات استعلام معقدة (مصفوفات، كائنات، سلاسل نصية كبيرة)
- عندما يكون محتوى الطلب مفضّلًا لأسباب تتعلق بالأمان أو الخصوصية
- تحميل الملفات المتدفّق أو البيانات الكبيرة
المصادقة
مطلوب: نعم الطريقة: مصادقة أساسية باستخدام مفتاح/سر OpenAPI الأذونات: الأذونات المناسبة لنقطة نهاية الاستعلام
تهيئة الطلب
معلمات عنوان URL
| المعلمة | مطلوب | الوصف |
|---|---|---|
queryEndpointId |
نعم | المعرّف الفريد لنقطة نهاية الاستعلام المطلوب تشغيلها |
معلمات الاستعلام
| المعلمة | مطلوب | الوصف | مثال |
|---|---|---|---|
format |
لا | تنسيق الاستجابة (يدعم جميع تنسيقات ClickHouse) | ?format=JSONEachRow |
param_:name |
لا | متغيرات الاستعلام عندما يكون نص الطلب دفقًا. استبدل :name باسم المتغير الخاص بك |
?param_year=2024 |
request_timeout |
لا | مهلة الاستعلام بالمللي ثانية (الافتراضي: 30000) | ?request_timeout=60000 |
:clickhouse_setting |
لا | أي إعداد في ClickHouse مدعوم | ?max_threads=8 |
الترويسات
| الترويسة | مطلوب | الوصف | القيم |
|---|---|---|---|
x-clickhouse-endpoint-version |
لا | يحدد إصدار نقطة النهاية | 1 أو 2 (الإعداد الافتراضي: آخر إصدار محفوظ) |
x-clickhouse-endpoint-upgrade |
لا | يُفعّل ترقية إصدار نقطة النهاية (يُستخدم مع ترويسة الإصدار) | 1 للترقية |
جسم الطلب
المعلمات
| المعلمة | النوع | مطلوب | الوصف |
|---|---|---|---|
queryVariables |
كائن | لا | المتغيرات المستخدمة في الاستعلام |
format |
سلسلة نصية | لا | تنسيق الاستجابة |
التنسيقات المدعومة
| الإصدار | التنسيقات المدعومة |
|---|---|
| الإصدار 2 | جميع التنسيقات التي يدعمها ClickHouse |
| الإصدار 1 (محدود) | TabSeparated TabSeparatedWithNames TabSeparatedWithNamesAndTypes JSON JSONEachRow CSV CSVWithNames CSVWithNamesAndTypes |
الاستجابات
نجاح
الحالة: 200 OK
تم تنفيذ الاستعلام بنجاح.
رموز الخطأ
| رمز الحالة | الوصف |
|---|---|
400 Bad Request |
كان الطلب سيئ الصياغة |
401 Unauthorized |
المصادقة مفقودة أو الأذونات غير كافية |
404 Not Found |
لم يتم العثور على نقطة نهاية الاستعلام المحددة |
أفضل الممارسات لمعالجة الأخطاء
- تأكد من تضمين بيانات اعتماد مصادقة صالحة في الطلب
- تحقّق من صحة
queryEndpointIdوqueryVariablesقبل الإرسال - طبّق معالجة مناسبة للأخطاء مع رسائل خطأ ملائمة
ترقية إصدارات endpoint
للترقية من الإصدار 1 إلى الإصدار 2:
- أدرِج الترويسة
x-clickhouse-endpoint-upgradeمع تعيينها إلى1 - أدرِج الترويسة
x-clickhouse-endpoint-versionمع تعيينها إلى2
يؤدي ذلك إلى إتاحة الوصول إلى ميزات الإصدار 2، بما في ذلك:
- دعم جميع تنسيقات ClickHouse
- إمكانات بث الاستجابة
- تحسينات في الأداء والوظائف
أمثلة
طلب بسيط
استعلام SQL الخاص بـ نقطة نهاية واجهة برمجة تطبيقات الاستعلام:
SELECT database, name AS num_tables FROM system.tables LIMIT 3;الإصدار 1
curl -X POST 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run' \
--user '<openApiKeyId:openApiKeySecret>' \
-H 'Content-Type: application/json' \
-d '{ "format": "JSONEachRow" }'fetch(
"https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run",
{
method: "POST",
headers: {
Authorization: "Basic <base64_encoded_credentials>",
"Content-Type": "application/json",
},
body: JSON.stringify({
format: "JSONEachRow",
}),
}
)
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));{
"data": {
"columns": [
{
"name": "database",
"type": "String"
},
{
"name": "num_tables",
"type": "String"
}
],
"rows": [
["INFORMATION_SCHEMA", "COLUMNS"],
["INFORMATION_SCHEMA", "KEY_COLUMN_USAGE"],
["INFORMATION_SCHEMA", "REFERENTIAL_CONSTRAINTS"]
]
}
}الإصدار 2
curl 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONEachRow' \
--user '<openApiKeyId:openApiKeySecret>' \
-H 'x-clickhouse-endpoint-version: 2'{"database":"INFORMATION_SCHEMA","num_tables":"COLUMNS"}
{"database":"INFORMATION_SCHEMA","num_tables":"KEY_COLUMN_USAGE"}
{"database":"INFORMATION_SCHEMA","num_tables":"REFERENTIAL_CONSTRAINTS"}curl -X POST 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONEachRow' \
--user '<openApiKeyId:openApiKeySecret>' \
-H 'Content-Type: application/json' \
-H 'x-clickhouse-endpoint-version: 2'fetch(
"https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONEachRow",
{
method: "POST",
headers: {
Authorization: "Basic <base64_encoded_credentials>",
"Content-Type": "application/json",
"x-clickhouse-endpoint-version": "2",
},
}
)
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));{"database":"INFORMATION_SCHEMA","num_tables":"COLUMNS"}
{"database":"INFORMATION_SCHEMA","num_tables":"KEY_COLUMN_USAGE"}
{"database":"INFORMATION_SCHEMA","num_tables":"REFERENTIAL_CONSTRAINTS"}طلب مع متغيرات الاستعلام والإصدار 2 بتنسيق JSONCompactEachRow
SQL الخاص بنقطة نهاية واجهة برمجة تطبيقات الاستعلام:
SELECT name, database FROM system.tables WHERE match(name, {tableNameRegex: String}) AND database = {database: String};curl 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONCompactEachRow¶m_tableNameRegex=query.*¶m_database=system' \
--user '<openApiKeyId:openApiKeySecret>' \
-H 'x-clickhouse-endpoint-version: 2'["query_cache", "system"]
["query_log", "system"]
["query_views_log", "system"]curl -X POST 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONCompactEachRow' \
--user '<openApiKeyId:openApiKeySecret>' \
-H 'Content-Type: application/json' \
-H 'x-clickhouse-endpoint-version: 2' \
-d '{ "queryVariables": { "tableNameRegex": "query.*", "database": "system" } }'fetch(
"https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONCompactEachRow",
{
method: "POST",
headers: {
Authorization: "Basic <base64_encoded_credentials>",
"Content-Type": "application/json",
"x-clickhouse-endpoint-version": "2",
},
body: JSON.stringify({
queryVariables: {
tableNameRegex: "query.*",
database: "system",
},
}),
}
)
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));["query_cache", "system"]
["query_log", "system"]
["query_views_log", "system"]طلب يستخدم مصفوفة في متغيرات الاستعلام لإدراج بيانات في جدول
تعليمة SQL للجدول:
CREATE TABLE default.t_arr
(
`arr` Array(Array(Array(UInt32)))
)
ENGINE = MergeTree
ORDER BY tuple()SQL لنقطة نهاية واجهة برمجة تطبيقات الاستعلام:
INSERT INTO default.t_arr VALUES ({arr: Array(Array(Array(UInt32)))});curl -X POST 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run' \
--user '<openApiKeyId:openApiKeySecret>' \
-H 'Content-Type: application/json' \
-H 'x-clickhouse-endpoint-version: 2' \
-d '{
"queryVariables": {
"arr": [[[12, 13, 0, 1], [12]]]
}
}'fetch(
"https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run",
{
method: "POST",
headers: {
Authorization: "Basic <base64_encoded_credentials>",
"Content-Type": "application/json",
"x-clickhouse-endpoint-version": "2",
},
body: JSON.stringify({
queryVariables: {
arr: [[[12, 13, 0, 1], [12]]],
},
}),
}
)
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));OKطلب مع تعيين إعداد ClickHouse max_threads إلى 8
SQL الخاص بـ نقطة نهاية واجهة برمجة تطبيقات الاستعلام:
SELECT * FROM system.tables;curl 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?max_threads=8' \
--user '<openApiKeyId:openApiKeySecret>' \
-H 'x-clickhouse-endpoint-version: 2'curl -X POST 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?max_threads=8,' \
--user '<openApiKeyId:openApiKeySecret>' \
-H 'Content-Type: application/json' \
-H 'x-clickhouse-endpoint-version: 2' \fetch(
"https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?max_threads=8",
{
method: "POST",
headers: {
Authorization: "Basic <base64_encoded_credentials>",
"Content-Type": "application/json",
"x-clickhouse-endpoint-version": "2",
},
}
)
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));أرسل الطلب وحلّل الاستجابة كتدفق
SQL الخاص بنقطة نهاية واجهة برمجة تطبيقات الاستعلام:
SELECT name, database FROM system.tables;async function fetchAndLogChunks(
url: string,
openApiKeyId: string,
openApiKeySecret: string
) {
const auth = Buffer.from(`${openApiKeyId}:${openApiKeySecret}`).toString(
"base64"
);
const headers = {
Authorization: `Basic ${auth}`,
"x-clickhouse-endpoint-version": "2",
};
const response = await fetch(url, {
headers,
method: "POST",
body: JSON.stringify({ format: "JSONEachRow" }),
});
if (!response.ok) {
console.error(`HTTP error! Status: ${response.status}`);
return;
}
const reader = response.body as unknown as Readable;
reader.on("data", (chunk) => {
console.log(chunk.toString());
});
reader.on("end", () => {
console.log("Stream ended.");
});
reader.on("error", (err) => {
console.error("Stream error:", err);
});
}
const endpointUrl =
"https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONEachRow";
const openApiKeyId = "<myOpenApiKeyId>";
const openApiKeySecret = "<myOpenApiKeySecret>";
// مثال للاستخدام
fetchAndLogChunks(endpointUrl, openApiKeyId, openApiKeySecret).catch((err) =>
console.error(err)
);> npx tsx index.ts
> {"name":"COLUMNS","database":"INFORMATION_SCHEMA"}
> {"name":"KEY_COLUMN_USAGE","database":"INFORMATION_SCHEMA"}
...
> Stream ended.إدراج دفق من ملف في جدول
أنشئ ملفًا باسم ./samples/my_first_table_2024-07-11.csv بالمحتوى التالي:
"user_id","json","name"
"1","{""name"":""John"",""age"":30}","John"
"2","{""name"":""Jane"",""age"":25}","Jane"صيغة SQL للأمر CREATE TABLE:
create table default.my_first_table
(
user_id String,
json String,
name String,
) ENGINE = MergeTree()
ORDER BY user_id;عبارة SQL الخاصة بـ نقطة نهاية واجهة برمجة تطبيقات الاستعلام:
INSERT INTO default.my_first_tablecat ./samples/my_first_table_2024-07-11.csv | curl --user '<openApiKeyId:openApiKeySecret>' \
-X POST \
-H 'Content-Type: application/octet-stream' \
-H 'x-clickhouse-endpoint-version: 2' \
"https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=CSV" \
--data-binary @-