flusso_query/handles/
compound.rs1use std::marker::PhantomData;
7
8use serde_json::{Map, Value};
9
10use super::{BoostMode, Common, ScoreMode, common_opts, wrap};
11use crate::query::{AsQuery, Query, Root};
12
13fn clause_value<S>(query: impl AsQuery<S>) -> Value {
14 query
15 .into_query()
16 .map_or_else(super::match_all_value, |q| q.to_value())
17}
18
19pub fn constant_score<S>(filter: impl AsQuery<S>) -> ConstantScoreQuery<S> {
21 ConstantScoreQuery {
22 filter: clause_value(filter),
23 common: Common::default(),
24 _scope: PhantomData,
25 }
26}
27
28#[derive(Debug, Clone)]
30pub struct ConstantScoreQuery<S = Root> {
31 filter: Value,
32 common: Common,
33 _scope: PhantomData<fn() -> S>,
34}
35
36impl<S> ConstantScoreQuery<S> {
37 common_opts!(common);
38}
39
40impl<S> AsQuery<S> for ConstantScoreQuery<S> {
41 fn into_query(self) -> Option<Query<S>> {
42 let mut body = Map::new();
43 body.insert("filter".to_string(), self.filter);
44 self.common.write(&mut body);
45 Some(wrap("constant_score", body))
46 }
47}
48
49pub fn dis_max<S>(queries: impl IntoIterator<Item = impl AsQuery<S>>) -> DisMaxQuery<S> {
52 DisMaxQuery {
53 queries: queries.into_iter().map(clause_value).collect(),
54 tie_breaker: None,
55 common: Common::default(),
56 _scope: PhantomData,
57 }
58}
59
60#[derive(Debug, Clone)]
62pub struct DisMaxQuery<S = Root> {
63 queries: Vec<Value>,
64 tie_breaker: Option<f32>,
65 common: Common,
66 _scope: PhantomData<fn() -> S>,
67}
68
69impl<S> DisMaxQuery<S> {
70 #[must_use]
72 pub fn tie_breaker(mut self, tie_breaker: f32) -> Self {
73 self.tie_breaker = Some(tie_breaker);
74 self
75 }
76
77 common_opts!(common);
78}
79
80impl<S> AsQuery<S> for DisMaxQuery<S> {
81 fn into_query(self) -> Option<Query<S>> {
82 let mut body = Map::new();
83 body.insert("queries".to_string(), Value::Array(self.queries));
84 if let Some(tie_breaker) = self.tie_breaker {
85 body.insert("tie_breaker".to_string(), Value::from(tie_breaker));
86 }
87 self.common.write(&mut body);
88 Some(wrap("dis_max", body))
89 }
90}
91
92pub fn boosting<S>(
95 positive: impl AsQuery<S>,
96 negative: impl AsQuery<S>,
97 negative_boost: f32,
98) -> BoostingQuery<S> {
99 BoostingQuery {
100 positive: clause_value(positive),
101 negative: clause_value(negative),
102 negative_boost,
103 common: Common::default(),
104 _scope: PhantomData,
105 }
106}
107
108#[derive(Debug, Clone)]
110pub struct BoostingQuery<S = Root> {
111 positive: Value,
112 negative: Value,
113 negative_boost: f32,
114 common: Common,
115 _scope: PhantomData<fn() -> S>,
116}
117
118impl<S> BoostingQuery<S> {
119 common_opts!(common);
120}
121
122impl<S> AsQuery<S> for BoostingQuery<S> {
123 fn into_query(self) -> Option<Query<S>> {
124 let mut body = Map::new();
125 body.insert("positive".to_string(), self.positive);
126 body.insert("negative".to_string(), self.negative);
127 body.insert(
128 "negative_boost".to_string(),
129 Value::from(self.negative_boost),
130 );
131 self.common.write(&mut body);
132 Some(wrap("boosting", body))
133 }
134}
135
136pub fn function_score<S>(query: impl AsQuery<S>) -> FunctionScoreQuery<S> {
138 FunctionScoreQuery {
139 query: clause_value(query),
140 functions: Vec::new(),
141 opts: Map::new(),
142 common: Common::default(),
143 _scope: PhantomData,
144 }
145}
146
147#[derive(Debug, Clone)]
151pub struct FunctionScoreQuery<S = Root> {
152 query: Value,
153 functions: Vec<Value>,
154 opts: Map<String, Value>,
155 common: Common,
156 _scope: PhantomData<fn() -> S>,
157}
158
159impl<S> FunctionScoreQuery<S> {
160 #[must_use]
162 pub fn weight(mut self, weight: f32) -> Self {
163 let mut function = Map::new();
164 function.insert("weight".to_string(), Value::from(weight));
165 self.functions.push(Value::Object(function));
166 self
167 }
168
169 #[must_use]
171 pub fn weight_when(mut self, weight: f32, filter: impl AsQuery<S>) -> Self {
172 let mut function = Map::new();
173 function.insert("weight".to_string(), Value::from(weight));
174 function.insert("filter".to_string(), clause_value(filter));
175 self.functions.push(Value::Object(function));
176 self
177 }
178
179 #[must_use]
183 pub fn function(mut self, function: Value) -> Self {
184 self.functions.push(function);
185 self
186 }
187
188 #[must_use]
190 pub fn score_mode(mut self, score_mode: ScoreMode) -> Self {
191 self.opts.insert(
192 "score_mode".to_string(),
193 Value::String(score_mode.as_str().to_string()),
194 );
195 self
196 }
197
198 #[must_use]
201 pub fn boost_mode(mut self, boost_mode: BoostMode) -> Self {
202 self.opts.insert(
203 "boost_mode".to_string(),
204 Value::String(boost_mode.as_str().to_string()),
205 );
206 self
207 }
208
209 #[must_use]
211 pub fn max_boost(mut self, max_boost: f32) -> Self {
212 self.opts
213 .insert("max_boost".to_string(), Value::from(max_boost));
214 self
215 }
216
217 #[must_use]
219 pub fn min_score(mut self, min_score: f32) -> Self {
220 self.opts
221 .insert("min_score".to_string(), Value::from(min_score));
222 self
223 }
224
225 common_opts!(common);
226}
227
228impl<S> AsQuery<S> for FunctionScoreQuery<S> {
229 fn into_query(self) -> Option<Query<S>> {
230 let mut body = self.opts;
231 body.insert("query".to_string(), self.query);
232 if !self.functions.is_empty() {
233 body.insert("functions".to_string(), Value::Array(self.functions));
234 }
235 self.common.write(&mut body);
236 Some(wrap("function_score", body))
237 }
238}