Menu Docs
Página inicial do Docs
/ / /
Driver Rust
/ / /

Acessar dados usando um cursor

Nesta página

  • Visão geral
  • Dados de amostra para exemplos
  • Recuperar documentos individualmente
  • Padrão integrado
  • Padrão de implementação de fluxo
  • Recuperar documentos como um array
  • Especificar comportamento do cursor
  • Informações adicionais
  • Documentação da API

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, ao executar uma operação de localizar 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:

  • Amostra de dados para exemplos apresenta os dados de amostra que são usados pelos exemplos do cursor

  • Recuperar documentos Descreve individualmente como usar a iteração ou um fluxo para acessar os resultados um de cada vez

  • Recuperar documentos como array descreve como acessar todos os resultados como um único array coletando os resultados do cursor retornado

  • Especificar o Comportamento do Cursor descreve como configurar o cursor que um método retorna

  • Informações adicionais fornecem links para recursos e documentação da API para os tipos e métodos mencionados neste guia

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.

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

Specifies the maximum number of documents the server returns per cursor batch. This option sets the number of documents the cursor keeps in memory rather than the number of documents the cursor returns.

Type: u32
Default: 101 documents initially, 16 MB maximum for subsequent batches

cursor_type

Specifies the type of cursor to return. You can set this option to produce a tailable cursor. To learn more about tailable cursors, see Tailable Cursors in the Server manual.

Type: CursorType
Default: CursorType::NonTailable

no_cursor_timeout

Specifies whether the server closes the cursor after a period of inactivity.

IMPORTANT: Because the Cursor type implements the Drop trait, the server closes a cursor when it goes out of scope. The server runs an asynchronous killCursors command to close the cursor. See killCursors in the Server manual to learn more.
Type: bool
Default: 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:

Voltar

Especificar uma query