postgresqlrustactix-webtokio-postgres

How do you convert a collection to a Result in rust and actix to return data from postgres?


Using rust and the actix framework, I am trying to fetch a list of records from postgres and return it as JSON.

I am referencing this example code: https://github.com/actix/examples/tree/master/databases/postgres

The following are my changes. The get_users function returns only one user because of the pop. How do I fix this to return the entire list of users so I can return it as JSON?

    pub async fn get_users(client: &Client) -> Result<User, MyError> {
        client
            .query("SELECT * FROM testing.users", &[])
            .await?
            .iter()
            .map(|row| User::from_row_ref(row).unwrap())
            .collect::<Vec<User>>()
            .pop()
            .ok_or(MyError::NotFound)
        
    }

Solution

  • Try this:

    pub async fn get_users(client: &Client) -> Result<Vec<User>, MyError> {
        let res = client
            .query("SELECT * FROM testing.users", &[])
            .await?
            .iter()
            .map(|row| User::from_row_ref(row).unwrap())
            .collect::<Vec<User>>();
        Ok(res)
    }
    

    We changed the return type from Result<User, MyError> to Result<Vec<User>, MyError>.

    Let's follow what we changed in the function implementation. The result of collect() is Vec<User>. In your piece of code, the pop() function returns an Option, which will be None if the vector is empty. In that case you convert the None to an error (via ok_or()). Now the calls to pop() and ok_or() become redundant. Since your function returns a Result, you need to manually wrap the Vec<User> that comes from collect() in a Result::Ok (remember, the ok_or() did that for you - in the case of Some, it would create a Result::Ok).