1use serde::{de::DeserializeOwned, Deserialize, Serialize};
4use serde_json::{json, Map, Value};
5
6use crate::{client::Parse, error::ParseError, Pointer};
7
8#[derive(Debug, Clone)]
10pub struct ParseQuery {
11 class_name: String,
12 conditions: Map<String, Value>,
13 limit: Option<isize>, skip: Option<usize>,
15 order: Option<String>,
16 include: Option<String>,
17 keys: Option<String>, use_master_key: bool, }
23
24impl ParseQuery {
25 pub fn new(class_name: &str) -> Self {
30 Self {
31 class_name: class_name.to_string(),
32 conditions: Map::new(),
33 limit: None,
34 skip: None,
35 order: None,
36 include: None,
37 keys: None,
38 use_master_key: false, }
41 }
42
43 pub fn class_name(&self) -> &str {
45 &self.class_name
46 }
47
48 pub fn uses_master_key(&self) -> bool {
50 self.use_master_key
51 }
52
53 pub fn set_master_key(&mut self, use_key: bool) -> &mut Self {
55 self.use_master_key = use_key;
56 self
57 }
58
59 fn add_simple_condition(&mut self, key: &str, value: Value) -> &mut Self {
61 self.conditions.insert(key.to_string(), value);
62 self
63 }
64
65 fn add_operator_condition(&mut self, key: &str, operator: &str, value: Value) -> &mut Self {
67 let mut op_map = Map::new();
68 op_map.insert(operator.to_string(), value);
69 self.conditions
70 .insert(key.to_string(), Value::Object(op_map));
71 self
72 }
73
74 pub fn equal_to<V: Serialize>(&mut self, key: &str, value: V) -> &mut Self {
76 match serde_json::to_value(value) {
77 Ok(json_val) => self.add_simple_condition(key, json_val),
78 Err(_) => {
79 self
81 }
82 }
83 }
84
85 pub fn not_equal_to<V: Serialize>(&mut self, key: &str, value: V) -> &mut Self {
87 match serde_json::to_value(value) {
88 Ok(json_val) => self.add_operator_condition(key, "$ne", json_val),
89 Err(_) => self,
90 }
91 }
92
93 pub fn exists(&mut self, key: &str) -> &mut Self {
95 self.add_operator_condition(key, "$exists", serde_json::Value::Bool(true))
96 }
97
98 pub fn does_not_exist(&mut self, key: &str) -> &mut Self {
100 self.add_operator_condition(key, "$exists", serde_json::Value::Bool(false))
101 }
102
103 pub fn greater_than<V: Serialize>(&mut self, key: &str, value: V) -> &mut Self {
105 match serde_json::to_value(value) {
106 Ok(json_val) => self.add_operator_condition(key, "$gt", json_val),
107 Err(_) => self,
108 }
109 }
110
111 pub fn greater_than_or_equal_to<V: Serialize>(&mut self, key: &str, value: V) -> &mut Self {
113 match serde_json::to_value(value) {
114 Ok(json_val) => self.add_operator_condition(key, "$gte", json_val),
115 Err(_) => self,
116 }
117 }
118
119 pub fn less_than<V: Serialize>(&mut self, key: &str, value: V) -> &mut Self {
121 match serde_json::to_value(value) {
122 Ok(json_val) => self.add_operator_condition(key, "$lt", json_val),
123 Err(_) => self,
124 }
125 }
126
127 pub fn less_than_or_equal_to<V: Serialize>(&mut self, key: &str, value: V) -> &mut Self {
129 match serde_json::to_value(value) {
130 Ok(json_val) => self.add_operator_condition(key, "$lte", json_val),
131 Err(_) => self,
132 }
133 }
134
135 pub fn contained_in<V: Serialize>(&mut self, key: &str, values: Vec<V>) -> &mut Self {
137 match serde_json::to_value(values) {
138 Ok(json_val_array) => self.add_operator_condition(key, "$in", json_val_array),
139 Err(_) => self,
140 }
141 }
142
143 pub fn not_contained_in<V: Serialize>(&mut self, key: &str, values: Vec<V>) -> &mut Self {
145 match serde_json::to_value(values) {
146 Ok(json_val_array) => self.add_operator_condition(key, "$nin", json_val_array),
147 Err(_) => self,
148 }
149 }
150
151 pub fn contains_all<V: Serialize>(&mut self, key: &str, values: Vec<V>) -> &mut Self {
153 match serde_json::to_value(values) {
154 Ok(json_val_array) => self.add_operator_condition(key, "$all", json_val_array),
155 Err(_) => self,
156 }
157 }
158
159 pub fn starts_with(&mut self, key: &str, prefix: &str) -> &mut Self {
161 self.add_operator_condition(
162 key,
163 "$regex",
164 Value::String(format!("^{}", regex::escape(prefix))),
165 )
166 }
167
168 pub fn ends_with(&mut self, key: &str, suffix: &str) -> &mut Self {
170 self.add_operator_condition(
171 key,
172 "$regex",
173 Value::String(format!("{}$", regex::escape(suffix))),
174 )
175 }
176
177 pub fn contains(&mut self, key: &str, substring: &str) -> &mut Self {
180 self.add_operator_condition(
181 key,
182 "$regex",
183 Value::String(format!(".*{}.*", regex::escape(substring))),
184 )
185 }
186
187 pub fn matches_regex(
190 &mut self,
191 key: &str,
192 regex_pattern: &str,
193 modifiers: Option<&str>,
194 ) -> &mut Self {
195 let mut regex_map = Map::new();
196 regex_map.insert(
197 "$regex".to_string(),
198 Value::String(regex_pattern.to_string()),
199 );
200 if let Some(mods) = modifiers {
201 regex_map.insert("$options".to_string(), Value::String(mods.to_string()));
202 }
203 self.conditions
204 .insert(key.to_string(), Value::Object(regex_map));
205 self
206 }
207
208 pub fn search(
218 &mut self,
219 key: &str,
220 term: &str,
221 language: Option<&str>,
222 case_sensitive: Option<bool>,
223 diacritic_sensitive: Option<bool>,
224 ) -> &mut Self {
225 let mut search_params_map = Map::new();
226 search_params_map.insert("$term".to_string(), Value::String(term.to_string()));
227
228 if let Some(lang) = language {
229 search_params_map.insert("$language".to_string(), Value::String(lang.to_string()));
230 }
231 if let Some(cs) = case_sensitive {
232 search_params_map.insert("$caseSensitive".to_string(), Value::Bool(cs));
233 }
234 if let Some(ds) = diacritic_sensitive {
235 search_params_map.insert("$diacriticSensitive".to_string(), Value::Bool(ds));
236 }
237
238 let mut search_op = Map::new();
239 search_op.insert("$search".to_string(), Value::Object(search_params_map));
240
241 let mut text_op = Map::new();
242 text_op.insert("$text".to_string(), Value::Object(search_op));
243
244 self.conditions
245 .insert(key.to_string(), Value::Object(text_op));
246 self
247 }
248
249 pub fn related_to(&mut self, parent_object: &Pointer, key_on_parent_object: &str) -> &mut Self {
264 let mut related_to_map = Map::new();
265 match serde_json::to_value(parent_object) {
266 Ok(parent_ptr_json) => {
267 related_to_map.insert("object".to_string(), parent_ptr_json);
268 related_to_map.insert(
269 "key".to_string(),
270 Value::String(key_on_parent_object.to_string()),
271 );
272 self.conditions
273 .insert("$relatedTo".to_string(), Value::Object(related_to_map));
274 }
275 Err(_) => {
276 }
280 }
281 self
282 }
283
284 pub fn limit(&mut self, count: isize) -> &mut Self {
288 self.limit = Some(count);
289 self
290 }
291
292 pub fn skip(&mut self, count: usize) -> &mut Self {
294 self.skip = Some(count);
295 self
296 }
297
298 pub fn order(&mut self, field_names: &str) -> &mut Self {
302 self.order = Some(field_names.to_string());
303 self
304 }
305
306 fn append_order_key(&mut self, key: &str, descending: bool) {
308 let prefix = if descending { "-" } else { "" };
309 let new_order_key = format!("{}{}", prefix, key);
310 if let Some(existing_order) = &mut self.order {
311 if !existing_order.is_empty() {
312 existing_order.push(',');
313 }
314 existing_order.push_str(&new_order_key);
315 } else {
316 self.order = Some(new_order_key);
317 }
318 }
319
320 pub fn order_by_ascending(&mut self, key: &str) -> &mut Self {
322 self.order = Some(key.to_string());
323 self
324 }
325
326 pub fn order_by_descending(&mut self, key: &str) -> &mut Self {
328 self.order = Some(format!("-{}", key));
329 self
330 }
331
332 pub fn add_ascending_order(&mut self, key: &str) -> &mut Self {
334 self.append_order_key(key, false);
335 self
336 }
337
338 pub fn add_descending_order(&mut self, key: &str) -> &mut Self {
340 self.append_order_key(key, true);
341 self
342 }
343
344 pub fn include(&mut self, keys_to_include: &[&str]) -> &mut Self {
347 let current_include = self.include.take().unwrap_or_default();
348 let mut include_parts: Vec<&str> = current_include
349 .split(',')
350 .filter(|s| !s.is_empty())
351 .collect();
352 include_parts.extend(keys_to_include.iter().cloned());
353 include_parts.sort_unstable(); include_parts.dedup();
355 self.include = Some(include_parts.join(","));
356 self
357 }
358
359 pub fn select(&mut self, keys_to_select: &[&str]) -> &mut Self {
361 let current_keys = self.keys.take().unwrap_or_default();
362 let mut select_parts: Vec<&str> =
363 current_keys.split(',').filter(|s| !s.is_empty()).collect();
364 select_parts.extend(keys_to_select.iter().cloned());
365 select_parts.sort_unstable(); select_parts.dedup();
367 self.keys = Some(select_parts.join(","));
368 self
369 }
370
371 pub fn build_query_params(&self) -> Vec<(String, String)> {
375 let mut params = Vec::new();
376 if !self.conditions.is_empty() {
377 if let Ok(where_json) = serde_json::to_string(&self.conditions) {
378 params.push(("where".to_string(), where_json));
379 }
380 }
381 if let Some(limit_val) = self.limit {
382 params.push(("limit".to_string(), limit_val.to_string()));
383 }
384 if let Some(skip_val) = self.skip {
385 params.push(("skip".to_string(), skip_val.to_string()));
386 }
387 if let Some(order_val) = &self.order {
388 params.push(("order".to_string(), order_val.clone()));
389 }
390 if let Some(include_val) = &self.include {
391 params.push(("include".to_string(), include_val.clone()));
392 }
393 if let Some(keys_val) = &self.keys {
394 params.push(("keys".to_string(), keys_val.clone()));
395 }
396 params
397 }
398
399 async fn find_raw<T: DeserializeOwned + Send + Sync + 'static>(
400 &self,
401 client: &Parse,
402 ) -> Result<FindResponse<T>, ParseError> {
403 let endpoint = format!("classes/{}", self.class_name);
404 let params = self.build_query_params();
405 let response_wrapper: FindResponse<T> = client
406 ._get_with_url_params(&endpoint, ¶ms, self.use_master_key, None)
407 .await?;
408 Ok(response_wrapper)
409 }
410
411 async fn first_raw<T: DeserializeOwned + Send + Sync + 'static>(
412 &self,
413 client: &Parse,
414 ) -> Result<Option<T>, ParseError> {
415 let mut query_clone = self.clone();
416 query_clone.limit(1);
417 let endpoint = format!("classes/{}", query_clone.class_name);
418 let params = query_clone.build_query_params();
419 let response_wrapper: FindResponse<T> = client
420 ._get_with_url_params(&endpoint, ¶ms, self.use_master_key, None)
421 .await?;
422 Ok(response_wrapper.results.into_iter().next())
423 }
424
425 pub async fn find<T: DeserializeOwned + Send + Sync + 'static>(
427 &self,
428 client: &Parse,
429 ) -> Result<Vec<T>, ParseError> {
430 let response_wrapper = self.find_raw(client).await?;
431 Ok(response_wrapper.results)
432 }
433
434 pub async fn first<T: DeserializeOwned + Send + Sync + 'static>(
436 &self,
437 client: &Parse,
438 ) -> Result<Option<T>, ParseError> {
439 self.first_raw(client).await
440 }
441
442 pub async fn get<T: DeserializeOwned + Send + Sync + 'static>(
445 &self,
446 object_id: &str,
447 client: &Parse,
448 ) -> Result<T, ParseError> {
449 let endpoint = format!("classes/{}/{}", self.class_name, object_id);
450 let params = self.build_query_params();
451 client
452 ._get_with_url_params(&endpoint, ¶ms, self.use_master_key, None)
453 .await
454 }
455
456 pub async fn count(&self, client: &Parse) -> Result<u64, ParseError> {
458 let mut query_clone = self.clone();
459 query_clone.limit(0); let endpoint = format!("classes/{}", query_clone.class_name);
462 let mut params = query_clone.build_query_params();
463 params.push(("count".to_string(), "1".to_string()));
464
465 let response_wrapper: CountResponse = client
466 ._get_with_url_params(&endpoint, ¶ms, self.use_master_key, None)
467 .await?;
468 Ok(response_wrapper.count)
469 }
470
471 pub async fn distinct<T: DeserializeOwned + Send + Sync + 'static>(
474 &self,
475 client: &Parse,
476 field: &str,
477 ) -> Result<Vec<T>, ParseError> {
478 let endpoint = format!("aggregate/{}", self.class_name);
479
480 let mut pipeline: Vec<Value> = Vec::new();
481
482 if !self.conditions.is_empty() {
484 pipeline.push(json!({
485 "$match": self.conditions
486 }));
487 }
488
489 pipeline.push(json!({
491 "$group": { "_id": format!("${}", field) } }));
493
494 let pipeline_json = serde_json::to_string(&pipeline).map_err(|e| {
496 ParseError::SerializationError(format!(
497 "Failed to serialize pipeline for distinct query: {}",
498 e
499 ))
500 })?;
501
502 let params = vec![("pipeline".to_string(), pipeline_json)];
503
504 #[derive(serde::Deserialize, Debug)]
507 struct DistinctItem<V> {
508 #[serde(rename = "objectId")] value: V,
510 }
511
512 let response_wrapper: FindResponse<DistinctItem<T>> = client
513 ._get_with_url_params(&endpoint, ¶ms, true, None) .await?;
515
516 let distinct_values = response_wrapper
518 .results
519 .into_iter()
520 .map(|item| item.value)
521 .collect();
522
523 Ok(distinct_values)
524 }
525
526 pub async fn aggregate<T: DeserializeOwned + Send + Sync + 'static>(
539 &self,
540 pipeline: Vec<Value>,
541 client: &crate::client::Parse,
542 ) -> Result<Vec<T>, crate::error::ParseError> {
543 client
544 .execute_aggregate(&self.class_name, serde_json::Value::Array(pipeline))
545 .await
546 }
547}
548
549#[derive(Debug, Deserialize)]
550struct FindResponse<T> {
551 results: Vec<T>,
552}
553
554#[derive(Debug, Deserialize)]
555struct CountResponse {
556 count: u64,
557}
558
559#[cfg(test)]
560mod tests {
561 }