1use serde_json::{Map, Value};
25
26use crate::query::Query;
27
28mod compound;
29mod extra;
30mod geo;
31mod map;
32mod nested;
33mod object;
34mod params;
35mod scalar;
36mod sort;
37mod string;
38
39pub use compound::{
40 BoostingQuery, ConstantScoreQuery, DisMaxQuery, FunctionScoreQuery, boosting, constant_score,
41 dis_max, function_score,
42};
43pub use extra::{
44 CombinedFieldsQuery, DistanceFeatureQuery, IdsQuery, MoreLikeThisQuery, QueryStringQuery,
45 RankFeatureQuery, ScriptQuery, ScriptScoreQuery, SimpleQueryStringQuery, combined_fields,
46 distance_feature, ids, more_like_this, query_string, rank_feature, script, script_score,
47 simple_query_string,
48};
49pub use geo::{Distance, DistanceUnit, Geo, GeoDistanceQuery, GeoPoint};
50pub use map::{DateMap, KeywordMap, MapSearch, NumberMap, TextMap};
51pub use nested::{Nested, NestedProjection, NestedQuery};
52pub use object::{Binary, Json, Object};
53pub use params::{
54 BoostMode, DistanceType, Fuzziness, MinimumShouldMatch, MultiMatchType, NestedScoreMode,
55 NumericType, Operator, RangeRelation, ScoreMode, ScriptSortType, ValidationMethod,
56 ZeroTermsQuery,
57};
58pub use scalar::{Bool, Date, EqQuery, Number, RangeQuery, TermsQuery};
59pub use sort::{
60 MapKeySort, MaybeOrderBy, Missing, OrderBy, Sort, SortBuilder, SortMode, SortOrder, Sortable,
61};
62pub use string::{
63 FuzzyQuery, Keyword, MapKey, MatchQuery, MultiMatchQuery, NoSubfields, PrefixQuery,
64 RegexpQuery, TermQuery, Text, WildcardQuery, WithSubfields, multi_match,
65};
66
67fn single<S>(wrapper: &str, path: &str, value: Value) -> Query<S> {
69 let mut inner = Map::new();
70 inner.insert(path.to_string(), value);
71 wrap(wrapper, inner)
72}
73
74fn wrap<S>(wrapper: &str, body: Map<String, Value>) -> Query<S> {
76 let mut outer = Map::new();
77 outer.insert(wrapper.to_string(), Value::Object(body));
78 Query::leaf(Value::Object(outer))
79}
80
81#[derive(Debug, Clone, Default)]
86pub(crate) struct Common {
87 boost: Option<f32>,
88 name: Option<String>,
89}
90
91impl Common {
92 pub(crate) fn set_boost(&mut self, boost: f32) {
93 self.boost = Some(boost);
94 }
95
96 pub(crate) fn set_name(&mut self, name: String) {
97 self.name = Some(name);
98 }
99
100 pub(crate) fn is_empty(&self) -> bool {
102 self.boost.is_none() && self.name.is_none()
103 }
104
105 pub(crate) fn write(&self, map: &mut Map<String, Value>) {
107 if let Some(boost) = self.boost {
108 map.insert("boost".to_string(), Value::from(boost));
109 }
110 if let Some(name) = &self.name {
111 map.insert("_name".to_string(), Value::String(name.clone()));
112 }
113 }
114}
115
116macro_rules! common_opts {
119 ($field:ident) => {
120 #[must_use]
122 pub fn boost(mut self, boost: f32) -> Self {
123 self.$field.set_boost(boost);
124 self
125 }
126
127 #[must_use]
129 pub fn name(mut self, name: impl Into<String>) -> Self {
130 self.$field.set_name(name.into());
131 self
132 }
133 };
134}
135pub(crate) use common_opts;
136
137fn keyed_value_query<S>(
142 wrapper: &str,
143 path: &str,
144 key: &str,
145 value: Value,
146 mut opts: Map<String, Value>,
147) -> Query<S> {
148 if opts.is_empty() {
149 single(wrapper, path, value)
150 } else {
151 opts.insert(key.to_string(), value);
152 single(wrapper, path, Value::Object(opts))
153 }
154}
155
156fn exists_q<S>(path: &str) -> Query<S> {
158 let mut inner = Map::new();
159 inner.insert("field".to_string(), Value::String(path.to_string()));
160 let mut outer = Map::new();
161 outer.insert("exists".to_string(), Value::Object(inner));
162 Query::leaf(Value::Object(outer))
163}
164
165pub(crate) fn match_all_value() -> Value {
167 let mut outer = Map::new();
168 outer.insert("match_all".to_string(), Value::Object(Map::new()));
169 Value::Object(outer)
170}
171
172pub mod kind {
177 #[derive(Debug)]
179 pub enum Keyword {}
180 #[derive(Debug)]
182 pub enum Text {}
183 #[derive(Debug)]
185 pub enum Bool {}
186 #[derive(Debug)]
188 pub enum Byte {}
189 #[derive(Debug)]
191 pub enum Short {}
192 #[derive(Debug)]
194 pub enum Integer {}
195 #[derive(Debug)]
197 pub enum Long {}
198 #[derive(Debug)]
200 pub enum Float {}
201 #[derive(Debug)]
203 pub enum Double {}
204 #[derive(Debug)]
206 pub enum Decimal {}
207 #[derive(Debug)]
209 pub enum Date {}
210}
211
212#[diagnostic::on_unimplemented(
225 message = "`{Self}` is not a valid value for a `{K}` field",
226 label = "unsupported field type",
227 note = "use a built-in leaf type, or add `#[derive(FlussoValue)]` (with the matching kind) to `{Self}`"
228)]
229pub trait FlussoValue<K>: serde::Serialize {}
230
231impl FlussoValue<kind::Keyword> for String {}
232impl FlussoValue<kind::Keyword> for &str {}
233#[cfg(feature = "uuid")]
234impl FlussoValue<kind::Keyword> for uuid::Uuid {}
235#[cfg(feature = "uuid")]
236impl FlussoValue<kind::Keyword> for &uuid::Uuid {}
237
238impl FlussoValue<kind::Text> for String {}
239impl FlussoValue<kind::Text> for &str {}
240
241impl FlussoValue<kind::Bool> for bool {}
242
243macro_rules! number_values {
249 ($kind:path: $($ty:ty),+ $(,)?) => { $(impl FlussoValue<$kind> for $ty {})+ };
250}
251number_values!(kind::Byte: i8);
252number_values!(kind::Short: i8, i16);
253number_values!(kind::Integer: i8, i16, i32);
254number_values!(kind::Long: i8, i16, i32, i64);
255number_values!(kind::Float: i8, i16, f32);
256number_values!(kind::Double: i8, i16, i32, f32, f64);
257number_values!(kind::Decimal: i8, i16, i32, i64);
258#[cfg(feature = "decimal")]
259impl FlussoValue<kind::Decimal> for crate::Decimal {}
260
261impl FlussoValue<kind::Date> for String {}
262impl FlussoValue<kind::Date> for &str {}
263#[cfg(feature = "chrono")]
264impl FlussoValue<kind::Date> for chrono::NaiveDate {}
265#[cfg(feature = "chrono")]
266impl FlussoValue<kind::Date> for chrono::NaiveDateTime {}
267#[cfg(feature = "chrono")]
268impl FlussoValue<kind::Date> for chrono::DateTime<chrono::Utc> {}
269
270#[diagnostic::on_unimplemented(
281 message = "`{Self}` is not a valid map for a `{K}` field",
282 label = "unsupported map type",
283 note = "use `HashMap<String, V>` with a `{K}` value type, or add `#[derive(FlussoMap)]` (with the matching kind) to `{Self}`"
284)]
285pub trait FlussoMap<K> {}
286
287impl<K, V: FlussoValue<K>> FlussoMap<K> for std::collections::HashMap<String, V> {}