MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Cursor e contagem de agregação Mongo


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:

  1. 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".

  2. 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.