La fonctionnalité Query API Endpoints vous permet de créer un endpoint d’API directement à partir de n’importe quelle requête SQL enregistrée dans la console ClickHouse Cloud. Vous pourrez accéder à ces endpoints d’API via HTTP afin d’exécuter vos requêtes enregistrées sans avoir à vous connecter à votre service ClickHouse Cloud à l’aide d’un driver natif.
Avant de continuer, assurez-vous d’avoir :
- une clé API avec les autorisations appropriées
- un rôle Admin dans la Console
Vous pouvez suivre ce guide pour créer une clé API si vous n’en avez pas encore.
Autorisations minimalesPour interroger un endpoint d’API, la clé API doit disposer du rôle d’organisation Member avec l’accès au service Query Endpoints. Le rôle de base de données est configuré lors de la création de l’endpoint.
Créer une requête enregistrée
Si vous avez déjà une requête enregistrée, vous pouvez ignorer cette étape.Ouvrez un nouvel onglet de requête. À des fins de démonstration, nous utiliserons le jeu de données YouTube, qui contient environ 4,5 milliards d’enregistrements.
Suivez les étapes de la section “Create table” pour créer la table sur votre service Cloud et y insérer des données.Limiter le nombre de lignes avec LIMITLe tutoriel sur le jeu de données d’exemple insère un volume important de données — 4,65 milliards de lignes — ce qui peut prendre un certain temps.
Pour ce guide, nous recommandons d’utiliser la clause LIMIT afin d’insérer un plus petit volume de données,
par exemple 10 millions de lignes.
À titre d’exemple, nous allons renvoyer les 10 comptes ayant publié des vidéos avec la moyenne de vues par vidéo la plus élevée pour un paramètre year saisi par l’utilisateur.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
Notez que cette requête contient un paramètre (year), mis en évidence dans l’extrait ci-dessus.
Vous pouvez spécifier des paramètres de requête à l’aide de { } avec le type du paramètre.
L’éditeur de requêtes de la console SQL détecte automatiquement les expressions de paramètres de requête ClickHouse et fournit un champ de saisie pour chaque paramètre.Exécutons rapidement cette requête pour vérifier qu’elle fonctionne en spécifiant l’année 2010 dans la zone de saisie des variables de requête située à droite de l’éditeur SQL :Ensuite, enregistrez la requête :Vous trouverez plus d’informations sur les requêtes enregistrées dans la section “Saving a query”.Configuration de l’endpoint d’API de requête
Les endpoints d’API de requête peuvent être configurés directement depuis la vue de requête en cliquant sur le bouton Share, puis en sélectionnant API Endpoint.
Il vous sera demandé de préciser quelles clés API doivent pouvoir accéder à l’endpoint :Après avoir sélectionné une clé API, il vous sera demandé de :
- Sélectionner le rôle de base de données qui sera utilisé pour exécuter la requête (
Full access, Read only ou Create a custom role)
- Spécifier les domaines autorisés pour le partage de ressources entre origines (CORS)
Après avoir sélectionné ces options, l’endpoint d’API de requête sera automatiquement provisionné.Un exemple de commande curl s’affichera afin que vous puissiez envoyer une requête de test :La commande curl affichée dans l’interface est reproduite ci-dessous pour plus de commodité :curl -H "Content-Type: application/json" -s --user '<key_id>:<key_secret>' '<API-endpoint>?format=JSONEachRow¶m_year=<value>'
Paramètres de l’API de requête
Les paramètres d’une requête peuvent être spécifiés avec la syntaxe {parameter_name: type}. Ces paramètres seront automatiquement détectés et l’exemple de payload de requête contiendra un objet queryVariables vous permettant de transmettre ces paramètres.Test et monitoring
Une fois un endpoint d’API de requête créé, vous pouvez vérifier son fonctionnement à l’aide de curl ou de tout autre client HTTP :Après l’envoi de votre première requête, un nouveau bouton devrait apparaître immédiatement à droite du bouton Share. En cliquant dessus, vous ouvrirez un panneau latéral contenant des données de monitoring sur la requête :
Cet endpoint exécute des requêtes sur vos Query API endpoints enregistrés.
Il prend en charge plusieurs versions, des formats de réponse flexibles, des requêtes paramétrées et des réponses en streaming facultatives (version 2 uniquement).
Endpoint :
GET /query-endpoints/{queryEndpointId}/run
POST /query-endpoints/{queryEndpointId}/run
| Méthode | Cas d’utilisation | Paramètres |
|---|
| GET | Requêtes simples avec paramètres | Transmettez les variables de requête via les paramètres d’URL (?param_name=value) |
| POST | Requêtes complexes ou lorsque le corps de la requête est utilisé | Transmettez les variables de requête dans le corps de la requête (objet queryVariables) |
Quand utiliser GET :
- Requêtes simples sans données imbriquées complexes
- Les paramètres peuvent être facilement encodés dans l’URL
- La mise en cache tire parti de la sémantique HTTP de GET
Quand utiliser POST :
- Variables de requête complexes (tableaux, objets, chaînes longues)
- Lorsque le corps de la requête est préférable pour des raisons de sécurité ou de confidentialité
- Téléversement de fichiers en continu ou données volumineuses
Obligatoire : Oui
Méthode : Basic Auth avec OpenAPI Key/Secret
Permissions : Permissions appropriées pour l’endpoint de requête
Configuration de la requête
| Paramètre | Obligatoire | Description |
|---|
queryEndpointId | Oui | L’identifiant unique de l’endpoint de requête à exécuter |
| Paramètre | Obligatoire | Description | Exemple |
|---|
format | Non | Format de réponse (prend en charge tous les formats ClickHouse) | ?format=JSONEachRow |
param_:name | Non | Variables de requête si le corps de la requête est un flux. Remplacez `:name“ par le nom de votre variable | ?param_year=2024 |
request_timeout | Non | Délai d’expiration de la requête en millisecondes (par défaut : 30000) | ?request_timeout=60000 |
:clickhouse_setting | Non | Tout paramètre ClickHouse pris en charge | ?max_threads=8 |
| En-tête | Obligatoire | Description | Valeurs |
|---|
x-clickhouse-endpoint-version | Non | Spécifie la version de l’endpoint | 1 ou 2 (par défaut : dernière version enregistrée) |
x-clickhouse-endpoint-upgrade | Non | Déclenche la mise à niveau de la version de l’endpoint (à utiliser avec l’en-tête de version) | 1 pour mettre à niveau |
| Paramètre | Type | Obligatoire | Description |
|---|
queryVariables | objet | Non | Variables à utiliser dans la requête |
format | chaîne | Non | Format de réponse |
| Version | Formats pris en charge |
|---|
| Version 2 | Tous les formats pris en charge par ClickHouse |
| Version 1 (limité) | TabSeparated TabSeparatedWithNames TabSeparatedWithNamesAndTypes JSON JSONEachRow CSV CSVWithNames CSVWithNamesAndTypes |
Statut : 200 OK
La requête a bien été exécutée.
| Code d’état | Description |
|---|
400 Bad Request | La requête est mal formée |
401 Unauthorized | Authentification manquante ou permissions insuffisantes |
404 Not Found | L’endpoint de requête spécifié est introuvable |
Bonnes pratiques de gestion des erreurs
- Assurez-vous que des identifiants d’authentification valides sont inclus dans la requête
- Validez
queryEndpointId et queryVariables avant l’envoi
- Mettez en place une gestion appropriée des erreurs avec des messages d’erreur adaptés
Mise à niveau des versions d’endpoint
Pour passer de la version 1 à la version 2 :
- Incluez l’en-tête
x-clickhouse-endpoint-upgrade défini sur 1
- Incluez l’en-tête
x-clickhouse-endpoint-version défini sur 2
Cela active l’accès aux fonctionnalités de la version 2, notamment :
- La prise en charge de tous les formats ClickHouse
- Le streaming des réponses
- Des performances et fonctionnalités améliorées
SQL du Query API Endpoint :
SELECT database, name AS num_tables FROM system.tables LIMIT 3;
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"]
]
}
}
GET (cURL)
POST (cURL)
JavaScript
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"}
SQL du Query API Endpoint :
SELECT name, database FROM system.tables WHERE match(name, {tableNameRegex: String}) AND database = {database: String};
GET (cURL)
POST (cURL)
JavaScript
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"]
Requête avec un Array dans les variables de requête qui insère des données dans une table
SQL de la table :
CREATE TABLE default.t_arr
(
`arr` Array(Array(Array(UInt32)))
)
ENGINE = MergeTree
ORDER BY tuple()
SQL du Query API Endpoint :
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));
Requête avec le paramètre ClickHouse max_threads défini sur 8
SQL du Query API Endpoint :
SELECT * FROM system.tables;
GET (cURL)
POST (cURL)
JavaScript
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 du Query API Endpoint :
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>";
// Exemple d'utilisation
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.
Insérer un flux de données provenant d’un fichier dans une table
Créez un fichier ./samples/my_first_table_2024-07-11.csv avec le contenu suivant :
"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 du Query API Endpoint :
INSERT INTO default.my_first_table
cat ./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 @-