nodedb_lite/engine/fts/
analyzer.rs1use super::manager::registry::fts_err;
23use super::manager::{FtsCollectionManager, resident_index};
24use crate::engine::fts::LiteFtsIndex;
25use crate::error::LiteError;
26
27impl FtsCollectionManager {
28 pub fn set_collection_analyzer(
35 &mut self,
36 collection: &str,
37 analyzer_name: &str,
38 ) -> Result<(), LiteError> {
39 self.collection_analyzers
40 .insert(collection.to_string(), analyzer_name.to_string());
41 for key in self.collection_keys(collection) {
42 if let Some(idx) = self.indices.get(&key) {
43 idx.set_collection_analyzer(0, 0, &key, analyzer_name)
44 .map_err(|e| fts_err(collection, e))?;
45 }
46 }
47 Ok(())
48 }
49
50 pub fn set_collection_fuzzy(&mut self, collection: &str, fuzzy: bool) -> Result<(), LiteError> {
54 self.collection_fuzzy_defaults
55 .insert(collection.to_string(), fuzzy);
56 for key in self.collection_keys(collection) {
57 if let Some(idx) = self.indices.get(&key) {
58 idx.set_collection_fuzzy(0, 0, &key, fuzzy)
59 .map_err(|e| fts_err(collection, e))?;
60 }
61 }
62 Ok(())
63 }
64
65 pub(crate) fn analyzer_for(&self, collection: &str) -> Option<&str> {
67 self.collection_analyzers
68 .get(collection)
69 .map(String::as_str)
70 }
71
72 pub(crate) fn fuzzy_for(&self, collection: &str) -> Option<bool> {
74 self.collection_fuzzy_defaults.get(collection).copied()
75 }
76
77 pub(crate) fn new_index_for(
84 &self,
85 collection: &str,
86 key: &str,
87 ) -> Result<LiteFtsIndex, LiteError> {
88 let idx = resident_index(std::sync::Arc::clone(&self.governor));
89 if let Some(name) = self.analyzer_for(collection) {
90 idx.set_collection_analyzer(0, 0, key, name)
91 .map_err(|e| fts_err(collection, e))?;
92 }
93 if let Some(fuzzy) = self.fuzzy_for(collection) {
94 idx.set_collection_fuzzy(0, 0, key, fuzzy)
95 .map_err(|e| fts_err(collection, e))?;
96 }
97 Ok(idx)
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::FtsCollectionManager;
104 use crate::engine::fts::manager::test_governor;
105
106 const DOC_KEY: &str = "col";
107
108 fn doc_index_config(mgr: &FtsCollectionManager) -> (Option<String>, bool) {
111 let idx = mgr
112 .indices
113 .get(DOC_KEY)
114 .expect("whole-document index must exist");
115 (
116 idx.get_collection_analyzer(0, 0, DOC_KEY)
117 .expect("meta read must succeed"),
118 idx.get_collection_fuzzy(0, 0, DOC_KEY)
119 .expect("meta read must succeed"),
120 )
121 }
122
123 #[test]
124 fn setting_analyzer_leaves_fuzzy_default_unchanged() {
125 let mut mgr = FtsCollectionManager::new(test_governor());
126 mgr.index_document("col", "doc1", "the quick brown fox")
127 .expect("index update must succeed");
128
129 mgr.set_collection_fuzzy("col", true)
130 .expect("config binding must succeed");
131 mgr.set_collection_analyzer("col", "german")
132 .expect("config binding must succeed");
133
134 let (analyzer, fuzzy) = doc_index_config(&mgr);
135 assert_eq!(analyzer.as_deref(), Some("german"));
136 assert!(
137 fuzzy,
138 "binding the analyzer must not clear the fuzzy default"
139 );
140 assert_eq!(mgr.fuzzy_for("col"), Some(true));
141 }
142
143 #[test]
144 fn setting_fuzzy_default_leaves_analyzer_unchanged() {
145 let mut mgr = FtsCollectionManager::new(test_governor());
146 mgr.index_document("col", "doc1", "the quick brown fox")
147 .expect("index update must succeed");
148
149 mgr.set_collection_analyzer("col", "german")
150 .expect("config binding must succeed");
151 mgr.set_collection_fuzzy("col", true)
152 .expect("config binding must succeed");
153
154 let (analyzer, fuzzy) = doc_index_config(&mgr);
155 assert_eq!(
156 analyzer.as_deref(),
157 Some("german"),
158 "binding the fuzzy default must not clear the analyzer"
159 );
160 assert!(fuzzy);
161 assert_eq!(mgr.analyzer_for("col"), Some("german"));
162 }
163
164 #[test]
165 fn config_bound_before_any_index_is_inherited_by_later_indexes() {
166 let mut mgr = FtsCollectionManager::new(test_governor());
167 mgr.set_collection_analyzer("col", "german")
169 .expect("config binding must succeed");
170 mgr.set_collection_fuzzy("col", true)
171 .expect("config binding must succeed");
172 assert!(mgr.indices.is_empty());
173
174 mgr.index_document("col", "doc1", "der schnelle braune fuchs")
175 .expect("index update must succeed");
176
177 let (analyzer, fuzzy) = doc_index_config(&mgr);
178 assert_eq!(analyzer.as_deref(), Some("german"));
179 assert!(fuzzy);
180 }
181
182 #[test]
183 fn config_bound_before_any_index_is_inherited_by_later_field_indexes() {
184 let mut mgr = FtsCollectionManager::new(test_governor());
185 mgr.set_collection_analyzer("col", "german")
186 .expect("config binding must succeed");
187 mgr.set_collection_fuzzy("col", true)
188 .expect("config binding must succeed");
189
190 mgr.index_field("col", "title", "doc1", "der schnelle braune fuchs")
191 .expect("index update must succeed");
192
193 let key = "col:title";
194 let idx = mgr.indices.get(key).expect("field index must exist");
195 assert_eq!(
196 idx.get_collection_analyzer(0, 0, key)
197 .expect("meta read must succeed")
198 .as_deref(),
199 Some("german")
200 );
201 assert!(
202 idx.get_collection_fuzzy(0, 0, key)
203 .expect("meta read must succeed")
204 );
205 }
206
207 #[test]
208 fn binding_nothing_leaves_the_collection_at_its_defaults() {
209 let mut mgr = FtsCollectionManager::new(test_governor());
212 mgr.index_document("col", "doc1", "the quick brown fox")
213 .expect("index update must succeed");
214
215 let (analyzer, fuzzy) = doc_index_config(&mgr);
216 assert_eq!(analyzer, None);
217 assert!(!fuzzy);
218 assert_eq!(mgr.analyzer_for("col"), None);
219 assert_eq!(mgr.fuzzy_for("col"), None);
220 }
221
222 #[test]
223 fn config_is_bound_to_the_exact_collection_name() {
224 let mut mgr = FtsCollectionManager::new(test_governor());
225 mgr.set_collection_analyzer("a:b", "german")
226 .expect("config binding must succeed");
227 mgr.set_collection_fuzzy("a:b", true)
228 .expect("config binding must succeed");
229
230 assert_eq!(mgr.analyzer_for("a:b"), Some("german"));
231 assert_eq!(mgr.fuzzy_for("a:b"), Some(true));
232 assert_eq!(mgr.analyzer_for("a"), None);
233 assert_eq!(mgr.fuzzy_for("a"), None);
234 }
235}