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}