rs_es/query/
compound.rs

1/*
2 * Copyright 2016-2018 Ben Ashford
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//! Compound queries
18
19use serde::{Serialize, Serializer};
20
21use crate::{json::ShouldSkip, units::OneOrMany};
22
23use super::{functions::Function, MinimumShouldMatch, Query, ScoreMode};
24
25/// BoostMode
26#[derive(Debug, Copy, Clone)]
27pub enum BoostMode {
28    Multiply,
29    Replace,
30    Sum,
31    Avg,
32    Max,
33    Min,
34}
35
36impl Serialize for BoostMode {
37    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
38    where
39        S: Serializer,
40    {
41        match self {
42            BoostMode::Multiply => "multiply",
43            BoostMode::Replace => "replace",
44            BoostMode::Sum => "sum",
45            BoostMode::Avg => "avg",
46            BoostMode::Max => "max",
47            BoostMode::Min => "min",
48        }
49        .serialize(serializer)
50    }
51}
52
53/// Constant score query
54#[derive(Debug, Default, Serialize)]
55pub struct ConstantScoreQuery {
56    query: Query,
57    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
58    boost: Option<f64>,
59}
60
61impl Query {
62    pub fn build_constant_score<A>(query: A) -> ConstantScoreQuery
63    where
64        A: Into<Query>,
65    {
66        ConstantScoreQuery {
67            query: query.into(),
68            ..Default::default()
69        }
70    }
71}
72
73impl ConstantScoreQuery {
74    add_field!(with_boost, boost, f64);
75
76    build!(ConstantScore);
77}
78
79/// Bool query
80#[derive(Debug, Default, Serialize)]
81pub struct BoolQuery {
82    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
83    must: Option<OneOrMany<Query>>,
84    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
85    filter: Option<Query>,
86    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
87    should: Option<OneOrMany<Query>>,
88    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
89    must_not: Option<OneOrMany<Query>>,
90    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
91    minimum_should_match: Option<MinimumShouldMatch>,
92    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
93    boost: Option<f64>,
94    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
95    disable_coord: Option<bool>,
96}
97
98impl Query {
99    pub fn build_bool() -> BoolQuery {
100        Default::default()
101    }
102}
103
104impl BoolQuery {
105    add_field!(with_must, must, OneOrMany<Query>);
106    add_field!(with_filter, filter, Query);
107    add_field!(with_should, should, OneOrMany<Query>);
108    add_field!(with_must_not, must_not, OneOrMany<Query>);
109    add_field!(
110        with_minimum_should_match,
111        minimum_should_match,
112        MinimumShouldMatch
113    );
114    add_field!(with_boost, boost, f64);
115    add_field!(with_disable_coord, disable_coord, bool);
116
117    build!(Bool);
118}
119
120/// DisMax query
121#[derive(Debug, Default, Serialize)]
122pub struct DisMaxQuery {
123    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
124    tie_breaker: Option<f64>,
125    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
126    boost: Option<f64>,
127    queries: Vec<Query>,
128}
129
130impl Query {
131    pub fn build_dis_max<A>(queries: A) -> DisMaxQuery
132    where
133        A: Into<Vec<Query>>,
134    {
135        DisMaxQuery {
136            queries: queries.into(),
137            ..Default::default()
138        }
139    }
140}
141
142impl DisMaxQuery {
143    add_field!(with_tie_breaker, tie_breaker, f64);
144    add_field!(with_boost, boost, f64);
145
146    build!(DisMax);
147}
148
149/// Function Score query
150#[derive(Debug, Default, Serialize)]
151pub struct FunctionScoreQuery {
152    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
153    query: Option<Query>,
154    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
155    boost: Option<f64>,
156    functions: Vec<Function>,
157    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
158    max_boost: Option<f64>,
159    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
160    score_mode: Option<ScoreMode>,
161    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
162    boost_mode: Option<BoostMode>,
163    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
164    min_score: Option<f64>,
165}
166
167impl Query {
168    pub fn build_function_score() -> FunctionScoreQuery {
169        Default::default()
170    }
171}
172
173impl FunctionScoreQuery {
174    add_field!(with_query, query, Query);
175    add_field!(with_boost, boost, f64);
176    add_field!(with_max_boost, max_boost, f64);
177    add_field!(with_score_mode, score_mode, ScoreMode);
178    add_field!(with_boost_mode, boost_mode, BoostMode);
179    add_field!(with_min_score, min_score, f64);
180
181    pub fn with_functions<A: Into<Vec<Function>>>(mut self, functions: A) -> Self {
182        self.functions = functions.into();
183        self
184    }
185
186    pub fn with_function<A: Into<Function>>(mut self, function: A) -> Self {
187        self.functions = vec![function.into()];
188        self
189    }
190
191    build!(FunctionScore);
192}
193
194/// Boosting query
195#[derive(Debug, Default, Serialize)]
196pub struct BoostingQuery {
197    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
198    positive: Option<Query>,
199    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
200    negative: Option<Query>,
201    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
202    negative_boost: Option<f64>,
203}
204
205impl Query {
206    pub fn build_boosting() -> BoostingQuery {
207        Default::default()
208    }
209}
210
211impl BoostingQuery {
212    add_field!(with_positive, positive, Query);
213    add_field!(with_negative, negative, Query);
214    add_field!(with_negative_boost, negative_boost, f64);
215
216    build!(Boosting);
217}
218
219/// Indices query
220#[derive(Debug, Default, Serialize)]
221pub struct IndicesQuery {
222    indices: OneOrMany<String>,
223    query: Query,
224    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
225    no_match_query: Option<NoMatchQuery>,
226}
227
228impl Query {
229    pub fn build_indices<A, B>(indices: A, query: B) -> IndicesQuery
230    where
231        A: Into<OneOrMany<String>>,
232        B: Into<Query>,
233    {
234        IndicesQuery {
235            indices: indices.into(),
236            query: query.into(),
237            ..Default::default()
238        }
239    }
240}
241
242impl IndicesQuery {
243    add_field!(with_no_match_query, no_match_query, NoMatchQuery);
244
245    build!(Indices);
246}
247
248/// Options for the `no_match_query` option of IndicesQuery
249#[derive(Debug)]
250pub enum NoMatchQuery {
251    None,
252    All,
253    Query(Query),
254}
255
256from_exp!(Query, NoMatchQuery, from, NoMatchQuery::Query(from));
257
258impl Serialize for NoMatchQuery {
259    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
260    where
261        S: Serializer,
262    {
263        use self::NoMatchQuery::*;
264        match self {
265            None => "none".serialize(serializer),
266            All => "all".serialize(serializer),
267            Query(ref q) => q.serialize(serializer),
268        }
269    }
270}