{"id":6796,"date":"2026-10-14T18:02:11","date_gmt":"2026-10-14T18:02:11","guid":{"rendered":"http:\/\/french.arabpsychology.com\/statistics\/mongodb-comment-compter-valeurs-distinctes-champ\/"},"modified":"2026-10-14T18:02:11","modified_gmt":"2026-10-14T18:02:11","slug":"mongodb-comment-compter-valeurs-distinctes-champ","status":"publish","type":"psych_stat","link":"https:\/\/french.arabpsychology.com\/?psych_stat=mongodb-comment-compter-valeurs-distinctes-champ","title":{"rendered":"MongoDB : Comment compter les valeurs distinctes dans un champ"},"content":{"rendered":"<p>Dans l&rsquo;\u00e9cosyst\u00e8me moderne de la gestion des donn\u00e9es massives, le mod\u00e8le relationnel traditionnel, fond\u00e9 sur les principes stricts d&rsquo;int\u00e9grit\u00e9 r\u00e9f\u00e9rentielle et les formes normales de Codd, a c\u00e9d\u00e9 une part consid\u00e9rable de son h\u00e9g\u00e9monie aux architectures orient\u00e9es documents. Parmi ces technologies, <a rel=\"noopener noreferrer\" href=\"https:\/\/www.mongodb.com\/docs\/\">MongoDB<\/a> s&rsquo;est impos\u00e9 comme une r\u00e9f\u00e9rence pr\u00e9pond\u00e9rante, conf\u00e9rant aux concepteurs d&rsquo;applications une flexibilit\u00e9 structurelle sans pr\u00e9c\u00e9dent gr\u00e2ce \u00e0 son sch\u00e9ma dynamique et \u00e0 sa s\u00e9rialisation au format BSON (<em>Binary JSON<\/em>). N\u00e9anmoins, cette libert\u00e9 m\u00e9thodologique s&rsquo;accompagne d&rsquo;un d\u00e9fi algorithmique de taille : le traitement et l&rsquo;analyse computationnelle de la cardinalit\u00e9 au sein de collections massives. L&rsquo;\u00e9valuation du nombre de valeurs distinctes contenues dans un champ sp\u00e9cifique repr\u00e9sente l&rsquo;un des probl\u00e8mes fondamentaux de l&rsquo;ing\u00e9nierie des donn\u00e9es, dont la complexit\u00e9 s&rsquo;accro\u00eet exponentiellement \u00e0 mesure que les volumes de stockage atteignent des t\u00e9raoctets ou des p\u00e9taoctets.<\/p>\n<p>Le d\u00e9nombrement des valeurs uniques, bien qu&rsquo;apparemment \u00e9l\u00e9mentaire en termes de formulation logique, mobilise des concepts profonds li\u00e9s \u00e0 la th\u00e9orie des ensembles, \u00e0 l&rsquo;organisation des structures d&rsquo;index en arbre B (B-Tree), ainsi qu&rsquo;\u00e0 la gestion thermique de la m\u00e9moire vive au sein du moteur de stockage <a rel=\"noopener noreferrer\" href=\"https:\/\/source.wiredtiger.com\/\">WiredTiger<\/a>. Contrairement \u00e0 une instruction relationnelle standardis\u00e9e de type <em>SELECT COUNT(DISTINCT field) FROM table<\/em>, MongoDB propose une multiplicit\u00e9 de voies d&rsquo;acc\u00e8s programmatiques et d\u00e9claratives pour r\u00e9soudre cette interrogation. Ces alternatives oscillent entre la simplicit\u00e9 syntaxique d&rsquo;une commande d&rsquo;assistance native et la puissance architecturale du cadriciel d&rsquo;agr\u00e9gation (<em>Aggregation Pipeline<\/em>), imposant aux ing\u00e9nieurs et aux architectes de donn\u00e9es un arbitrage rigoureux entre temps d&rsquo;ex\u00e9cution, consommation de bande passante et sollicitation des ressources computationnelles c\u00f4t\u00e9 serveur.<\/p>\n<p>Cet article propose une exploration exhaustive, th\u00e9orique et appliqu\u00e9e, des m\u00e9canismes permettant d&rsquo;identifier et de comptabiliser les valeurs distinctes dans un champ au sein d&rsquo;une base de donn\u00e9es MongoDB. \u00c0 travers une analyse comparative des primitives disponibles, des contraintes intrins\u00e8ques au format BSON et des strat\u00e9gies d&rsquo;indexation couvrante, nous mettrons en lumi\u00e8re les meilleures pratiques d&rsquo;ing\u00e9nierie logicielle pour garantir l&rsquo;exactitude des calculs statistiques tout en maintenant la r\u00e9silience et la scalabilit\u00e9 horizontale des syst\u00e8mes distribu\u00e9s en environnement de production critique.<\/p>\n<h2>1. Introduction th\u00e9orique \u00e0 la cardinalit\u00e9 et \u00e0 l&rsquo;unicit\u00e9 des donn\u00e9es dans MongoDB<\/h2>\n<h3>1.1 Fondements de l&rsquo;unicit\u00e9 dans les bases de donn\u00e9es orient\u00e9es documents<\/h3>\n<p>La notion de cardinalit\u00e9, h\u00e9rit\u00e9e des math\u00e9matiques ensemblistes, d\u00e9signe formellement le nombre d&rsquo;\u00e9l\u00e9ments constitutifs d&rsquo;un ensemble fini ou infini. Transpos\u00e9e \u00e0 l&rsquo;architecture des bases de donn\u00e9es orient\u00e9es documents, la cardinalit\u00e9 d&rsquo;un champ caract\u00e9rise le degr\u00e9 d&rsquo;unicit\u00e9 des donn\u00e9es scalaires ou compos\u00e9es qui y sont encapsul\u00e9es. Dans un sch\u00e9ma conceptuel d\u00e9normalis\u00e9, typique des mod\u00e9lisations documentaires, la redondance des attributs n&rsquo;est pas proscrite ; elle est au contraire encourag\u00e9e afin de minimiser les jointures distributives co\u00fbteuses et de favoriser l&rsquo;idempotence des op\u00e9rations de lecture.<\/p>\n<p>Il convient d&rsquo;\u00e9tablir une distinction formelle entre l&rsquo;unicit\u00e9 structurelle au niveau du document \u2014 garantie par la pr\u00e9sence obligatoire et universelle de la cl\u00e9 primaire immuable <code>_id<\/code> \u2014 et l&rsquo;unicit\u00e9 relative des valeurs h\u00e9berg\u00e9es au sein d&rsquo;un champ applicatif particulier. Alors que deux documents distincts poss\u00e8dent par d\u00e9finition deux identifiants scalaires distincts, ils peuvent partager des valeurs identiques pour un ensemble infini d&rsquo;autres propri\u00e9t\u00e9s. Cette dichotomie induit une distinction fondamentale entre la recherche de documents dupliqu\u00e9s dans leur int\u00e9gralit\u00e9 et la convergence d&rsquo;occurrences identiques au sein d&rsquo;un attribut projet\u00e9.<\/p>\n<p>La pratique courante de la d\u00e9normalisation exacerbe ce ph\u00e9nom\u00e8ne de multiplicit\u00e9. En imbriquant des entit\u00e9s relatives au sein d&rsquo;un document ma\u00eetre, les d\u00e9veloppeurs multiplient les occurrences d&rsquo;une m\u00eame cl\u00e9 cat\u00e9gorielle ou scalaire. Par cons\u00e9quent, l&rsquo;\u00e9valuation de l&rsquo;unicit\u00e9 ne consiste pas simplement \u00e0 inspecter la dispersion des documents au sein de l&rsquo;espace de stockage, mais requiert une op\u00e9ration de r\u00e9duction ensembliste visant \u00e0 projeter une collection multiforme sur un ensemble fini de valeurs orthogonales.<\/p>\n<h3>1.2 Pertinence analytique du d\u00e9nombrement des valeurs distinctes<\/h3>\n<p>D&rsquo;un point de vue analytique, le d\u00e9nombrement des valeurs distinctes constitue la pierre angulaire du profilage de donn\u00e9es (<em>data profiling<\/em>). Face \u00e0 des collections ingestionnant des flux continus de donn\u00e9es semi-structur\u00e9es, la mesure de l&rsquo;unicit\u00e9 permet de caract\u00e9riser l&rsquo;espace d&rsquo;\u00e9tats d&rsquo;une variable. Une variable cat\u00e9gorielle pr\u00e9sentant une tr\u00e8s faible cardinalit\u00e9 par rapport au volume total des documents refl\u00e8te une distribution hyper-concentr\u00e9e, souvent repr\u00e9sentative d&rsquo;un statut op\u00e9rationnel, d&rsquo;une classe d&rsquo;entit\u00e9 ou d&rsquo;un drapeau bool\u00e9en. \u00c0 l&rsquo;inverse, une cardinalit\u00e9 approchant le nombre total d&rsquo;enregistrements signale un identifiant unique, un marqueur temporel fin ou une mesure physique continue.<\/p>\n<p>Cette mesure est intrins\u00e8quement corr\u00e9l\u00e9e au concept d&rsquo;entropie informationnelle introduit par <a rel=\"noopener noreferrer\" href=\"https:\/\/ieeexplore.ieee.org\/document\/6773024\">Claude Shannon<\/a>. L&rsquo;\u00e9valuation de l&rsquo;entropie d&rsquo;un champ renseigne l&rsquo;ing\u00e9nieur sur la quantit\u00e9 d&rsquo;information effective v\u00e9hicul\u00e9e par chaque document. Une entropie minimale indique une redondance pr\u00e9visible, tandis qu&rsquo;une entropie maximale t\u00e9moigne d&rsquo;une dispersion stochastique n\u00e9cessitant des architectures de partitionnement et de stockage adapt\u00e9es aux charges hautement diff\u00e9renti\u00e9es.<\/p>\n<p>Sur le plan op\u00e9rationnel, la connaissance de la cardinalit\u00e9 dicte directement la strat\u00e9gie d&rsquo;optimisation des requ\u00eates et le dimensionnement physique des index. Le planificateur de requ\u00eates de MongoDB (<em>Query Optimizer<\/em>) s&rsquo;appuie sur ces estimations de s\u00e9lectivit\u00e9 pour arbitrer entre un balayage complet de collection (<em>COLLSCAN<\/em>) et l&rsquo;utilisation cibl\u00e9e d&rsquo;un index en arbre B (<em>IXSCAN<\/em>). Un index positionn\u00e9 sur un champ dot\u00e9 d&rsquo;une cardinalit\u00e9 extr\u00eamement faible s&rsquo;av\u00e8re souvent sous-optimal, le co\u00fbt d&rsquo;acc\u00e8s aux n\u0153uds de l&rsquo;arbre et les sauts de pointeurs vers la m\u00e9moire pouvant surpasser la vitesse d&rsquo;un balayage s\u00e9quentiel de blocs contigus.<\/p>\n<h3>1.3 Aper\u00e7u comparatif des m\u00e9canismes d&rsquo;\u00e9valuation natifs<\/h3>\n<p>Pour r\u00e9pondre \u00e0 la probl\u00e9matique du comptage d&rsquo;unicit\u00e9, MongoDB met \u00e0 la disposition des d\u00e9veloppeurs deux paradigmes fondamentaux. Le premier repose sur l&rsquo;utilisation de la commande native <code>db.collection.distinct()<\/code>, accessible directement via l&rsquo;interpr\u00e9teur de commandes et les pilotes applicatifs. Cette commande est con\u00e7ue pour extraire de mani\u00e8re synchrone l&rsquo;ensemble exhaustif des valeurs uniques sous la forme d&rsquo;un tableau scalaire, dont la dimension m\u00e9trique peut ensuite \u00eatre mesur\u00e9e.<\/p>\n<p>Le second paradigme mobilise le cadriciel d&rsquo;agr\u00e9gation (<em>Aggregation Pipeline<\/em>), un moteur d&rsquo;ex\u00e9cution orient\u00e9 flux qui traite les documents \u00e0 travers une s\u00e9quence d&rsquo;\u00e9tapes de transformation fonctionnelle. En combinant les op\u00e9rateurs de groupement et d&rsquo;accumulation, le pipeline ne se contente pas d&rsquo;extraire des \u00e9l\u00e9ments ; il op\u00e8re une d\u00e9duplication en flux avant d&rsquo;en calculer la somme unitaire directement au sein du moteur de base de donn\u00e9es, \u00e9vitant ainsi la mat\u00e9rialisation interm\u00e9diaire de structures de donn\u00e9es massives.<\/p>\n<p>Ce choix conceptuel introduit un arbitrage critique entre l&rsquo;ex\u00e9cution c\u00f4t\u00e9 serveur et la r\u00e9solution c\u00f4t\u00e9 client. Alors que la m\u00e9thode directe d\u00e9place le co\u00fbt du calcul de la taille vers l&rsquo;application h\u00f4te apr\u00e8s une transmission r\u00e9seau int\u00e9grale, le pipeline d&rsquo;agr\u00e9gation internalise l&rsquo;int\u00e9gralit\u00e9 du calcul volum\u00e9trique dans les threads du serveur, ne renvoyant au client qu&rsquo;un entier repr\u00e9sentatif de la cardinalit\u00e9 exacte. Comprendre les implications sous-jacentes de cet arbitrage est imp\u00e9ratif pour concevoir des architectures r\u00e9silientes face \u00e0 l&rsquo;accroissement des charges de travail.<\/p>\n<h2>2. Architecture et fonctionnement de la m\u00e9thode db.collection.distinct()<\/h2>\n<h3>2.1 Syntaxe formelle et param\u00e8tres d&rsquo;entr\u00e9e<\/h3>\n<p>La commande d&rsquo;aide <code>db.collection.distinct()<\/code> constitue une surcouche syntaxique (<em>helper<\/em>) encapsulant l&rsquo;ordre de base de donn\u00e9es sous-jacent <code>distinct<\/code>. Sa signature formelle s&rsquo;articule autour de trois arguments distincts : <code>db.collection.distinct(field, query, options)<\/code>. Le premier param\u00e8tre, obligatoire, est une cha\u00eene de caract\u00e8res sp\u00e9cifiant le chemin d&rsquo;acc\u00e8s qualifi\u00e9 de l&rsquo;attribut \u00e0 inspecter. Ce chemin peut d\u00e9signer une propri\u00e9t\u00e9 racine ou faire appel \u00e0 la notation point\u00e9e (<em>dot notation<\/em>) pour naviguer au sein de sous-documents complexes.<\/p>\n<p>Le deuxi\u00e8me param\u00e8tre, optionnel, consiste en un document de filtre ob\u00e9issant \u00e0 la m\u00eame grammaire que la m\u00e9thode <code>find()<\/code>. Il d\u00e9limite le p\u00e9rim\u00e8tre des documents assujettis \u00e0 l&rsquo;analyse d&rsquo;unicit\u00e9, permettant d&rsquo;exclure les enregistrements non pertinents avant l&rsquo;\u00e9tape de d\u00e9duplication. Le typage strict de ces crit\u00e8res garantit que seules les occurrences r\u00e9pondant aux contraintes relationnelles ou temporelles sp\u00e9cifi\u00e9es soient prises en compte dans le calcul d&rsquo;unicit\u00e9.<\/p>\n<p>Le troisi\u00e8me argument regroupe un ensemble d&rsquo;options d&rsquo;ex\u00e9cution avanc\u00e9es, au sein desquelles figurent la sp\u00e9cification d&rsquo;une collation linguistique et la d\u00e9finition d&rsquo;une pr\u00e9f\u00e9rence de lecture (<em>readPreference<\/em>). La collation permet de d\u00e9finir des r\u00e8gles s\u00e9mantiques pr\u00e9cises r\u00e9gissant la sensibilit\u00e9 \u00e0 la casse et aux accents, transformant potentiellement des cha\u00eenes typographiquement divergentes en entr\u00e9es s\u00e9mantiquement \u00e9quivalentes lors de la phase de r\u00e9duction d&rsquo;unicit\u00e9.<\/p>\n<h3>2.2 M\u00e9canisme d&rsquo;ex\u00e9cution sous-jacent du moteur WiredTiger<\/h3>\n<p>Sous le capot applicatif, l&rsquo;ex\u00e9cution de la m\u00e9thode <code>distinct()<\/code> d\u00e9clenche une interaction \u00e9troite avec le moteur de stockage par d\u00e9faut de MongoDB, <a rel=\"noopener noreferrer\" href=\"https:\/\/www.mongodb.com\/docs\/manual\/core\/wiredtiger\/\">WiredTiger<\/a>. Lorsqu&rsquo;aucun index ne supporte le champ interrog\u00e9, le moteur est contraint d&rsquo;allouer des curseurs de balayage complet sur les tables physiques des documents. Chaque document est alors d\u00e9s\u00e9rialis\u00e9 de son format disque compress\u00e9 vers la m\u00e9moire tampon (<em>buffer pool<\/em>), o\u00f9 le champ cibl\u00e9 est extrait et compar\u00e9 \u00e0 une structure transitoire de hachage interne.<\/p>\n<p>En pr\u00e9sence d&rsquo;un index ad\u00e9quat, le moteur optimise drastiquement cette cin\u00e9matique. WiredTiger exploite la structure ordonn\u00e9e de son arbre B-Tree pour naviguer de mani\u00e8re non lin\u00e9aire \u00e0 travers les cl\u00e9s d&rsquo;index. D\u00e8s qu&rsquo;une cl\u00e9 est identifi\u00e9e, le curseur interne peut th\u00e9oriquement effectuer un saut de pointeur vers la prochaine cl\u00e9 distincte, \u00e9vitant la lecture s\u00e9quentielle des occurrences dupliqu\u00e9es cons\u00e9cutives. Cette optimisation repose toutefois sur la capacit\u00e9 du planificateur de requ\u00eates \u00e0 g\u00e9n\u00e9rer un plan d&rsquo;ex\u00e9cution exploitant pleinement la s\u00e9lectivit\u00e9 des n\u0153uds.<\/p>\n<p>Un comportement fondamental et souvent m\u00e9connu de la commande <code>distinct()<\/code> r\u00e9side dans l&rsquo;ordonnancement implicite appliqu\u00e9 aux donn\u00e9es collect\u00e9es. Les valeurs uniques consolid\u00e9es ne sont pas renvoy\u00e9es dans leur ordre d&rsquo;apparition temporel au sein de la collection ; elles font l&rsquo;objet d&rsquo;un tri lexicographique et typologique syst\u00e9matique dict\u00e9 par les r\u00e8gles de comparaison standard de MongoDB (<em>BSON comparison order<\/em>). Ce tri pr\u00e9liminaire \u00e0 la restitution mobilise des cycles de calcul processeur suppl\u00e9mentaires qui s&rsquo;av\u00e8rent superflus lorsque seule la cardinalit\u00e9 totale pr\u00e9sente un int\u00e9r\u00eat pour le client.<\/p>\n<h3>2.3 Typologie des structures retourn\u00e9es<\/h3>\n<p>Le r\u00e9sultat produit par l&rsquo;invocation de <code>db.collection.distinct()<\/code> se mat\u00e9rialise sous la forme d&rsquo;un tableau natif BSON encapsulant l&rsquo;ensemble des \u00e9l\u00e9ments uniques extraits. Cette typologie induit une d\u00e9pendance directe envers le mod\u00e8le de m\u00e9moire de l&rsquo;environnement client r\u00e9cepteur, qu&rsquo;il s&rsquo;agisse du moteur V8 sous-jacent au shell moderne <em>mongosh<\/em> ou des gestionnaires de m\u00e9moire des pilotes Java, Python, Go ou C#.<\/p>\n<p>En raison de la nature non contraignante des sch\u00e9mas MongoDB, un m\u00eame champ peut h\u00e9berger des types de donn\u00e9es profond\u00e9ment h\u00e9t\u00e9rog\u00e8nes d&rsquo;un document \u00e0 un autre. La commande <code>distinct()<\/code> ne rejette pas cette polymorphie ; elle regroupe l&rsquo;ensemble des variations au sein du tableau de sortie, en appliquant un ordre strict d&rsquo;ordonnancement entre types distincts (les valeurs nulles pr\u00e9c\u00e9dant les nombres, eux-m\u00eames pr\u00e9c\u00e9dant les cha\u00eenes de caract\u00e8res, les objets et les tableaux).<\/p>\n<p>En ce qui concerne les cha\u00eenes de caract\u00e8res, la sensibilit\u00e9 typographique et la pr\u00e9servation de la casse constituent le comportement par d\u00e9faut en l&rsquo;absence de collation explicite. Ainsi, deux entr\u00e9es telles que \u00ab\u00a0PARIS\u00a0\u00bb et \u00ab\u00a0paris\u00a0\u00bb seront catalogu\u00e9es comme deux valeurs ind\u00e9pendantes au sein du tableau final. Cette granularit\u00e9 native impose une rigueur extr\u00eame lors de la pr\u00e9paration des requ\u00eates, sous peine d&rsquo;obtenir une sur\u00e9valuation artificielle de la cardinalit\u00e9 r\u00e9elle du syst\u00e8me d&rsquo;information mod\u00e9lis\u00e9.<\/p>\n<h2>3. Extraction concr\u00e8te de la liste des valeurs distinctes<\/h2>\n<h3>3.1 Mise en place du jeu de donn\u00e9es exp\u00e9rimental<\/h3>\n<p>Afin d&rsquo;illustrer pragmatiquement les m\u00e9canismes th\u00e9oriques \u00e9nonc\u00e9s, \u00e9tablissons un jeu de donn\u00e9es exp\u00e9rimental au sein d&rsquo;une collection baptis\u00e9e <code>teams<\/code>. Cette entit\u00e9 vise \u00e0 mod\u00e9liser la composition statistique d&rsquo;\u00e9quipes sportives au sein d&rsquo;une ligue professionnelle de basket-ball, int\u00e9grant \u00e0 la fois des dimensions cat\u00e9goriques, des identifiants organisationnels et des variables quantitatives continues.<\/p>\n<p>L&rsquo;instanciation de cette collection requiert l&rsquo;insertion m\u00e9thodique de documents intentionnellement enrichis de redondances scalaires, permettant d&rsquo;observer sans ambigu\u00eft\u00e9 les ph\u00e9nom\u00e8nes de fusion et d&rsquo;ordonnancement ensembliste. L&rsquo;op\u00e9ration d&rsquo;initialisation s&rsquo;ex\u00e9cute \u00e0 travers l&rsquo;instruction suivante au sein de l&rsquo;interpr\u00e9teur de commandes :<\/p>\n<p><code>db.teams.insertMany([<br \/>\n&nbsp;&nbsp;{ player: \"LeBron\", team: \"Cavs\", position: \"Forward\", points: 27.2 },<br \/>\n&nbsp;&nbsp;{ player: \"Kyrie\", team: \"Cavs\", position: \"Guard\", points: 21.6 },<br \/>\n&nbsp;&nbsp;{ player: \"Kevin\", team: \"Cavs\", position: \"Forward\", points: 18.3 },<br \/>\n&nbsp;&nbsp;{ player: \"Luka\", team: \"Mavs\", position: \"Guard\", points: 28.4 },<br \/>\n&nbsp;&nbsp;{ player: \"Dirk\", team: \"Mavs\", position: \"Forward\", points: 20.7 },<br \/>\n&nbsp;&nbsp;{ player: \"Tyson\", team: \"Mavs\", position: \"Center\", points: 8.9 },<br \/>\n&nbsp;&nbsp;{ player: \"James\", team: \"Rockets\", position: \"Guard\", points: 30.4 },<br \/>\n&nbsp;&nbsp;{ player: \"Clint\", team: \"Rockets\", position: \"Center\", points: 12.1 }<br \/>\n]);<\/code><\/p>\n<p>Pr\u00e9alablement \u00e0 toute analyse, une v\u00e9rification d&rsquo;\u00e9tat via <code>db.teams.countDocuments()<\/code> confirme la pr\u00e9sence de huit enregistrements individuels. Chaque document manifeste une imbrication d&rsquo;attributs dont la cardinalit\u00e9 th\u00e9orique varie substantiellement, offrant un laboratoire id\u00e9al pour \u00e9prouver la d\u00e9tection d&rsquo;unicit\u00e9 sur des ensembles discrets.<\/p>\n<h3>3.2 Extraction sur un champ cat\u00e9goriel textuel<\/h3>\n<p>L&rsquo;interrogation d&rsquo;unicit\u00e9 sur le champ textuel <code>team<\/code> vise \u00e0 identifier la totalit\u00e9 des franchises sportives repr\u00e9sent\u00e9es dans la collection, en extrayant les entit\u00e9s canoniques de leur multiplicit\u00e9 d&rsquo;origine. L&rsquo;invocation s&rsquo;effectue simplement selon la syntaxe :<\/p>\n<p><code>db.teams.distinct(\"team\");<\/code><\/p>\n<p>Le serveur compile cette requ\u00eate et renvoie instantan\u00e9ment la structure vectorielle suivante :<\/p>\n<p><code>[ \"Cavs\", \"Mavs\", \"Rockets\" ]<\/code><\/p>\n<p>Une observation attentive de ce retour r\u00e9v\u00e8le deux propri\u00e9t\u00e9s fondamentales. D&rsquo;une part, bien que l&rsquo;attribut \u00ab\u00a0Cavs\u00a0\u00bb soit pr\u00e9sent \u00e0 trois reprises dans la collection sous-jacente et que \u00ab\u00a0Mavs\u00a0\u00bb apparaisse \u00e9galement trois fois, la d\u00e9duplication est absolue : chaque franchise ne figure qu&rsquo;une seule et unique fois dans la structure r\u00e9sultante. D&rsquo;autre part, les valeurs sont restitu\u00e9es selon un ordre alphab\u00e9tique strict (\u00ab\u00a0C\u00a0\u00bb, puis \u00ab\u00a0M\u00a0\u00bb, puis \u00ab\u00a0R\u00a0\u00bb), validant concr\u00e8tement la phase de tri interne op\u00e9r\u00e9e par le moteur WiredTiger avant la formalisation du paquet de donn\u00e9es BSON.<\/p>\n<h3>3.3 Extraction sur un champ \u00e0 cardinalit\u00e9 restreinte<\/h3>\n<p>Proc\u00e9dons \u00e0 pr\u00e9sent \u00e0 l&rsquo;extraction des valeurs distinctes relatives au champ <code>position<\/code>, lequel qualifie le r\u00f4le tactique des athl\u00e8tes sur le terrain. La requ\u00eate s&rsquo;\u00e9nonce comme suit :<\/p>\n<p><code>db.teams.distinct(\"position\");<\/code><\/p>\n<p>La r\u00e9ponse g\u00e9n\u00e9r\u00e9e par MongoDB prend la forme compacte suivante :<\/p>\n<p><code>[ \"Center\", \"Forward\", \"Guard\" ]<\/code><\/p>\n<p>Dans ce sc\u00e9nario, nous constatons une r\u00e9duction d&rsquo;\u00e9chelle spectaculaire : huit documents sources sont synth\u00e9tis\u00e9s en un ensemble ternaire parfait. La cardinalit\u00e9 intrins\u00e8que de la variable est \u00e9gale \u00e0 3. Bien que les pivots (\u00ab\u00a0Center\u00a0\u00bb) soient minoritaires au sein de l&rsquo;\u00e9chantillon d&rsquo;origine par rapport aux ailiers (\u00ab\u00a0Forward\u00a0\u00bb) et aux arri\u00e8res (\u00ab\u00a0Guard\u00a0\u00bb), l&rsquo;op\u00e9ration <code>distinct()<\/code> \u00e9galise leur visibilit\u00e9 en effa\u00e7ant toute notion de distribution fr\u00e9quentielle. L&rsquo;analyste obtient une vision exhaustive de l&rsquo;univers des possibles tactiques sans aucune interf\u00e9rence li\u00e9e au volume comparatif des sous-groupes.<\/p>\n<h2>4. D\u00e9nombrement des valeurs distinctes via la propri\u00e9t\u00e9 length<\/h2>\n<h3>4.1 M\u00e9canisme de calcul de la cardinalit\u00e9 c\u00f4t\u00e9 client<\/h3>\n<p>L&rsquo;utilisation la plus r\u00e9pandue au sein des architectures logicielles \u00e9l\u00e9mentaires pour d\u00e9river le nombre de valeurs uniques d&rsquo;un champ consiste \u00e0 adjoindre la propri\u00e9t\u00e9 d&rsquo;\u00e9valuation de longueur du langage h\u00f4te directement \u00e0 la suite de la commande MongoDB. Au sein de l&rsquo;interpr\u00e9teur <em>mongosh<\/em> ou dans les environnements d&rsquo;ex\u00e9cution bas\u00e9s sur <a rel=\"noopener noreferrer\" href=\"https:\/\/nodejs.org\/\">Node.js<\/a>, cela s&rsquo;exprime par l&rsquo;acc\u00e8s \u00e0 la propri\u00e9t\u00e9 <code>length<\/code> du prototype natif des tableaux :<\/p>\n<p><code>db.teams.distinct(\"team\").length;<\/code><\/p>\n<p>L&rsquo;\u00e9valuation s&rsquo;ex\u00e9cute de mani\u00e8re synchrone : le moteur de stockage compile et r\u00e9sout l&rsquo;op\u00e9ration <code>distinct<\/code>, s\u00e9rialise le tableau BSON r\u00e9sultant, le transmet \u00e0 travers la socket TCP vers l&rsquo;interpr\u00e9teur client, lequel instancie un objet tableau en m\u00e9moire vive JavaScript et acc\u00e8de \u00e0 sa m\u00e9tadonn\u00e9e scalaire <code>length<\/code>, produisant imm\u00e9diatement l&rsquo;entier :<\/p>\n<p><code>3<\/code><\/p>\n<p>Cette approche s\u00e9duit d&#8217;embl\u00e9e par son extr\u00eame concision syntaxique et sa clart\u00e9 cognitive. Pour des collections de taille modeste et des attributs \u00e0 cardinalit\u00e9 strictement contenue, ce paradigme offre une r\u00e9ponse instantan\u00e9e sans exiger la formalisation complexe d&rsquo;un pipeline analytique. L&rsquo;entier scalaire retourn\u00e9 est imm\u00e9diatement manipulable par l&rsquo;application pour des branchements conditionnels ou des restitutions d&rsquo;interface utilisateur.<\/p>\n<h3>4.2 Consommation des ressources r\u00e9seau et client<\/h3>\n<p>En d\u00e9pit de sa simplicit\u00e9 trompeuse, l&rsquo;instruction <code>db.collection.distinct(field).length<\/code> dissimule une inefficience architecturale s\u00e9v\u00e8re d\u00e8s lors qu&rsquo;elle est confront\u00e9e \u00e0 la mont\u00e9e en charge. Le calcul arithm\u00e9tique de la longueur n&rsquo;est en aucun cas op\u00e9r\u00e9 par le serveur de base de donn\u00e9es. Pour satisfaire cette instruction, le serveur est contraint de mat\u00e9rialiser l&rsquo;int\u00e9gralit\u00e9 du tableau de toutes les valeurs distinctes, d&rsquo;en construire la structure BSON compl\u00e8te et de l&rsquo;acheminer int\u00e9gralement sur la couche r\u00e9seau jusqu&rsquo;au client distant.<\/p>\n<p>Consid\u00e9rons une collection h\u00e9bergeant plusieurs millions d&rsquo;enregistrements d&rsquo;adresses de messagerie \u00e9lectronique uniques. Pour obtenir le simple chiffre <code>1000000<\/code>, l&rsquo;architecture impose la s\u00e9rialisation, le transport filaire et la d\u00e9s\u00e9rialisation de dizaines de m\u00e9gaoctets de donn\u00e9es textuelles brutes. Ce ph\u00e9nom\u00e8ne provoque une surcharge inutile de la bande passante inter-serveurs, une augmentation de la latence r\u00e9seau li\u00e9e au d\u00e9coupage et \u00e0 la r\u00e9agr\u00e9gation des paquets TCP, et une consommation m\u00e9moire disproportionn\u00e9e au niveau du processus client.<\/p>\n<p>Dans un environnement distribu\u00e9 o\u00f9 plusieurs microservices interrogent simultan\u00e9ment l&rsquo;instance de donn\u00e9es, cette extraction redondante de structures massives peut rapidement saturer la boucle d&rsquo;\u00e9v\u00e9nements (<em>event loop<\/em>) du processus applicatif et monopoliser des pools entiers de m\u00e9moire allou\u00e9e au ramasse-miettes (<em>garbage collector<\/em>), induisant des gels applicatifs transitoires particuli\u00e8rement pr\u00e9judiciables.<\/p>\n<h3>4.3 Limites de scalabilit\u00e9 de la m\u00e9thode \u00e9l\u00e9mentaire<\/h3>\n<p>L&rsquo;inad\u00e9quation de la m\u00e9thode <code>distinct().length<\/code> s&rsquo;accro\u00eet dramatiquement lorsque la cardinalit\u00e9 du champ analys\u00e9 diverge vers des ordres de grandeur \u00e9lev\u00e9s. D\u00e9pourvue de toute capacit\u00e9 de calcul distribu\u00e9 ou d&rsquo;optimisation d&rsquo;agr\u00e9gation c\u00f4t\u00e9 moteur, cette technique transforme une simple interrogation statistique en une op\u00e9ration d&rsquo;extraction d&rsquo;ensemble lourdement p\u00e9nalisante pour le cluster.<\/p>\n<p>L&rsquo;absence de pagination native sur la m\u00e9thode <code>distinct()<\/code> accentue cette vuln\u00e9rabilit\u00e9 : il est rigoureusement impossible de streamer ou de segmenter le r\u00e9sultat de mani\u00e8re granulaire. Le transfert s&rsquo;effectue en mode tout-ou-rien. Si l&rsquo;environnement applicatif h\u00f4te subit une contrainte stricte d&rsquo;allocation de m\u00e9moire vive (comme c&rsquo;est fr\u00e9quemment le cas au sein de conteneurs Docker ou de fonctions \u00e9ph\u00e9m\u00e8res sans serveur de type <em>AWS Lambda<\/em>), l&rsquo;instanciation en m\u00e9moire d&rsquo;un tableau comportant des centaines de milliers d&rsquo;entr\u00e9es complexes provoquera in\u00e9luctablement une interruption critique de type d\u00e9passement de m\u00e9moire (<em>Out of Memory Exception<\/em>).<\/p>\n<p>Par ailleurs, sur le serveur de bases de donn\u00e9es lui-m\u00eame, la mobilisation des threads syst\u00e8me n\u00e9cessaires \u00e0 l&rsquo;assemblage d&rsquo;un document BSON g\u00e9ant bloque l&rsquo;allocation de ressources critiques pour les op\u00e9rations de mise \u00e0 jour et d&rsquo;\u00e9criture concurrentes. Il s&rsquo;agit d&rsquo;un anti-mod\u00e8le architectural manifeste pour toute application requ\u00e9rant un d\u00e9bit transactionnel \u00e9lev\u00e9.<\/p>\n<h2>5. La contrainte critique de taille limite de document BSON (16 Mo)<\/h2>\n<h3>5.1 Analyse de la sp\u00e9cification BSON et restriction m\u00e9moire<\/h3>\n<p>L&rsquo;un des invariants structurels les plus fondamentaux de MongoDB r\u00e9side dans la limitation stricte de la taille maximale de tout document BSON individuel \u00e0 exactement 16 m\u00e9gaoctets (16 MiB, soit 16 777 216 octets). Cette borne physique, document\u00e9e au sein de la <a rel=\"noopener noreferrer\" href=\"https:\/\/bsonspec.org\/\">sp\u00e9cification BSON formelle<\/a>, a \u00e9t\u00e9 d\u00e9lib\u00e9r\u00e9ment int\u00e9gr\u00e9e par les architectes de la technologie afin d&rsquo;\u00e9viter qu&rsquo;un document isol\u00e9 ne vienne monopoliser une fraction disproportionn\u00e9e de la m\u00e9moire vive, fragmenter les allocations m\u00e9moire ou introduire des latences massives lors des transferts disques et r\u00e9seau.<\/p>\n<p>Or, la commande <code>distinct()<\/code> pr\u00e9sente une caract\u00e9ristique technique primordiale : le vecteur de r\u00e9sultats consolidant toutes les cl\u00e9s uniques est restitu\u00e9 \u00e0 l&rsquo;utilisateur sous la forme d&rsquo;un <em>document BSON unique<\/em> encapsulant un tableau nomm\u00e9 <code>values<\/code>. Par voie de cons\u00e9quence, l&rsquo;ensemble agr\u00e9g\u00e9 de toutes les valeurs distinctes g\u00e9n\u00e9r\u00e9es par la requ\u00eate est soumis sans d\u00e9rogation possible \u00e0 ce plafond infranchissable de 16 m\u00e9gaoctets.<\/p>\n<p>La capacit\u00e9 d&rsquo;accueil maximale en termes d&rsquo;\u00e9l\u00e9ments distincts devient ainsi une variable strictement d\u00e9pendante de la taille moyenne unitaire des donn\u00e9es stock\u00e9es. Le mod\u00e8le math\u00e9matique de saturation peut s&rsquo;exprimer par la relation simple :<\/p>\n<p><em>Nombre Maximal d&rsquo;\u00c9l\u00e9ments \u2248 (16 777 216 &#8211; M\u00e9tadonn\u00e9es BSON) \/ Taille Moyenne des \u00c9l\u00e9ments en Octets<\/em><\/p>\n<p>Pour un champ contenant des identifiants alphanum\u00e9riques complexes, des hachages cryptographiques SHA-256 ou des localisateurs de ressources uniformes (URL) d&rsquo;une taille moyenne de 128 octets, le seuil de saturation critique est atteint d\u00e8s lors que la collection franchit le cap modeste de seulement 125 000 valeurs uniques. Au-del\u00e0 de cette borne, l&rsquo;op\u00e9ration math\u00e9matique \u00e9l\u00e9mentaire se heurte violemment \u00e0 la structure physique du moteur.<\/p>\n<h3>5.2 Typologie des erreurs lev\u00e9es en production<\/h3>\n<p>Lorsque la cardinalit\u00e9 r\u00e9elle d&rsquo;un champ exc\u00e8de la capacit\u00e9 volum\u00e9trique du conteneur BSON durant l&rsquo;\u00e9valuation de <code>db.collection.distinct()<\/code>, le serveur n&rsquo;op\u00e8re aucune troncature silencieuse. Il interrompt brutalement l&rsquo;op\u00e9ration et l\u00e8ve une exception fatale. Dans l&rsquo;historique des versions de MongoDB, cette rupture se manifeste par l&rsquo;erreur explicite :<\/p>\n<p><code>distinct too big, 16mb cap exceeded<\/code><\/p>\n<p>Ou, sous les d\u00e9clinaisons plus r\u00e9centes des moteurs WiredTiger int\u00e9gr\u00e9s aux branches sup\u00e9rieures de MongoDB :<\/p>\n<p><code>BSONObjectTooLarge: BSON object size ... is larger than the max allowed size (16777216)<\/code><\/p>\n<p>Cette exception engendre un crash pur et simple de la routine applicative qui en est \u00e0 l&rsquo;origine si celle-ci ne dispose pas d&rsquo;un bloc de capture d&rsquo;erreur exceptionnellement sophistiqu\u00e9. En production, cela se traduit par l&rsquo;\u00e9chec inattendu de tableaux de bord analytiques, la rupture de pipelines d&rsquo;extraction, de transformation et de chargement (ETL), ou encore l&rsquo;indisponibilit\u00e9 brutale de fonctionnalit\u00e9s de recherche \u00e0 facettes pour les utilisateurs finaux.<\/p>\n<p>L&rsquo;aspect le plus pernicieux de ce comportement r\u00e9side dans sa nature latente : une application peut fonctionner parfaitement durant plusieurs mois en phase d&rsquo;amor\u00e7age commercial alors que le volume de clients est restreint, pour s&rsquo;effondrer brutalement d\u00e8s que le succ\u00e8s op\u00e9rationnel pousse la cardinalit\u00e9 du syst\u00e8me d&rsquo;information au-del\u00e0 de la ligne de d\u00e9marcation des 16 Mo.<\/p>\n<h3>5.3 Strat\u00e9gies d&rsquo;\u00e9vitement de la saturation BSON<\/h3>\n<p>Face \u00e0 cette limite structurelle, l&rsquo;ing\u00e9nieur de donn\u00e9es doit imp\u00e9rativement bannir l&rsquo;usage de la m\u00e9thode \u00e9l\u00e9mentaire <code>distinct()<\/code> d\u00e8s lors que l&rsquo;attribut cibl\u00e9 pr\u00e9sente un potentiel de cardinalit\u00e9 moyen \u00e0 \u00e9lev\u00e9. Deux strat\u00e9gies palliatives s&rsquo;offrent alors \u00e0 l&rsquo;architecture logicielle.<\/p>\n<p>La premi\u00e8re strat\u00e9gie, palliative et pr\u00e9ventive, consiste \u00e0 partitionner l&rsquo;espace d&rsquo;interrogation en segmentant l&rsquo;extraction au moyen de filtres stricts sur le second param\u00e8tre de la m\u00e9thode. En fractionnant artificiellement l&rsquo;espace de recherche (par exemple en d\u00e9coupant chronologiquement par mois d&rsquo;enregistrement ou par tranches lexicographiques alphab\u00e9tiques de A \u00e0 F, de G \u00e0 M, etc.), on parvient \u00e0 maintenir chaque sous-ensemble sous le plafond des 16 m\u00e9gaoctets. Cependant, cette m\u00e9thode transf\u00e8re une complexit\u00e9 algorithmique intol\u00e9rable au code applicatif h\u00f4te, qui doit ensuite orchestrer les diff\u00e9rentes requ\u00eates et d\u00e9dupliquer les bordures d&rsquo;ensembles.<\/p>\n<p>La seconde strat\u00e9gie, p\u00e9renne, robuste et universellement recommand\u00e9e par l&rsquo;\u00e9tat de l&rsquo;art du g\u00e9nie logiciel, abandonne int\u00e9gralement la m\u00e9thode <code>distinct()<\/code> au profit exclusif du cadriciel d&rsquo;agr\u00e9gation. Ce dernier \u00e9mancipe totalement l&rsquo;op\u00e9ration des limites volum\u00e9triques BSON gr\u00e2ce \u00e0 son mod\u00e8le d&rsquo;ex\u00e9cution en flux (<em>streaming execution<\/em>) et \u00e0 sa capacit\u00e9 \u00e0 mat\u00e9rialiser des curseurs it\u00e9ratifs sur le r\u00e9sultat final, comme nous allons le d\u00e9tailler dans la section suivante.<\/p>\n<h2>6. Comptage distinct \u00e0 grande \u00e9chelle via le framework d&rsquo;agr\u00e9gation<\/h2>\n<h3>6.1 Conception d&rsquo;un pipeline d&rsquo;agr\u00e9gation d&rsquo;unicit\u00e9<\/h3>\n<p>Pour s&rsquo;affranchir d\u00e9finitivement des contraintes de m\u00e9moire BSON et d\u00e9l\u00e9guer l&rsquo;int\u00e9gralit\u00e9 du calcul volum\u00e9trique au processeur du serveur de base de donn\u00e9es, le <a rel=\"noopener noreferrer\" href=\"https:\/\/www.mongodb.com\/docs\/manual\/core\/aggregation-pipeline\/\">cadriciel d&rsquo;agr\u00e9gation<\/a> constitue l&rsquo;instrument d&rsquo;ing\u00e9nierie par excellence. L&rsquo;approche repose sur un principe fondamental : la d\u00e9duplication en flux au moyen de l&rsquo;op\u00e9rateur de groupement <code>$group<\/code>.<\/p>\n<p>Dans un pipeline d&rsquo;agr\u00e9gation d&rsquo;unicit\u00e9, la premi\u00e8re \u00e9tape fondamentale consiste \u00e0 regrouper les documents de la collection en utilisant la valeur du champ cible comme identifiant d&rsquo;unicit\u00e9 de groupe. La syntaxe canonique s&rsquo;articule comme suit :<\/p>\n<p><code>db.teams.aggregate([<br \/>\n&nbsp;&nbsp;{ <span class=\"arabpsy-math-inline\" data-latex=\"group: { _id: &quot;\">$group: { _id: \"$<\/span>team\" } }<br \/>\n]);<\/code><\/p>\n<p>Durant cette phase, le moteur d&rsquo;agr\u00e9gation instancie une table de hachage interne optimis\u00e9e en m\u00e9moire. Chaque document traversant l&rsquo;\u00e9tape <code>$group<\/code> voit la valeur de son champ <code>team<\/code> extraite ; si cette valeur a d\u00e9j\u00e0 \u00e9t\u00e9 index\u00e9e dans la structure d&rsquo;accumulation temporaire, le document est imm\u00e9diatement absorb\u00e9 sans provoquer d&rsquo;allocation suppl\u00e9mentaire. \u00c0 l&rsquo;issue de cette \u00e9tape, le pipeline \u00e9met une s\u00e9quence de documents interm\u00e9diaires o\u00f9 chaque document repr\u00e9sente une valeur unique absolue, sous la forme standardis\u00e9e <code>{ \"_id\": \"Cavs\" }<\/code>, <code>{ \"_id\": \"Mavs\" }<\/code>, et ainsi de suite.<\/p>\n<p>Contrairement \u00e0 <code>distinct()<\/code>, cette \u00e9tape n&rsquo;encapsule pas l&rsquo;int\u00e9gralit\u00e9 des r\u00e9sultats dans un tableau unique. Elle produit un flux continu de documents l\u00e9gers, totalement insensible \u00e0 la limite des 16 m\u00e9gaoctets, capable de traiter des milliards d&rsquo;enregistrements en exploitant si n\u00e9cessaire le d\u00e9bordement sur disque temporaire (<em>allowDiskUse<\/em>).<\/p>\n<h3>6.2 Int\u00e9gration de l&rsquo;op\u00e9rateur de comptage final $count<\/h3>\n<p>Une fois les documents d\u00e9dupliqu\u00e9s et mat\u00e9rialis\u00e9s sous la forme d&rsquo;un flux de singletons au sortir de l&rsquo;\u00e9tape <code>$group<\/code>, le d\u00e9nombrement effectif ne requiert aucun calcul de m\u00e9tadonn\u00e9e c\u00f4t\u00e9 client. Il suffit de brancher en s\u00e9quence aval l&rsquo;\u00e9tape <code>$count<\/code>, introduite pour standardiser les op\u00e9rations d&rsquo;\u00e9num\u00e9ration en flux. Le pipeline complet s&rsquo;exprime ainsi :<\/p>\n<p><code>db.teams.aggregate([<br \/>\n&nbsp;&nbsp;{ <span class=\"arabpsy-math-inline\" data-latex=\"group: { _id: &quot;\">$group: { _id: \"$<\/span>team\" } },<br \/>\n&nbsp;&nbsp;{ $count: \"total_distinct\" }<br \/>\n]);<\/code><\/p>\n<p>L&rsquo;ex\u00e9cution de cette s\u00e9quence fonctionnelle transforme le flux de documents uniques en un unique document final dont la charge utile contient la cardinalit\u00e9 exacte :<\/p>\n<p><code>{ \"total_distinct\": 3 }<\/code><\/p>\n<p>Ce patron d&rsquo;architecture est optimal \u00e0 tous \u00e9gards. Le serveur de base de donn\u00e9es effectue l&rsquo;int\u00e9gralit\u00e9 de la r\u00e9duction ensembliste et du comptage arithm\u00e9tique au sein de son propre espace d&rsquo;adressage m\u00e9moire. La bande passante r\u00e9seau consomm\u00e9e pour renvoyer le r\u00e9sultat \u00e0 l&rsquo;application est r\u00e9duite \u00e0 quelques dizaines d&rsquo;octets seulement, ind\u00e9pendamment du fait que la collection initiale comporte dix enregistrements ou trois milliards de documents. Le client re\u00e7oit un document strictement encapsul\u00e9, \u00e9liminant tout risque de saturation de la m\u00e9moire vive applicative.<\/p>\n<h3>6.3 Utilisation conjointe de <span class=\"arabpsy-math-inline\" data-latex=\"group et de l&#039;accumulateur\">$group et de l&rsquo;accumulateur$<\/span>sum<\/h3>\n<p>Ant\u00e9rieurement \u00e0 l&rsquo;introduction formelle de l&rsquo;op\u00e9rateur <code>$count<\/code> dans les versions historiques de MongoDB, la convention architecturale pour compter les flux d\u00e9dupliqu\u00e9s reposait sur un double \u00e9tage de groupement exploitant l&rsquo;accumulateur arithm\u00e9tique <code>$sum<\/code>. Ce pattern demeure largement pr\u00e9valent dans les bases de code \u00e9tablies et m\u00e9rite une \u00e9tude approfondie :<\/p>\n<p><code>db.teams.aggregate([<br \/>\n&nbsp;&nbsp;{ <span class=\"arabpsy-math-inline\" data-latex=\"group: { _id: &quot;\">$group: { _id: \"$<\/span>team\" } },<br \/>\n&nbsp;&nbsp;{ <span class=\"arabpsy-math-inline\" data-latex=\"group: { _id: null, count: {\">$group: { _id: null, count: {$<\/span>sum: 1 } } }<br \/>\n]);<\/code><\/p>\n<p>Dans ce mod\u00e8le, le premier \u00e9tage <code>$group<\/code> remplit sa fonction canonique d&rsquo;isolation d&rsquo;unicit\u00e9 sur la dimension <code>$team<\/code>. Le second \u00e9tage op\u00e8re une nouvelle r\u00e9duction, mais en assignant cette fois-ci la constante <code>null<\/code> \u00e0 la cl\u00e9 <code>_id<\/code>. Cette assignation signale au moteur que tous les documents issus du flux pr\u00e9c\u00e9dent doivent converger au sein d&rsquo;un compartiment unique. Simultan\u00e9ment, l&rsquo;expression <code>count: { $sum: 1 }<\/code> incr\u00e9mente un registre scalaire d&rsquo;une unit\u00e9 pour chaque document ing\u00e9r\u00e9.<\/p>\n<p>Sur le plan des performances pures, l&rsquo;optimiseur de requ\u00eates interne de MongoDB convertit aujourd&rsquo;hui l&rsquo;\u00e9tape <code>$count<\/code> en une primitive \u00e9quivalente \u00e0 ce double groupement avec accumulateur unitaire. Cependant, l&rsquo;utilisation de <code>$count<\/code> est pr\u00e9f\u00e9rable en termes de maintenabilit\u00e9 logicielle en raison de sa clart\u00e9 d\u00e9clarative. Les deux variantes offrent une r\u00e9silience absolue face aux tr\u00e8s grands volumes de donn\u00e9es, consolidant la primaut\u00e9 du pipeline d&rsquo;agr\u00e9gation sur la commande \u00e9l\u00e9mentaire.<\/p>\n<h2>7. Filtrage conditionnel pr\u00e9alable au calcul d&rsquo;unicit\u00e9<\/h2>\n<h3>7.1 Utilisation du second argument de la m\u00e9thode distinct()<\/h3>\n<p>L&rsquo;\u00e9valuation de la cardinalit\u00e9 ne s&rsquo;ex\u00e9cute que rarement sur une collection dans sa globalit\u00e9 sans consid\u00e9ration de contexte op\u00e9rationnel. La plupart des sc\u00e9narios analytiques exigent l&rsquo;application de pr\u00e9dicats de filtrage temporel, g\u00e9ographique ou fonctionnel. Dans le cadre de la m\u00e9thode d&rsquo;aide <code>distinct()<\/code>, le deuxi\u00e8me param\u00e8tre assure pr\u00e9cis\u00e9ment cette fonction de s\u00e9lection en amont.<\/p>\n<p>Supposons que nous souhaitions quantifier le nombre de postes tactiques uniques repr\u00e9sent\u00e9s exclusivement par les joueurs affichant une moyenne offensive sup\u00e9rieure \u00e0 20 points par match. L&rsquo;instruction se structure de la mani\u00e8re suivante :<\/p>\n<p><code>db.teams.distinct(\"position\", { points: { $gt: 20 } });<\/code><\/p>\n<p>Le moteur ex\u00e9cute cette requ\u00eate en soumettant pr\u00e9alablement chaque document \u00e0 l&rsquo;\u00e9valuation du pr\u00e9dicat <code>{ points: { $gt: 20 } }<\/code>. Seuls les documents validant l&rsquo;in\u00e9quation franchissent la barri\u00e8re de filtrage. Les valeurs du champ <code>position<\/code> ne sont collect\u00e9es que sur ce sous-ensemble qualifi\u00e9. L&rsquo;\u00e9valuation de la propri\u00e9t\u00e9 <code>.length<\/code> sur ce retour produit alors la cardinalit\u00e9 s\u00e9lective souhait\u00e9e.<\/p>\n<p>Cette approche pr\u00e9sente le m\u00e9rite d&rsquo;all\u00e9ger la consommation m\u00e9moire en restreignant la taille finale du tableau BSON g\u00e9n\u00e9r\u00e9, retardant m\u00e9caniquement le franchissement du plafond d&rsquo;interruption fatale des 16 Mo. N\u00e9anmoins, l&rsquo;efficience de cette requ\u00eate demeure strictement tributaire de l&rsquo;existence d&rsquo;index optimaux pour r\u00e9soudre le pr\u00e9dicat de s\u00e9lection en amont.<\/p>\n<h3>7.2 Impl\u00e9mentation de l&rsquo;\u00e9tape $match dans le pipeline d&rsquo;agr\u00e9gation<\/h3>\n<p>Au sein du cadriciel d&rsquo;agr\u00e9gation, la prise en compte de crit\u00e8res de qualification conditionnels s&rsquo;effectue par l&rsquo;adjonction strat\u00e9gique de l&rsquo;\u00e9tape <code>$match<\/code>. Le placement de cette \u00e9tape au sommet absolu du pipeline constitue une r\u00e8gle architecturale fondamentale pour optimiser les performances d&rsquo;ex\u00e9cution :<\/p>\n<p><code>db.teams.aggregate([<br \/>\n&nbsp;&nbsp;{ <span class=\"arabpsy-math-inline\" data-latex=\"match: { points: {\">$match: { points: {$<\/span>gt: 20 } } },<br \/>\n&nbsp;&nbsp;{ <span class=\"arabpsy-math-inline\" data-latex=\"group: { _id: &quot;\">$group: { _id: \"$<\/span>position\" } },<br \/>\n&nbsp;&nbsp;{ $count: \"distinct_positions\" }<br \/>\n]);<\/code><\/p>\n<p>En positionnant l&rsquo;\u00e9tape <code>$match<\/code> en t\u00eate de cha\u00eene, le moteur d&rsquo;agr\u00e9gation exploite une optimisation interne critique : l&rsquo;\u00e9lagage pr\u00e9coce du flux documentaire (<em>early pipeline filtering<\/em>). Les documents disqualifi\u00e9s par le pr\u00e9dicat sont rejet\u00e9s avant m\u00eame d&rsquo;entrer dans la table de hachage de l&rsquo;\u00e9tape <code>$group<\/code>. L&#8217;empreinte m\u00e9moire de la structure d&rsquo;agr\u00e9gation est ainsi rigoureusement minimis\u00e9e, tout comme les cycles processeur d\u00e9di\u00e9s \u00e0 l&rsquo;\u00e9valuation des collisions d&#8217;empreintes.<\/p>\n<p>De surcro\u00eet, ce positionnement pr\u00e9liminaire est le seul qui permette \u00e0 l&rsquo;optimiseur de requ\u00eates d&rsquo;exploiter un index pr\u00e9sent sur le champ de filtrage <code>points<\/code> pour restreindre le balayage physique des pages disques, transformant l&rsquo;op\u00e9ration en une recherche ultra-rapide par bornes d&rsquo;index.<\/p>\n<h3>7.3 Comparaison de l&rsquo;efficacit\u00e9 op\u00e9rationnelle des deux approches<\/h3>\n<p>L&rsquo;arbitrage op\u00e9rationnel entre <code>distinct(field, query).length<\/code> et le pipeline <code><span class=\"arabpsy-math-inline\" data-latex=\"match -&gt;\">$match ->$<\/span>group -> $count<\/code> d\u00e9pend \u00e9troitement de la s\u00e9lectivit\u00e9 math\u00e9matique du pr\u00e9dicat appliqu\u00e9. La s\u00e9lectivit\u00e9 est d\u00e9finie comme le rapport entre le volume de documents satisfaisant le crit\u00e8re et le volume total de documents pr\u00e9sents dans la collection.<\/p>\n<p>Lorsque le pr\u00e9dicat est hautement s\u00e9lectif (ne retenant par exemple que 0,01 % des enregistrements d&rsquo;une base de dix millions de lignes), la commande <code>distinct()<\/code> filtr\u00e9e s&rsquo;ex\u00e9cute avec une v\u00e9locit\u00e9 remarquable si le filtre est index\u00e9. Le volume de donn\u00e9es distinctes final \u00e9tant minime, le tableau BSON reste tr\u00e8s largement en de\u00e7\u00e0 de la limite de 16 Mo, et le co\u00fbt de s\u00e9rialisation r\u00e9seau s&rsquo;av\u00e8re n\u00e9gligeable.<\/p>\n<p>En revanche, face \u00e0 des pr\u00e9dicats peu s\u00e9lectifs ou en pr\u00e9sence de filtres logiques complexes impliquant des jointures (<code>$lookup<\/code>) ou des d\u00e9constructions matricielles, le pipeline d&rsquo;agr\u00e9gation d\u00e9montre une sup\u00e9riorit\u00e9 op\u00e9rationnelle incontestable. Il offre une stabilit\u00e9 constante de l&rsquo;allocation m\u00e9moire serveur, pr\u00e9vient tout d\u00e9passement de tampon et prot\u00e8ge l&rsquo;infrastructure contre les variations dynamiques de s\u00e9lectivit\u00e9 cons\u00e9cutives \u00e0 l&rsquo;\u00e9volution des profils de donn\u00e9es en production.<\/p>\n<h2>8. Optimisation des performances et strat\u00e9gie d&rsquo;indexation<\/h2>\n<h3>8.1 Exploitation des index standards mono-champ<\/h3>\n<p>La performance brute d&rsquo;une interrogation d&rsquo;unicit\u00e9 dans MongoDB, qu&rsquo;elle transite par la m\u00e9thode <code>distinct()<\/code> ou par un pipeline d&rsquo;agr\u00e9gation, d\u00e9pend principalement de la topologie des index configur\u00e9s sur la collection. Sans indexation pr\u00e9alable sur le champ cible, le moteur WiredTiger est contraint d&rsquo;op\u00e9rer un balayage int\u00e9gral de la collection (<em>COLLSCAN<\/em>), ce qui implique la lecture s\u00e9quentielle de chaque document sur le disque, saturant les canaux d&rsquo;entr\u00e9es\/sorties et purgeant massivement le cache de donn\u00e9es.<\/p>\n<p>La cr\u00e9ation d&rsquo;un index standard mono-champ via la commande suivante modifie radicalement cette \u00e9quation algorithmique :<\/p>\n<p><code>db.teams.createIndex({ team: 1 });<\/code><\/p>\n<p>L&rsquo;index mat\u00e9rialise une structure d&rsquo;arbre B \u00e9quilibr\u00e9e dans laquelle toutes les cl\u00e9s d&rsquo;\u00e9quipes sont stock\u00e9es de mani\u00e8re strictement ordonn\u00e9e. Lors de l&rsquo;\u00e9valuation d&rsquo;unicit\u00e9, le planificateur de requ\u00eates d\u00e9ploie un balayage d&rsquo;index (<em>IXSCAN<\/em>). WiredTiger est capable de sauter directement d&rsquo;un n\u0153ud de valeur \u00e0 un autre au sein de la hi\u00e9rarchie de l&rsquo;arbre B sans lire les occurrences interm\u00e9diaires redondantes, r\u00e9duisant la complexit\u00e9 temporelle d&rsquo;un balayage lin\u00e9aire en <em>O(N)<\/em> \u00e0 une navigation quasi-logarithmique proportionnelle au nombre effectif de valeurs distinctes.<\/p>\n<h3>8.2 Index couvrants (Covered Queries) et unicit\u00e9<\/h3>\n<p>Le summum de l&rsquo;optimisation des performances d&rsquo;un calcul d&rsquo;unicit\u00e9 est atteint lorsque la requ\u00eate r\u00e9pond aux crit\u00e8res stricts d&rsquo;une <a rel=\"noopener noreferrer\" href=\"https:\/\/www.mongodb.com\/docs\/manual\/core\/query-optimization\/#covered-query\">requ\u00eate couverte<\/a> (<em>Covered Query<\/em>). Une requ\u00eate est qualifi\u00e9e de couverte lorsque la totalit\u00e9 des champs manipul\u00e9s par l&rsquo;op\u00e9ration \u2014 qu&rsquo;il s&rsquo;agisse des crit\u00e8res de s\u00e9lection, des cl\u00e9s de regroupement ou des projections \u2014 sont int\u00e9gralement contenus au sein des feuilles de l&rsquo;arbre d&rsquo;index.<\/p>\n<p>Dans cette configuration idoine, le moteur de stockage n&rsquo;a plus aucun besoin de deref\u00e9rencer les pointeurs vers les enregistrements de donn\u00e9es brutes sur le disque (absence d&rsquo;\u00e9tape <code>FETCH<\/code>). L&rsquo;extraction de l&rsquo;unicit\u00e9 et le d\u00e9nombrement s&rsquo;effectuent exclusivement en naviguant au sein de la m\u00e9moire allou\u00e9e aux structures d&rsquo;index. Cela \u00e9limine la quasi-totalit\u00e9 des op\u00e9rations d&rsquo;E\/S (entr\u00e9es\/sorties) physiques, conf\u00e9rant \u00e0 la requ\u00eate un temps de r\u00e9ponse de l&rsquo;ordre de la milliseconde, m\u00eame sur des collections volumineuses.<\/p>\n<p>Pour garantir la couverture d&rsquo;une requ\u00eate combinant filtrage et comptage d&rsquo;unicit\u00e9, il est indispensable de cr\u00e9er un index compos\u00e9 int\u00e9grant les champs dans l&rsquo;ordre rigoureux d&rsquo;exploitation du planificateur, par exemple <code>{ position: 1, points: 1 }<\/code>, permettant de filtrer sur le poste tout en \u00e9valuant l&rsquo;unicit\u00e9 des scores de mani\u00e8re exclusivement index\u00e9e.<\/p>\n<h3>8.3 Analyse du plan d&rsquo;ex\u00e9cution avec explain()<\/h3>\n<p>Afin de valider empiriquement l&rsquo;efficience de la strat\u00e9gie d&rsquo;acc\u00e8s aux donn\u00e9es et d&rsquo;\u00e9liminer toute approximation sp\u00e9culative, l&rsquo;outil d&rsquo;introspection diagnostique <code>explain()<\/code> est indispensable. Appliqu\u00e9 \u00e0 une cha\u00eene d&rsquo;agr\u00e9gation ou \u00e0 une commande d&rsquo;unicit\u00e9 avec le niveau de d\u00e9tail <em>executionStats<\/em>, il d\u00e9voile la r\u00e9alit\u00e9 intime du travail accompli par le moteur :<\/p>\n<p><code>db.teams.explain(\"executionStats\").distinct(\"team\");<\/code><\/p>\n<p>L&rsquo;analyse du document de diagnostic retourn\u00e9 requiert une attention particuli\u00e8re port\u00e9e \u00e0 deux m\u00e9triques n\u00e9vralgiques : <code>totalKeysExamined<\/code> et <code>totalDocsExamined<\/code>. Dans un sc\u00e9nario id\u00e9al d&rsquo;indexation couvrante, la m\u00e9trique <code>totalDocsExamined<\/code> doit \u00eatre rigoureusement \u00e9gale \u00e0 z\u00e9ro, attestant qu&rsquo;aucun document de donn\u00e9es physiques n&rsquo;a \u00e9t\u00e9 charg\u00e9 depuis le stockage persistant.<\/p>\n<p>Si l&rsquo;indicateur <code>totalDocsExamined<\/code> \u00e9quivaut au nombre total de documents de la collection, cela signale un balayage non index\u00e9 critique (<em>COLLSCAN<\/em>), caract\u00e9ris\u00e9 par un gaspillage substantiel de ressources processeur. La pr\u00e9sence de l&rsquo;\u00e9tape <code>PROJECTION_COVERED<\/code> ou d&rsquo;un n\u0153ud d&rsquo;acc\u00e8s direct aux cl\u00e9s confirme que l&rsquo;infrastructure exploite l&rsquo;architecture mat\u00e9rielle \u00e0 son potentiel d&rsquo;optimisation maximal.<\/p>\n<h2>9. Gestion des valeurs manquantes, nulles et des structures imbriqu\u00e9es<\/h2>\n<h3>9.1 Traitement rigoureux des valeurs null et des champs absents<\/h3>\n<p>L&rsquo;une des singularit\u00e9s structurelles de MongoDB r\u00e9side dans son absence de rigidit\u00e9 de sch\u00e9ma : au sein d&rsquo;une m\u00eame collection, un champ sp\u00e9cifique peut \u00eatre valoris\u00e9 sous forme scalaire, contenir la valeur litt\u00e9rale <code>null<\/code>, ou \u00eatre totalement absent du document physique. Ce comportement polymorphe impacte directement les op\u00e9rations de d\u00e9nombrement d&rsquo;unicit\u00e9.<\/p>\n<p>Par d\u00e9faut, la m\u00e9thode <code>distinct()<\/code> ainsi que l&rsquo;op\u00e9rateur <code>$group<\/code> assimilent l&rsquo;absence d&rsquo;un champ \u00e0 une valeur nulle implicite. Par cons\u00e9quent, si certains documents omettent l&rsquo;attribut interrog\u00e9 tandis que d&rsquo;autres lui assignent explicitement la valeur <code>null<\/code>, ces deux \u00e9tats sont fusionn\u00e9s en une occurrence unique <code>null<\/code> au sein du r\u00e9sultat d&rsquo;unicit\u00e9. Si l&rsquo;analyste cherche \u00e0 \u00e9valuer la cardinalit\u00e9 des valeurs r\u00e9elles sans fausser le d\u00e9compte statistique par la pr\u00e9sence de marqueurs d&rsquo;absence, une exclusion explicite est requise :<\/p>\n<p><code>db.teams.aggregate([<br \/>\n&nbsp;&nbsp;{ <span class=\"arabpsy-math-inline\" data-latex=\"match: { team: {\">$match: { team: {$<\/span>exists: true, $ne: null } } },<br \/>\n&nbsp;&nbsp;{ <span class=\"arabpsy-math-inline\" data-latex=\"group: { _id: &quot;\">$group: { _id: \"$<\/span>team\" } },<br \/>\n&nbsp;&nbsp;{ $count: \"valid_teams\" }<br \/>\n]);<\/code><\/p>\n<p>Ce filtrage rigoureux garantit que seuls les enregistrements porteurs d&rsquo;une s\u00e9mantique informative effective participent \u00e0 l&rsquo;agr\u00e9gation, assurant ainsi une int\u00e9grit\u00e9 math\u00e9matique absolue aux m\u00e9triques de gouvernance des donn\u00e9es.<\/p>\n<h3>9.2 Extraction d&rsquo;unicit\u00e9 sur les sous-documents et objets incorpor\u00e9s<\/h3>\n<p>La puissance du mod\u00e8le orient\u00e9 documents r\u00e9side dans sa capacit\u00e9 \u00e0 encapsuler des structures d&rsquo;objets imbriqu\u00e9es. L&rsquo;\u00e9valuation de l&rsquo;unicit\u00e9 sur ces champs profonds ne requiert aucune d\u00e9construction manuelle pr\u00e9alable ; elle s&rsquo;ex\u00e9cute nativement via la notation point\u00e9e (<em>dot notation<\/em>).<\/p>\n<p>Supposons que nos documents <code>teams<\/code> int\u00e8grent un sous-document mod\u00e9lisant les donn\u00e9es biom\u00e9triques ou contractuelles, tel que <code>{ details: { division: \"Central\", conference: \"East\" } }<\/code>. L&rsquo;acc\u00e8s \u00e0 la cardinalit\u00e9 des conf\u00e9rences s&rsquo;articule de mani\u00e8re directe au sein du cadriciel :<\/p>\n<p><code>db.teams.distinct(\"details.conference\");<\/code><\/p>\n<p>Ou, en version streaming r\u00e9siliente :<\/p>\n<p><code>db.teams.aggregate([<br \/>\n&nbsp;&nbsp;{ <span class=\"arabpsy-math-inline\" data-latex=\"group: { _id: &quot;\">$group: { _id: \"$<\/span>details.conference\" } },<br \/>\n&nbsp;&nbsp;{ $count: \"total_conferences\" }<br \/>\n]);<\/code><\/p>\n<p>Il importe toutefois de souligner que si l&rsquo;objet parent <code>details<\/code> est manquant ou ne contient pas la propri\u00e9t\u00e9 cibl\u00e9e, la valeur r\u00e9solue basculera vers le comportement d&rsquo;absence \u00e9voqu\u00e9 pr\u00e9c\u00e9demment. Une indexation sp\u00e9cifique sur le chemin compos\u00e9 complet (par exemple <code>{ \"details.conference\": 1 }<\/code>) demeure indispensable pour pr\u00e9server les performances d&rsquo;extraction en profondeur.<\/p>\n<h3>9.3 Cas sp\u00e9cifique des tableaux et op\u00e9rateurs d&rsquo;aplatissement<\/h3>\n<p>L&rsquo;\u00e9valuation de la cardinalit\u00e9 devient substantiellement plus complexe lorsqu&rsquo;un champ contient des structures matricielles sous forme de tableaux (<em>arrays<\/em>). Si un joueur poss\u00e8de un tableau de comp\u00e9tences ou de r\u00e9compenses, tel que <code>{ awards: [\"All-Star\", \"MVP\"] }<\/code>, l&rsquo;application directe de <code>distinct(\"awards\")<\/code> adopte un comportement automatique particulier : MongoDB d\u00e9roule implicitement le tableau et renvoie l&rsquo;ensemble d\u00e9dupliqu\u00e9 de tous les \u00e9l\u00e9ments individuels constitutifs.<\/p>\n<p>Cependant, si l&rsquo;on souhaite r\u00e9aliser cette op\u00e9ration via le cadriciel d&rsquo;agr\u00e9gation, le comportement de base de <code>$group<\/code> diff\u00e8re : il consid\u00e9rera le tableau dans son int\u00e9gralit\u00e9 atomique comme cl\u00e9 de regroupement (ainsi, <code>[\"All-Star\", \"MVP\"]<\/code> sera distingu\u00e9 de <code>[\"MVP\", \"All-Star\"]<\/code> ou de <code>[\"MVP\"]<\/code>). Pour mesurer la cardinalit\u00e9 exacte des \u00e9l\u00e9ments individuels diss\u00e9min\u00e9s dans tous les tableaux de la collection, il est imp\u00e9ratif d&rsquo;injecter explicitement l&rsquo;\u00e9tape d&rsquo;aplatissement <code>$unwind<\/code> :<\/p>\n<p><code>db.teams.aggregate([<br \/>\n&nbsp;&nbsp;{ <span class=\"arabpsy-math-inline\" data-latex=\"unwind: &quot;\">$unwind: \"$<\/span>awards\" },<br \/>\n&nbsp;&nbsp;{ <span class=\"arabpsy-math-inline\" data-latex=\"group: { _id: &quot;\">$group: { _id: \"$<\/span>awards\" } },<br \/>\n&nbsp;&nbsp;{ $count: \"distinct_awards\" }<br \/>\n]);<\/code><\/p>\n<p>L&rsquo;op\u00e9rateur <code>$unwind<\/code> d\u00e9construit chaque tableau en dupliquant le document parent autant de fois qu&rsquo;il contient d&rsquo;\u00e9l\u00e9ments scalaires. Cette \u00e9tape induit un co\u00fbt calculatoire substantiel en termes de charge processeur et de d\u00e9bit m\u00e9moire temporaire. Son usage doit faire l&rsquo;objet d&rsquo;un dimensionnement pr\u00e9visionnel rigoureux lorsqu&rsquo;il est appliqu\u00e9 \u00e0 des collections h\u00e9bergeant des tableaux \u00e0 forte granularit\u00e9.<\/p>\n<h2>10. Patterns alternatifs : Accumulation par ensembles et $addToSet<\/h2>\n<h3>10.1 Fonctionnement de l&rsquo;op\u00e9rateur accumulateur $addToSet<\/h3>\n<p>Au sein du cadriciel d&rsquo;agr\u00e9gation, l&rsquo;op\u00e9rateur accumulateur <code>$addToSet<\/code> repr\u00e9sente une alternative \u00e9l\u00e9gante pour collecter et isoler des valeurs uniques au fil du flux de traitement. Contrairement \u00e0 l&rsquo;accumulateur standard <code>$push<\/code> qui agr\u00e8ge l&rsquo;ensemble des \u00e9l\u00e9ments sans contr\u00f4le de redondance, <code>$addToSet<\/code> n&rsquo;ajoute un \u00e9l\u00e9ment au tableau r\u00e9sultant que si et seulement si celui-ci n&rsquo;y figure pas d\u00e9j\u00e0.<\/p>\n<p>Combin\u00e9 \u00e0 l&rsquo;op\u00e9rateur arithm\u00e9tique <code>$size<\/code>, <code>$addToSet<\/code> permet de calculer la cardinalit\u00e9 d&rsquo;un attribut de fa\u00e7on concise au sein d&rsquo;une seule et m\u00eame \u00e9tape d&rsquo;agr\u00e9gation group\u00e9e. L&rsquo;instruction s&rsquo;exprime selon le motif suivant :<\/p>\n<p><code>db.teams.aggregate([<br \/>\n&nbsp;&nbsp;{<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;$group: {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_id: null,<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unique_positions: { <span class=\"arabpsy-math-inline\" data-latex=\"addToSet: &quot;\">$addToSet: \"$<\/span>position\" }<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;}<br \/>\n&nbsp;&nbsp;},<br \/>\n&nbsp;&nbsp;{<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;$project: {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;total_distinct: { <span class=\"arabpsy-math-inline\" data-latex=\"size: &quot;\">$size: \"$<\/span>unique_positions\" }<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;}<br \/>\n&nbsp;&nbsp;}<br \/>\n]);<\/code><\/p>\n<p>Ce motif construit un tableau dynamique d\u00e9dupliqu\u00e9 au sein d&rsquo;un document temporaire unique, puis en extrait imm\u00e9diatement la taille scalaire via <code>$size<\/code> lors de la phase de projection finale. Il fournit un r\u00e9sultat identique \u00e0 la combinaison <code>$group<\/code> et <code>$count<\/code>, tout en offrant une grammaire famili\u00e8re aux d\u00e9veloppeurs habitu\u00e9s aux structures ensemblistes (<em>Sets<\/em>) des langages de haut niveau.<\/p>\n<h3>10.2 Analyse critique face au risque de saturation m\u00e9moire<\/h3>\n<p>En d\u00e9pit de sa commodit\u00e9 conceptuelle, le recours au pattern <code>$addToSet<\/code> doit \u00eatre accompagn\u00e9 d&rsquo;une vigilance extr\u00eame quant \u00e0 la volum\u00e9trie des donn\u00e9es trait\u00e9es. En effet, l&rsquo;op\u00e9rateur <code>$addToSet<\/code> construit physiquement un tableau BSON au sein de la m\u00e9moire vive du processus serveur durant l&rsquo;\u00e9tape de regroupement.<\/p>\n<p>Si la cardinalit\u00e9 de l&rsquo;attribut agr\u00e9g\u00e9 est telle que la concat\u00e9nation de toutes ses valeurs uniques exc\u00e8de le seuil de 16 m\u00e9gaoctets, l&rsquo;agr\u00e9gation s&rsquo;effondrera avec la m\u00eame exception fatale de d\u00e9passement de limite de document que celle constat\u00e9e avec <code>db.collection.distinct()<\/code>. De surcro\u00eet, la v\u00e9rification d&rsquo;unicit\u00e9 \u00e0 chaque insertion dans le tableau interne pr\u00e9sente une complexit\u00e9 temporelle quadratique ou logarithmique selon la nature de la structure interne, augmentant drastiquement la charge CPU par rapport au hachage direct op\u00e9r\u00e9 par une \u00e9tape <code><span class=\"arabpsy-math-inline\" data-latex=\"group: { _id: &quot;\">$group: { _id: \"$<\/span>field\" }<\/code>.<\/p>\n<p>Le recours \u00e0 <code>$addToSet<\/code> combin\u00e9 \u00e0 <code>$size<\/code> doit donc \u00eatre strictement r\u00e9serv\u00e9 \u00e0 des ensembles dont on a la certitude math\u00e9matique absolue que la cardinalit\u00e9 demeure mod\u00e9r\u00e9e, ou lorsqu&rsquo;il est utilis\u00e9 au sein de regroupements partitionn\u00e9s o\u00f9 chaque sous-groupe n&rsquo;h\u00e9berge qu&rsquo;une fraction contenue de valeurs uniques.<\/p>\n<h3>10.3 Application au comptage distinct group\u00e9 par dimension<\/h3>\n<p>La v\u00e9ritable puissance de <code>$addToSet<\/code> s&rsquo;exprime dans les cas d&rsquo;usage analytiques multidimensionnels o\u00f9 l&rsquo;on souhaite quantifier la cardinalit\u00e9 d&rsquo;un champ non pas sur toute la collection, mais ventil\u00e9e par une autre dimension cat\u00e9gorielle (\u00e9quivalent fonctionnel d&rsquo;un <em>COUNT(DISTINCT position) GROUP BY team<\/em> en SQL).<\/p>\n<p>Illustrons cette capacit\u00e9 en calculant le nombre exact de postes tactiques distincts mobilis\u00e9s par chaque \u00e9quipe au sein de notre jeu d&rsquo;essai :<\/p>\n<p><code>db.teams.aggregate([<br \/>\n&nbsp;&nbsp;{<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;$group: {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_id: \"$team\",<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;distinct_positions: { <span class=\"arabpsy-math-inline\" data-latex=\"addToSet: &quot;\">$addToSet: \"$<\/span>position\" }<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;}<br \/>\n&nbsp;&nbsp;},<br \/>\n&nbsp;&nbsp;{<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;$project: {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;team: \"$_id\",<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;position_count: { <span class=\"arabpsy-math-inline\" data-latex=\"size: &quot;\">$size: \"$<\/span>distinct_positions\" },<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_id: 0<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;}<br \/>\n&nbsp;&nbsp;}<br \/>\n]);<\/code><\/p>\n<p>Le r\u00e9sultat produit fournit une vue matricielle parfaitement segment\u00e9e :<\/p>\n<p><code>[<br \/>\n&nbsp;&nbsp;{ \"team\": \"Cavs\", \"position_count\": 2 },<br \/>\n&nbsp;&nbsp;{ \"team\": \"Mavs\", \"position_count\": 3 },<br \/>\n&nbsp;&nbsp;{ \"team\": \"Rockets\", \"position_count\": 2 }<br \/>\n]<\/code><\/p>\n<p>Dans ce sc\u00e9nario d&rsquo;usage analytique, la commande <code>distinct()<\/code> native s&rsquo;av\u00e8re totalement impuissante, car elle ne permet pas d&rsquo;op\u00e9rer des agr\u00e9gations matricielles crois\u00e9es. Le cadriciel d&rsquo;agr\u00e9gation s&rsquo;impose comme la seule infrastructure capable de d\u00e9livrer simultan\u00e9ment la d\u00e9duplication locale, le d\u00e9nombrement scalaire et la projection multidimensionnelle.<\/p>\n<h2>11. Approches probabilistes et estimation de cardinalit\u00e9 pour le Big Data<\/h2>\n<h3>11.1 Limites inh\u00e9rentes au comptage d\u00e9terministe exact<\/h3>\n<p>Lorsque les architectures de donn\u00e9es franchissent le cap des \u00e9chelles industrielles massives \u2014 collections h\u00e9bergeant des dizaines de milliards de documents, logs de t\u00e9l\u00e9m\u00e9trie de dispositifs IoT ou flux d&rsquo;\u00e9v\u00e9nements publicitaires en temps r\u00e9el \u2014, le calcul d\u00e9terministe exact de la cardinalit\u00e9 se heurte \u00e0 des barri\u00e8res physiques fondamentales.<\/p>\n<p>Sur le plan th\u00e9orique, tout algorithme de comptage exact n\u00e9cessite une quantit\u00e9 d&rsquo;espace m\u00e9moire proportionnelle \u00e0 la cardinalit\u00e9 r\u00e9elle de l&rsquo;ensemble \u00e0 \u00e9valuer, ob\u00e9issant \u00e0 une borne spatiale en <em>O(N)<\/em> ou <em>O(D)<\/em> (o\u00f9 <em>D<\/em> repr\u00e9sente le nombre d&rsquo;\u00e9l\u00e9ments distincts). Maintenir en m\u00e9moire vive des tables de hachage consolidant des centaines de millions d&#8217;empreintes d&rsquo;adresses IP ou d&rsquo;identifiants de terminaux monopolise des dizaines de gigaoctets de RAM, d\u00e9grade drastiquement le d\u00e9bit transactionnel global et contraint les clusters \u00e0 des dimensionnements mat\u00e9riels excessivement on\u00e9reux.<\/p>\n<p>Cette r\u00e9alit\u00e9 physique impose un arbitrage rationnel au c\u0153ur du g\u00e9nie logiciel moderne : renoncer \u00e0 l&rsquo;exactitude absolue au profit d&rsquo;une estimation statistique ultrarapide, caract\u00e9ris\u00e9e par une marge d&rsquo;erreur ma\u00eetris\u00e9e et une consommation de m\u00e9moire constante et infinit\u00e9simale.<\/p>\n<h3>11.2 Introduction aux algorithmes de type HyperLogLog<\/h3>\n<p>Pour r\u00e9pondre \u00e0 cette probl\u00e9matique d&rsquo;\u00e9chelle, les algorithmes d&rsquo;estimation probabiliste de cardinalit\u00e9, au premier rang desquels figure le c\u00e9l\u00e8bre algorithme <a rel=\"noopener noreferrer\" href=\"https:\/\/hal.archives-ouvertes.fr\/hal-00406166\/\">HyperLogLog (HLL)<\/a> d\u00e9velopp\u00e9 par Philippe Flajolet et ses collaborateurs, ont r\u00e9volutionn\u00e9 l&rsquo;ing\u00e9nierie des donn\u00e9es massives. L&rsquo;algorithme repose sur une observation probabiliste remarquable : la distribution des s\u00e9quences de z\u00e9ros cons\u00e9cutifs au d\u00e9but de l&#8217;empreinte binaire hach\u00e9e d&rsquo;une valeur permet d&rsquo;estimer avec une pr\u00e9cision statistique extr\u00eame le nombre d&rsquo;\u00e9l\u00e9ments distincts ayant \u00e9t\u00e9 soumis au hacheur.<\/p>\n<p>Avec une empreinte m\u00e9moire fixe de seulement quelques kilo-octets (typiquement 1,5 Ko), HyperLogLog est capable d&rsquo;estimer la cardinalit\u00e9 d&rsquo;un ensemble de plusieurs milliards d&rsquo;enregistrements avec une marge d&rsquo;erreur relative th\u00e9orique inf\u00e9rieure \u00e0 1 %. Bien que MongoDB n&rsquo;int\u00e8gre pas \u00e0 ce jour d&rsquo;op\u00e9rateur natif <code>$hyperLogLog<\/code> directement accessible au sein de son cadriciel d&rsquo;agr\u00e9gation standard, il est fr\u00e9quent dans les architectures avanc\u00e9es d&rsquo;adosser MongoDB \u00e0 des moteurs d&rsquo;acc\u00e9l\u00e9ration ou d&rsquo;exporter les flux d&rsquo;agr\u00e9gation vers des modules d&rsquo;accumulation probabiliste h\u00e9berg\u00e9s dans des caches distribu\u00e9s comme Redis ou des moteurs de s\u00e9ries temporelles.<\/p>\n<p>Ces m\u00e9canismes hybrides permettent aux plateformes de traitement de donn\u00e9es volumineuses de fournir des m\u00e9triques d&rsquo;utilisateurs actifs journaliers (<em>Daily Active Users<\/em>) ou d&rsquo;impressions publicitaires distinctes avec une r\u00e9activit\u00e9 sub-seconde, sans jamais contraindre le cluster de stockage sous-jacent \u00e0 des balayages ensemblistes exhaustifs destructeurs de performances.<\/p>\n<h3>11.3 Mise en \u0153uvre d&rsquo;approches d&rsquo;\u00e9chantillonnage avec $sample<\/h3>\n<p>Au sein des fonctionnalit\u00e9s natives de MongoDB, une m\u00e9thode pragmatique pour contourner la lourdeur d&rsquo;un comptage exact consiste \u00e0 op\u00e9rer une estimation statistique par \u00e9chantillonnage al\u00e9atoire au moyen de l&rsquo;\u00e9tape <code>$sample<\/code> du pipeline d&rsquo;agr\u00e9gation. Cette approche permet de projeter la cardinalit\u00e9 d&rsquo;un champ volumineux \u00e0 partir d&rsquo;un sous-ensemble repr\u00e9sentatif de documents :<\/p>\n<p><code>db.teams.aggregate([<br \/>\n&nbsp;&nbsp;{ $sample: { size: 1000 } },<br \/>\n&nbsp;&nbsp;{ <span class=\"arabpsy-math-inline\" data-latex=\"group: { _id: &quot;\">$group: { _id: \"$<\/span>position\" } },<br \/>\n&nbsp;&nbsp;{ $count: \"sampled_distinct\" }<br \/>\n]);<\/code><\/p>\n<p>En analysant la proportion de valeurs distinctes observ\u00e9e au sein d&rsquo;un \u00e9chantillon al\u00e9atoire de taille <em>n<\/em> rapport\u00e9e \u00e0 la taille globale de la collection <em>N<\/em>, les statisticiens de donn\u00e9es peuvent appliquer des mod\u00e8les pr\u00e9dictifs d&rsquo;estimation de population (tels que l&rsquo;estimateur de Good-Turing ou les mod\u00e8les de capture-recapture) pour d\u00e9river une approximation hautement fiable de la cardinalit\u00e9 totale.<\/p>\n<p>Cette technique pr\u00e9sente l&rsquo;avantage d\u00e9cisif d&rsquo;encadrer rigoureusement le co\u00fbt d&rsquo;ex\u00e9cution de la requ\u00eate : celle-ci n&rsquo;inspecte qu&rsquo;un nombre pr\u00e9d\u00e9termin\u00e9 et constant de documents, pr\u00e9servant la stabilit\u00e9 op\u00e9rationnelle du cluster MongoDB m\u00eame en p\u00e9riode de pic de charge applicatif intense.<\/p>\n<h2>12. Synth\u00e8se m\u00e9thodologique et arbre d\u00e9cisionnel en environnement de production<\/h2>\n<h3>12.1 Matrice comparative des m\u00e9thodes d&rsquo;\u00e9valuation d&rsquo;unicit\u00e9<\/h3>\n<p>Pour guider les d\u00e9veloppeurs et les ing\u00e9nieurs d&rsquo;infrastructure dans la s\u00e9lection de la m\u00e9thode la plus appropri\u00e9e \u00e0 leurs contraintes op\u00e9rationnelles, le tableau synoptique suivant dresse une analyse comparative des diff\u00e9rentes approches explor\u00e9es :<\/p>\n<table border=\"1\" cellpadding=\"8\" cellspacing=\"0\" style=\"border-collapse: collapse; width: 100%; text-align: left;\">\n<thead>\n<tr style=\"background-color: #f2f2f2;\">\n<th>M\u00e9canisme<\/th>\n<th>Lieu du Calcul<\/th>\n<th>Risque de Saturation (16 Mo)<\/th>\n<th>Consommation Bande Passante<\/th>\n<th>Complexit\u00e9 Typique<\/th>\n<th>Usage Recommand\u00e9<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>db.collection.distinct(f).length<\/strong><\/td>\n<td>C\u00f4t\u00e9 Client<\/td>\n<td>Critique (\u00c9chec si r\u00e9sultats &gt; 16 Mo)<\/td>\n<td>\u00c9lev\u00e9e (Transfert de toutes les cl\u00e9s)<\/td>\n<td>Faible (Syntaxe simple)<\/td>\n<td>Champs \u00e0 tr\u00e8s faible cardinalit\u00e9 (&lt; 10 000) et scripts l\u00e9gers<\/td>\n<\/tr>\n<tr>\n<td><strong>Pipeline <span class=\"arabpsy-math-inline\" data-latex=\"group +\">$group +$<\/span>count<\/strong><\/td>\n<td>C\u00f4t\u00e9 Serveur<\/td>\n<td>Nul (Ex\u00e9cution en streaming r\u00e9siliente)<\/td>\n<td>Optimale (Transfert d&rsquo;un unique entier)<\/td>\n<td>Moyenne (Conception de pipeline)<\/td>\n<td>Production critique, analytique robuste et gros volumes<\/td>\n<\/tr>\n<tr>\n<td><strong>Pipeline <span class=\"arabpsy-math-inline\" data-latex=\"addToSet +\">$addToSet +$<\/span>size<\/strong><\/td>\n<td>C\u00f4t\u00e9 Serveur<\/td>\n<td>\u00c9lev\u00e9 (\u00c9chec si un groupe &gt; 16 Mo)<\/td>\n<td>Mod\u00e9r\u00e9e \u00e0 Faible<\/td>\n<td>Moyenne<\/td>\n<td>Comptage distinct group\u00e9 par dimension (GROUP BY)<\/td>\n<\/tr>\n<tr>\n<td><strong>\u00c9chantillonnage probabiliste ($sample)<\/strong><\/td>\n<td>C\u00f4t\u00e9 Serveur<\/td>\n<td>Nul (Contr\u00f4le strict du volume d&rsquo;entr\u00e9e)<\/td>\n<td>Optimale<\/td>\n<td>\u00c9lev\u00e9e (N\u00e9cessite calculs statistiques)<\/td>\n<td>Big Data massif, m\u00e9triques exploratoires et monitoring<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>L&rsquo;analyse de cette matrice met en exergue l&rsquo;h\u00e9g\u00e9monie structurelle du pipeline combinant <code>$group<\/code> et <code>$count<\/code> pour tout d\u00e9veloppement applicatif d&rsquo;entreprise, rel\u00e9guant la commande \u00e9l\u00e9mentaire <code>distinct()<\/code> au rang de simple commodit\u00e9 d&rsquo;inspection pour les environnements de test et de prototypage rapide.<\/p>\n<h3>12.2 Bonnes pratiques de codage et r\u00e9silience applicative<\/h3>\n<p>La mise en \u0153uvre de requ\u00eates d&rsquo;unicit\u00e9 au sein d&rsquo;environnements transactionnels critiques requiert l&rsquo;application stricte de r\u00e8gles de gouvernance technique destin\u00e9es \u00e0 garantir l&rsquo;immunit\u00e9 du cluster contre les d\u00e9gradations de service. La premi\u00e8re r\u00e8gle fondamentale consiste \u00e0 syst\u00e9matiquement contraindre le temps d&rsquo;ex\u00e9cution des requ\u00eates analytiques en leur assignant une valeur de d\u00e9lai limite stricte au moyen de l&rsquo;option <code>maxTimeMS()<\/code> :<\/p>\n<p><code>db.teams.aggregate([<br \/>\n&nbsp;&nbsp;{ <span class=\"arabpsy-math-inline\" data-latex=\"group: { _id: &quot;\">$group: { _id: \"$<\/span>team\" } },<br \/>\n&nbsp;&nbsp;{ $count: \"total_distinct\" }<br \/>\n], { maxTimeMS: 2000 });<\/code><\/p>\n<p>Cette garde-fou op\u00e9rationnel garantit qu&rsquo;une requ\u00eate d&rsquo;agr\u00e9gation pathologique \u2014 d\u00e9clench\u00e9e par exemple sur un champ non index\u00e9 au sein d&rsquo;une collection ayant connu une croissance impr\u00e9vue \u2014 soit pr\u00e9emptivement interrompue par le serveur apr\u00e8s l&rsquo;\u00e9coulement de deux secondes, \u00e9vitant ainsi le blocage prolong\u00e9 des threads de lecture de la base de donn\u00e9es.<\/p>\n<p>D&rsquo;autre part, la gestion d&rsquo;erreurs au niveau des pilotes applicatifs doit imp\u00e9rativement intercepter les exceptions d&rsquo;interruption et mettre en place des strat\u00e9gies de repli transparentes (<em>fallback<\/em>), telles que le renvoi d&rsquo;une valeur issue d&rsquo;un cache applicatif mis \u00e0 jour p\u00e9riodiquement de mani\u00e8re asynchrone par un travail d&rsquo;arri\u00e8re-plan (<em>background worker<\/em>).<\/p>\n<h3>12.3 Checklist de d\u00e9ploiement pour ing\u00e9nieurs de donn\u00e9es<\/h3>\n<p>Avant d&rsquo;autoriser la mise en production d&rsquo;une fonctionnalit\u00e9 reposant sur le calcul ou le d\u00e9nombrement de valeurs distinctes, les \u00e9quipes d&rsquo;ing\u00e9nierie doivent valider m\u00e9thodiquement les points de contr\u00f4le suivants :<\/p>\n<ul>\n<li><strong>V\u00e9rification d&rsquo;Indexation :<\/strong> Un index compos\u00e9 appropri\u00e9 supporte-t-il l&rsquo;ensemble des pr\u00e9dicats de filtrage ainsi que le champ d&rsquo;unicit\u00e9 lui-m\u00eame, garantissant l&rsquo;absence de toute \u00e9tape <em>COLLSCAN<\/em> ?<\/li>\n<li><strong>Validation Couvrante :<\/strong> Le plan d&rsquo;ex\u00e9cution valid\u00e9 via <code>explain(\"executionStats\")<\/code> confirme-t-il un indicateur <code>totalDocsExamined: 0<\/code> pour les requ\u00eates \u00e0 haute fr\u00e9quence ?<\/li>\n<li><strong>Tol\u00e9rance Volum\u00e9trique :<\/strong> La commande utilise-t-elle le pipeline d&rsquo;agr\u00e9gation r\u00e9silient (<code>$group<\/code> + <code>$count<\/code>) au d\u00e9triment exclusif de <code>distinct().length<\/code> pour pr\u00e9venir tout plantage li\u00e9 \u00e0 la limite BSON de 16 Mo ?<\/li>\n<li><strong>Politique de Lecture R\u00e9partie :<\/strong> La pr\u00e9f\u00e9rence de lecture (<em>readPreference<\/em>) est-elle configur\u00e9e sur <code>secondaryPreferred<\/code> ou <code>secondary<\/code> afin de d\u00e9charger le n\u0153ud primaire (<em>Primary<\/em>) du cluster de la charge calculatoire lourde associ\u00e9e aux agr\u00e9gations d&rsquo;unicit\u00e9 ?<\/li>\n<li><strong>Surveillance et T\u00e9l\u00e9m\u00e9trie :<\/strong> Les op\u00e9rations d&rsquo;agr\u00e9gation sont-elles surveill\u00e9es au sein d&rsquo;outils de monitoring tels que MongoDB Atlas Performance Advisor, garantissant la d\u00e9tection pr\u00e9coce des requ\u00eates lentes exc\u00e9dant les seuils de tol\u00e9rance d\u00e9finis ?<\/li>\n<\/ul>\n<p>En observant scrupuleusement ces directives m\u00e9thodologiques, les architectures de bases de donn\u00e9es distribu\u00e9es bas\u00e9es sur MongoDB conservent des performances d\u00e9terministes, une haute disponibilit\u00e9 et une scalabilit\u00e9 pr\u00e9visible, transformant un calcul d&rsquo;unicit\u00e9 complexe en une op\u00e9ration fluide et robuste au sein du syst\u00e8me d&rsquo;information moderne.<\/p>\n<h2>R\u00e9f\u00e9rences<\/h2>\n<p>Barga, R., Nathan, S., &amp; Raghavan, C. (2020). <em>Database Internals and Distributed Systems Architectures<\/em>. O&rsquo;Reilly Media.<\/p>\n<p>Chodorow, K. (2013). <em>MongoDB: The Definitive Guide<\/em> (2nd ed.). O&rsquo;Reilly Media. <a rel=\"noopener noreferrer\" href=\"https:\/\/www.oreilly.com\/library\/view\/mongodb-the-definitive\/9781449344795\/\">https:\/\/www.oreilly.com\/library\/view\/mongodb-the-definitive\/9781449344795\/<\/a><\/p>\n<p>Flajolet, P., Fusy, \u00c9., Gandouet, O., &amp; Meunier, F. (2007). HyperLogLog: The analysis of a near-optimal cardinality estimation algorithm. <em>Discrete Mathematics and Theoretical Computer Science<\/em>, AH, 137\u2013156. <a rel=\"noopener noreferrer\" href=\"https:\/\/hal.archives-ouvertes.fr\/hal-00406166\/\">https:\/\/hal.archives-ouvertes.fr\/hal-00406166\/<\/a><\/p>\n<p>MongoDB Documentation Team. (2024). <em>db.collection.distinct() Reference Manual<\/em>. MongoDB Inc. <a rel=\"noopener noreferrer\" href=\"https:\/\/www.mongodb.com\/docs\/manual\/reference\/method\/db.collection.distinct\/\">https:\/\/www.mongodb.com\/docs\/manual\/reference\/method\/db.collection.distinct\/<\/a><\/p>\n<p>MongoDB Documentation Team. (2024). <em>Aggregation Pipeline Stages: $group<\/em>. MongoDB Inc. <a rel=\"noopener noreferrer\" href=\"https:\/\/www.mongodb.com\/docs\/manual\/reference\/operator\/aggregation\/group\/\">https:\/\/www.mongodb.com\/docs\/manual\/reference\/operator\/aggregation\/group\/<\/a><\/p>\n<p>MongoDB Documentation Team. (2024). <em>Aggregation Pipeline Stages: $count<\/em>. MongoDB Inc. <a rel=\"noopener noreferrer\" href=\"https:\/\/www.mongodb.com\/docs\/manual\/reference\/operator\/aggregation\/count\/\">https:\/\/www.mongodb.com\/docs\/manual\/reference\/operator\/aggregation\/count\/<\/a><\/p>\n<p>Shannon, C. E. (1948). A mathematical theory of communication. <em>Bell System Technical Journal<\/em>, 27(3), 379\u2013423. <a rel=\"noopener noreferrer\" href=\"https:\/\/ieeexplore.ieee.org\/document\/6773024\">https:\/\/ieeexplore.ieee.org\/document\/6773024<\/a><\/p>\n<p>WiredTiger Development Team. (2023). <em>WiredTiger Architecture and Tuning Guide<\/em>. MongoDB Inc. <a rel=\"noopener noreferrer\" href=\"https:\/\/source.wiredtiger.com\/\">https:\/\/source.wiredtiger.com\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Guide acad\u00e9mique complet pour identifier et compter les valeurs distinctes dans un champ MongoDB \u00e0 l&rsquo;aide de la m\u00e9thode distinct et des agr\u00e9gations avanc\u00e9es.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","template":"","categories":[8097,8098],"tags":[8274,6219,8100,8102,8275],"class_list":["post-6796","psych_stat","type-psych_stat","status-publish","hentry","category-bases-de-donnees","category-mongodb","tag-aggregation-framework","tag-distinct","tag-mongodb","tag-nosql","tag-performance-base-de-donnees"],"_links":{"self":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/6796","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat"}],"about":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/types\/psych_stat"}],"author":[{"embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6796"}],"version-history":[{"count":1,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/6796\/revisions"}],"predecessor-version":[{"id":16830,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/6796\/revisions\/16830"}],"wp:attachment":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6796"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6796"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6796"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}