Cela mérite peut-être une explication complète pour ceux qui pourraient rechercher cela, donc en ajouter une pour la postérité.
Plus précisément, ce qui est renvoyé est un flux d'événements pour node.js qui encapsule efficacement le stream.Readable interface avec quelques méthodes pratiques. Un .count()
n'en fait pas partie pour le moment et compte tenu de l'interface actuellement utilisée, cela n'aurait pas beaucoup de sens.
Semblable au résultat renvoyé par le .stream()
méthode disponible pour les objets curseur, un "compte" n'aurait pas beaucoup de sens ici lorsque vous considérez l'implémentation, car il est censé être traité comme un "flux" où vous finirez par atteindre une "fin" mais sinon vous voulez juste traiter jusqu'à y arriver.
Si vous considérez l'interface "Curseur" standard du pilote, il existe de bonnes raisons pour lesquelles le curseur d'agrégation n'est pas le même :
-
Les curseurs permettent aux actions "modificateurs" d'être traitées avant l'exécution. Ceux-ci entrent dans les catégories de
.sort()
,.limit()
et.skip()
. Tous ces éléments ont en fait des directives homologues dans le cadre d'agrégation qui sont spécifiés dans le pipeline. En tant qu'étapes de pipeline qui pourraient apparaître "n'importe où" et pas seulement comme une option de post-traitement pour une simple requête, cela n'aurait pas beaucoup de sens d'offrir le même traitement "curseur". -
D'autres modificateurs de curseur incluent des spéciaux comme
.hint()
,.min()
et.max()
qui sont des modifications de la "sélection d'index" et du traitement. Bien que ceux-ci puissent être utiles au pipeline d'agrégation, il n'existe actuellement aucun moyen simple de les inclure dans la sélection des requêtes. Généralement, la logique du point précédent remplace tout point d'utilisation du même type d'interface pour un "curseur".
Les autres considérations sont ce que vous voulez réellement faire avec un curseur et pourquoi vous "voulez" en renvoyer un. Étant donné qu'un curseur est généralement un "aller simple" dans le sens où il n'est généralement traité que jusqu'à ce qu'une fin soit atteinte et en "lots" utilisables, il en résulte une conclusion raisonnable que le "compte" vient en fait à la fin, alors qu'en fait cette "file d'attente" est finalement épuisée.
S'il est vrai qu'en fait l'implémentation standard du "curseur" contient quelques astuces, la raison principale est que cela ne fait qu'étendre un concept de "méta" données car le moteur de profilage de requête doit "scanner" un certain nombre de documents afin de déterminer lesquels éléments à renvoyer dans le résultat.
Le cadre d'agrégation joue un peu avec ce concept cependant. Car non seulement il y a les mêmes résultats que ceux qui seraient traités par le profileur de requête standard, mais il y a aussi des étapes supplémentaires. Chacune de ces étapes a le potentiel de "modifier" le "compte" résultant qui serait en fait renvoyé dans le "flux" à traiter.
Encore une fois, si vous voulez regarder cela d'un point de vue académique et dire que "Bien sûr, le moteur de requête devrait conserver les" métadonnées "pour le décompte, mais ne pouvons-nous pas suivre ce qui est modifié après?". Ce serait un argument juste, et les opérateurs de pipeline tels que $match
et $group
ou $unwind
et éventuellement même en incluant $project
et le nouveau $redact
, tous pourraient être considérés comme un cas raisonnable pour garder leur propre trace des "documents traités" à chaque étape du pipeline et les mettre à jour dans les "métadonnées" qui pourraient éventuellement être renvoyées pour expliquer le nombre total de résultats du pipeline.
Le dernier argument est raisonnable, mais considérez également qu'à l'heure actuelle, l'implémentation d'un concept de "curseur" pour les résultats du pipeline d'agrégation est un nouveau concept pour MongoDB. On pourrait raisonnablement affirmer que toutes les attentes "raisonnables" au premier point de conception auraient été que "la plupart" des résultats de la combinaison de documents ne seraient pas d'une taille restrictive par rapport aux limitations du BSON. Mais à mesure que l'utilisation se développe, les perceptions sont modifiées et les choses changent pour s'adapter.
Donc, cela "pourrait" éventuellement être modifié, mais ce n'est pas la façon dont il est "actuellement" implémenté. Tant que .count()
sur une implémentation de curseur standard a accès aux "métadonnées" où le numéro scanné est enregistré, toute méthode sur l'implémentation actuelle entraînerait la récupération de tous les résultats du curseur, tout comme .itcount()
fait dans le shell.
Traitez les éléments "curseur" en comptant sur l'événement "data" et en émettant quelque chose (éventuellement un générateur de flux JSON) comme "compte" à la fin. Pour tout cas d'utilisation qui nécessiterait un décompte "initial", cela ne semblerait pas être une utilisation valide pour un curseur de toute façon, car la sortie serait sûrement un document entier d'une taille raisonnable.