Skip to main content

qdrant_client/builders/
text_index_params_builder.rs

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