Isso possivelmente merece uma explicação completa para aqueles que podem procurar por isso, adicionando uma para a posteridade.
Especificamente, o que é retornado é um Event Stream para node.js que envolve efetivamente o stream.Readable interface com alguns métodos de conveniência. Um
.count()
não é um deles no momento e considerando a interface atual usada não faria muito sentido. Semelhante ao resultado retornado do
.stream()
método disponível para objetos de cursor, uma "contagem" não faria muito sentido aqui quando você considera a implementação, pois ela deve ser processada como um "fluxo" onde eventualmente você chegará a um "fim", mas de outra forma apenas deseja processar até chegar lá. Se você considerou a interface "Cursor" padrão do driver, existem algumas razões sólidas pelas quais o cursor de agregação não é o mesmo:
-
Os cursores permitem que ações "modificadoras" sejam processadas antes da execução. Eles se enquadram nas categorias de.sort()
,.limit()
e.skip()
. Todos eles realmente têm diretivas de contrapartida na estrutura de agregação que são especificadas no pipeline. Como estágios de pipeline que podem aparecer "em qualquer lugar" e não apenas como uma opção de pós-processamento para uma consulta simples, não faria muito sentido oferecer o mesmo processamento "cursor".
-
Outros modificadores de cursor incluem especiais como.hint()
,.min()
e.max()
que são alterações na "seleção de índice" e no processamento. Embora eles possam ser úteis para o pipeline de agregação, atualmente não há uma maneira simples de incluí-los na seleção de consulta. Principalmente a lógica do ponto anterior substitui qualquer ponto de usar o mesmo tipo de interface para um "Cursor".
As outras considerações são o que você realmente deseja fazer com um cursor e por que você "quer" que ele seja retornado. Uma vez que um cursor é geralmente uma "viagem de ida" no sentido de que eles geralmente são processados apenas até que um fim seja alcançado e em "lotes" utilizáveis, então chega-se a uma conclusão razoável de que a "contagem" realmente vem no final, quando na verdade essa "fila" está finalmente esgotada.
Embora seja verdade que, de fato, a implementação padrão de "cursor" contém alguns truques, a principal razão é que isso apenas estende um conceito de "meta" dados, pois o mecanismo de criação de perfil de consulta deve "varrer" um certo número de documentos para determinar qual itens para retornar no resultado.
A estrutura de agregação brinca um pouco com esse conceito. Uma vez que não há apenas os mesmos resultados que seriam processados pelo criador de perfil de consulta padrão, mas também há estágios adicionais. Qualquer um desses estágios tem o potencial de "modificar" a "contagem" resultante que realmente seria retornada no "stream" a ser processado.
Novamente, se você quiser olhar para isso de um ponto de vista acadêmico e dizer que "Claro, o mecanismo de consulta deve manter os 'metadados' para a contagem, mas não podemos rastrear o que é modificado depois?". Este seria um argumento justo, e operadores de pipeline como
$match
e $group
ou $unwind
e possivelmente até incluindo $project
e o novo $redact
, todos poderiam ser considerados um caso razoável para manter seu próprio controle dos "documentos processados" em cada estágio do pipeline e atualizá-los nos "metadados" que poderiam ser retornados para explicar a contagem completa de resultados do pipeline. O último argumento é razoável, mas considere também que atualmente a implementação de um conceito "Cursor" para os resultados do pipeline de agregação é um conceito novo para o MongoDB. Pode-se argumentar com justiça que todas as expectativas "razoáveis" no primeiro ponto de design teriam sido que a "maioria" dos resultados da combinação de documentos não seria de um tamanho restritivo às limitações do BSON. Mas à medida que o uso se expande, as percepções são alteradas e as coisas mudam para se adaptar.
Portanto, isso "poderia" ser alterado, mas não é como está "atualmente" implementado. Enquanto
.count()
em uma implementação de cursor padrão tem acesso aos "metadados" onde o número digitalizado é registrado, qualquer método na implementação atual resultaria na recuperação de todos os resultados do cursor, assim como .itcount()
faz na casca. Processe os itens "cursor" contando com o evento "data" e emitindo algo (possivelmente um gerador de fluxo JSON) como a "contagem" no final. Para qualquer caso de uso que exija uma contagem "adiantada", não parece ser um uso válido para um cursor de qualquer maneira, pois certamente a saída seria um documento inteiro de tamanho razoável.