FONDEMENTS DU BIG DATA TRAVAUX
Module 4 — NoSQL en Pratique PRATIQUES
Enseignant : GOUAH Tato
Contact : gouahtato@[Link] Niveau : Debutants | Big Data
Serge
CONTEXTE PROFESSIONNEL
Vous integrez l’equipe data d’une fintech ivoirienne qui gere une plateforme de mobile money concurrente
de Wave et MTN Mobile Money. L’entreprise traite des millions de transactions par mois et a decide de
migrer sa base de donnees clients vers MongoDB, une base NoSQL documentaire.
Votre responsable technique vous confie la mise en place de la base de donnees clients, l’injection des
donnees et la creation des requetes d’analyse. Ces requetes seront ensuite utilisees par les equipes metier
pour piloter l’activite.
OBJECTIFS DU TP
A l’issue de ce travail pratique, vous serez capable de :
• Creer et configurer un cluster MongoDB Atlas gratuit
• Connecter Python a MongoDB via pymongo
• Concevoir un schema de document NoSQL adapte a un cas metier mobile money
• Inserer, lire, modifier et supprimer des documents (operations CRUD)
• Ecrire des pipelines d’agregation pour produire des indicateurs metier
• Comprendre pourquoi NoSQL est adapte aux volumes Big Data transactionnels
OUTILS ET ENVIRONNEMENT
Outil Role dans ce TP Acces
Base de donnees NoSQL dans le cloud
MongoDB Atlas [Link]
(cluster gratuit)
pymongo Driver Python officiel pour MongoDB !pip install pymongo
Environnement d’execution Python
Google Colab [Link]
dans le cloud
Requis pour la connexion MongoDB
dnspython !pip install dnspython
Atlas via SRV
CONTEXTE METIER : BASE CLIENTS MOBILE MONEY
La plateforme stocke des informations sur ses clients et leurs transactions. Contrairement a une base
relationnelle (SQL), MongoDB stocke chaque client dans un document JSON autonome qui peut contenir
toutes ses informations, y compris ses transactions recentes.
Structure d’un document client dans la base :
{
"id_client" : "MMI-00001",
"nom" : "Kouassi Aya",
"telephone" : "+2250707123456",
"region" : "Abidjan",
"type_compte" : "basic",
"solde_fcfa" : 45000,
"kyc_valide" : true,
"date_inscription" : "2022-03-15",
"transactions" : [
{ "type": "depot", "montant": 20000, "date": "2024-01-10", "statut": "succes" },
{ "type": "retrait", "montant": 5000, "date": "2024-01-12", "statut": "succes" },
{ "type": "transfert","montant": 10000, "date": "2024-01-15", "statut": "echoue" }
]
}
DICTIONNAIRE DES CHAMPS
type_compte : basic (plafond 200 000 FCFA) | premium (plafond 2 000 000 FCFA) | merchant
(commercant)
kyc_valide : Know Your Customer — verification d’identite obligatoire (loi ARTCI)
transactions : tableau imbrique — c’est l’avantage majeur de NoSQL vs SQL
statut : succes | echoue | en_attente
PARTIE 1
CONNEXION ET CONFIGURATION
Etape prealable — Creer votre cluster MongoDB Atlas :
• Rendez-vous sur [Link] et creez un compte gratuit
• Creez un cluster en choisissant le plan FREE (M0 Sandbox)
• Selectionnez la region AWS / Europe (Paris) ou AWS / US East
• Dans Database Access, creez un utilisateur avec mot de passe
• Dans Network Access, ajoutez [Link]/0 pour autoriser toutes les IP (Colab)
• Cliquez sur Connect > Connect your application > Python 3.6+ et copiez la chaine de connexion
CHAINE DE CONNEXION
La chaine de connexion ressemble a : mongodb+srv://user:password@[Link]/
1. Installez les librairies pymongo et dnspython dans votre notebook, puis importez-les.
2. Connectez-vous a votre cluster MongoDB Atlas en utilisant votre chaine de connexion. Affichez la
liste des bases de donnees disponibles pour confirmer que la connexion fonctionne.
3. Creez une base de donnees nommee mobile_money_civ et une collection nommee clients. Affichez
le nom de la base active pour confirmer.
PARTIE 2
INSERTION DE DOCUMENTS (CREATE)
4. Inserez un seul document client dans la collection clients. Utilisez la structure definie dans le
contexte metier. Verifiez que l’insertion a reussi en affichant l’identifiant genere (_id).
5. Inserez les 8 clients suivants en une seule operation (insertion multiple) :
Nb
type_com solde_fcf kyc_valid
id_client nom region transactio
pte a e
ns
MMI-00002 Traore Moussa Bouake premium 850 000 true 5
Bamba
MMI-00003 Daloa basic 12 000 false 2
Fatoumata
MMI-00004 Kone Ibrahim Abidjan merchant 1 200 000 true 8
Ouattara
MMI-00005 Korhogo basic 3 500 true 1
Mariam
MMI-00006 Yao Francois San-Pedro premium 420 000 true 6
MMI-00007 Diallo Aminata Abidjan basic 67 000 false 3
MMI-00008 Coulibaly Sekou Man basic 8 900 true 4
MMI-00009 N’Guessan Lea Abidjan merchant 3 400 000 true 12
Chaque client doit avoir au moins 2 transactions imbriqueees dans son document (inventez des donnees
coherentes pour les transactions).
6. Affichez le nombre total de documents dans la collection apres insertion. Combien obtenez-vous ?
PARTIE 3
LECTURE ET FILTRAGE (READ)
7. Affichez tous les clients de la collection. Combien en trouvez-vous ?
8. Affichez uniquement les clients de la region Abidjan.
9. Affichez les clients avec un solde superieur a 100 000 FCFA. Afficher uniquement leurs champs :
id_client, nom, region, solde_fcfa.
10. Affichez les clients qui ne sont PAS encore valides KYC (kyc_valide = false).
11. Affichez le client avec le solde le plus eleve. Quel est son type de compte ?
12. Affichez les clients de type merchant OU premium ayant un solde superieur a 400 000 FCFA.
POURQUOI C’EST IMPORTANT
Les requetes de lecture sont le cœur de votre travail quotidien en Big Data.
En entreprise, ces requetes alimentent des tableaux de bord, des rapports de conformite et des
alertes automatiques.
PARTIE 4
MODIFICATION ET SUPPRESSION (UPDATE / DELETE)
13. Le client MMI-00003 (Bamba Fatoumata) a effectue sa verification d’identite. Mettez a jour son
champ kyc_valide a true. Verifiez la modification en relisant son document.
14. L’operateur credite 5 000 FCFA sur le compte de tous les clients basic. Mettez a jour le solde de
TOUS les clients basic en une seule operation.
15. Ajoutez un nouveau champ derniere_activite avec la valeur '2024-01-20' a tous les documents de la
collection. Verifiez qu’il apparait bien sur un document.
16. Le client MMI-00007 (Diallo Aminata) a clos son compte. Supprimez son document de la collection.
Verifiez que la collection contient bien 8 documents apres suppression.
PARTIE 5
AGREGATIONS ET INDICATEURS METIER
Votre responsable vous demande les indicateurs suivants pour le comite de direction. Utilisez le pipeline
d’agregation MongoDB.
17. Calculez le nombre de clients et le solde moyen par type de compte (basic, premium, merchant).
Quel type de compte a le solde moyen le plus eleve ?
18. Calculez le solde total de tous les clients par region. Quelle region concentre le plus de liquidites ?
19. Identifiez les 3 clients ayant les soldes les plus eleves. Affichez leur nom, region et solde.
20. Calculez le pourcentage de clients avec KYC valide sur l’ensemble de la collection.
21. Dans les transactions imbriqueees, comptez le nombre total de transactions par statut (succes,
echoue, en_attente) sur l’ensemble de la collection. Utilisez $unwind et $group.
OPERATEURS D’AGREGATION UTILES
$match : filtrer des documents (equivalent du WHERE en SQL)
$group : regrouper et calculer des agregats (equivalent du GROUP BY)
$sort : trier les resultats
$limit : limiter le nombre de resultats
$unwind : decomposer un tableau imbrique en documents individuels
$project: selectionner / renommer les champs a afficher
PARTIE 6
INDEXATION ET RAPPORT FINAL
22. Creez un index sur le champ region pour accelerer les requetes geographiques. Affichez la liste des
index de la collection clients.
23. Creez un index unique sur le champ telephone pour garantir qu’aucun numero ne peut etre inscrit
deux fois (contrainte metier critique en mobile money).
24. Tentez d’inserer un client avec le meme numero de telephone qu’un client existant. Que se passe-t-il
? Quel message d’erreur obtenez-vous ?
25. Redigez une cellule Markdown dans votre notebook resumant : le schema de document choisi et
pourquoi MongoDB est adapte au mobile money, les 3 indicateurs metier les plus importants tires de
vos agregations, et une limite ou risque que vous identifiez dans ce systeme.
LIVRABLES A REMETTRE
# Livrable Contenu attendu
Notebook complet avec code + resultats executes +
1 TP_Module4_VotreNom.ipynb
cellule Markdown
Capture d’ecran de votre collection dans l’interface
2 Capture_Atlas.png
MongoDB Atlas
3 Rapport Markdown (dans le notebook) Schema justifie + indicateurs metier + limite identifiee
CORRECTION — ELEMENTS DE REPONSE
ATTENTION — Document reserve a l’enseignant
Des approches alternatives produisant des resultats corrects et commentes sont acceptees.
PARTIE 1 — CONNEXION ET CONFIGURATION
Q1 Installation, connexion et creation de la base
-2-
3
# Q1 — Installation
!pip install pymongo dnspython -q
import pymongo
from pymongo import MongoClient
from datetime import datetime
print(f'pymongo version : {pymongo.__version__}')
# Q2 — Connexion a MongoDB Atlas
# Remplacez par votre propre chaine de connexion
MONGO_URI = 'mongodb+srv://user:password@[Link]/'
client = MongoClient(MONGO_URI)
# Verification : lister les bases disponibles
print('Bases disponibles :', client.list_database_names())
# Q3 — Creation de la base et de la collection
db = client['mobile_money_civ']
collection = db['clients']
print('Base active :', [Link])
RESULTAT ATTENDU
En MongoDB, la base et la collection sont creees automatiquement au premier insert.
list_database_names() ne montre pas la base tant qu’elle est vide : c’est normal.
Attendu apres connexion : ['admin', 'local'] ou les bases deja existantes sur votre cluster.
PARTIE 2 — INSERTION DE DOCUMENTS
Q4 Insertion d’un seul document
# Q4 — Insertion d’un document unique
client_1 = {
"id_client" : "MMI-00001",
"nom" : "Kouassi Aya",
"telephone" : "+2250707123456",
"region" : "Abidjan",
"type_compte" : "basic",
"solde_fcfa" : 45000,
"kyc_valide" : True,
"date_inscription" : "2022-03-15",
"transactions" : [
{"type": "depot", "montant": 20000, "date": "2024-01-10", "statut": "succes"},
{"type": "retrait", "montant": 5000, "date": "2024-01-12", "statut": "succes"},
{"type": "transfert","montant": 10000, "date": "2024-01-15", "statut": "echoue"}
]
}
resultat = collection.insert_one(client_1)
print(f'Document insere, _id : {resultat.inserted_id}')
Q5 Insertion multiple (8 clients)
# Q5 — Insertion de plusieurs documents en une seule operation
clients_batch = [
{"id_client":"MMI-00002","nom":"Traore Moussa","telephone":"+2250101000002",
"region":"Bouake","type_compte":"premium","solde_fcfa":850000,"kyc_valide":True,
"date_inscription":"2021-06-10",
"transactions":[
{"type":"depot","montant":500000,"date":"2024-01-05","statut":"succes"},
{"type":"retrait","montant":50000,"date":"2024-01-08","statut":"succes"},
{"type":"transfert","montant":100000,"date":"2024-01-12","statut":"succes"},
{"type":"depot","montant":200000,"date":"2024-01-14","statut":"succes"},
{"type":"retrait","montant":20000,"date":"2024-01-18","statut":"echoue"}
]},
{"id_client":"MMI-00003","nom":"Bamba Fatoumata","telephone":"+2250101000003",
"region":"Daloa","type_compte":"basic","solde_fcfa":12000,"kyc_valide":False,
"date_inscription":"2023-11-02",
"transactions":[
{"type":"depot","montant":15000,"date":"2024-01-03","statut":"succes"},
{"type":"retrait","montant":3000,"date":"2024-01-09","statut":"succes"}
]},
{"id_client":"MMI-00004","nom":"Kone Ibrahim","telephone":"+2250101000004",
"region":"Abidjan","type_compte":"merchant","solde_fcfa":1200000,"kyc_valide":True,
"date_inscription":"2020-02-20",
"transactions":[
{"type":"depot","montant":800000,"date":"2024-01-02","statut":"succes"},
{"type":"transfert","montant":200000,"date":"2024-01-05","statut":"succes"},
{"type":"depot","montant":400000,"date":"2024-01-10","statut":"succes"},
{"type":"retrait","montant":100000,"date":"2024-01-13","statut":"succes"},
{"type":"transfert","montant":50000,"date":"2024-01-15","statut":"echoue"},
{"type":"depot","montant":600000,"date":"2024-01-17","statut":"succes"},
{"type":"retrait","montant":80000,"date":"2024-01-19","statut":"succes"},
{"type":"depot","montant":300000,"date":"2024-01-20","statut":"succes"}
]},
{"id_client":"MMI-00005","nom":"Ouattara Mariam","telephone":"+2250101000005",
"region":"Korhogo","type_compte":"basic","solde_fcfa":3500,"kyc_valide":True,
"date_inscription":"2023-08-14",
"transactions":[
{"type":"depot","montant":5000,"date":"2024-01-07","statut":"succes"},
{"type":"retrait","montant":1500,"date":"2024-01-11","statut":"succes"}
]},
{"id_client":"MMI-00006","nom":"Yao Francois","telephone":"+2250101000006",
"region":"San-Pedro","type_compte":"premium","solde_fcfa":420000,"kyc_valide":True,
"date_inscription":"2021-09-30",
"transactions":[
{"type":"depot","montant":200000,"date":"2024-01-04","statut":"succes"},
{"type":"transfert","montant":80000,"date":"2024-01-06","statut":"succes"},
{"type":"depot","montant":150000,"date":"2024-01-09","statut":"succes"},
{"type":"retrait","montant":30000,"date":"2024-01-13","statut":"succes"},
{"type":"transfert","montant":20000,"date":"2024-01-16","statut":"echoue"},
{"type":"depot","montant":100000,"date":"2024-01-19","statut":"succes"}
]},
{"id_client":"MMI-00007","nom":"Diallo Aminata","telephone":"+2250101000007",
"region":"Abidjan","type_compte":"basic","solde_fcfa":67000,"kyc_valide":False,
"date_inscription":"2023-05-22",
"transactions":[
{"type":"depot","montant":80000,"date":"2024-01-06","statut":"succes"},
{"type":"retrait","montant":10000,"date":"2024-01-10","statut":"succes"},
{"type":"transfert","montant":3000,"date":"2024-01-14","statut":"echoue"}
]},
{"id_client":"MMI-00008","nom":"Coulibaly Sekou","telephone":"+2250101000008",
"region":"Man","type_compte":"basic","solde_fcfa":8900,"kyc_valide":True,
"date_inscription":"2022-12-01",
"transactions":[
{"type":"depot","montant":10000,"date":"2024-01-03","statut":"succes"},
{"type":"retrait","montant":500,"date":"2024-01-07","statut":"succes"},
{"type":"depot","montant":5000,"date":"2024-01-12","statut":"succes"},
{"type":"transfert","montant":4600,"date":"2024-01-16","statut":"echoue"}
]},
{"id_client":"MMI-00009","nom":"N'Guessan Lea","telephone":"+2250101000009",
"region":"Abidjan","type_compte":"merchant","solde_fcfa":3400000,"kyc_valide":True,
"date_inscription":"2019-11-15",
"transactions":[
{"type":"depot","montant":1000000,"date":"2024-01-01","statut":"succes"},
{"type":"transfert","montant":500000,"date":"2024-01-03","statut":"succes"},
{"type":"depot","montant":800000,"date":"2024-01-06","statut":"succes"},
{"type":"retrait","montant":200000,"date":"2024-01-08","statut":"succes"},
{"type":"depot","montant":600000,"date":"2024-01-10","statut":"succes"},
{"type":"transfert","montant":300000,"date":"2024-01-12","statut":"succes"},
{"type":"depot","montant":400000,"date":"2024-01-14","statut":"succes"},
{"type":"retrait","montant":100000,"date":"2024-01-16","statut":"succes"},
{"type":"depot","montant":700000,"date":"2024-01-18","statut":"succes"},
{"type":"transfert","montant":250000,"date":"2024-01-19","statut":"echoue"},
{"type":"depot","montant":500000,"date":"2024-01-20","statut":"succes"},
{"type":"retrait","montant":150000,"date":"2024-01-21","statut":"succes"}
]},
]
resultat = collection.insert_many(clients_batch)
print(f'Documents inseres : {len(resultat.inserted_ids)}')
Q6 Compter les documents
# Q6 — Compter le total de documents
total = collection.count_documents({})
print(f'Nombre de documents dans la collection : {total}') # attendu : 9
PARTIE 3 — LECTURE ET FILTRAGE
Q7 Requetes de lecture
-12
# Q7 — Tous les clients
for doc in [Link]():
print(doc['id_client'], doc['nom'], doc['region'])
# Q8 — Clients d'Abidjan
for doc in [Link]({'region': 'Abidjan'}):
print(doc['id_client'], doc['nom'])
# Attendu : MMI-00001, MMI-00004, MMI-00007, MMI-00009
# Q9 — Solde > 100 000 FCFA, champs selectionnes
projection = {'_id':0, 'id_client':1, 'nom':1, 'region':1, 'solde_fcfa':1}
for doc in [Link]({'solde_fcfa': {'$gt': 100000}}, projection):
print(doc)
# Attendu : MMI-00002, MMI-00004, MMI-00006, MMI-00009
# Q10 — KYC non valide
for doc in [Link]({'kyc_valide': False}):
print(doc['id_client'], doc['nom'], '| KYC:', doc['kyc_valide'])
# Attendu : MMI-00003, MMI-00007 (avant la mise a jour Q13)
# Q11 — Client avec le solde le plus eleve
top = collection.find_one({}, sort=[('solde_fcfa', -1)])
print(f"Solde max : {top['nom']} | {top['solde_fcfa']:,} FCFA | type :
{top['type_compte']}")
# Attendu : N'Guessan Lea | 3 400 000 FCFA | merchant
# Q12 — merchant OU premium avec solde > 400 000
filtre = {
'$or': [
{'type_compte': 'merchant'},
{'type_compte': 'premium'}
],
'solde_fcfa': {'$gt': 400000}
}
for doc in [Link](filtre,
{'_id':0,'id_client':1,'nom':1,'type_compte':1,'solde_fcfa':1}):
print(doc)
# Attendu : MMI-00002 (850 000), MMI-00004 (1 200 000), MMI-00009 (3 400 000)
PARTIE 4 — MODIFICATION ET SUPPRESSION
Q1 Operations Update et Delete
3-
16
# Q13 — Mise a jour KYC d'un client specifique
collection.update_one(
{'id_client': 'MMI-00003'},
{'$set': {'kyc_valide': True}}
)
doc = collection.find_one({'id_client': 'MMI-00003'})
print(f"KYC MMI-00003 : {doc['kyc_valide']}") # attendu : True
# Q14 — Credit de 5 000 FCFA sur tous les comptes basic
resultat = collection.update_many(
{'type_compte': 'basic'},
{'$inc': {'solde_fcfa': 5000}}
)
print(f'Documents modifies : {resultat.modified_count}') # attendu : 5
# Q15 — Ajout d'un nouveau champ sur tous les documents
collection.update_many(
{},
{'$set': {'derniere_activite': '2024-01-20'}}
)
doc = collection.find_one({'id_client': 'MMI-00001'})
print(f"Derniere activite : {doc['derniere_activite']}")
# Q16 — Suppression d'un document
collection.delete_one({'id_client': 'MMI-00007'})
total = collection.count_documents({})
print(f'Documents restants : {total}') # attendu : 8
OPERATEURS DE MODIFICATION
update_one : modifie le PREMIER document correspondant au filtre.
update_many : modifie TOUS les documents correspondants.
$set : modifie ou ajoute un champ.
$inc : incremente une valeur numerique (essentiel pour les soldes).
delete_one : supprime le premier document correspondant au filtre.
PARTIE 5 — AGREGATIONS ET INDICATEURS METIER
Q1 Nombre de clients et solde moyen par type de compte
7
pipeline = [
{'$group': {
'_id' : '$type_compte',
'nb_clients' : {'$sum': 1},
'solde_moyen' : {'$avg': '$solde_fcfa'},
'solde_total' : {'$sum': '$solde_fcfa'}
}},
{'$sort': {'solde_moyen': -1}}
]
for r in [Link](pipeline):
print(f"{r['_id']:10} | Clients: {r['nb_clients']} | Solde moy:
{r['solde_moyen']:>12,.0f} FCFA")
# merchant a le solde moyen le plus eleve (commerce genere plus de flux)
Q1 Solde total par region
8
pipeline = [
{'$group': {
'_id' : '$region',
'solde_total' : {'$sum': '$solde_fcfa'},
'nb_clients' : {'$sum': 1}
}},
{'$sort': {'solde_total': -1}}
]
for r in [Link](pipeline):
print(f"{r['_id']:12} | {r['solde_total']:>12,.0f} FCFA | {r['nb_clients']} clients")
# Abidjan concentre la majorite des liquidites (merchants + clients premium)
Q1 Top 3 clients par solde
9
pipeline = [
{'$sort' : {'solde_fcfa': -1}},
{'$limit' : 3},
{'$project': {'_id':0,'nom':1,'region':1,'solde_fcfa':1,'type_compte':1}}
]
for r in [Link](pipeline):
print(r)
Q2 Pourcentage de clients KYC valide
0
pipeline = [
{'$group': {
'_id' : '$kyc_valide',
'count' : {'$sum': 1}
}}
]
resultats = list([Link](pipeline))
total = sum(r['count'] for r in resultats)
for r in resultats:
statut = 'KYC valide' if r['_id'] else 'KYC non valide'
pct = r['count'] / total * 100
print(f'{statut} : {r["count"]} clients ({pct:.1f}%)')
# Apres la mise a jour Q13 : 8/8 valides = 100%
Q2 Transactions par statut avec $unwind
1
pipeline = [
{'$unwind' : '$transactions'},
{'$group' : {
'_id' : '$[Link]',
'total' : {'$sum': 1},
'montant_total': {'$sum': '$[Link]'}
}},
{'$sort': {'total': -1}}
]
for r in [Link](pipeline):
print(f"Statut: {r['_id']:12} | Nb: {r['total']:>3} | Montant:
{r['montant_total']:>12,.0f} FCFA")
COMPRENDRE $unwind
$unwind '$transactions' : decompose le tableau transactions de chaque client
en autant de documents individuels. Un client avec 5 transactions donne 5 documents.
Sans $unwind, impossible d’agreger sur les champs du tableau imbrique.
C’est l’operation la plus puissante et la plus specifique a MongoDB.
PARTIE 6 — INDEXATION ET RAPPORT FINAL
Q2 Index et gestion des contraintes
2-
24
# Q22 — Index sur le champ region
collection.create_index('region')
print('Index crees :')
for idx in collection.list_indexes():
print(' -', idx['name'], '|', idx['key'])
# Q23 — Index unique sur telephone
collection.create_index('telephone', unique=True)
print('Index unique sur telephone cree.')
# Q24 — Tentative d'insertion avec telephone duplique
try:
collection.insert_one({
'id_client' : 'MMI-99999',
'nom' : 'Test Doublon',
'telephone' : '+2250707123456', # numero deja utilise par MMI-00001
'region' : 'Abidjan',
'type_compte': 'basic',
'solde_fcfa' : 0,
'kyc_valide' : False
})
except Exception as e:
print(f'ERREUR attendue : {type(e).__name__}')
print(f'Message : E11000 duplicate key error - telephone deja existant')
POURQUOI LES INDEX SONT CRITIQUES EN BIG DATA
L’erreur E11000 DuplicateKeyError est generee automatiquement par MongoDB.
C’est une protection critique en mobile money : un seul compte par numero de telephone.
Les index accelerent aussi les requetes : sur 10 millions de documents,
une requete sans index scanne TOUT. Avec index : acces direct en millisecondes.
Q2 Rapport Markdown attendu
5
## Rapport de synthese — Base MongoDB Mobile Money CIV
### 1. Choix du schema NoSQL
Les transactions sont **imbriqueees dans le document client** (modele embarque).
Ce choix est adapte car :
- 1 requete suffit pour obtenir un client ET ses transactions (pas de JOIN)
- Les transactions sont toujours consultees avec leur client
- Volume de transactions par client reste raisonnable (< 100/mois)
### 2. Indicateurs metier cles
- **Abidjan concentre ~80% des liquidites** : priorite pour les agents de recharge
- **Les merchants ont le solde moyen le plus eleve** : segment a fideliser
- **~15% de transactions echouees** : signal d’alerte pour la qualite du reseau
### 3. Limite identifiee
Si un client a des milliers de transactions, le document devient trop volumineux.
Limite MongoDB : 16 Mo par document. Solution : collection separee pour transactions.
GOUAH Tato Serge — gouahtato@[Link] — +225 07 78 43 83 04