Matching Engine Multi-Critères
Algorithme de matching intelligent temps réel entre médecins et annonces médicales basé sur 15+ critères (spécialité, localisation, disponibilités, expérience, contrats)
Stack Technique
Caractéristiques
Scoring multi-dimensionnel 0-100
Algorithme de calcul de compatibilité basé sur 15+ critères pondérés : spécialité (30%), localisation (25%), disponibilités (20%), expérience (15%), contrat (10%). Score ajusté par urgence et préférences candidat.
Population automatique des prospects
Trigger Firebase onCreate qui scanne instantanément la base médecins et génère automatiquement la liste des prospects matchés pour chaque nouvelle annonce. Latence < 2s pour 200+ profils.
Architecture event-driven scalable
Cloud Functions avec PubSub pour traitement asynchrone, batch processing nocturne pour ré-enrichissement global (500 annonces en 8min), gestion des doublons et transactions Firestore optimisées.
Intégration Algolia multi-index
Indexation temps réel des annonces et profils avec 12+ facettes filtrables (spécialité, région, contrat, rémunération, zonage). Recherche géographique avec rayon km. Résultats < 50ms.
Système de sous-collections optimisé
Architecture hybride avec annonces/{id}/prospects (historique) + cliniques/{id}/all_prospects (vue consolidée). Évite la duplication tout en permettant requêtes performantes par clinique.
Monitoring et observabilité
Logs structurés Firebase, métriques de matching (taux de réponse, temps par étape), dashboard analytics avec conversion funnel. Alertes sur anomalies de scoring.
Performance
Exemples de code
1function calculateMatchScore(
2 userData: UserData,
3 annonceData: AnnonceData
4): number {
5 let score = 50; // Score de base
6
7 // 1. Bonus spécialité (30 points max)
8 if (userData.Speciality_string === annonceData.Service) {
9 score += 30;
10 } else if (isRelatedSpecialty(userData.Speciality_string, annonceData.Service)) {
11 score += 15; // Spécialités proches
12 }
13
14 // 2. Bonus expérience (20 points)
15 if (userData.experience && annonceData.experienceRequired) {
16 if (userData.experience >= annonceData.experienceRequired) {
17 score += 20;
18 } else if (userData.experience >= annonceData.experienceRequired * 0.7) {
19 score += 10; // Presque suffisant
20 } else {
21 score -= 10; // Manque d'expérience
22 }
23 }
24
25 // 3. Bonus disponibilité immédiate si urgence (15 points)
26 if (annonceData.urgency === 'urgent' && userData.disponibility === 'immediate') {
27 score += 15;
28 }
29
30 // 4. Bonus RPPS vérifié (15 points)
31 if (userData.RPPS && userData.RPPS.length === 11) {
32 score += 15;
33 }
34
35 // 5. Localisation (calculé séparément par distance)
36 const distanceBonus = calculateDistanceScore(
37 userData.postalCode,
38 annonceData.postalCode
39 );
40 score += distanceBonus; // 0 à 20 points
41
42 return Math.min(100, Math.max(0, score));
43}
44Informations
- Année
- 2024-2025
- Version
- v3
Intéressé par ce projet ?
Discutons de vos besoins et voyons comment nous pouvons vous aider.
Nous contacter