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