I am trying to understand mongodb driver for rust.
When building this query
doc! { "section_id": section_id }
I get this error:
--> src/main.rs:61:30
|
61 | doc! { "section_id": section_id }
| ---------------------^^^^^^^^^^--
| | |
| | the trait `From<u8>` is not implemented for `Bson`
| required by a bound introduced by this call
|
= help: the following other types implement trait `From<T>`:
<Bson as From<&T>>
<Bson as From<&[T]>>
<Bson as From<&str>>
<Bson as From<Regex>>
<Bson as From<Vec<T>>>
<Bson as From<[u8; 12]>>
<Bson as From<bool>>
<Bson as From<chrono::datetime::DateTime<T>>>
and 19 others
section_id
is from the following struct
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
struct ChaptersFilterOptions {
section_id: Option<u8>
}
How do I solve this? Do I have to implement From
for every type that I will use?
The doc!
macro requires that all the types you use with it can be converted to the Bson
type, which is done with the From
trait. In other words, Bson
needs to implement From<Option<u8>>
for you to be able to use section_id
.
The reason the error message mentions From<u8>
is because the Bson
implements From
for all Option<T>
where T
can be converted into Bson
(this implementation is here: Bson in bson - Rust). So From<Option<u8>>
is implemented for Bson
if From<u8>
is implemented.
You can't implement From<u8>
for Bson
because neither the trait nor type are local to your crate. From
comes from std
and Bson
from bson
. Rust doesn't allow you to implement foreign traits for foreign types.
You can convert section_id
to some other type T
that does implement From<T>
for Bson
, like u32
:
doc! { "section_id": section_id.map(u32::from) }; // turns section_id from Option<u8> into Option<u32>
3 Likes
@Heliozoa, thanks for the reply. I tried your suggestion. It is not working. As it turns out, I did not clearly communicated my code. In the following code, I face problem in the match expression in build_chapters_query_and_options
function. .map
does not work because, it is not an Option
type, I suppose!:
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let client_uri = ...;
let options =
ClientOptions::parse_with_resolver_config(&client_uri, ResolverConfig::cloudflare())
.await?;
let client = Client::with_options(options)?;
print_find_options();
Ok(())
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
struct ChaptersFilterOptions {
section_id: Option<u8>
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
struct PaginationOptions {
skip: i64,
limit: i64
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
struct ChaptersQueryOptions {
filter_options: ChaptersFilterOptions,
pagination_options: PaginationOptions
}
pub fn build_chapters_query_and_options(query_options: ChaptersQueryOptions) -> (Document, FindOptions) {
let filter_options = query_options.filter_options;
let pagination_options = query_options.pagination_options;
let find_options = FindOptions::builder()
.skip(pagination_options.skip)
.limit(pagination_options.limit).build();
let filter = match filter_options.section_id {
Some(section_id) => {
doc! { "section_id": section_id }
}
None => {
doc! { }
}
};
return (filter, find_options);
}
fn print_find_options() {
let query_options = ChaptersQueryOptions {
filter_options: ChaptersFilterOptions {
section_id: Some(10)
},
pagination_options: PaginationOptions {
skip: 0,
limit: 10,
}
};
let (options) = build_chapters_query_and_options(query_options);
println!("{:?}", options);
}
@Heliozoa. Never mind! I have found the issue. My bad that I did not understood what type of parameter is needed for .skip
& .limit
methods. They are Option u64, i64
respectively. Similarly, for some reason u8
did not work. Mongodb driver only expects u32
. I've sorted them out! Thanks for your time.