Para agentes de IA: um índice de documentação está disponível em https://www.mongodb.com/pt-br/docs/llms.txt — as versões de markdown de todas as páginas estão disponíveis anexando .md a qualquer caminho de URL.
Menu Docs

Acessar dados usando um cursor

Neste guia, você aprenderá a usar o driver Rust para acessar os dados retornados de uma operação de leitura ou agregação usando um cursor . Um cursor é um mecanismo que permite iterar vários documentos enquanto mantém apenas um subconjunto deles na memória em determinado momento.

O driver oferece o tipo Cursor para recuperar documentos de um cursor. Por exemplo, quando você executa uma operação de busca que pode retornar vários documentos, o driver retorna uma instância do Cursor da qual você pode acessar os documentos correspondentes.

Após executar uma operação de leitura ou agregação, a instância do Cursor retornada contém o primeiro lote de resultados da operação. À medida que você itera pelo cursor, o servidor retorna mais resultados individuais. Se houver mais documentos correspondentes depois que você chegar ao final de um lote de resultados, a instância Cursor buscará o próximo lote de documentos até que todos os resultados sejam retornados.

Este guia inclui as seguintes seções:

Os exemplos deste guia usam os seguintes dados armazenados em uma estrutura:

let docs = vec! [
Fruit {
name: "strawberry".to_string(),
color: "red".to_string()
},
Fruit {
name: "banana".to_string(),
color: "yellow".to_string()
},
Fruit {
name: "pomegranate".to_string(),
color: "red".to_string()
},
Fruit {
name: "pineapple".to_string(),
color: "yellow".to_string()
}
];

O driver fornece os seguintes padrões de acesso para iterar por meio de documentos retornados por uma instância Cursor :

As seções a seguir descrevem esses padrões de acesso e métodos correspondentes em mais detalhes.

Você pode usar o padrão de acesso integrado do driver para recuperar e processar documentos um a um.

O tipo Cursor inclui os métodos advance() e deserialize_current() para iterar por meio de um cursor e acessar documentos individualmente.

O método advance() move o cursor para a frente e envia uma solicitação ao reconhecimento de data center para mais resultados quando o buffer local se esgota, o que ocorre quando o cursor atinge o final de um lote de resultados. Cada vez que o cursor chega ao final de um lote de resultados, ele solicita o próximo lote. O cursor fica esgotado quando não tem mais documentos correspondentes para retornar e não pode mais ser usado. O método advance() retorna um resultado true se os novos resultados forem retornados com êxito e um resultado false se o cursor estiver fechado.

O método deserialize_current() retorna uma referência ao resultado atual no cursor e desserializa o resultado no tipo associado ao cursor. A menos que você especifique um tipo, o método usa o mesmo tipo com o qual sua coleção é parametrizada.

Importante

Você pode chamar o método deserialize_current() somente se o método advance() retornar um resultado true . O driver gera um erro se você chamar deserialize_current() no cursor sem um resultado true ou sem chamar anteriormente advance().

O exemplo a seguir mostra como implementar esse padrão de acesso para iterar os resultados de uma operação de localizar na coleção fruits :

let mut cursor = my_coll.find(doc! { "color": "red" }).await?;
while cursor.advance().await? {
println!("{:?}", cursor.deserialize_current()?);
}
Fruit { name: "strawberry", color: "red" }
Fruit { name: "pomegranate", color: "red" }

Você pode acessar os resultados do cursor como um fluxo para recuperar documentos individuais ou coletar vários documentos de uma só vez.

O tipo Cursor implementa a Stream , para que você possa iterar por meio de um cursor como um fluxo. Você pode usar esse padrão para escrever um código mais conciso do que com o padrão integrado, pois a extensão Stream StreamExt fornece inúmeras funções para combinar operações e confirmar código.

Você pode usar os seguintes métodos para usar o padrão de fluxo:

  • next(): avança o cursor para o próximo resultado e retorna um tipo Option<Result<T>>

  • try_next(): avança o cursor para o próximo resultado e retorna um tipo Result<Option<T>>

Importante

Importações necessárias para métodos de padrão de stream

Para usar o método next() , você deve importar o traço StreamExt . Para usar o método try_next() , você deve importar o traço TryStreamExt .

O exemplo a seguir mostra como implementar os dois métodos de fluxo para iterar os resultados das operações de localização na collection fruits :

let mut cursor = my_coll.find(doc! { "color": "red" }).await?;
println!("Output from next() iteration:");
while let Some(doc) = cursor.next().await {
println!("{:?}", doc?);
}
println!();
let mut cursor = my_coll.find(doc! { "color": "yellow" }).await?;
println!("Output from try_next() iteration:");
while let Some(doc) = cursor.try_next().await? {
println!("{:?}", doc);
}
Output from next() iteration:
Fruit { name: "strawberry", color: "red" }
Fruit { name: "pomegranate", color: "red" }
Output from try_next() iteration:
Fruit { name: "banana", color: "yellow" }
Fruit { name: "pineapple", color: "yellow" }

Como o tipo Cursor implementa a Stream , você pode coletar os resultados de um cursor em uma array.

