I am working on a REST API written in Rust using actix-web, SQLx and PostgreSQL for storage. Let's suppose this is my schema (expressed as Rust structs):
struct User {
pub id: Uuid,
pub email: String
// And so on...
}
struct Customer {
pub id: Uuid,
pub user_id: Uuid,
pub name: String,
// And so on...
}
My current goal is to implement an endpoint, that returns all users with their customers nested. I.e. like this:
// GET /users
// Response from endpoint
[{
"id": "uuid-1",
"email": "test@test.com",
"customers": [{
"id": "uuid-customer-1",
"name": "Customer 1"
}, {
"id": "uuid-customer-2",
"name": "Customer 2"
}]
}]
The payload above could be expressed using the following structs:
#[derive(Serialize)]
struct CustomerData {
pub id: Uuid,
pub name: String
}
#[derive(Serialize)]
struct UserData {
pub id: Uuid,
pub email: String,
pub customers: Vec<CustomerData>
}
Using SQLx macro query_as!
I came up with following solution attempt:
let result = sqlx::query_as!(
UserData,
r#"
SELECT U.id, U.email, array_agg((C.id, C.name)) as "customers" FROM users U
INNER JOIN customers C ON user_id = U.id
GROUP BY U.id
"#
)
.fetch_all(pool.as_ref())
.await?;
This, however fails, because the result returned by array_agg
is of type RECORD[]
, which SQLx apparently does not yet support.
This issue got me wondering:
- Is there a way to get SQLx to properly map the result of
array_agg
tocustomers
? - Given, that my actual schema has at least few more levels in the hierarchy, is this even the right way to go? Would it be "better" to split it in several queries and piecewise construct the response?