Cassandra Query Language
Apache Cassandra dispose d’un langage de requête, nommé CQL pour Cassandra Query Language. Bien qu’il ressemble à SQL, il est conçu pour les opérations de base de données distribuées sans prise en charge de certaines fonctionnalités comme les jointures.
Présentation des données
Pour mieux comprendre les commandes CQL, nous allons utiliser un exemple de données d’une bibliothèque. Les données sont stockées dans un keyspace biblio qui contient deux tables : utilisateurs et emprunts.
Table utilisateurs
La table utilisateurs contient les informations des utilisateurs de la bibliothèque :
-
id: identifiant unique de l’utilisateur -
nom: nom de l’utilisateur -
age: âge de l’utilisateur
Ci-dessous un exemple de données pour la table utilisateurs :
| id | nom | age |
|---|---|---|
| 6a6148d1-4a56-4d6a-a610 | Alice | 30 |
| 79e9b9b4-8b76-4cb7-8419 | Bob | 23 |
| cb923190-d658-4471-827d | Charlie | 45 |
| 8eabd71d-c1f0-4496-9415 | Dalia | 28 |
| 2c524549-09f0-4e8e-9afc | Eve | 36 |
Table emprunts
La table emprunts contient les informations des emprunts de livres :
-
livre_id: identifiant du livre emprunté -
utilisateur_id: identifiant de l’utilisateur -
emprunt_id: identifiant unique de l’emprunt -
timestamp: date et heure de l’emprunt
Voici des données pour la table emprunts :
| livre_id | emprunt_id | utilisateur_id | timestamp |
|---|---|---|---|
| 549d7790-2aa1-4710-88d4 | 437c10d7-5508-4ecf-b821 | 6a6148d1-4a56-4d6a-a610 | 2021-03-31 10:00:00+0000 |
| 616be2d4-d205-4278-ad6d | dc880752-f900-4454-8993 | 6a6148d1-4a56-4d6a-a610 | 2022-08-06 15:00:00+0000 |
| 549d7790-2aa1-4710-88d4 | 4c63cb26-f5f1-4ca3-bd62 | 79e9b9b4-8b76-4cb7-8419 | 2023-35-22 11:00:00+0000 |
| b3420ae3-88b8-45f7-adc1 | 4e1e806b-872b-421e-a461 | cb923190-d658-4471-827d | 2025-10-03 12:00:00+0000 |
| 0d7c6069-d250-431a-8573 | 8eabd71d-c1f0-4496-9415 | 8eabd71d-c1f0-4496-9415 | 2021-11-14 13:00:00+0000 |
| 2f228bd5-a517-4214-8303 | f93925d8-79e6-461d-ace8 | 2c524549-09f0-4e8e-9afc | 2021-12-05 14:00:00+0000 |
Commandes CQL
Voici quelques exemples de commandes CQL pour interagir avec la base de données biblio qui contient les données des utilisateurs et des emprunts de livres d’une bibliothèque.
Keyspaces
Cassandra définit des keyspaces pour regrouper les tables. Un keyspace est l’équivalent d’une base de données dans un système de gestion de base de données relationnelle. Les keyspaces ont des propriétés de réplication qui définissent comment les données sont répliquées sur les nœuds du cluster.
- Création d’un keyspace :
CREATE KEYSPACE biblio WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 3}; - Changement de keyspace :
USE biblio ;L’instruction
USEreplace le keyspace courant par celui spécifié dans la requête. Ainsi, toutes les requêtes suivantes seront exécutées dans le keyspacebiblio. Il n’est pas nécessaire de spécifier le keyspace dans les requêtes suivantes. On peut écrire directementCREATE TABLE utilisateurs (...)sans spécifier le keyspace. - Liste des keyspaces :
DESCRIBE KEYSPACES;Cette commande permet de lister tous les keyspaces disponibles dans le cluster.
- Description d’un keyspace :
DESCRIBE KEYSPACE biblio;Cette commande permet de voir les détails du keyspace
biblio. - Suppression d’un keyspace :
DROP KEYSPACE IF EXISTS biblio;
Création de tables
La création de tables en CQL est similaire à SQL. Il faut veiller à bien définir la clé primaire pour chaque table qui est essentielle pour la distribution des données dans le cluster.
- Clé primaire simple
CREATE TABLE biblio.utilisateurs ( id UUID PRIMARY KEY, nom TEXT, age INT );Pour plus d’informations sur les types de données supportés par Apache Cassandra, vous pouvez consulter la documentation.
- Clé primaire composite
CREATE TABLE biblio.emprunts ( livre_id UUID, emprunt_id UUID, utilisateur_id UUID, timestamp TIMESTAMP, PRIMARY KEY (emprunt_id, utilisateur_id) );Ici nous avons une table qui possède deux colonnes comme clé primaire. Cela signifie que la combinaison de
emprunt_idetutilisateur_iddoit être unique. - Clé de clustering
CREATE TABLE biblio.emprunts ( livre_id UUID, emprunt_id UUID, utilisateur_id UUID, timestamp TIMESTAMP, PRIMARY KEY ((emprunt_id, utilisateur_id), timestamp) ) WITH CLUSTERING ORDER BY (timestamp DESC);Ici la clé primaire est composée de
emprunt_idetutilisateur_id, et la clé de clustering esttimestamp. On ajouteWITH CLUSTERING ORDER BY (timestamp DESC)pour trier les données par ordre décroissant detimestamp.
Manipulation de données
Une fois que les données sont insérées dans le cluster, il est possible de les manipuler en utilisant des requêtes CQL via les clauses SELECT, INSERT, UPDATE et DELETE.
- Liste des tables :
DESCRIBE TABLES;Cette commande permet de lister toutes les tables du keyspace courant.
- Description d’une table :
DESCRIBE TABLE biblio.utilisateurs;Cette commande permet de voir les détails de la table
utilisateursdu keyspacebiblio. - Insertion de données :
INSERT INTO biblio.utilisateurs (id, nom, age) VALUES (6a6148d1-4a56-4d6a-a610-cdf7b7e3b959, 'Alice', 30); INSERT INTO biblio.utilisateurs (id, nom, age) VALUES (uuid(), 'Bob', 23);Ici, l’identifiant de Bob est généré automatiquement par Cassandra via la fonction
uuid(). - Sélection de données :
SELECT nom, age FROM biblio.utilisateurs WHERE age > 35;Cette requête permet de sélectionner le nom et l’âge des utilisateurs de plus de 35 ans.
- Mise à jour de données :
UPDATE biblio.utilisateurs SET age = 31 WHERE id = 6a6148d1-4a56-4d6a-a610-cdf7b7e3b959;Ici, on met à jour l’âge d’Alice (qui possède l’identifiant
6a6148d1-4a56-4d6a-a610-cdf7b7e3b959) de 30 à 31 ans. - Suppression de données :
DELETE FROM biblio.utilisateurs WHERE id = 6a6148d1-4a56-4d6a-a610-cdf7b7e3b959;De même, qu’il est possible de supprimer les données d’Alice de la table
utilisateurs. Dans notre cas, il faudrait également supprimer les emprunts d’Alice dans la tableemprunts. - Suppression d’une table :
DROP TABLE IF EXISTS biblio.utilisateurs;Si l’on veut supprimer une table, il suffit d’utiliser la commande
DROP TABLEcomme en SQL.
Index
Les index peuvent être créés pour améliorer les performances des requêtes. Cela permet de rechercher plus rapidement les colonnes qui ne sont pas définies dans la clé de partitionnement.
- Création d’un index :
CREATE INDEX IF NOT EXISTS nom_index ON biblio.utilisateurs (nom); - Suppression d’un index :
DROP INDEX IF EXISTS nom_index;
Clé primaire et partitionnement
Il est important de bien choisir la clé de partition et la clé de clustering pour optimiser les performances de la base de données. Aussi, il peut être nécessaire de dupliquer les données pour répondre à différents types de requêtes.
Toutes les colonnes qui sont dans la PRIMARY KEY doivent être utilisées dans la clauseWHEREde la requêteSELECT. Par exemple, si la clé primaire est composée deidetnom, la requêteSELECTdoit contenir ces deux colonnes dans la clauseWHERE.SELECT * FROM biblio.utilisateurs WHERE id = 6a6148d1-4a56-4d6a-a610-cdf7b7e3b959 AND nom = 'Alice';
Pour plus d’informations sur les commandes CQL, vous pouvez consulter la documentation officielle d’Apache Cassandra :
- Manipulation de données : CREATE, ALTER, DROP (table, keyspace)
- Requêtes : SELECT, INSERT, UPDATE, DELETE
Initialisation d’une base de données
Pour ce TP, nous allons créer une base de données Apache Cassandra via Docker. Docker est une plateforme de conteneurisation qui permet de créer, déployer et exécuter des applications dans des conteneurs. Un conteneur est une unité légère et autonome qui contient tout ce dont une application a besoin pour fonctionner, y compris le code, les packages, les dépendances et les fichiers de configuration.
Pour créer la base de données, il suffit d’exécuter les commandes suivantes dans votre terminal (PowerShell, Git bash, etc.) :
- Téléchargement de l’image Apache Cassandra en local.
docker pull cassandra:latest - Exécuter le serveur
cassandraen local.docker run -d --rm --name cassandra -p 9042:9042 cassandra - Ensuite, pour accéder à la base de données Cassandra, il faut exécuter la commande suivante :
docker exec -it cassandra cqlshVous devriez voir une sortie similaire à celle-ci, indiquant que vous êtes connecté à la base de données Cassandra et que vous pouvez commencer à exécuter des commandes CQL (après le
cqlsh>).Connected to Test Cluster at 127.0.0.1:9042 [cqlsh 6.2.0 | Cassandra 5.0.6 | CQL spec 3.4.7 | Native protocol v5] Use HELP for help. cqlsh>
Ainsi, vous accédez à l’interface de ligne de commande de Cassandra, appelée cqlsh, qui vous permet d’exécuter des commandes CQL pour interagir avec la base de données. Vous pouvez écrire les commandes CQL directement dans l’interface après le prompt cqlsh>. Vous pouvez maintenant créer un keyspace, des tables et insérer des données dans votre base de données Cassandra en utilisant les commandes CQL présentées précédemment.
Il est possible que vous ayez une
Connection errorlors de l’exécution de la commandedocker exec -it cassandra cqlsh. Si c’est le cas, attendez quelques secondes et réessayez la commande. Il faut un peu de temps pour que le conteneur Cassandra soit complètement opérationnel et prêt à accepter les connexions.
Pour ceux qui sont à l’aise avec les notebooks Jupyter, il est également possible d’exécuter des commandes CQL directement dans un notebook en utilisant la bibliothèque
cassandra-driverde Python. Vous pouvez installer cette bibliothèque via pip :pip install cassandra-driverEnsuite, vous pouvez utiliser le code suivant pour vous connecter à la base de données Cassandra et exécuter des commandes CQL :
from cassandra.cluster import Cluster from cassandra.auth import PlainTextAuthProvider # Connexion au cluster cluster = Cluster(contact_points=['127.0.0.1'], port=9042) session = cluster.connect() # Sélectionner le keyspace session.set_keyspace('votre_keyspace') # Replacer par le nom du keyspace print("Connected to Cassandra cluster!") # Requête example rows = session.execute("SELECT * FROM system_schema.keyspaces LIMIT 5;") for row in rows: print(row)
Cas pratique
Objectif
L’objectif de ce TP est de se familiariser avec la base de données Apache Cassandra en réalisant les tâches suivantes :
- Création d’un keyspace et d’une table
- Insertion de données
- Requêtes sur les données
- Suppression de données
- Mise à jour de données
Présentation des données
Dans ce TP, vous allez manipuler une base de données Cassandra destinée à stocker des informations sur les cas médicaux et les patients. Pour cela, nous avons accès à 2 jeux de données : d’une part, les cas médicaux et d’autre part, les patients. Chaque cas médical est associé à un patient et à une pathologie, et est identifié par un identifiant unique.
Cas médicaux
La table cas_medicaux contient les informations des cas médicaux :
| Colonne | Description |
|---|---|
id | Identifiant unique du cas médical |
code_patho | Code de la pathologie |
date_diag | Date du diagnostic |
dept_code | Code du département |
dept_nom | Nom du département |
pathologie | Pathologie diagnostiquée |
patient_date_naissance | Date de naissance du patient |
patient_prenom | Prénom du patient |
patient_sexe | Sexe du patient |
Patients
La table patients contient les informations des patients :
| Colonne | Description |
|---|---|
id | Identifiant unique du patient |
prenom | Prénom du patient |
sexe | Sexe du patient |
date_naissance | Date de naissance du patient |
pathologies | Liste de pathologies du patient |
Requêtage des données
1. Création d’un keyspace
Nous avons créé un keyspace hopital lors de la création de la base de données. Nous allons donc l’utiliser pour stocker nos données. Nous allons maintenant populer ce keyspace avec les données des cas médicaux et des patients.
2. Création du schéma de données
À partir du cours, créez les tables cas_medicaux et patients dans le keyspace hopital avec les colonnes décrites ci-dessus.
Correction
-- Table pour les cas médicaux
DROP TABLE IF EXISTS cas_medicaux;
CREATE TABLE IF NOT EXISTS cas_medicaux (
id TEXT PRIMARY KEY,
date_diag DATE,
pathologie TEXT,
code_patho TEXT,
patient_prenom TEXT,
patient_sexe TEXT,
patient_date_naissance DATE,
dept_code TEXT,
dept_nom TEXT
);
-- Table pour les patients avec leur historique de pathologies
DROP TABLE IF EXISTS patients;
CREATE TABLE IF NOT EXISTS patients (
id TEXT PRIMARY KEY,
prenom TEXT,
sexe TEXT,
date_naissance DATE,
pathologies LIST<FROZEN<MAP<TEXT, TEXT>>>
);
3. Insertion des données
Insérer dans la table cas_medicaux les données du patient 23257.
| id | code_patho | date_diag | dept_code | dept_nom | pathologie | patient_date_naissance | patient_prenom | patient_sexe |
|---|---|---|---|---|---|---|---|---|
| 23257 | addictions | 2021-01-12 | 72 | Sarthe | Troubles addictifs | 1946-08-27 | aaliyah | f |
Correction
INSERT INTO cas_medicaux (id, date_diag, pathologie, code_patho, patient_prenom, patient_sexe, patient_date_naissance, dept_code, dept_nom)
VALUES (
'23257',
'2021-01-12',
'Troubles addictifs',
'addictions',
'aaliyah',
'F',
'1946-08-27',
'72',
'Sarthe'
);
Puis, insérer dans la table patients les données suivantes :
| id | date_naissance | pathologies | prenom | sexe |
|---|---|---|---|---|
| 403 | 1927-02-11 | [{‘date’: ‘2021-08-08’, ‘dept’: ‘09’, ‘intitule’: ‘Maladies inflammatoires chroniques’}, {‘date’: ‘2023-04-11’, ‘dept’: ‘09’, ‘intitule’: ‘Accident vasculaire cérébral’}, {‘date’: ‘2022-07-02’, ‘dept’: ‘09’, ‘intitule’: ‘Maladies métaboliques, héréditaires ou amylose’}] | allison | f |
Correction
INSERT INTO patients (id, prenom, sexe, date_naissance, pathologies)
VALUES (
'403',
'allison',
'f',
'1927-02-11',
[{'intitule': 'Maladies inflammatoires chroniques', 'date': '2021-08-08', 'dept': '09'}, {'intitule': 'Accident vasculaire cérébral', 'date': '2023-04-11', 'dept': '09'}, {'intitule': 'Maladies métaboliques, héréditaires ou amylose', 'date': '2022-07-02', 'dept': '09'}]
);
Une fois les deux requêtes d’insertion effectuées, vous pouvez insérer les données contenues dans le fichier init.cql qui est téléchargeable ici.
4. Requêtes sur les données
1) Afficher les 5 premiers cas médicaux.
2) Afficher les patients ayant les identifiants 408 et 500.
3) Quel est le résultat de la requête suivante ?
SELECT *
FROM cas_medicaux
WHERE pathologie='Diabète';
Est-elle valide ? Si non, que faire pour corriger cette requête ?
4) Mettre à jour la pathologie du patient 23350 pour remplacer Diabète par Diabète de type 2 (champ pathologie).
5) Supprimer les informations concernant le cas médical 23265 (patient Aaren).
6) Comment requêter les patients vivant dans le département de la Sarthe ?
7) Créer une nouvelle table patients_pathologie_dept avec les champs suivants :
| Colonne | Type |
|---|---|
id | TEXT |
prenom | TEXT |
sexe | TEXT |
date_naissance | DATE |
pathologie_nom | TEXT |
pathologie_date | DATE |
dept | TEXT |
Où dept est la clé primaire.
8) Insérer les données des patients ayant des pathologies dans la table patients_pathologie_dept qui sont ici.
Bravo, vous venez de requêter des données de santé stockées dans une base de données Apache Cassandra avec CQL !