I am trying to use the aggregation pipeline in rust driver to return a vector of a specific type. At the moment I am only able to get Vec Document type. How do I transform this to Vec T type?
my current code looks like this
#[derive(Debug, Deserialize, Serialize, Validate)]
pub struct Bill {
#[serde(
skip_serializing_if = "Option::is_none",
serialize_with = "serialize_object_id",
rename(serialize = "id")
)]
pub _id: Option<oid::ObjectId>,
#[serde(skip_serializing_if = "Option::is_none")]
#[validate(required)]
pub frequency: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[validate(required)]
pub amount: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_date: Option<DateTime<Utc>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub end_date: Option<DateTime<Utc>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[validate(required)]
pub contact_number: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub policy_number: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[validate(required)]
pub title: Option<String>,
#[serde(
skip_serializing_if = "Option::is_none",
serialize_with = "serialize_object_id"
)]
#[validate(required)]
pub property_id: Option<oid::ObjectId>,
}
let collection = db.collection::<Document>("bills");
let pipeline: Vec<Document> = vec![doc! {
"$match": {
"property_id": oid::ObjectId::parse_str(id)?
},
}];
let cursor: Cursor<Document> = collection.aggregate(pipeline, None).await?;
let bills: Result<Vec<Document>, _> = cursor.try_collect().await;
Ok(bills?)
I have tried to change the collection type using turbo fish syntax but that only seems to work with basic query syntax like find but not aggregation. Something like this
let collection = db.collection::<Bill>("bills");
let pipeline: Vec<Document> = vec![doc! {
"$match": {
"property_id": oid::ObjectId::parse_str(id)?
},
}];
let cursor: Cursor<Bill> = collection.aggregate(pipeline, None).await?;
let bills: Result<Vec<Bill>, _> = cursor.try_collect().await;
Ok(bills?)
but then I get the following error
`?` operator has incompatible types
`?` operator cannot convert from `mongodb::Cursor<mongodb::bson::Document>` to `mongodb::Cursor<Bill>`
expected struct `mongodb::Cursor<Bill>`
found struct `mongodb::Cursor<mongodb::bson::Document>`
My only other thing I can think of is to map over the bills iterator and use from_document bson function to deserialize to the Bill type but that doesnt seem to be performant and also Im struggling to implement it. It currently looks something like this.
let newBills:Vec<Bill> = bills?.iter().map(|&e| from_document::<Bill>(e)).collect();
I then get the following error
a value of type `Vec<Bill>` cannot be built from an iterator over elements of type `Result<Bill, mongodb::bson::de::Error>`
the trait `FromIterator<Result<Bill, mongodb::bson::de::Error>>` is not implemented for `Vec<Bill>`
the trait `FromIterator<T>` is implemented for `Vec<T>`
Any help would be greatly appreciated