Visão geral
As operações de leitura que retornam vários documentos não retornam imediatamente todos os valores correspondentes à query. Como uma query pode potencialmente corresponder a conjuntos muito grandes de documentos, essas operações retornam um objeto chamado cursor, que faz referência a documentos identificados pela query. Um cursor obtém documentos em lotes para reduzir o consumo de memória e o uso da largura de banda da rede. Os cursores são altamente configuráveis e oferecem vários paradigmas de interação para diferentes casos de uso.
As seguintes funções retornam cursores diretamente:
- Collection.find()
- Collection.aggregate()
- Collection.listIndexes()
- Collection.listSearchIndexes()
- Db.aggregate()
- Db.listCollections()
Outros métodos, como Collection.findOne() e Collection.watch() use cursores internamente e retorne os resultados das operações em vez de um cursor.
Paradigmas de cursor
Você pode usar vários paradigmas de cursor diferentes para acessar dados. A maioria deles permite acessar os resultados da query um documento de cada vez, abstraindo a lógica de rede e de cache. No entanto, como os casos de uso são diferentes, outros paradigmas oferecem padrões de acesso diferentes, como a extração de todos os documentos correspondentes para uma coleção na memória do processo.
Aviso
Não combine diferentes paradigmas de cursor em um único cursor. Operações como hasNext() e toArray() modificam previsivelmente o cursor original. Se você misturar essas chamadas
em um único cursor, poderá receber resultados inesperados.
Aviso
Como as chamadas assíncronas modificam diretamente o cursor, a execução simultânea de chamadas assíncronas em um único cursor também pode causar comportamento indefinido. Aguarde sempre que a operação assíncrona anterior seja concluída antes de executar outra.
Observação
Quando você chega ao último resultado por meio de iteração ou de uma busca simultânea, o cursor fica esgotado, o que significa que ele para de responder aos métodos que acessam os resultados.
iteração assíncrona
Os cursores implementam a interface AsyncIterator, que permite usar cursores em loops for await...of:
  const cursor = myColl.find({});   console.log("async");   for await (const doc of cursor) {     console.log(doc);   } 
Iteração manual
Você pode utilizar o método hasNext() para verificar se um cursor pode recuperar mais dados e, em seguida, utilizar o método next() para recuperar o elemento subsequente do cursor:
  const cursor = myColl.find({});   while (await cursor.hasNext()) {     console.log(await cursor.next());   } 
Retornar uma bandeja de todos os documentos
Para casos de uso que exigem que todos os documentos correspondidos por uma query sejam mantidos na memória ao mesmo tempo, use o método toArray(). Observe que um grande número de documentos correspondentes pode causar problemas de desempenho ou falhas se a operação exceder as restrições de memória. Considere usar a sintaxe for await...of para iterar os resultados em vez de retornar todos os documentos de uma só vez.
  const cursor = myColl.find({});   const allValues = await cursor.toArray(); 
API de transmissão
Os cursores expõem o método stream() para convertê-los em fluxos legíveis de nó. Esses fluxos operam no Modo de Objeto, que passa objetos JavaScript em vez de Buffers ou Strings pelo pipeline.
  const cursor = myColl.find({});   cursor.stream().on("data", doc => console.log(doc)); 
API de eventos
Como fluxos legíveis, os cursores também são compatíveis com os eventos close, data, end e readable da API de eventos:
  const cursor = myColl.find({});   // the "data" event is fired once per document   cursor.on("data", data => console.log(data)); 
Métodos de Utilidade do Cursor
Retroceder
Para redefinir um cursor para sua posição inicial no conjunto de documentos retornados, use rewind().
  const cursor = myColl.find({});   const firstResult = await cursor.toArray();   console.log("First count: " + firstResult.length);   await cursor.rewind();   const secondResult = await cursor.toArray();   console.log("Second count: " + secondResult.length); 
Fechar
Os cursores consomem memória e recursos de rede tanto no aplicação cliente quanto na instância conectada do MongoDB. Use close() para liberar os recursos de um cursor no aplicação cliente e no MongoDB Server, conforme mostrado no exemplo a seguir:
  await cursor.close(); 
Recomendamos fechar manualmente todos os cursores não esgotados que seu aplicação não usa mais para evitar vazamentos de recursos.
Dica
Gerenciamento explícito de recursos
O driver Node.js suporta nativamente o gerenciamento explícito de recursos para MongoClient, ClientSession, ChangeStreams e cursores. Este recurso é experimental e sujeito a alterações. Para saber como usar o gerenciamento explícito de recursos, consulte as Notas de versão do v6.9.
Abortar
Você pode cancelar operações do cursor usando um sinal de abortamento. Isso pode ajudar a gerenciar seus recursos ao liberar memória e recursos de rede usados pelo cursor, caso não sejam mais necessários.
Observação
Este recurso é experimental. Abortar um sinal encerra uma conexão, o que pode levar ao restabelecimento desnecessário da conexão.
Você pode passar o comando signal para os seguintes métodos:
- collection.find()
- collection.findOne()
- collection.aggregate()
- collection.countDocuments()
- db.listCollections()
- db.command()
Para utilizar um sinal de abortar, crie uma instância de AbortController e extraia o signal do controlador. Neste exemplo de código, o processo escuta por um SIGINT (Ctrl+C) para trigger o método abort(). Você pode passar a opção signal para o método find() para abortar a operação do cursor se o sinal for acionado, conforme mostrado no exemplo a seguir:
  const controller = new AbortController();   const { signal } = controller;   process.on('SIGINT', () => controller.abort(new Error('^C pressed')));   try {     const cursor = myColl.find({}, { signal });     for await (const doc of cursor) {       console.log(doc);     }   } catch (error) {     if (error === signal.reason) {       console.error('Operation aborted:', error);     } else {       console.error('Unexpected error:', error);     }   }