Você pode usar os seguintes métodos para recuperar documentos como um array:

  • collect(): coleta resultados de um cursor em um tipo Vec<Result<T>>

  • try_collect(): coleta resultados de um cursor em um tipo Result<Vec<T>>

Observação

Para usar o método collect() , você deve importar o traço StreamExt . Para usar o método try_collect() , você deve importar o traço TryStreamExt .

let cursor = my_coll.find(doc! { "color": "red" }).await?;
println!("Output from collect():");
let v: Vec<Result<Fruit>> = cursor.collect().await;
println!("{:?}", v);
println!();
let cursor = my_coll.find(doc! { "color": "yellow" }).await?;
println!("Output from try_collect():");
let v: Vec<Fruit> = cursor.try_collect().await?;
println!("{:?}", v);
Output from collect():
[Ok(Fruit { name: "strawberry", color: "red" }), Ok(Fruit { name: "pomegranate", color: "red" })]
Output from try_collect():
[Fruit { name: "banana", color: "yellow" }, Fruit { name: "pineapple", color: "yellow" }]

Aviso

Evite exceder os limites de memória do aplicativo

Evite converter grandes conjuntos de resultados em arrays. Se a array exceder o tamanho da memória disponível do aplicação , seu aplicação poderá falhar. Se você espera um conjunto de resultados grande, recupere os documentos do cursor individualmente. Para saber como fazer a iteração por meio do cursor, consulte a seção Recuperar documentos individualmente deste guia.

Você pode chamar o método batch() em operações de retorno de cursor, como find() para retornar um RawBatchCursor. Isso permite que você itere sobre lotes de documento BSON brutos retornados pelo servidor em vez de valores desserializados individuais. Este módulo oferece uma maneira de alto desempenho de processar documentos quando você precisa de acesso direto aos lotes de resposta do servidor . Use o modo de lote bruto para aplicativos de cursor sensíveis ao desempenho com alta taxa de transferência.

Para usar a API de cursor de lote bruto, chame o método batch() em uma operação de retorno de cursor para retornar um RawBatchCursor em vez de um Cursor normal. Você pode então iterar por lotes e acessar documentos individuais dentro de cada lote.

O exemplo a seguir mostra como usar o cursor de lote bruto para processar documentos:

let mut cursor = my_coll.find(doc! { "color": "red" }).batch().await?;
while let Some(batch) = cursor.next().await {
let batch = batch?;
let doc_slices = batch.doc_slices()?;
let count = doc_slices.into_iter().count();
println!("Processing batch with {} documents", count);
for doc_result in batch.doc_slices()? {
let doc = doc_result?;
if let mongodb::bson::RawBsonRef::Document(raw_doc) = doc {
println!("Raw document size: {} bytes", raw_doc.as_bytes().len());
}
}
}
Processing batch with 4 documents
Raw document size: 58 bytes
Raw document size: 59 bytes
Raw document size: 58 bytes
Raw document size: 59 bytes

Para saber mais sobre a API do cursor de lote bruto, consulte a página bruto_batch_cursor na documentação da API.

Para modificar o cursor que uma operação retorna, encadeie os métodos do construtor de opções ao método que retorna a instância Cursor . Por exemplo, é possível encadear métodos de construtor de opção relacionados ao cursor ao método find() .

Observação

Opções de configuração

Você pode definir FindOptions campos encadeando métodos de construtor de opções diretamente à chamada de método find() . Se você estiver utilizando uma versão anterior do driver, você deverá construir uma instância do FindOptions encadeando métodos de construtor de opção ao método builder() . Em seguida, passe sua instância FindOptions como parâmetro para find().

A tabela a seguir descreve as opções relacionadas ao cursor que você pode definir chamando o método de construtor correspondente:

Contexto
Descrição

batch_size

Especifica o número máximo de documentos que o servidor retorna por lote de cursor. Essa opção define o número de documentos que o cursor mantém na memória, em vez do número de documentos que o cursor retorna.

Tipo: u32
Padrão: 101 documentos inicialmente, 16 MB máximo para lotes subsequentes

cursor_type

Especifica o tipo de cursor a ser retornado. Você pode definir esta opção para produzir um cursor persistente. Para saber mais sobre cursores persistentes, consulte Cursores persistentes no manual do servidor.

Tipo: CursorType
Padrão: CursorType::NonTailable

no_cursor_timeout

Especifica se o servidor fecha o cursor após um período de inatividade.

IMPORTANTE: Como o tipo Cursor implementa a característica Drop, o servidor fecha um cursor quando ele sai do escopo. O servidor executa um comando assíncrono killCursors para fechar o cursor. Consulte killCursors no manual do servidor para aprender mais.

Tipo: bool
Padrão: false

O código a seguir mostra como especificar configurações relacionadas ao cursor encadeando métodos de construtor de opção ao método find() :

let mut cursor = my_coll.find(doc! { "color": "red" })
.batch_size(5)
.cursor_type(CursorType::Tailable)
.no_cursor_timeout(true)
.await?;

Para saber mais sobre as operações neste guia, consulte a seguinte documentação:

Para saber mais sobre a conversão entre tipos de Rust e BSON, consulte o guia sobre modelagem de dados e serialização.

Para saber mais sobre os métodos e tipos mencionados neste guia, consulte a documentação da API abaixo: