elasticsearch_dsl/search/queries/specialized/
percolate_query.rs

1use crate::search::*;
2use crate::util::*;
3use serde::Serialize;
4
5/// The `percolate` query can be used to match queries stored in an index. The percolate query
6/// itself contains the document that will be used as query to match with the stored queries.
7///
8/// To percolate single document:
9/// ```
10/// # use elasticsearch_dsl::queries::*;
11/// # use elasticsearch_dsl::queries::params::*;
12/// # use serde_json::json;
13/// # let query =
14/// Query::percolate("field", json!({ "message": "search text" }));
15/// ```
16/// To percolate multiple documents:
17/// ```
18/// # use elasticsearch_dsl::queries::*;
19/// # use elasticsearch_dsl::queries::params::*;
20/// # use serde_json::json;
21/// # let query =
22/// Query::percolate("field", vec![json!({ "message": "search text" }), json!({ "message": "another search text" })]);
23/// ```
24/// <https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-percolate-query.html>
25#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
26#[serde(remote = "Self")]
27pub struct PercolateQuery {
28    field: String,
29
30    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
31    name: Option<String>,
32
33    #[serde(flatten)]
34    source: PercolateSource,
35}
36
37impl Query {
38    /// Creates an instance of [`PercolateQuery`]
39    ///
40    /// - `field` - The field of type `percolator` that holds the indexed queries
41    /// - `source` - [Source](PercolateSource) to percolate
42    pub fn percolate<S, T>(field: S, source: T) -> PercolateQuery
43    where
44        S: ToString,
45        T: Serialize,
46    {
47        let source = serde_json::to_value(source).unwrap_or_default();
48        let source = if let Some(array) = source.as_array() {
49            PercolateSource::Documents(array.to_vec())
50        } else {
51            PercolateSource::Document(source)
52        };
53
54        PercolateQuery {
55            field: field.to_string(),
56            source,
57            name: None,
58        }
59    }
60}
61
62impl PercolateQuery {
63    /// The suffix to be used for the `_percolator_document_slot` field in case multiple `percolate`
64    /// queries have been specified. This is an optional parameter
65    pub fn name<S>(mut self, name: S) -> Self
66    where
67        S: ToString,
68    {
69        self.name = Some(name.to_string());
70        self
71    }
72}
73
74impl ShouldSkip for PercolateQuery {
75    fn should_skip(&self) -> bool {
76        self.source.should_skip()
77    }
78}
79
80serialize_with_root!("percolate": PercolateQuery);
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn serialization() {
88        #[derive(Serialize)]
89        struct Source {
90            id: i32,
91            message: &'static str,
92        }
93
94        assert_serialize_query(
95            Query::percolate(
96                "field_name",
97                Source {
98                    id: 1,
99                    message: "search text",
100                },
101            ),
102            json!({
103                "percolate": {
104                    "field": "field_name",
105                    "document": {
106                        "id": 1,
107                        "message": "search text",
108                    }
109                }
110            }),
111        );
112
113        assert_serialize_query(
114            Query::percolate(
115                "field_name",
116                [Source {
117                    id: 1,
118                    message: "search text",
119                }],
120            ),
121            json!({
122                "percolate": {
123                    "field": "field_name",
124                    "documents": [
125                        {
126                            "id": 1,
127                            "message": "search text",
128                        }
129                    ]
130                }
131            }),
132        );
133
134        assert_serialize_query(
135            Query::percolate("field_name", json!({"message": "lol"})),
136            json!({
137                "percolate": {
138                    "field": "field_name",
139                    "document": {
140                        "message": "lol"
141                    }
142                }
143            }),
144        );
145
146        assert_serialize_query(
147            Query::percolate("field_name", json!({"message": "lol"})).name("toast"),
148            json!({
149                "percolate": {
150                    "field": "field_name",
151                    "name": "toast",
152                    "document": {
153                        "message": "lol"
154                    }
155                }
156            }),
157        );
158
159        assert_serialize_query(
160            Query::percolate("field_name", [json!({"message": "lol"})]),
161            json!({
162                "percolate": {
163                    "field": "field_name",
164                    "documents": [
165                        {
166                            "message": "lol"
167                        }
168                    ]
169                }
170            }),
171        );
172
173        assert_serialize_query(
174            Query::percolate("field_name", [json!({"message": "lol"})]).name("toast"),
175            json!({
176                "percolate": {
177                    "field": "field_name",
178                    "name": "toast",
179                    "documents": [
180                        {
181                            "message": "lol"
182                        }
183                    ]
184                }
185            }),
186        );
187    }
188}