elasticsearch_dsl/search/queries/term_level/regexp_query.rs
1use crate::search::*;
2use crate::util::*;
3use serde::Serialize;
4
5/// Returns documents that contain terms matching a
6/// [regular expression](https://en.wikipedia.org/wiki/Regular_expression).
7///
8/// A regular expression is a way to match patterns in data using placeholder characters, called
9/// operators. For a list of operators supported by the `regexp` query, see
10/// [Regular expression syntax](https://www.elastic.co/guide/en/elasticsearch/reference/current/regexp-syntax.html).
11///
12/// To create a regexp query:
13/// ```
14/// # use elasticsearch_dsl::queries::*;
15/// # use elasticsearch_dsl::queries::params::*;
16/// # let query =
17/// Query::regexp("test", "username");
18/// ```
19/// <https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-regexp-query.html>
20#[derive(Debug, Clone, PartialEq, Serialize)]
21#[serde(remote = "Self")]
22pub struct RegexpQuery {
23 #[serde(skip)]
24 field: String,
25
26 value: String,
27
28 #[serde(
29 skip_serializing_if = "ShouldSkip::should_skip",
30 serialize_with = "join_with_pipe"
31 )]
32 flags: Vec<RegexpFlag>,
33
34 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
35 case_insensitive: Option<bool>,
36
37 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
38 max_determinized_states: Option<u64>,
39
40 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
41 rewrite: Option<Rewrite>,
42
43 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
44 boost: Option<f32>,
45
46 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
47 _name: Option<String>,
48}
49
50impl Query {
51 /// Creates an instance of [`RegexpQuery`]
52 ///
53 /// - `field` - Field you wish to search.
54 /// - `value` - Regular expression for terms you wish to find in the provided field. For a list
55 /// of supported operators, see
56 /// [Regular expression syntax](https://www.elastic.co/guide/en/elasticsearch/reference/current/regexp-syntax.html). <br/>
57 ///
58 /// By default, regular expressions are limited to 1,000 characters. You can change this limit
59 /// using the
60 /// [`index.max_regex_length`](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#index-max-regex-length) setting.
61 pub fn regexp<S>(field: S, value: S) -> RegexpQuery
62 where
63 S: ToString,
64 {
65 RegexpQuery {
66 field: field.to_string(),
67 value: value.to_string(),
68 flags: vec![],
69 case_insensitive: None,
70 max_determinized_states: None,
71 rewrite: None,
72 boost: None,
73 _name: None,
74 }
75 }
76}
77
78impl RegexpQuery {
79 /// Enables optional operators for the regular expression. For valid values and more
80 /// information, see
81 /// [Regular expression syntax](https://www.elastic.co/guide/en/elasticsearch/reference/current/regexp-syntax.html#regexp-optional-operators).
82 pub fn flags<I>(mut self, flags: I) -> Self
83 where
84 I: IntoIterator<Item = RegexpFlag>,
85 {
86 self.flags.extend(flags);
87 self
88 }
89
90 /// Allows case insensitive matching of the regular expression value with the indexed field
91 /// values when set to `true`. Default is `false` which means the case sensitivity of matching
92 /// depends on the underlying field’s mapping.
93 pub fn case_insensitive(mut self, case_insensitive: bool) -> Self {
94 self.case_insensitive = Some(case_insensitive);
95 self
96 }
97
98 /// Maximum number of
99 /// [automaton states](https://en.wikipedia.org/wiki/Deterministic_finite_automaton)
100 /// required for the query. Default is 10000.
101 ///
102 /// Elasticsearch uses [Apache Lucene](https://lucene.apache.org/core/) internally to parse
103 /// regular expressions. Lucene converts each regular expression to a finite automaton
104 /// containing a number of determinized states.
105 ///
106 /// You can use this parameter to prevent that conversion from unintentionally consuming too
107 /// many resources. You may need to increase this limit to run complex regular expressions.
108 pub fn max_determinized_states(mut self, max_determinized_states: u64) -> Self {
109 self.max_determinized_states = Some(max_determinized_states);
110 self
111 }
112
113 /// Method used to rewrite the query. For valid values and more information, see the
114 /// [rewrite](Rewrite) parameter.
115 pub fn rewrite(mut self, rewrite: Rewrite) -> Self {
116 self.rewrite = Some(rewrite);
117 self
118 }
119
120 add_boost_and_name!();
121}
122
123impl ShouldSkip for RegexpQuery {
124 fn should_skip(&self) -> bool {
125 self.value.should_skip()
126 }
127}
128
129serialize_with_root_keyed!("regexp": RegexpQuery);
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134
135 #[test]
136 fn serialization() {
137 assert_serialize_query(
138 Query::regexp("test", "regexp"),
139 json!({
140 "regexp": {
141 "test": {
142 "value": "regexp"
143 }
144 }
145 }),
146 );
147
148 assert_serialize_query(
149 Query::regexp("test", "regexp")
150 .flags([RegexpFlag::Complement, RegexpFlag::Interval])
151 .case_insensitive(false)
152 .max_determinized_states(2)
153 .rewrite(Rewrite::ConstantScore)
154 .boost(2)
155 .name("test"),
156 json!({
157 "regexp": {
158 "test": {
159 "value": "regexp",
160 "flags": "COMPLEMENT|INTERVAL",
161 "case_insensitive": false,
162 "max_determinized_states": 2,
163 "rewrite": "constant_score",
164 "boost": 2.0,
165 "_name": "test"
166 }
167 }
168 }),
169 );
170 }
171}