Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get collection of document from mongodb cursor?

Tags:

mongodb

rust

bson

I have the following code which should return a list of documents from mongodb.

struct Vehicle{
    id: String,
    name: String
}

pub async fn list_all() -> Vec<Vehicle>{
    let mongodb = connection_bd::connection_mongodb().await;
    let mongodb_collection = mongodb.collection("Vehicle");
    let result = mongodb_collection.find(None, None).await; //result: Result<Cursor<Document>, Error>
    let cursor = match result { //cursor: Cursor<Document>
        Ok(x) => x,
        Err(_) => return vec![]
    };
    //...
}

I can't finish the code because I don't know how to convert Cursor<Document> to Vec<T>, it's my first time seeing Cursor<Document> and I don't know what it is.

Updated
Error message:

error[E0308]: mismatched types
  --> src\vehicle_repo.rs:77:40
   |
77 |   pub async fn list_all() -> Vec<Vehicle>{
   |  ________________________________________^
78 | |     let mongodb = connection_bd::connection_mongodb().await;
79 | |     let mongodb_collection = mongodb.collection("Vehicle");
...  |
84 | |     };
85 | | }
   | |_^ expected struct `Vec`, found `()`
   |
   = note: expected struct `Vec<Vehicle>`
           found unit type `()`
like image 647
Daniel Avatar asked Oct 15 '25 10:10

Daniel


1 Answers

A mongodb Cursor implements Stream from the futures crate. This is mentioned in the docs:

Additionally, all the other methods that a Stream has are available on Cursor as well. This includes all of the functionality provided by StreamExt, which provides similar functionality to the standard library Iterator trait. For instance, if the number of results from a query is known to be small, it might make sense to collect them into a vector:

let results: Vec<Result<Document>> = cursor.collect().await;

I would actually recommend using the try_collect() function from the TryStreamExt trait to get a Result<Vec<Document>> instead. Then you can use unwrap_or_else() to return the list. You should also use the collection_with_type() method to get the collection so that your results will be automatically deserialized to the proper type instead of just Document (just make sure it implements Debug, Serialize and Deserialize).

Here's a working sample

use futures::TryStreamExt;
use mongodb::Client;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
struct Vehicle {
    id: String,
    name: String,
}

async fn list_all() -> Vec<Vehicle> {
    let client = Client::with_uri_str("mongodb://example.com").await.unwrap();
    let database = client.database("test");
    let collection = database.collection_with_type::<Vehicle>("vehicles");
    let cursor = match collection.find(None, None).await {
        Ok(cursor) => cursor,
        Err(_) => return vec![],
    };

    cursor.try_collect().await.unwrap_or_else(|_| vec![])
}
like image 77
kmdreko Avatar answered Oct 17 '25 03:10

kmdreko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!