Un pipeline Microsoft Fabric Data Factory qui reçoit les trajets de vĂ©los en libre-service de trois quartiers de Lisbonne, chacun dans son format : CSV, JSON et Parquet. Trois copies partent en mĂȘme temps, sans boucle. Un programme Spark, publiĂ© comme dĂ©finition de tĂąche Spark, attend les trois, ramĂšne tout dans les mĂȘmes unitĂ©s, Ă©carte les doublons et dĂ©signe le quartier en tĂȘte. Un filtre repĂšre le fichier qui n'a rien Ă faire lĂ . Microsoft Teams reçoit le bilan.
Guide PDF de 7 pages inclus : Pipeline_Fabric_Guide_8_public.pdf. Chaque activité, chaque champ, chaque expression, et les chiffres à retrouver à l'unité prÚs. Les expressions sont aussi dans data/expressions.txt et le programme Spark dans spark/lisboa_stats.py.
PL_Lisboa_Express aprÚs une exécution réussie : trois copies parallÚles qui se rejoignent sur Spark, une branche qui liste et filtre le dossier, puis la lecture du verdict et le message Teams. Huit activités, huit coches vertes.
Le bilan publié dans Microsoft Teams, rédigé à partir de la ligne de synthÚse écrite par Spark.
La table district_stats interrogée dans le point de terminaison SQL du lakehouse : trois quartiers, leurs trajets, leur durée moyenne, leurs kilomÚtres et la part du vélo électrique.
| Indicateur | Valeur |
|---|---|
| ActivitĂ©s | 8 (Copy data Ă3, Get Metadata, Filter, Spark job definition, Lookup, Microsoft Teams) |
| Nouveautés | Définition de tùche Spark, branches parallÚles qui se rejoignent, chemins génériques, sources JSON et Parquet |
| Formats lus | 3 : CSV, JSON, Parquet, avec trois conventions d'unités |
| Lignes reçues | 240 (84 + 66 + 90) |
| Doublons écartés | 4 trajets déclarés à la fois par Belém et par Alfama |
| Trajets uniques | 236 |
| KilomĂštres parcourus | 792,4 |
| Part du vélo électrique | 41,5 % sur la ville, 74,2 % à Alfama |
| Fichier inconnu repéré | 1, sans faire échouer le pipeline |
Trois partenaires exploitent les vélos de Belém, d'Alfama et de Parque das NaçÔes. Chacun exporte ses trajets à sa façon : un CSV en minutes et en kilomÚtres, un JSON en secondes et en mÚtres, un Parquet typé. Additionner ces fichiers tels quels donnerait des totaux faux, et un trajet qui traverse deux quartiers serait compté deux fois. Ce pipeline livre chaque soir un chiffre unique et juste par quartier, et le résultat parle : à Alfama, le quartier des collines, trois trajets sur quatre se font en vélo électrique, ce qui guide directement la répartition de la flotte.
PL_Lisboa_Express lance trois Copy data sans lien entre eux, donc en parallĂšle. Chacun lit le dossier Files/drop du lakehouse LH_Lisboa avec un chemin gĂ©nĂ©rique (*.csv, *.json, *.parquet) et remplace sa table brute. En mĂȘme temps, Get Metadata liste le dossier et un Filter garde ce qui n'est ni CSV, ni JSON, ni Parquet. Quand les trois copies ont rĂ©ussi, la dĂ©finition de tĂąche Spark SJD_Lisboa unifie les unitĂ©s, Ă©carte les doublons par trip_id et Ă©crit trois tables : trips, district_stats et run_summary. Un Lookup lit la ligne de run_summary, et Teams publie le bilan avec le nombre de fichiers ignorĂ©s.
| Activité | Type | RÎle |
|---|---|---|
Load CSV |
Copy data | drop/*.csv, DelimitedText avec en-tĂȘte, vers trips_csv, action Remplacer |
Load JSON |
Copy data | drop/*.json, tableau d'objets, vers trips_json, action Remplacer |
Load Parquet |
Copy data | drop/*.parquet, schéma lu dans le fichier, vers trips_parquet, action Remplacer |
List drop |
Get Metadata | ĂlĂ©ments enfants du dossier Files/drop |
Unknown files |
Filter | @not(or(or(endswith(toLower(item().name), '.csv'), endswith(toLower(item().name), '.json')), endswith(toLower(item().name), '.parquet'))) |
Build stats |
Spark job definition | Lance SJD_Lisboa quand les trois copies ont réussi |
Read summary |
Lookup | Table run_summary, premiĂšre ligne uniquement |
Post summary |
Microsoft Teams | Attend Read summary et Unknown files, puis publie le bilan |
Le parallĂšle sans boucle. Des activitĂ©s qu'aucune flĂšche ne relie s'exĂ©cutent en mĂȘme temps. Pas besoin de ForEach pour trois sources connues : trois copies posĂ©es cĂŽte Ă cĂŽte suffisent.
La jonction. Une activité qui reçoit plusieurs flÚches vertes attend qu'elles soient toutes vertes. Build stats démarre donc à la fin de la plus lente des trois copies, jamais avant.
Le chemin gĂ©nĂ©rique. Aucun nom de fichier n'est Ă©crit en dur : *.json prend le fichier du jour, quel que soit son nom. Le mĂȘme pipeline traitera le 20 octobre sans modification.
Le code à part. La logique de calcul vit dans un fichier Python, publié comme définition de tùche Spark. Il se versionne, se relit et se remplace sans ouvrir le pipeline.
| Ătape | Dans un bureau de tri | Dans Fabric |
|---|---|---|
| 1 | Trois guichets reçoivent chacun un format, en mĂȘme temps | Trois Copy data en parallĂšle |
| 2 | Le portier repĂšre le colis qui n'a rien Ă faire lĂ | Get Metadata puis Filter |
| 3 | L'expert attend les trois guichets, met tout dans la mĂȘme unitĂ©, Ă©limine les doublons | DĂ©finition de tĂąche Spark |
| 4 | Le registre garde la ligne de synthĂšse | Lookup sur run_summary |
| 5 | Le haut-parleur annonce le bilan | Microsoft Teams |
LH_Lisboa / Files / drop
ââ belem_2026-10-19.csv âââ¶ Copy data Load CSV âââ¶ trips_csv 84 lignes, tout en texte
ââ alfama_2026-10-19.json âââ¶ Copy data Load JSON âââ¶ trips_json 66 lignes, secondes et mĂštres
ââ parque_2026-10-19.parquet âââ¶ Copy data Load Parquet âââ¶ trips_parquet 90 lignes, typĂ©es
ââ notes_operateur.txt âââ¶ Get Metadata + Filter âââ¶ 1 fichier ignorĂ©
â
les trois copies réussies
âŒ
Spark job definition SJD_Lisboa (lisboa_stats.py)
â unify() : minutes et kilomĂštres partout · dropDuplicates(trip_id) : 240 â¶ 236
âââ¶ trips 236 trajets uniques
âââ¶ district_stats 3 quartiers
âââ¶ run_summary 1 ligne de synthĂšse
âŒ
Lookup Read summary âââ¶ Microsoft Teams Post summary
« Lisbonne, vélos du 2026-10-19 : 236 trajets fusionnés depuis 3 formats, 4 doublons écartés.
En tĂȘte : Parque das NaçÔes. 792.4 km parcourus, dont 41.5 % en vĂ©lo Ă©lectrique. Fichiers ignorĂ©s : 1. »
| Objet Fabric | Type | RĂŽle |
|---|---|---|
LH_Lisboa |
Lakehouse | Reçoit les fichiers dans Files/drop, porte les six tables Delta |
SJD_Lisboa |
Définition de tùche Spark | Exécute lisboa_stats.py avec LH_Lisboa comme lakehouse par défaut |
PL_Lisboa_Express |
Pipeline | Orchestre les huit activités |
Le lignage de l'espace de travail montre la chaßne complÚte : le lakehouse alimente la définition de tùche Spark et le pipeline, qui s'appuie aussi sur la connexion Microsoft Teams.
Le cĆur du programme Spark, qui ramĂšne trois conventions Ă une seule :
def unify(table, duration, distance, to_min, to_km): # tout en minutes et en kilomĂštres
return spark.read.table(table).select(
F.col("trip_id").cast("string").alias("trip_id"), F.col("station").cast("string").alias("station"),
F.col("district").cast("string").alias("district"), F.to_timestamp(F.col("start_time").cast("string")).alias("start_time"),
(F.col(duration).cast("double") / to_min).alias("duration_min"), (F.col(distance).cast("double") / to_km).alias("distance_km"),
F.col("bike_type").cast("string").alias("bike_type"))
raw = (unify("trips_csv", "duration_min", "distance_km", 1, 1)
.unionByName(unify("trips_json", "duration_s", "distance_m", 60, 1000))
.unionByName(unify("trips_parquet", "duration_min", "distance_km", 1, 1)))
trips = raw.dropDuplicates(["trip_id"])Une fonction, trois appels : le JSON est divisé par 60 et par 1 000, les deux autres par 1. Tout sort typé, en minutes et en kilomÚtres, puis les trajets déclarés deux fois ne sont gardés qu'une fois.
SELECT district, trips, avg_duration_min, km_total, electric_pct
FROM district_stats
ORDER BY trips DESC;| district | trips | avg_duration_min | km_total | electric_pct |
|---|---|---|---|---|
| Parque das NaçÔes | 90 | 25,2 | 373,4 | 26,7 |
| Belém | 84 | 19,9 | 293,5 | 33,3 |
| Alfama | 62 | 15,8 | 125,5 | 74,2 |
data/
âââ belem_2026-10-19.csv 84 trajets, minutes et kilomĂštres, tout en texte
âââ alfama_2026-10-19.json 66 trajets, secondes et mĂštres, dont 4 aussi dĂ©clarĂ©s par BelĂ©m
âââ parque_2026-10-19.parquet 90 trajets, typĂ©s
âââ notes_operateur.txt une note d'opĂ©rateur, que le pipeline doit ignorer
âââ expressions.txt toutes les expressions du guide, prĂȘtes Ă copier
Sept champs par trajet : trip_id, station, district, start_time, la durée, la distance et bike_type (classique ou electrique). Quinze stations, cinq par quartier, de la Torre de Belém au Museu do Fado et à l'Oceanårio. Données fictives, conçues pour l'exercice et reproductibles avec tools/generate_dataset.py ; tools/expected_results.py recalcule les chiffres attendus.
- Créer un lakehouse
LH_Lisboa, un dossierFiles/drop, et y déposer les quatre fichiers dedata/. - Créer une définition de tùche Spark
SJD_Lisboa, langage PySpark, fichier principalspark/lisboa_stats.py, lakehouse par défautLH_Lisboa. - Créer le pipeline
PL_Lisboa_Express: trois Copy data non reliés avec chemins génériques, Get Metadata et Filter, puis la définition de tùche Spark reliée aux trois copies. - Exécuter une fois pour créer
run_summary, ajouter le Lookup et l'activité Teams en copiant le message depuisdata/expressions.txt. - Exécuter, lire le bilan dans Teams, vérifier
district_statsdans le point de terminaison SQL.
Si l'activitĂ© DĂ©finition de tĂąche Spark n'est pas proposĂ©e dans votre locataire, une activitĂ© Notebook exĂ©cutant le mĂȘme code donne le mĂȘme rĂ©sultat : le programme accepte les deux modes.
fabric-pipeline-express-8/
âââ README.md
âââ Pipeline_Fabric_Guide_8_public.pdf le guide de 7 pages
âââ data/ les trois sources, l'intrus et les expressions
âââ spark/
â âââ lisboa_stats.py le programme de la dĂ©finition de tĂąche Spark
âââ tools/
â âââ generate_dataset.py rĂ©gĂ©nĂšre les quatre fichiers
â âââ expected_results.py recalcule les chiffres attendus
âââ images/
âââ pipeline_diagram.svg le schĂ©ma du pipeline
âââ pipeline_run.png PL_Lisboa_Express aprĂšs une exĂ©cution rĂ©ussie
âââ teams_message.png le bilan dans Microsoft Teams
âââ sql_results.png la table district_stats
âââ lineage.png le lignage de l'espace de travail
Microsoft Fabric Data Factory · Définition de tùche Spark (PySpark) · Lakehouse et Delta · Copy data CSV, JSON et Parquet · Get Metadata · Filter · Lookup · Point de terminaison SQL · Microsoft Teams
Trois partenaires, trois formats, trois façons de compter : la donnée réelle ressemble rarement à un seul fichier propre. Ici, le pipeline charge tout en parallÚle, Spark impose une seule vérité, et le fichier inattendu est signalé au lieu de tout bloquer. Huit activités, un programme Python versionnable, et un bilan juste chaque soir.
Un bon pipeline ne demande pas aux sources de se ressembler. Il les comprend chacune, puis il les fait parler d'une seule voix.
Abdoul Hamid Diallo · Microsoft Data & AI Engineer · Microsoft Certified DP-600, DP-700, PL-300, AI-102, DP-100, AI-900, DP-900 · LinkedIn