subgraph/data_sources/mongo/services/find_many/
mod.rs1use async_graphql::{futures_util::StreamExt, Error, ErrorExtensions};
2use bson::{doc, Document};
3use log::{debug, error, trace};
4use mongodb::Database;
5
6use crate::{
7 data_sources::mongo::{EagerLoadOptions, MongoDataSource},
8 graphql::schema::create_options_input::OptionsInput,
9};
10
11use super::Services;
12
13impl Services {
14 pub async fn find_many(
15 db: Database,
16 filter: Document,
17 collection: String,
18 eager_load_options: Vec<EagerLoadOptions>,
19 ) -> Result<(Vec<Option<Document>>, i64), async_graphql::Error> {
20 let coll = db.collection::<Document>(&collection);
21
22 debug!("Find Many: {:?}", filter);
23
24 let query = match filter.get("query") {
25 Some(query) => query,
26 None => return Err(Error::new("Query filter not found")),
27 };
28
29 let query_doc = match query.as_document() {
30 Some(query_doc) => query_doc,
31 None => return Err(Error::new("Failed to convert query filter to document.")),
32 };
33
34 let nested_find_filter = Services::create_nested_find_filter(&query_doc);
35
36 let opts_bson = match filter.get("opts") {
37 Some(opts_doc) => opts_doc.clone(),
38 None => {
39 trace!("No opts found, using default opts.");
40 let default_opts = doc! {
41 "per_page": 10,
42 "page": 1,
43 "sort": [
44 {
45 "field": "_id",
46 "direction": "Asc"
47 }
48 ]
49 };
50 bson::to_bson(&default_opts).unwrap()
51 }
52 };
53
54 let opts: Option<OptionsInput> = match bson::from_bson(opts_bson) {
56 Ok(opts) => opts,
57 Err(error) => {
58 error!("Failed to convert opts to OptionsInput: {:?}", error);
59 return Err(Error::new("Failed to convert opts to OptionsInput."));
60 }
61 };
62
63 let aggregation =
64 MongoDataSource::create_aggregation(&nested_find_filter, eager_load_options, opts)?;
65
66 let mut cursor = coll.aggregate(aggregation, None).await?;
67
68 trace!("Find Many Cursor: {:?}", cursor);
69
70 let mut result_doc = None;
71
72 while let Some(result) = cursor.next().await {
73 match result {
74 Ok(document) => {
75 result_doc = Some(document);
76 break;
77 }
78 Err(_error) => Err(Error::new("Can't find results.")
79 .extend_with(|err, e| e.set("details", err.message.as_str())))?,
80 }
81 }
82
83 trace!("Find Many Result: {:?}", result_doc);
84
85 if result_doc.is_none() {
86 return Err(Error::new("Can't find matched results."));
87 }
88 let results = match result_doc.as_ref().unwrap().get("documents") {
89 Some(documents) => {
90 let documents = match documents.as_array() {
91 Some(documents) => documents.clone(),
92 None => Vec::<bson::Bson>::new(),
93 };
94 let documents = documents
95 .clone()
96 .into_iter()
97 .map(|doc| Some(doc.as_document().unwrap().clone()))
98 .collect::<Vec<Option<Document>>>();
99 documents
100 }
101 None => Vec::<Option<Document>>::new(),
102 };
103
104 let total_count = if let Some(total_count_docs) = result_doc
105 .as_ref()
106 .unwrap()
107 .get("total_count")
108 .unwrap()
109 .as_array()
110 {
111 if total_count_docs.len() > 0 {
112 let total_count_doc = total_count_docs.get(0).unwrap().as_document().unwrap();
113 let total_count = total_count_doc
114 .get("total_count")
115 .unwrap_or(&bson::Bson::Int32(0))
116 .as_i32()
117 .unwrap();
118 total_count
119 } else {
120 0
121 }
122 } else {
123 0
124 };
125
126 Ok((results, total_count as i64))
127 }
128}