1use super::Query;
9use super::types::{QueryGenericLang, QuerySearchLimit, QuerySearchOffset};
10use crate::config::{ConfigNormalization, ConfigStopwords, ConfigTokenization};
11use crate::lexer::{TokenLexerBuilder, TokenLexerMode};
12use crate::store::StoreItemBuilder;
13
14impl<'a> Query<'a> {
15 #[allow(clippy::too_many_arguments)] pub fn search(
17 query_id: &'a str,
18 collection: &'a str,
19 bucket: &'a str,
20 terms: &'a str,
21 limit: QuerySearchLimit,
22 offset: QuerySearchOffset,
23 lang: Option<QueryGenericLang>,
24 normalization_config: ConfigNormalization,
25 tokenization_config: ConfigTokenization,
26 stopwords_config: &'a ConfigStopwords,
27 ) -> Result<Self, ()> {
28 match (
29 StoreItemBuilder::from_depth_2(collection, bucket),
30 TokenLexerBuilder::from(
31 TokenLexerMode::from_query_lang(&lang),
32 lang.and_then(QueryGenericLang::into_lang_opt),
33 terms,
34 normalization_config,
35 tokenization_config,
36 stopwords_config,
37 ),
38 ) {
39 (Ok(store), Ok(text_lexed)) => {
40 Ok(Query::Search(store, query_id, text_lexed, limit, offset))
41 }
42 _ => Err(()),
43 }
44 }
45
46 #[allow(clippy::too_many_arguments)] pub fn suggest(
48 query_id: &'a str,
49 collection: &'a str,
50 bucket: &'a str,
51 terms: &'a str,
52 limit: QuerySearchLimit,
53 normalization_config: ConfigNormalization,
54 tokenization_config: ConfigTokenization,
55 stopwords_config: &'a ConfigStopwords,
56 ) -> Result<Self, ()> {
57 match (
58 StoreItemBuilder::from_depth_2(collection, bucket),
59 TokenLexerBuilder::from(
60 TokenLexerMode::NormalizeOnly,
61 None,
62 terms,
63 normalization_config,
64 tokenization_config,
65 stopwords_config,
66 ),
67 ) {
68 (Ok(store), Ok(text_lexed)) => Ok(Query::Suggest(store, query_id, text_lexed, limit)),
69 _ => Err(()),
70 }
71 }
72
73 pub fn list(
74 query_id: &'a str,
75 collection: &'a str,
76 bucket: &'a str,
77 limit: QuerySearchLimit,
78 offset: QuerySearchOffset,
79 ) -> Result<Self, ()> {
80 match StoreItemBuilder::from_depth_2(collection, bucket) {
81 Ok(store) => Ok(Query::List(store, query_id, limit, offset)),
82 _ => Err(()),
83 }
84 }
85
86 #[allow(clippy::too_many_arguments)] pub fn push(
88 collection: &'a str,
89 bucket: &'a str,
90 object: &'a str,
91 text: &'a str,
92 lang: Option<QueryGenericLang>,
93 normalization_config: ConfigNormalization,
94 tokenization_config: ConfigTokenization,
95 stopwords_config: &'a ConfigStopwords,
96 ) -> Result<Self, ()> {
97 match (
98 StoreItemBuilder::from_depth_3(collection, bucket, object),
99 TokenLexerBuilder::from(
100 TokenLexerMode::from_query_lang(&lang),
101 lang.and_then(QueryGenericLang::into_lang_opt),
102 text,
103 normalization_config,
104 tokenization_config,
105 stopwords_config,
106 ),
107 ) {
108 (Ok(store), Ok(text_lexed)) => Ok(Query::Push(store, text_lexed)),
109 _ => Err(()),
110 }
111 }
112
113 pub fn pop(
114 collection: &'a str,
115 bucket: &'a str,
116 object: &'a str,
117 text: &'a str,
118 normalization_config: ConfigNormalization,
119 tokenization_config: ConfigTokenization,
120 stopwords_config: &'a ConfigStopwords,
121 ) -> Result<Self, ()> {
122 match (
123 StoreItemBuilder::from_depth_3(collection, bucket, object),
124 TokenLexerBuilder::from(
125 TokenLexerMode::NormalizeOnly,
126 None,
127 text,
128 normalization_config,
129 tokenization_config,
130 stopwords_config,
131 ),
132 ) {
133 (Ok(store), Ok(text_lexed)) => Ok(Query::Pop(store, text_lexed)),
134 _ => Err(()),
135 }
136 }
137
138 pub fn count(
139 collection: &'a str,
140 bucket: Option<&'a str>,
141 object: Option<&'a str>,
142 ) -> Result<Self, ()> {
143 let store_result = match (bucket, object) {
144 (Some(bucket_inner), Some(object_inner)) => {
145 StoreItemBuilder::from_depth_3(collection, bucket_inner, object_inner)
146 }
147 (Some(bucket_inner), None) => StoreItemBuilder::from_depth_2(collection, bucket_inner),
148 _ => StoreItemBuilder::from_depth_1(collection),
149 };
150
151 match store_result {
152 Ok(store) => Ok(Query::Count(store)),
153 _ => Err(()),
154 }
155 }
156
157 pub fn flushc(collection: &'a str) -> Result<Self, ()> {
158 match StoreItemBuilder::from_depth_1(collection) {
159 Ok(store) => Ok(Query::FlushC(store)),
160 _ => Err(()),
161 }
162 }
163
164 pub fn flushb(collection: &'a str, bucket: &'a str) -> Result<Self, ()> {
165 match StoreItemBuilder::from_depth_2(collection, bucket) {
166 Ok(store) => Ok(Query::FlushB(store)),
167 _ => Err(()),
168 }
169 }
170
171 pub fn flusho(collection: &'a str, bucket: &'a str, object: &'a str) -> Result<Self, ()> {
172 match StoreItemBuilder::from_depth_3(collection, bucket, object) {
173 Ok(store) => Ok(Query::FlushO(store)),
174 _ => Err(()),
175 }
176 }
177}
178
179#[cfg(test)]
180mod tests {
181 use std::sync::LazyLock;
182
183 use super::*;
184
185 const NORMALIZATION_CONFIG: ConfigNormalization = ConfigNormalization {
186 unicode_normalization: None,
187 diacritic_folding_enabled: false,
188 stemming_enabled: false,
189 };
190 const TOKENIZATION_CONFIG: ConfigTokenization = ConfigTokenization {
191 detect_special_patterns: true,
192 compat_split_special_patterns: false,
193 };
194 static STOPWORDS_CONFIG: LazyLock<ConfigStopwords> = LazyLock::new(|| ConfigStopwords {
195 allow: Default::default(),
196 deny: Default::default(),
197 });
198
199 #[test]
200 fn it_builds_search_query() {
201 #[rustfmt::skip]
202 assert!(Query::search(
203 "id1", "c:test:1", "b:test:1", "Michael Dake", 10, 20, None,
204 NORMALIZATION_CONFIG, TOKENIZATION_CONFIG, &STOPWORDS_CONFIG,
205 ).is_ok());
206
207 #[rustfmt::skip]
208 assert!(Query::search(
209 "id2", "c:test:1", "", "Michael Dake", 1, 0, None,
210 NORMALIZATION_CONFIG, TOKENIZATION_CONFIG, &STOPWORDS_CONFIG,
211 ).is_err());
212 }
213
214 #[test]
215 fn it_builds_suggest_query() {
216 #[rustfmt::skip]
217 assert!(Query::suggest(
218 "id1", "c:test:2", "b:test:2", "Micha", 5,
219 NORMALIZATION_CONFIG, TOKENIZATION_CONFIG, &STOPWORDS_CONFIG,
220 ).is_ok());
221
222 #[rustfmt::skip]
223 assert!(Query::suggest(
224 "id2", "c:test:2", "", "Micha", 1,
225 NORMALIZATION_CONFIG, TOKENIZATION_CONFIG, &STOPWORDS_CONFIG,
226 ).is_err());
227 }
228
229 #[test]
230 fn it_builds_list_query() {
231 assert!(Query::list("id1", "c:test:2", "b:test:2", 100, 0).is_ok());
232 assert!(Query::list("id2", "c:test:2", "", 10, 0).is_err());
233 }
234
235 #[test]
236 fn it_builds_push_query() {
237 #[rustfmt::skip]
238 assert!(Query::push(
239 "c:test:3", "b:test:3", "o:test:3", "My name is Michael Dake. I'm ordering in the US.", None,
240 NORMALIZATION_CONFIG, TOKENIZATION_CONFIG, &STOPWORDS_CONFIG,
241 ).is_ok());
242
243 #[rustfmt::skip]
244 assert!(Query::push(
245 "c:test:3", "", "o:test:3", "My name is Michael Dake.", None,
246 NORMALIZATION_CONFIG, TOKENIZATION_CONFIG, &STOPWORDS_CONFIG,
247 ).is_err());
248 }
249
250 #[test]
251 fn it_builds_pop_query() {
252 #[rustfmt::skip]
253 assert!(Query::pop(
254 "c:test:4", "b:test:4", "o:test:4", "ordering US",
255 NORMALIZATION_CONFIG, TOKENIZATION_CONFIG, &STOPWORDS_CONFIG,
256 ).is_ok());
257
258 #[rustfmt::skip]
259 assert!(Query::pop(
260 "c:test:4", "", "o:test:4", "ordering US",
261 NORMALIZATION_CONFIG, TOKENIZATION_CONFIG, &STOPWORDS_CONFIG,
262 ).is_err());
263 }
264
265 #[test]
266 fn it_builds_count_query() {
267 assert!(Query::count("c:test:5", None, None).is_ok());
268 assert!(Query::count("c:test:5", Some("b:test:5"), None).is_ok());
269 assert!(Query::count("c:test:5", Some("b:test:5"), Some("o:test:5")).is_ok());
270 assert!(Query::count("c:test:5", Some(""), Some("o:test:5")).is_err());
271 }
272
273 #[test]
274 fn it_builds_flushc_query() {
275 assert!(Query::flushc("c:test:6").is_ok());
276 assert!(Query::flushc("").is_err());
277 }
278
279 #[test]
280 fn it_builds_flushb_query() {
281 assert!(Query::flushb("c:test:7", "b:test:7").is_ok());
282 assert!(Query::flushb("c:test:7", "").is_err());
283 }
284
285 #[test]
286 fn it_builds_flusho_query() {
287 assert!(Query::flusho("c:test:8", "b:test:8", "o:test:8").is_ok());
288 assert!(Query::flusho("c:test:8", "b:test:8", "").is_err());
289 }
290}