1use serde_json::{Map, Value};
24
25use crate::query::Query;
26
27mod compound;
28mod extra;
29mod geo;
30mod nested;
31mod object;
32mod scalar;
33mod sort;
34mod string;
35
36pub use compound::{
37 BoostingQuery, ConstantScoreQuery, DisMaxQuery, FunctionScoreQuery, boosting, constant_score,
38 dis_max, function_score,
39};
40pub use extra::{
41 CombinedFieldsQuery, DistanceFeatureQuery, IdsQuery, MoreLikeThisQuery, QueryStringQuery,
42 RankFeatureQuery, ScriptQuery, ScriptScoreQuery, SimpleQueryStringQuery, combined_fields,
43 distance_feature, ids, more_like_this, query_string, rank_feature, script, script_score,
44 simple_query_string,
45};
46pub use geo::{Geo, GeoDistanceQuery, GeoPoint};
47pub use nested::{Nested, NestedProjection, NestedQuery};
48pub use object::{Binary, Json, Object};
49pub use scalar::{Bool, Date, EqQuery, Number, RangeQuery, TermsQuery};
50pub use sort::{Sort, SortMode, SortOrder};
51pub use string::{
52 FuzzyQuery, Keyword, MatchQuery, MultiMatchQuery, PrefixQuery, RegexpQuery, TermQuery, Text,
53 WildcardQuery, multi_match,
54};
55
56fn single<S>(wrapper: &str, path: &str, value: Value) -> Query<S> {
58 let mut inner = Map::new();
59 inner.insert(path.to_string(), value);
60 wrap(wrapper, inner)
61}
62
63fn wrap<S>(wrapper: &str, body: Map<String, Value>) -> Query<S> {
65 let mut outer = Map::new();
66 outer.insert(wrapper.to_string(), Value::Object(body));
67 Query::leaf(Value::Object(outer))
68}
69
70#[derive(Debug, Clone, Default)]
75pub(crate) struct Common {
76 boost: Option<f32>,
77 name: Option<String>,
78}
79
80impl Common {
81 pub(crate) fn set_boost(&mut self, boost: f32) {
82 self.boost = Some(boost);
83 }
84
85 pub(crate) fn set_name(&mut self, name: String) {
86 self.name = Some(name);
87 }
88
89 pub(crate) fn is_empty(&self) -> bool {
91 self.boost.is_none() && self.name.is_none()
92 }
93
94 pub(crate) fn write(&self, map: &mut Map<String, Value>) {
96 if let Some(boost) = self.boost {
97 map.insert("boost".to_string(), Value::from(boost));
98 }
99 if let Some(name) = &self.name {
100 map.insert("_name".to_string(), Value::String(name.clone()));
101 }
102 }
103}
104
105macro_rules! common_opts {
108 ($field:ident) => {
109 #[must_use]
111 pub fn boost(mut self, boost: f32) -> Self {
112 self.$field.set_boost(boost);
113 self
114 }
115
116 #[must_use]
118 pub fn name(mut self, name: impl Into<String>) -> Self {
119 self.$field.set_name(name.into());
120 self
121 }
122 };
123}
124pub(crate) use common_opts;
125
126fn keyed_value_query<S>(
131 wrapper: &str,
132 path: &str,
133 key: &str,
134 value: Value,
135 mut opts: Map<String, Value>,
136) -> Query<S> {
137 if opts.is_empty() {
138 single(wrapper, path, value)
139 } else {
140 opts.insert(key.to_string(), value);
141 single(wrapper, path, Value::Object(opts))
142 }
143}
144
145fn exists_q<S>(path: &str) -> Query<S> {
147 let mut inner = Map::new();
148 inner.insert("field".to_string(), Value::String(path.to_string()));
149 let mut outer = Map::new();
150 outer.insert("exists".to_string(), Value::Object(inner));
151 Query::leaf(Value::Object(outer))
152}
153
154pub(crate) fn match_all_value() -> Value {
156 let mut outer = Map::new();
157 outer.insert("match_all".to_string(), Value::Object(Map::new()));
158 Value::Object(outer)
159}
160
161pub mod kind {
166 #[derive(Debug)]
168 pub enum Keyword {}
169 #[derive(Debug)]
171 pub enum Text {}
172 #[derive(Debug)]
174 pub enum Number {}
175 #[derive(Debug)]
177 pub enum Date {}
178}
179
180#[diagnostic::on_unimplemented(
191 message = "`{Self}` is not a valid value for a `{K}` field",
192 label = "unsupported field type",
193 note = "use a built-in leaf type, or add `#[derive(FlussoValue)]` (with the matching kind) to `{Self}`"
194)]
195pub trait FlussoValue<K> {}
196
197impl FlussoValue<kind::Keyword> for String {}
198impl FlussoValue<kind::Keyword> for &str {}
199#[cfg(feature = "uuid")]
200impl FlussoValue<kind::Keyword> for uuid::Uuid {}
201#[cfg(feature = "uuid")]
202impl FlussoValue<kind::Keyword> for &uuid::Uuid {}
203
204impl FlussoValue<kind::Text> for String {}
205impl FlussoValue<kind::Text> for &str {}
206
207impl FlussoValue<kind::Number> for i8 {}
208impl FlussoValue<kind::Number> for i16 {}
209impl FlussoValue<kind::Number> for i32 {}
210impl FlussoValue<kind::Number> for i64 {}
211impl FlussoValue<kind::Number> for f32 {}
212impl FlussoValue<kind::Number> for f64 {}
213#[cfg(feature = "decimal")]
214impl FlussoValue<kind::Number> for crate::Decimal {}
215
216impl FlussoValue<kind::Date> for String {}