elasticsearch_dsl/search/queries/full_text/
match_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:
11/// ```
12/// # use elasticsearch_dsl::queries::*;
13/// # use elasticsearch_dsl::queries::params::*;
14/// # let query =
15/// Query::r#match("test", "search text")
16///     .boost(2)
17///     .name("test");
18/// ```
19/// <https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html>
20#[derive(Debug, Clone, PartialEq, Serialize)]
21#[serde(remote = "Self")]
22pub struct MatchQuery {
23    #[serde(skip)]
24    field: String,
25
26    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
27    query: Text,
28
29    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
30    analyzer: Option<String>,
31
32    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
33    auto_generate_synonyms_phrase_query: Option<bool>,
34
35    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
36    fuzziness: Option<Fuzziness>,
37
38    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
39    max_expansions: Option<u8>,
40
41    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
42    prefix_length: Option<u8>,
43
44    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
45    fuzzy_transpositions: Option<bool>,
46
47    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
48    fuzzy_rewrite: Option<Rewrite>,
49
50    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
51    lenient: Option<bool>,
52
53    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
54    operator: Option<Operator>,
55
56    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
57    minimum_should_match: Option<String>,
58
59    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
60    zero_terms_query: Option<ZeroTermsQuery>,
61
62    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
63    boost: Option<f32>,
64
65    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
66    _name: Option<String>,
67}
68
69impl Query {
70    /// Creates an instance of [`MatchQuery`]
71    ///
72    /// - `field` - Field you wish to search.
73    /// - `query` - Text, number, boolean value or date you wish to find in the provided
74    ///   `<field>`.<br/>
75    ///   The `match` query
76    ///   [analyzes](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis.html)
77    ///   any provided text before performing a search. This means the `match`
78    ///   query can search
79    ///   [`text`](https://www.elastic.co/guide/en/elasticsearch/reference/current/text.html)
80    ///   fields for analyzed tokens rather than an exact term.
81    pub fn r#match<T, U>(field: T, query: U) -> MatchQuery
82    where
83        T: ToString,
84        U: Into<Text>,
85    {
86        MatchQuery {
87            field: field.to_string(),
88            query: query.into(),
89            analyzer: None,
90            auto_generate_synonyms_phrase_query: None,
91            fuzziness: None,
92            max_expansions: None,
93            prefix_length: None,
94            fuzzy_transpositions: None,
95            fuzzy_rewrite: None,
96            lenient: None,
97            operator: None,
98            minimum_should_match: None,
99            zero_terms_query: None,
100            boost: None,
101            _name: None,
102        }
103    }
104}
105
106impl MatchQuery {
107    /// [Analyzer](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis.html)
108    /// used to convert the text in the `query` value into tokens. Defaults to the
109    /// [index-time analyzer](https://www.elastic.co/guide/en/elasticsearch/reference/current/specify-analyzer.html#specify-index-time-analyzer)
110    /// mapped for the `<field>`. If no analyzer is mapped, the index’s default analyzer is used.
111    pub fn analyzer<T>(mut self, analyzer: T) -> Self
112    where
113        T: ToString,
114    {
115        self.analyzer = Some(analyzer.to_string());
116        self
117    }
118
119    /// If `true`,
120    /// [match phrase](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase.html)
121    /// queries are automatically created for multi-term synonyms. Defaults to `true`.
122    ///
123    /// See [Use synonyms with match query](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html#query-dsl-match-query-synonyms)
124    /// for an example.
125    pub fn auto_generate_synonyms_phrase_query(
126        mut self,
127        auto_generate_synonyms_phrase_query: bool,
128    ) -> Self {
129        self.auto_generate_synonyms_phrase_query = Some(auto_generate_synonyms_phrase_query);
130        self
131    }
132
133    /// Maximum edit distance allowed for matching.
134    /// See [Fuzziness](Fuzziness)
135    /// for valid values and more information. See
136    /// [Fuzziness in the match query](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html#query-dsl-match-query-fuzziness)
137    /// for an example.
138    pub fn fuzziness<T>(mut self, fuzziness: T) -> Self
139    where
140        T: Into<Fuzziness>,
141    {
142        self.fuzziness = Some(fuzziness.into());
143        self
144    }
145
146    /// Maximum number of terms to which the query will expand.
147    /// Defaults to `50`.
148    pub fn max_expansions(mut self, max_expansions: u8) -> Self {
149        self.max_expansions = Some(max_expansions);
150        self
151    }
152
153    /// Number of beginning characters left unchanged for fuzzy matching.
154    /// Defaults to `0`.
155    pub fn prefix_length(mut self, prefix_length: u8) -> Self {
156        self.prefix_length = Some(prefix_length);
157        self
158    }
159
160    /// If `true`, edits for fuzzy matching include transpositions of two
161    /// adjacent characters (ab → ba). Defaults to `true`.
162    pub fn fuzzy_transpositions(mut self, fuzzy_transpositions: bool) -> Self {
163        self.fuzzy_transpositions = Some(fuzzy_transpositions);
164        self
165    }
166
167    /// Method used to rewrite the query. See the
168    /// [`rewrite` parameter](Rewrite) for valid values and
169    /// more information.
170    ///
171    /// If the `fuzziness` parameter is not `0`, the match query uses a
172    /// `fuzzy_rewrite` method of `top_terms_blended_freqs_${max_expansions}`
173    /// by default.
174    pub fn fuzzy_rewrite(mut self, fuzzy_rewrite: Rewrite) -> Self {
175        self.fuzzy_rewrite = Some(fuzzy_rewrite);
176        self
177    }
178
179    /// If `true`, format-based errors, such as providing a text `query`
180    /// value for a
181    /// [numeric](https://www.elastic.co/guide/en/elasticsearch/reference/current/number.html)
182    /// field, are ignored. Defaults to `false`.
183    pub fn lenient(mut self, lenient: bool) -> Self {
184        self.lenient = Some(lenient);
185        self
186    }
187
188    /// Boolean logic used to interpret text in the `query` value
189    pub fn operator(mut self, operator: Operator) -> Self {
190        self.operator = Some(operator);
191        self
192    }
193
194    /// Minimum number of clauses that must match for a document to be returned. See the
195    /// `minimum_should_match` parameter for valid values and more information.
196    pub fn minimum_should_match<T>(mut self, minimum_should_match: T) -> Self
197    where
198        T: ToString,
199    {
200        self.minimum_should_match = Some(minimum_should_match.to_string());
201        self
202    }
203
204    /// Indicates whether no documents are returned if the `analyzer` removes
205    /// all tokens, such as when using a `stop` filter.
206    pub fn zero_terms_query(mut self, zero_terms_query: ZeroTermsQuery) -> Self {
207        self.zero_terms_query = Some(zero_terms_query);
208        self
209    }
210
211    add_boost_and_name!();
212}
213
214impl ShouldSkip for MatchQuery {
215    fn should_skip(&self) -> bool {
216        self.query.should_skip()
217    }
218}
219
220serialize_with_root_keyed!("match": MatchQuery);
221
222#[cfg(test)]
223mod tests {
224    use super::*;
225
226    #[test]
227    fn serialization() {
228        assert_serialize_query(
229            Query::r#match("test", "search text"),
230            json!({
231                "match": {
232                    "test": {
233                        "query": "search text"
234                    }
235                }
236            }),
237        );
238
239        assert_serialize_query(
240            Query::r#match("test", "search text")
241                .analyzer("search_time_analyzer")
242                .auto_generate_synonyms_phrase_query(true)
243                .fuzziness(23)
244                .max_expansions(2)
245                .prefix_length(3)
246                .fuzzy_transpositions(false)
247                .fuzzy_rewrite(Rewrite::ConstantScoreBoolean)
248                .lenient(true)
249                .operator(Operator::And)
250                .minimum_should_match("22")
251                .zero_terms_query(ZeroTermsQuery::None)
252                .boost(2)
253                .name("test"),
254            json!({
255                "match": {
256                    "test": {
257                        "query": "search text",
258                        "analyzer": "search_time_analyzer",
259                        "auto_generate_synonyms_phrase_query": true,
260                        "fuzziness": 23,
261                        "max_expansions": 2,
262                        "prefix_length": 3,
263                        "fuzzy_transpositions": false,
264                        "fuzzy_rewrite": "constant_score_boolean",
265                        "lenient": true,
266                        "operator": "AND",
267                        "minimum_should_match": "22",
268                        "zero_terms_query": "none",
269                        "boost": 2.0,
270                        "_name": "test"
271                    }
272                }
273            }),
274        );
275    }
276}