Overview
En esta guía, aprenderá a usar el controlador de Rust para acceder a los datos devueltos por una operación de lectura o agregación mediante un cursor. Un cursor es un mecanismo que permite iterar a través de múltiples documentos manteniendo solo un subconjunto de ellos en memoria en un momento dado.
El conductor ofrece la Cursor Tipo para recuperar documentos de un cursor. Por ejemplo, al ejecutar una operación de búsqueda que puede devolver varios documentos, el controlador devuelve una instancia Cursor desde la que se puede acceder a los documentos coincidentes.
Tras ejecutar una operación de lectura o agregación, la instancia Cursor devuelta contiene el primer lote de resultados de la operación. A medida que se itera sobre el cursor, el servidor devuelve más resultados individuales. Si hay más documentos coincidentes después de llegar al final de un lote de resultados, la instancia Cursor recupera el siguiente lote de documentos hasta que se devuelvan todos los resultados.
Esta guía incluye las siguientes secciones:
Datos de muestra para ejemplos presenta los datos de muestra que se utilizan en los ejemplos del cursor
Recuperar documentos individualmente describe cómo usar la iteración o un flujo para acceder a los resultados de uno en uno
Recuperar documentos como una matriz describe cómo acceder a todos los resultados como una única matriz recopilando los resultados del cursor devueltos
Especificar el comportamiento del cursor describe cómo configurar el cursor que un método devuelve
Información adicional proporciona enlaces a recursos y documentación de API para los tipos y métodos mencionados en esta guía.
Datos de muestra para ejemplos
Los ejemplos de esta guía utilizan los siguientes datos almacenados en una estructura:
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() } ];
Recuperar documentos individualmente
El controlador proporciona los siguientes patrones de acceso para iterar a través de los documentos devueltos por una instancia Cursor:
Patrón incorporado: avanza el cursor, luego recupera y deserializa el documento actual
Patrón de implementación de flujo: itera sobre el cursor y llama a los métodos proporcionados por
Streampara procesar uno o varios documentos
Las siguientes secciones describen estos patrones de acceso y los métodos correspondientes con más detalle.
Patrón incorporado
Puede utilizar el patrón de acceso integrado del controlador para recuperar y procesar documentos uno por uno.
El tipo Cursor incluye los métodos advance() y deserialize_current() para iterar a través de un cursor y acceder a los documentos individualmente.
El método advance() mueve el cursor hacia adelante y envía una solicitud a la base de datos para obtener más resultados cuando el búfer local se agota, lo que ocurre cuando el cursor llega al final de un lote de resultados. Cada vez que el cursor llega al final de un lote de resultados, solicita el siguiente. El cursor se agota cuando no tiene más documentos coincidentes que devolver y ya no se puede utilizar. El método advance() devuelve un resultado true si se devuelven nuevos resultados correctamente y un resultado false si se cierra el cursor.
El método deserialize_current() devuelve una referencia al resultado actual en el cursor y lo deserializa al tipo asociado al cursor. A menos que especifique un tipo, el método utiliza el mismo tipo con el que está parametrizada su colección.
Importante
Solo se puede llamar al método deserialize_current() si el método advance() devuelve un resultado true. El controlador genera un error si se llama a deserialize_current() en el cursor sin un resultado true o sin haber llamado previamente a advance().
El siguiente ejemplo muestra cómo implementar este patrón de acceso para iterar a través de los resultados de una operación find en la colección 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" }
Patrón de implementación de flujo
Puede acceder a los resultados del cursor como un flujo para recuperar documentos individuales o recopilar varios documentos a la vez.
El tipo Cursor implementa el rasgo Stream, lo que permite iterar sobre un cursor como un flujo. Este patrón puede ayudarte a escribir código más conciso que con el patrón integrado, ya que el rasgo de extensión Stream StreamExt proporciona numerosas funciones para combinar operaciones y consolidar código.
Puede utilizar los siguientes métodos para utilizar el patrón de flujo:
next(): avanza el cursor al siguiente resultado y devuelve un tipoOption<Result<T>>try_next(): avanza el cursor al siguiente resultado y devuelve un tipoResult<Option<T>>
Importante
Importaciones requeridas para métodos de patrones de flujo
Para usar el método next(), debe importar el atributo StreamExt. Para usar el método try_next(), debe importar el atributo TryStreamExt.
El siguiente ejemplo muestra cómo implementar los dos métodos de flujo para iterar a través de los resultados de las operaciones de búsqueda en la colección 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" }
Recuperar documentos como una matriz
Debido a que el tipo Cursor implementa el rasgo Stream, puede recopilar los resultados de un cursor en una matriz.
Puede utilizar los siguientes métodos para recuperar documentos como una matriz:
collect(): recopila resultados de un cursor en un tipoVec<Result<T>>try_collect(): recopila resultados de un cursor en un tipoResult<Vec<T>>
Nota
Para usar el método collect(), debe importar el atributo StreamExt. Para usar el método try_collect(), debe importar el atributo 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" }]
Advertencia
Evite exceder los límites de memoria de la aplicación
Evite convertir grandes conjuntos de resultados en matrices. Si la matriz excede el tamaño de la memoria disponible de la aplicación, esta podría bloquearse. Si espera un conjunto de resultados grande, recupere los documentos del cursor individualmente. Para aprender a iterar sobre el cursor, consulte la sección "Recuperar documentos individualmente" de esta guía.
Especificar el comportamiento del cursor
Para modificar el cursor que devuelve una operación, encadene los métodos del generador de opciones al método que devuelve la instancia Cursor. Por ejemplo, puede encadenar los métodos del generador de opciones relacionados con el cursor al método find().
Nota
Opciones de configuración
Puede configurar los campos FindOptions encadenando los métodos del generador de opciones directamente a la llamada al método find(). Si utiliza una versión anterior del controlador, debe construir una instancia FindOptions encadenando los métodos del generador de opciones al método builder(). A continuación, pase la instancia FindOptions como parámetro a find().
La siguiente tabla describe las opciones relacionadas con el cursor que puede configurar llamando a su método de generación correspondiente:
Configuración | Descripción |
|---|---|
| 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: u32Default: 101 documents initially, 16 MB maximum for
subsequent batches |
| 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: CursorTypeDefault: CursorType::NonTailable |
| 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: boolDefault: false |
El siguiente código muestra cómo especificar configuraciones relacionadas con el cursor encadenando métodos de generación de opciones al método find():
let mut cursor = my_coll.find(doc! { "color": "red" }) .batch_size(5) .cursor_type(CursorType::Tailable) .no_cursor_timeout(true) .await?;
Información Adicional
Para obtener más información sobre las operaciones de esta guía, consulte la siguiente documentación:
Retrieve Data guide
Especificar una guía de consulta
Para obtener más información sobre la conversión entre tipos de Rust y BSON, consulte la guía sobre modelado y serialización de datos.
Documentación de la API
Para obtener más información sobre los métodos y tipos mencionados en esta guía, consulte la siguiente documentación de API:
next() en el
StreamExtrasgotry_next() en el
TryStreamExtrasgocollect() en el
StreamExtrasgotry_collect() en el
TryStreamExtrasgo