elasticsearch_dsl/search/queries/full_text/
simple_query_string_query.rs

1use crate::search::*;
2use crate::util::*;
3
4/// Returns documents that match a provided text, number, date or boolean value.
5/// The provided text is analyzed before matching.
6///
7/// The `match` query is the standard query for performing a full-text search,
8/// including options for fuzzy matching.
9///
10/// To create a Match query with numeric values:
11/// ```
12/// # use elasticsearch_dsl::queries::*;
13/// # use elasticsearch_dsl::queries::params::*;
14/// # let query =
15/// Query::simple_query_string("\"fried eggs\" +(eggplant | potato) -frittata")
16///     .boost(2)
17///     .name("test");
18/// ```
19/// <https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html>
20#[derive(Debug, Clone, PartialEq, Serialize)]
21#[serde(remote = "Self")]
22pub struct SimpleQueryStringQuery {
23    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
24    query: Text,
25
26    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
27    fields: Vec<String>,
28
29    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
30    default_operator: Option<Operator>,
31
32    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
33    analyze_wildcard: Option<bool>,
34
35    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
36    analyzer: Option<String>,
37
38    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
39    auto_generate_synonyms_phrase_query: Option<bool>,
40
41    #[serde(
42        skip_serializing_if = "ShouldSkip::should_skip",
43        serialize_with = "join_with_pipe"
44    )]
45    flags: Vec<SimpleQueryStringQueryFlags>,
46
47    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
48    fuzzy_max_expansions: Option<u32>,
49
50    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
51    fuzzy_prefix_length: Option<u32>,
52
53    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
54    fuzzy_transpositions: Option<bool>,
55
56    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
57    lenient: Option<bool>,
58
59    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
60    minimum_should_match: Option<String>,
61
62    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
63    quote_field_suffix: Option<String>,
64
65    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
66    boost: Option<f32>,
67
68    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
69    _name: Option<String>,
70}
71
72impl Query {
73    /// Creates an instance of [`SimpleQueryStringQuery`]
74    ///
75    /// - `query` - Query string you wish to parse and use for search. See
76    ///   [Simple query string syntax](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html#simple-query-string-syntax).
77    pub fn simple_query_string<S>(query: S) -> SimpleQueryStringQuery
78    where
79        S: Into<Text>,
80    {
81        SimpleQueryStringQuery {
82            query: query.into(),
83            fields: vec![],
84            default_operator: None,
85            analyze_wildcard: None,
86            analyzer: None,
87            auto_generate_synonyms_phrase_query: None,
88            fuzzy_transpositions: None,
89            fuzzy_max_expansions: None,
90            flags: vec![],
91            fuzzy_prefix_length: None,
92            quote_field_suffix: None,
93            lenient: None,
94            minimum_should_match: None,
95            boost: None,
96            _name: None,
97        }
98    }
99}
100
101impl SimpleQueryStringQuery {
102    /// Array of fields you wish to search.
103    ///
104    /// This field accepts wildcard expressions. You also can boost relevance
105    /// scores for matches to particular fields using a caret (`^`) notation.
106    /// See
107    /// [Wildcards and per-field boosts in the fields parameter](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html#simple-query-string-boost)
108    /// for examples.
109    ///
110    /// Defaults to the `index.query.default_field` index setting, which has a
111    /// default value of `*`. The `*` value extracts all fields that are
112    /// eligible to term queries and filters the metadata fields. All extracted
113    /// fields are then combined to build a query if no `prefix` is specified.
114    pub fn fields<I>(mut self, fields: I) -> Self
115    where
116        I: IntoIterator,
117        I::Item: ToString,
118    {
119        self.fields = fields.into_iter().map(|x| x.to_string()).collect();
120        self
121    }
122
123    /// Default boolean logic used to interpret text in the query string if no
124    /// operators are specified.
125    pub fn default_operator(mut self, default_operator: Operator) -> Self {
126        self.default_operator = Some(default_operator);
127        self
128    }
129
130    /// If `true`, the query attempts to analyze wildcard terms in the query
131    /// string.
132    ///
133    /// Defaults to `false`.
134    pub fn analyze_wildcard(mut self, analyze_wildcard: bool) -> Self {
135        self.analyze_wildcard = Some(analyze_wildcard);
136        self
137    }
138
139    /// [Analyzer](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis.html)
140    /// used to convert text in the query string into tokens. Defaults to the
141    /// [index-time analyzer](https://www.elastic.co/guide/en/elasticsearch/reference/current/specify-analyzer.html#specify-index-time-analyzer)
142    /// mapped for the `default_field`. If no analyzer is mapped, the index’s
143    /// default analyzer is used.
144    pub fn analyzer<T>(mut self, analyzer: T) -> Self
145    where
146        T: ToString,
147    {
148        self.analyzer = Some(analyzer.to_string());
149        self
150    }
151
152    /// If `true`, the parser creates a
153    /// [`match_phrase`](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase.html)
154    /// query for each
155    /// [multi-position token](https://www.elastic.co/guide/en/elasticsearch/reference/current/token-graphs.html#token-graphs-multi-position-tokens).
156    ///
157    /// Defaults to `true`. For examples, see
158    /// [Multi-position tokens](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html#simple-query-string-synonyms).
159    pub fn auto_generate_synonyms_phrase_query(
160        mut self,
161        auto_generate_synonyms_phrase_query: bool,
162    ) -> Self {
163        self.auto_generate_synonyms_phrase_query = Some(auto_generate_synonyms_phrase_query);
164        self
165    }
166
167    /// List of enabled operators for the simple query string syntax.
168    ///
169    /// Defaults to [ALL](SimpleQueryStringQueryFlags::All) (all operators).
170    /// See [Limit operators](SimpleQueryStringQueryFlags) for valid values.
171    pub fn flags<I>(mut self, flags: I) -> Self
172    where
173        I: IntoIterator<Item = SimpleQueryStringQueryFlags>,
174    {
175        self.flags.extend(flags);
176        self
177    }
178
179    /// Maximum number of terms to which the query expands for fuzzy matching.
180    ///
181    /// Defaults to `50`.
182    pub fn fuzzy_max_expansions(mut self, fuzzy_max_expansions: u32) -> Self {
183        self.fuzzy_max_expansions = Some(fuzzy_max_expansions);
184        self
185    }
186
187    /// Number of beginning characters left unchanged for fuzzy matching.
188    ///
189    /// Defaults to `0`.
190    pub fn fuzzy_prefix_length(mut self, fuzzy_prefix_length: u32) -> Self {
191        self.fuzzy_prefix_length = Some(fuzzy_prefix_length);
192        self
193    }
194
195    /// If `true`, edits for fuzzy matching include transpositions of two
196    /// adjacent characters (ab → ba).
197    ///
198    /// Defaults to `true`.
199    pub fn fuzzy_transpositions(mut self, fuzzy_transpositions: bool) -> Self {
200        self.fuzzy_transpositions = Some(fuzzy_transpositions);
201        self
202    }
203
204    /// If `true`, format-based errors, such as providing a text `query`
205    /// value for a
206    /// [numeric](https://www.elastic.co/guide/en/elasticsearch/reference/current/number.html)
207    /// field, are ignored.
208    ///
209    /// Defaults to `false`.
210    pub fn lenient(mut self, lenient: bool) -> Self {
211        self.lenient = Some(lenient);
212        self
213    }
214
215    /// Minimum number of clauses that must match for a document to be returned. See the
216    /// `minimum_should_match` parameter for valid values and more information.
217    pub fn minimum_should_match<T>(mut self, minimum_should_match: T) -> Self
218    where
219        T: ToString,
220    {
221        self.minimum_should_match = Some(minimum_should_match.to_string());
222        self
223    }
224
225    /// Suffix appended to quoted text in the query string.
226    ///
227    /// You can use this suffix to use a different analysis method for exact
228    /// matches. See
229    /// [Mixing exact search with stemming](https://www.elastic.co/guide/en/elasticsearch/reference/current/mixing-exact-search-with-stemming.html).
230    pub fn quote_field_suffix<S>(mut self, quote_field_suffix: S) -> Self
231    where
232        S: ToString,
233    {
234        self.quote_field_suffix = Some(quote_field_suffix.to_string());
235        self
236    }
237
238    add_boost_and_name!();
239}
240
241impl ShouldSkip for SimpleQueryStringQuery {
242    fn should_skip(&self) -> bool {
243        self.query.should_skip()
244    }
245}
246
247serialize_with_root!("simple_query_string": SimpleQueryStringQuery);
248
249#[cfg(test)]
250mod tests {
251    use super::*;
252
253    #[test]
254    fn serialization() {
255        assert_serialize_query(
256            Query::simple_query_string("search text"),
257            json!({
258                "simple_query_string": {
259                    "query": "search text",
260                }
261            }),
262        );
263
264        assert_serialize_query(
265            Query::simple_query_string("search text")
266                .fields(["database"])
267                .default_operator(Operator::And)
268                .analyze_wildcard(true)
269                .analyzer("search_time_analyzer")
270                .auto_generate_synonyms_phrase_query(true)
271                .flags([
272                    SimpleQueryStringQueryFlags::And,
273                    SimpleQueryStringQueryFlags::Escape,
274                ])
275                .fuzzy_max_expansions(20)
276                .fuzzy_prefix_length(3)
277                .fuzzy_transpositions(false)
278                .lenient(true)
279                .minimum_should_match("22")
280                .quote_field_suffix("s")
281                .boost(2)
282                .name("test"),
283            json!({
284                "simple_query_string": {
285                    "query": "search text",
286                    "fields": ["database"],
287                    "default_operator": "AND",
288                    "analyze_wildcard": true,
289                    "analyzer": "search_time_analyzer",
290                    "auto_generate_synonyms_phrase_query": true,
291                    "flags": "AND|ESCAPE",
292                    "fuzzy_max_expansions": 20,
293                    "fuzzy_prefix_length": 3,
294                    "fuzzy_transpositions": false,
295                    "lenient": true,
296                    "minimum_should_match": "22",
297                    "quote_field_suffix": "s",
298                    "boost": 2.0,
299                    "_name": "test",
300                }
301            }),
302        );
303    }
304}