Skip to main content

qdrant_client/builders/
text_index_params_builder.rs

1use crate::qdrant::*;
2
3#[derive(Clone)]
4pub struct TextIndexParamsBuilder {
5    /// Tokenizer type
6    pub(crate) tokenizer: Option<i32>,
7    /// If true - all tokens will be lowercase
8    pub(crate) lowercase: Option<Option<bool>>,
9    /// Minimal token length
10    pub(crate) min_token_len: Option<Option<u64>>,
11    /// Maximal token length
12    pub(crate) max_token_len: Option<Option<u64>>,
13    /// If true - store index on disk.
14    pub(crate) on_disk: Option<Option<bool>>,
15    pub(crate) stopwords: Option<Option<StopwordsSet>>,
16    /// If true - support phrase matching.
17    pub(crate) phrase_matching: Option<Option<bool>>,
18    /// Set an algorithm for stemming.
19    pub(crate) stemmer: Option<Option<StemmingAlgorithm>>,
20    /// If true, normalize tokens by folding accented characters to ASCII (e.g., "ação" -> "acao"). Default: false.
21    pub(crate) ascii_folding: Option<Option<bool>>,
22    /// If true - enable HNSW index for this field.
23    pub(crate) enable_hnsw: Option<Option<bool>>,
24}
25
26impl TextIndexParamsBuilder {
27    pub fn new(tokenizer: TokenizerType) -> Self {
28        let mut builder = Self::create_empty();
29        builder.tokenizer = Some(tokenizer.into());
30        builder
31    }
32
33    /// Tokenizer type
34    pub fn tokenizer(self, value: i32) -> Self {
35        let mut new = self;
36        new.tokenizer = Option::Some(value);
37        new
38    }
39    /// If true - all tokens will be lowercase
40    pub fn lowercase(self, value: bool) -> Self {
41        let mut new = self;
42        new.lowercase = Option::Some(Option::Some(value));
43        new
44    }
45    /// Minimal token length
46    pub fn min_token_len(self, value: u64) -> Self {
47        let mut new = self;
48        new.min_token_len = Option::Some(Option::Some(value));
49        new
50    }
51    /// Maximal token length
52    pub fn max_token_len(self, value: u64) -> Self {
53        let mut new = self;
54        new.max_token_len = Option::Some(Option::Some(value));
55        new
56    }
57    /// If true - store index on disk.
58    pub fn on_disk(self, value: bool) -> Self {
59        let mut new = self;
60        new.on_disk = Option::Some(Option::Some(value));
61        new
62    }
63
64    /// Stopwords for a single language for the text index
65    pub fn stopwords_language(self, language: String) -> Self {
66        let mut new = self;
67        let stopwords_set = StopwordsSet {
68            languages: vec![language],
69            custom: vec![],
70        };
71        new.stopwords = Some(Some(stopwords_set));
72        new
73    }
74
75    /// Stopwords for the text index
76    pub fn stopwords(self, stopwords_set: StopwordsSet) -> Self {
77        let mut new = self;
78        new.stopwords = Some(Some(stopwords_set));
79        new
80    }
81
82    /// If true - support phrase matching. Default is false.
83    pub fn phrase_matching(self, phrase_matching: bool) -> Self {
84        let mut new = self;
85        new.phrase_matching = Some(Some(phrase_matching));
86        new
87    }
88
89    /// Set snowball stemmer with the provided language
90    pub fn snowball_stemmer(self, language: String) -> Self {
91        let mut new: TextIndexParamsBuilder = self;
92        let stemmer = StemmingAlgorithm {
93            stemming_params: Some(stemming_algorithm::StemmingParams::Snowball(
94                SnowballParams { language },
95            )),
96        };
97        new.stemmer = Some(Some(stemmer));
98        new
99    }
100
101    /// Set an algorithm for stemming.
102    pub fn stemmer(self, stemming_params: stemming_algorithm::StemmingParams) -> Self {
103        let mut new = self;
104        let stemmer = StemmingAlgorithm {
105            stemming_params: Some(stemming_params),
106        };
107        new.stemmer = Some(Some(stemmer));
108        new
109    }
110
111    /// If true, normalize tokens by folding accented characters to ASCII (e.g., "ação" -> "acao"). Default: false.
112    pub fn ascii_folding(self, value: bool) -> Self {
113        let mut new = self;
114        new.ascii_folding = Option::Some(Option::Some(value));
115        new
116    }
117
118    /// If true - enable HNSW index for this field.
119    pub fn enable_hnsw(self, value: bool) -> Self {
120        let mut new = self;
121        new.enable_hnsw = Option::Some(Option::Some(value));
122        new
123    }
124
125    fn build_inner(self) -> Result<TextIndexParams, TextIndexParamsBuilderError> {
126        Ok(TextIndexParams {
127            tokenizer: match self.tokenizer {
128                Some(value) => value,
129                None => {
130                    return Result::Err(core::convert::Into::into(
131                        ::derive_builder::UninitializedFieldError::from("tokenizer"),
132                    ));
133                }
134            },
135            lowercase: self.lowercase.unwrap_or_default(),
136            min_token_len: self.min_token_len.unwrap_or_default(),
137            max_token_len: self.max_token_len.unwrap_or_default(),
138            on_disk: self.on_disk.unwrap_or_default(),
139            stopwords: self.stopwords.unwrap_or_default(),
140            phrase_matching: self.phrase_matching.unwrap_or_default(),
141            stemmer: self.stemmer.unwrap_or_default(),
142            ascii_folding: self.ascii_folding.unwrap_or_default(),
143            enable_hnsw: self.enable_hnsw.unwrap_or_default(),
144        })
145    }
146
147    /// Create an empty builder, with all fields set to `None` or `PhantomData`.
148    fn create_empty() -> Self {
149        Self {
150            tokenizer: Default::default(),
151            lowercase: Default::default(),
152            min_token_len: Default::default(),
153            max_token_len: Default::default(),
154            on_disk: Default::default(),
155            stopwords: Default::default(),
156            phrase_matching: Default::default(),
157            stemmer: Default::default(),
158            ascii_folding: Default::default(),
159            enable_hnsw: Default::default(),
160        }
161    }
162}
163
164impl From<TextIndexParamsBuilder> for TextIndexParams {
165    fn from(value: TextIndexParamsBuilder) -> Self {
166        value.build_inner().unwrap_or_else(|_| {
167            panic!(
168                "Failed to convert {0} to {1}",
169                "TextIndexParamsBuilder", "TextIndexParams"
170            )
171        })
172    }
173}
174
175impl TextIndexParamsBuilder {
176    /// Builds the desired type. Can often be omitted.
177    pub fn build(self) -> TextIndexParams {
178        self.build_inner().unwrap_or_else(|_| {
179            panic!(
180                "Failed to build {0} into {1}",
181                "TextIndexParamsBuilder", "TextIndexParams"
182            )
183        })
184    }
185}
186
187#[non_exhaustive]
188#[derive(Debug)]
189pub enum TextIndexParamsBuilderError {
190    /// Uninitialized field
191    UninitializedField(&'static str),
192    /// Custom validation error
193    ValidationError(String),
194}
195
196// Implementing the Display trait for better error messages
197impl std::fmt::Display for TextIndexParamsBuilderError {
198    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
199        match self {
200            Self::UninitializedField(field) => {
201                write!(f, "`{field}` must be initialized")
202            }
203            Self::ValidationError(error) => write!(f, "{error}"),
204        }
205    }
206}
207
208// Implementing the Error trait
209impl std::error::Error for TextIndexParamsBuilderError {}
210
211// Implementing From trait for conversion from UninitializedFieldError
212impl From<derive_builder::UninitializedFieldError> for TextIndexParamsBuilderError {
213    fn from(error: derive_builder::UninitializedFieldError) -> Self {
214        Self::UninitializedField(error.field_name())
215    }
216}
217
218// Implementing From trait for conversion from String
219impl From<String> for TextIndexParamsBuilderError {
220    fn from(error: String) -> Self {
221        Self::ValidationError(error)
222    }
223}