subgraph/data_sources/mongo/services/find_one/
mod.rs1use async_graphql::futures_util::StreamExt;
2use log::{debug, trace};
3use mongodb::{
4 bson::{doc, Document},
5 Database,
6};
7
8use crate::{
9 data_sources::mongo::{EagerLoadOptions, MongoDataSource},
10 graphql::schema::create_options_input::OptionsInput,
11};
12
13use super::Services;
14
15impl Services {
16 pub async fn find_one(
17 db: Database,
18 filter: Document,
19 collection: String,
20 eager_load_options: Vec<EagerLoadOptions>,
21 ) -> Result<Option<Document>, async_graphql::Error> {
22 debug!("Executing Find One - Mongo Data Source: {:?}", collection);
23 trace!("Filter: {:?}", filter);
24
25 let collection = db.collection::<Document>(&collection);
26
27 let query_filter = match filter.get("query") {
28 Some(query_filter) => query_filter,
29 None => return Err(async_graphql::Error::new("Query filter not found")),
30 };
31
32 let query_document = match query_filter.as_document() {
33 Some(query_document) => query_document,
34 None => return Err(async_graphql::Error::new("Query filter not found")),
35 };
36
37 let filter = Services::create_nested_find_filter(query_document);
38
39 if let Some(opts_doc) = filter.get("opts") {
40 let opts = match opts_doc.as_document() {
41 Some(opts) => opts.clone(),
42 None => {
43 let default_opts = doc! {
44 "per_page": 10,
45 "page": 1,
46 "sort": [
47 {
48 "field": "_id",
49 "direction": "Asc"
50 }
51 ]
52 };
53 default_opts
54 }
55 };
56 let opts: OptionsInput = bson::from_bson(bson::Bson::Document(opts))?;
58
59 let aggregation =
60 MongoDataSource::create_aggregation(&filter, eager_load_options, Some(opts))?;
61
62 let mut cursor = collection.aggregate(aggregation, None).await?;
64
65 while let Some(document) = cursor.next().await {
66 if let Ok(document) = document {
67 return Ok(Some(document));
68 }
69 }
70 } else {
71 let document = collection.find_one(filter, None).await?;
72
73 return Ok(document);
74 }
75
76 Ok(None)
77 }
78}