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