subgraph/data_sources/mongo/services/find_one/
mod.rs

1use 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            // Serialize the opts document to a OptionsInput
57            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 document = collection.find_one(filter, None).await?;
63            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}