1use crate::searchx::query_options::Location;
20use serde::Serialize;
21
22#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize)]
23#[serde(rename_all = "lowercase")]
24#[non_exhaustive]
25pub enum MatchOperator {
26 Or,
27 And,
28}
29
30#[derive(Debug, Clone, PartialEq, Serialize)]
31#[non_exhaustive]
32pub struct MatchQuery {
33 #[serde(skip_serializing_if = "Option::is_none")]
34 pub analyzer: Option<String>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub boost: Option<f32>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub field: Option<String>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 pub fuzziness: Option<u64>,
41 #[serde(rename = "match")]
42 pub match_input: String,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 pub operator: Option<MatchOperator>,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub prefix_length: Option<u64>,
47}
48
49impl MatchQuery {
50 pub fn new(match_input: impl Into<String>) -> Self {
51 Self {
52 analyzer: None,
53 boost: None,
54 field: None,
55 fuzziness: None,
56 match_input: match_input.into(),
57 operator: None,
58 prefix_length: None,
59 }
60 }
61
62 pub fn analyzer(mut self, analyzer: impl Into<Option<String>>) -> Self {
63 self.analyzer = analyzer.into();
64 self
65 }
66
67 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
68 self.boost = boost.into();
69 self
70 }
71
72 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
73 self.field = field.into();
74 self
75 }
76
77 pub fn fuzziness(mut self, fuzziness: impl Into<Option<u64>>) -> Self {
78 self.fuzziness = fuzziness.into();
79 self
80 }
81
82 pub fn operator(mut self, operator: impl Into<Option<MatchOperator>>) -> Self {
83 self.operator = operator.into();
84 self
85 }
86
87 pub fn prefix_length(mut self, prefix_length: impl Into<Option<u64>>) -> Self {
88 self.prefix_length = prefix_length.into();
89 self
90 }
91}
92
93#[derive(Debug, Clone, PartialEq, Serialize)]
94#[non_exhaustive]
95pub struct MatchPhraseQuery {
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub analyzer: Option<String>,
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub boost: Option<f32>,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub field: Option<String>,
102 pub match_phrase: String,
103}
104
105impl MatchPhraseQuery {
106 pub fn new(match_phrase: impl Into<String>) -> Self {
107 Self {
108 analyzer: None,
109 boost: None,
110 field: None,
111 match_phrase: match_phrase.into(),
112 }
113 }
114
115 pub fn analyzer(mut self, analyzer: impl Into<Option<String>>) -> Self {
116 self.analyzer = analyzer.into();
117 self
118 }
119
120 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
121 self.boost = boost.into();
122 self
123 }
124
125 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
126 self.field = field.into();
127 self
128 }
129}
130
131#[derive(Debug, Clone, PartialEq, Serialize)]
132#[non_exhaustive]
133pub struct RegexpQuery {
134 #[serde(skip_serializing_if = "Option::is_none")]
135 pub boost: Option<f32>,
136 #[serde(skip_serializing_if = "Option::is_none")]
137 pub field: Option<String>,
138 pub regexp: String,
139}
140
141impl RegexpQuery {
142 pub fn new(regexp: impl Into<String>) -> Self {
143 Self {
144 boost: None,
145 field: None,
146 regexp: regexp.into(),
147 }
148 }
149
150 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
151 self.boost = boost.into();
152 self
153 }
154
155 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
156 self.field = field.into();
157 self
158 }
159}
160
161#[derive(Debug, Clone, PartialEq, Serialize)]
162#[non_exhaustive]
163pub struct QueryStringQuery {
164 #[serde(skip_serializing_if = "Option::is_none")]
165 pub boost: Option<f32>,
166 pub query: String,
167}
168
169impl QueryStringQuery {
170 pub fn new(query: impl Into<String>) -> Self {
171 Self {
172 boost: None,
173 query: query.into(),
174 }
175 }
176
177 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
178 self.boost = boost.into();
179 self
180 }
181}
182
183#[derive(Debug, Default, Clone, PartialEq, Serialize)]
184#[non_exhaustive]
185pub struct NumericRangeQuery {
186 #[serde(skip_serializing_if = "Option::is_none")]
187 pub boost: Option<f32>,
188 #[serde(skip_serializing_if = "Option::is_none")]
189 pub field: Option<String>,
190 #[serde(skip_serializing_if = "Option::is_none")]
191 pub inclusive_min: Option<bool>,
192 #[serde(skip_serializing_if = "Option::is_none")]
193 pub inclusive_max: Option<bool>,
194 #[serde(skip_serializing_if = "Option::is_none")]
195 pub min: Option<f32>,
196 #[serde(skip_serializing_if = "Option::is_none")]
197 pub max: Option<f32>,
198}
199
200impl NumericRangeQuery {
201 pub fn new() -> Self {
202 Default::default()
203 }
204
205 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
206 self.boost = boost.into();
207 self
208 }
209
210 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
211 self.field = field.into();
212 self
213 }
214
215 pub fn inclusive_min(mut self, inclusive_min: impl Into<Option<bool>>) -> Self {
216 self.inclusive_min = inclusive_min.into();
217 self
218 }
219
220 pub fn inclusive_max(mut self, inclusive_max: impl Into<Option<bool>>) -> Self {
221 self.inclusive_max = inclusive_max.into();
222 self
223 }
224
225 pub fn min(mut self, min: impl Into<Option<f32>>) -> Self {
226 self.min = min.into();
227 self
228 }
229
230 pub fn max(mut self, max: impl Into<Option<f32>>) -> Self {
231 self.max = max.into();
232 self
233 }
234}
235
236#[derive(Debug, Default, Clone, PartialEq, Serialize)]
237#[non_exhaustive]
238pub struct DateRangeQuery {
239 #[serde(skip_serializing_if = "Option::is_none")]
240 pub boost: Option<f32>,
241 #[serde(skip_serializing_if = "Option::is_none")]
242 pub field: Option<String>,
243 #[serde(skip_serializing_if = "Option::is_none")]
244 pub datetime_parser: Option<String>,
245 #[serde(skip_serializing_if = "Option::is_none")]
246 pub end: Option<String>,
247 #[serde(skip_serializing_if = "Option::is_none")]
248 pub inclusive_start: Option<bool>,
249 #[serde(skip_serializing_if = "Option::is_none")]
250 pub inclusive_end: Option<bool>,
251 #[serde(skip_serializing_if = "Option::is_none")]
252 pub start: Option<String>,
253}
254
255impl DateRangeQuery {
256 pub fn new() -> Self {
257 Default::default()
258 }
259
260 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
261 self.boost = boost.into();
262 self
263 }
264
265 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
266 self.field = field.into();
267 self
268 }
269
270 pub fn datetime_parser(mut self, datetime_parser: impl Into<Option<String>>) -> Self {
271 self.datetime_parser = datetime_parser.into();
272 self
273 }
274
275 pub fn end(mut self, end: impl Into<Option<String>>) -> Self {
276 self.end = end.into();
277 self
278 }
279
280 pub fn inclusive_start(mut self, inclusive_start: impl Into<Option<bool>>) -> Self {
281 self.inclusive_start = inclusive_start.into();
282 self
283 }
284
285 pub fn inclusive_end(mut self, inclusive_end: impl Into<Option<bool>>) -> Self {
286 self.inclusive_end = inclusive_end.into();
287 self
288 }
289
290 pub fn start(mut self, start: impl Into<Option<String>>) -> Self {
291 self.start = start.into();
292 self
293 }
294}
295
296#[derive(Debug, Default, Clone, PartialEq, Serialize)]
297#[non_exhaustive]
298pub struct TermRangeQuery {
299 #[serde(skip_serializing_if = "Option::is_none")]
300 pub boost: Option<f32>,
301 #[serde(skip_serializing_if = "Option::is_none")]
302 pub field: Option<String>,
303 #[serde(skip_serializing_if = "Option::is_none")]
304 pub inclusive_min: Option<bool>,
305 #[serde(skip_serializing_if = "Option::is_none")]
306 pub inclusive_max: Option<bool>,
307 #[serde(skip_serializing_if = "Option::is_none")]
308 pub max: Option<String>,
309 #[serde(skip_serializing_if = "Option::is_none")]
310 pub min: Option<String>,
311}
312
313impl TermRangeQuery {
314 pub fn new() -> Self {
315 Default::default()
316 }
317
318 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
319 self.boost = boost.into();
320 self
321 }
322
323 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
324 self.field = field.into();
325 self
326 }
327
328 pub fn inclusive_min(mut self, inclusive_min: impl Into<Option<bool>>) -> Self {
329 self.inclusive_min = inclusive_min.into();
330 self
331 }
332
333 pub fn inclusive_max(mut self, inclusive_max: impl Into<Option<bool>>) -> Self {
334 self.inclusive_max = inclusive_max.into();
335 self
336 }
337
338 pub fn max(mut self, max: impl Into<Option<String>>) -> Self {
339 self.max = max.into();
340 self
341 }
342
343 pub fn min(mut self, min: impl Into<Option<String>>) -> Self {
344 self.min = min.into();
345 self
346 }
347}
348
349#[derive(Debug, Clone, PartialEq, Serialize)]
350#[non_exhaustive]
351pub struct ConjunctionQuery {
352 #[serde(skip_serializing_if = "Option::is_none")]
353 pub boost: Option<f32>,
354 pub conjuncts: Vec<Query>,
355}
356
357impl ConjunctionQuery {
358 pub fn new(conjuncts: Vec<Query>) -> Self {
359 Self {
360 boost: None,
361 conjuncts,
362 }
363 }
364
365 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
366 self.boost = boost.into();
367 self
368 }
369}
370
371#[derive(Debug, Clone, PartialEq, Serialize)]
372#[non_exhaustive]
373pub struct DisjunctionQuery {
374 #[serde(skip_serializing_if = "Option::is_none")]
375 pub boost: Option<f32>,
376 #[serde(skip_serializing_if = "Option::is_none")]
377 pub min: Option<u32>,
378 pub disjuncts: Vec<Query>,
379}
380
381impl DisjunctionQuery {
382 pub fn new(disjuncts: Vec<Query>) -> Self {
383 Self {
384 boost: None,
385 disjuncts,
386 min: None,
387 }
388 }
389
390 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
391 self.boost = boost.into();
392 self
393 }
394
395 pub fn min(mut self, min: impl Into<Option<u32>>) -> Self {
396 self.min = min.into();
397 self
398 }
399}
400
401#[derive(Debug, Default, Clone, PartialEq, Serialize)]
402#[non_exhaustive]
403pub struct BooleanQuery {
404 #[serde(skip_serializing_if = "Option::is_none")]
405 pub boost: Option<f32>,
406 #[serde(skip_serializing_if = "Option::is_none")]
407 pub must: Option<ConjunctionQuery>,
408 #[serde(skip_serializing_if = "Option::is_none")]
409 pub must_not: Option<DisjunctionQuery>,
410 #[serde(skip_serializing_if = "Option::is_none")]
411 pub should: Option<DisjunctionQuery>,
412}
413
414impl BooleanQuery {
415 pub fn new() -> Self {
416 Default::default()
417 }
418
419 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
420 self.boost = boost.into();
421 self
422 }
423
424 pub fn must(mut self, must: impl Into<Option<ConjunctionQuery>>) -> Self {
425 self.must = must.into();
426 self
427 }
428
429 pub fn must_not(mut self, must_not: impl Into<Option<DisjunctionQuery>>) -> Self {
430 self.must_not = must_not.into();
431 self
432 }
433
434 pub fn should(mut self, should: impl Into<Option<DisjunctionQuery>>) -> Self {
435 self.should = should.into();
436 self
437 }
438}
439
440#[derive(Debug, Clone, PartialEq, Serialize)]
441#[non_exhaustive]
442pub struct WildcardQuery {
443 #[serde(skip_serializing_if = "Option::is_none")]
444 pub boost: Option<f32>,
445 #[serde(skip_serializing_if = "Option::is_none")]
446 pub field: Option<String>,
447 pub wildcard: String,
448}
449
450impl WildcardQuery {
451 pub fn new(wildcard: impl Into<String>) -> Self {
452 Self {
453 boost: None,
454 field: None,
455 wildcard: wildcard.into(),
456 }
457 }
458
459 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
460 self.boost = boost.into();
461 self
462 }
463
464 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
465 self.field = field.into();
466 self
467 }
468}
469
470#[derive(Debug, Clone, PartialEq, Serialize)]
471#[non_exhaustive]
472pub struct DocIDQuery {
473 #[serde(skip_serializing_if = "Option::is_none")]
474 pub boost: Option<f32>,
475 pub ids: Vec<String>,
476}
477
478impl DocIDQuery {
479 pub fn new(ids: Vec<String>) -> Self {
480 Self { boost: None, ids }
481 }
482
483 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
484 self.boost = boost.into();
485 self
486 }
487}
488
489#[derive(Debug, Clone, PartialEq, Serialize)]
490#[non_exhaustive]
491pub struct BooleanFieldQuery {
492 #[serde(rename = "bool")]
493 pub bool_value: bool,
494 #[serde(skip_serializing_if = "Option::is_none")]
495 pub boost: Option<f32>,
496 #[serde(skip_serializing_if = "Option::is_none")]
497 pub field: Option<String>,
498}
499
500impl BooleanFieldQuery {
501 pub fn new(bool_value: bool) -> Self {
502 Self {
503 bool_value,
504 boost: None,
505 field: None,
506 }
507 }
508
509 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
510 self.boost = boost.into();
511 self
512 }
513
514 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
515 self.field = field.into();
516 self
517 }
518}
519
520#[derive(Debug, Clone, PartialEq, Serialize)]
521#[non_exhaustive]
522pub struct TermQuery {
523 #[serde(skip_serializing_if = "Option::is_none")]
524 pub boost: Option<f32>,
525 #[serde(skip_serializing_if = "Option::is_none")]
526 pub field: Option<String>,
527 #[serde(skip_serializing_if = "Option::is_none")]
528 pub fuzziness: Option<u32>,
529 #[serde(skip_serializing_if = "Option::is_none")]
530 pub prefix_length: Option<u32>,
531 pub term: String,
532}
533
534impl TermQuery {
535 pub fn new(term: impl Into<String>) -> Self {
536 Self {
537 boost: None,
538 field: None,
539 fuzziness: None,
540 prefix_length: None,
541 term: term.into(),
542 }
543 }
544
545 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
546 self.boost = boost.into();
547 self
548 }
549
550 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
551 self.field = field.into();
552 self
553 }
554
555 pub fn fuzziness(mut self, fuzziness: impl Into<Option<u32>>) -> Self {
556 self.fuzziness = fuzziness.into();
557 self
558 }
559
560 pub fn prefix_length(mut self, prefix_length: impl Into<Option<u32>>) -> Self {
561 self.prefix_length = prefix_length.into();
562 self
563 }
564}
565
566#[derive(Debug, Clone, PartialEq, Serialize)]
567#[non_exhaustive]
568pub struct PhraseQuery {
569 #[serde(skip_serializing_if = "Option::is_none")]
570 pub boost: Option<f32>,
571 #[serde(skip_serializing_if = "Option::is_none")]
572 pub field: Option<String>,
573 pub terms: Vec<String>,
574}
575
576impl PhraseQuery {
577 pub fn new(terms: Vec<String>) -> Self {
578 Self {
579 boost: None,
580 field: None,
581 terms,
582 }
583 }
584
585 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
586 self.boost = boost.into();
587 self
588 }
589
590 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
591 self.field = field.into();
592 self
593 }
594}
595
596#[derive(Debug, Clone, PartialEq, Serialize)]
597#[non_exhaustive]
598pub struct PrefixQuery {
599 #[serde(skip_serializing_if = "Option::is_none")]
600 pub boost: Option<f32>,
601 #[serde(skip_serializing_if = "Option::is_none")]
602 pub field: Option<String>,
603 pub prefix: String,
604}
605
606impl PrefixQuery {
607 pub fn new(prefix: impl Into<String>) -> Self {
608 Self {
609 boost: None,
610 field: None,
611 prefix: prefix.into(),
612 }
613 }
614
615 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
616 self.boost = boost.into();
617 self
618 }
619
620 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
621 self.field = field.into();
622 self
623 }
624}
625
626#[derive(Debug, Default, Clone, PartialEq)]
627#[non_exhaustive]
628pub struct MatchAllQuery {}
629
630impl MatchAllQuery {
631 pub fn new() -> Self {
632 Default::default()
633 }
634}
635
636impl Serialize for MatchAllQuery {
637 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
638 where
639 S: serde::Serializer,
640 {
641 use serde::ser::SerializeMap;
642 let mut map = serializer.serialize_map(Some(1))?;
643 map.serialize_entry("match_all", &serde_json::Value::Null)?;
644 map.end()
645 }
646}
647
648#[derive(Debug, Default, Clone, PartialEq)]
649#[non_exhaustive]
650pub struct MatchNoneQuery {}
651
652impl MatchNoneQuery {
653 pub fn new() -> Self {
654 Default::default()
655 }
656}
657
658impl Serialize for MatchNoneQuery {
659 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
660 where
661 S: serde::Serializer,
662 {
663 use serde::ser::SerializeMap;
664 let mut map = serializer.serialize_map(Some(1))?;
665 map.serialize_entry("match_none", &serde_json::Value::Null)?;
666 map.end()
667 }
668}
669
670#[derive(Debug, Clone, PartialEq, Serialize)]
671#[non_exhaustive]
672pub struct GeoDistanceQuery {
673 #[serde(skip_serializing_if = "Option::is_none")]
674 pub boost: Option<f32>,
675 #[serde(skip_serializing_if = "Option::is_none")]
676 pub field: Option<String>,
677 pub location: Location,
678 pub distance: String,
679}
680
681impl GeoDistanceQuery {
682 pub fn new(distance: impl Into<String>, location: Location) -> Self {
683 Self {
684 distance: distance.into(),
685 boost: None,
686 field: None,
687 location,
688 }
689 }
690
691 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
692 self.boost = boost.into();
693 self
694 }
695
696 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
697 self.field = field.into();
698 self
699 }
700}
701
702#[derive(Debug, Clone, PartialEq, Serialize)]
703#[non_exhaustive]
704pub struct GeoBoundingBoxQuery {
705 #[serde(skip_serializing_if = "Option::is_none")]
706 pub boost: Option<f32>,
707 #[serde(skip_serializing_if = "Option::is_none")]
708 pub field: Option<String>,
709 pub top_left: Location,
710 pub bottom_right: Location,
711}
712
713impl GeoBoundingBoxQuery {
714 pub fn new(top_left: impl Into<Location>, bottom_right: impl Into<Location>) -> Self {
715 Self {
716 bottom_right: bottom_right.into(),
717 boost: None,
718 field: None,
719 top_left: top_left.into(),
720 }
721 }
722
723 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
724 self.boost = boost.into();
725 self
726 }
727
728 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
729 self.field = field.into();
730 self
731 }
732}
733
734#[derive(Debug, Clone, PartialEq, Serialize)]
735#[non_exhaustive]
736pub struct GeoPolygonQuery {
737 #[serde(skip_serializing_if = "Option::is_none")]
738 pub boost: Option<f32>,
739 #[serde(skip_serializing_if = "Option::is_none")]
740 pub field: Option<String>,
741 pub polygon_points: Vec<Location>,
742}
743
744impl GeoPolygonQuery {
745 pub fn new(polygon_points: Vec<Location>) -> Self {
746 Self {
747 boost: None,
748 field: None,
749 polygon_points,
750 }
751 }
752
753 pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
754 self.boost = boost.into();
755 self
756 }
757
758 pub fn field(mut self, field: impl Into<Option<String>>) -> Self {
759 self.field = field.into();
760 self
761 }
762}
763
764#[derive(Debug, Clone, PartialEq, Serialize)]
765#[serde(untagged)]
766#[non_exhaustive]
767pub enum Query {
768 Match(MatchQuery),
769 MatchPhrase(MatchPhraseQuery),
770 Regexp(RegexpQuery),
771 QueryString(QueryStringQuery),
772 NumericRange(NumericRangeQuery),
773 DateRange(DateRangeQuery),
774 TermRange(TermRangeQuery),
775 Conjunction(ConjunctionQuery),
776 Disjunction(DisjunctionQuery),
777 Boolean(BooleanQuery),
778 Wildcard(WildcardQuery),
779 DocID(DocIDQuery),
780 BooleanField(BooleanFieldQuery),
781 Term(TermQuery),
782 Phrase(PhraseQuery),
783 Prefix(PrefixQuery),
784 MatchAll(MatchAllQuery),
785 MatchNone(MatchNoneQuery),
786 GeoDistance(GeoDistanceQuery),
787 GeoBoundingBox(GeoBoundingBoxQuery),
788 GeoPolygon(GeoPolygonQuery),
789}