1use derive_builder::Builder;
16use reqwest_middleware::ClientWithMiddleware;
17use serde::{Deserialize, Serialize};
18
19use crate::mochow::{client::IntoRequest, config::ClientConfiguration};
20
21use super::{AutoBuildPolicyType, IndexState, IndexType, MetricType};
22
23#[derive(Debug, Clone, Builder, Serialize)]
30pub struct CreateIndexArgs {
31 #[builder(setter(into))]
32 pub database: String,
33 #[builder(setter(into))]
34 pub table: String,
35 #[builder(default, setter(into))]
36 #[serde(default)]
37 pub indexes: Vec<IndexSchema>,
38}
39
40#[derive(Debug, Clone, Builder, Serialize, Deserialize)]
42pub struct IndexSchema {
43 #[builder(default, setter(into))]
44 #[serde(default, rename = "indexName")]
45 pub index_name: String,
46
47 #[builder(default, setter(into, strip_option))]
51 #[serde(default, rename = "indexType", skip_serializing_if = "Option::is_none")]
52 pub index_type: Option<IndexType>,
53
54 #[builder(default, setter(into, strip_option))]
59 #[serde(
60 default,
61 rename = "metricType",
62 skip_serializing_if = "Option::is_none"
63 )]
64 pub metric_type: Option<MetricType>,
65
66 #[builder(default, setter(strip_option))]
68 #[serde(default, skip_serializing_if = "Option::is_none")]
69 pub params: Option<VectorIndexParams>,
70
71 #[builder(default, setter(into))]
73 pub field: String,
74
75 #[builder(default, setter(into))]
77 #[serde(default, rename = "autoBuild")]
78 pub auto_build: bool,
79
80 #[builder(setter(skip))]
83 #[serde(default, skip_serializing)]
84 pub state: Option<IndexState>,
85
86 #[builder(default, setter(strip_option))]
87 #[serde(
88 default,
89 rename = "autoBuildPolicy",
90 skip_serializing_if = "Option::is_none"
91 )]
92 pub auto_build_policy: Option<AutoBuildPolicy>,
93
94 #[builder(default, setter(skip))]
97 #[serde(
98 default,
99 rename = "indexMajorVersion",
100 skip_serializing_if = "Option::is_none"
101 )]
102 pub index_major_version: Option<u64>,
103}
104
105#[derive(Debug, Clone, Builder, Default, Serialize, Deserialize)]
107pub struct AutoBuildPolicy {
108 #[builder(setter(into, strip_option))]
113 #[serde(
114 default,
115 rename = "policyType",
116 skip_serializing_if = "Option::is_none"
117 )]
118 pub policy_type: Option<AutoBuildPolicyType>,
119
120 #[builder(default, setter(into))]
124 #[serde(default, skip_serializing_if = "String::is_empty")]
125 pub timing: String,
126
127 #[builder(default, setter(into))]
130 #[serde(default, rename = "periodInSecond")]
131 pub period_in_second: u64,
132
133 #[builder(default, setter(into))]
135 #[serde(default, rename = "rowCountIncrement")]
136 pub row_count_increment: u64,
137
138 #[builder(default, setter(into))]
140 #[serde(default, rename = "rowCountIncrementRatio")]
141 pub row_count_increment_ratio: f64,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
145#[serde(untagged)]
146pub enum VectorIndexParams {
147 HNSWPQ(HNSWPQIndexParam),
149 HNSW(HNSWIndexParam),
151 PUCK(PUCKIndexParam),
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct HNSWIndexParam {
157 #[serde(rename = "M")]
160 pub m: u32,
161 #[serde(rename = "efConstruction")]
164 pub ef_construction: u32,
165}
166
167#[derive(Debug, Clone, Serialize, Deserialize)]
168pub struct HNSWPQIndexParam {
169 #[serde(rename = "M")]
172 pub m: u32,
173 #[serde(rename = "efConstruction")]
176 pub ef_construction: u32,
177
178 #[serde(rename = "NSQ")]
181 pub nsq: u32,
182
183 #[serde(rename = "sampleRate")]
186 pub sample_rate: f64,
187}
188
189#[derive(Debug, Clone, Serialize, Deserialize)]
190pub struct PUCKIndexParam {
191 #[serde(rename = "coarseClusterCount")]
194 pub coarse_cluster_count: u32,
195 #[serde(rename = "fineClusterCount")]
198 pub fine_cluster_count: u32,
199}
200
201#[derive(Debug, Clone, Builder, Serialize)]
205pub struct DescriptIndexArgs {
206 #[builder(setter(into))]
207 pub database: String,
208 #[builder(setter(into))]
209 pub table: String,
210 #[builder(setter(into))]
211 #[serde(rename = "indexName")]
212 pub index_name: String,
213}
214
215#[derive(Debug, Clone, Deserialize)]
216pub struct DescriptIndexResponse {
217 pub code: i32,
218 pub msg: String,
219
220 pub index: IndexSchema,
221}
222
223#[derive(Debug, Clone, Builder, Serialize)]
227pub struct RebuildIndexArgs {
228 #[builder(setter(into))]
229 pub database: String,
230 #[builder(setter(into))]
231 pub table: String,
232 #[builder(setter(into))]
233 #[serde(rename = "indexName")]
234 pub index_name: String,
235}
236
237#[derive(Debug, Clone, Builder, Serialize)]
241pub struct DeleteIndexArgs {
242 #[builder(setter(into))]
243 pub database: String,
244 #[builder(setter(into))]
245 pub table: String,
246 #[builder(setter(into))]
247 #[serde(rename = "indexName")]
248 pub index_name: String,
249}
250
251#[derive(Debug, Clone, Builder, Serialize)]
255pub struct ModifyIndexArgs {
256 #[builder(setter(into))]
257 pub database: String,
258 #[builder(setter(into))]
259 pub table: String,
260 #[builder(setter(into))]
261 pub index: IndexSchema,
262}
263
264impl IntoRequest for CreateIndexArgs {
265 fn into_request(
266 self,
267 config: &ClientConfiguration,
268 client: &ClientWithMiddleware,
269 ) -> reqwest_middleware::RequestBuilder {
270 let url = format!("{}/{}/index?create", config.endpoint, config.version);
271 client.post(url).json(&self)
272 }
273}
274
275impl IntoRequest for DescriptIndexArgs {
276 fn into_request(
277 self,
278 config: &ClientConfiguration,
279 client: &ClientWithMiddleware,
280 ) -> reqwest_middleware::RequestBuilder {
281 let url = format!("{}/{}/index?desc", config.endpoint, config.version);
282 client.post(url).json(&self)
283 }
284}
285
286impl IntoRequest for RebuildIndexArgs {
287 fn into_request(
288 self,
289 config: &ClientConfiguration,
290 client: &ClientWithMiddleware,
291 ) -> reqwest_middleware::RequestBuilder {
292 let url = format!("{}/{}/index?rebuild", config.endpoint, config.version);
293 client.post(url).json(&self)
294 }
295}
296
297impl IntoRequest for DeleteIndexArgs {
298 fn into_request(
299 self,
300 config: &ClientConfiguration,
301 client: &ClientWithMiddleware,
302 ) -> reqwest_middleware::RequestBuilder {
303 let url = format!("{}/{}/index", config.endpoint, config.version);
304 client.delete(url).json(&self)
305 }
306}
307
308impl IntoRequest for ModifyIndexArgs {
309 fn into_request(
310 self,
311 config: &ClientConfiguration,
312 client: &ClientWithMiddleware,
313 ) -> reqwest_middleware::RequestBuilder {
314 let url = format!("{}/{}/index?modify", config.endpoint, config.version);
315 client.post(url).json(&self)
316 }
317}
318
319#[cfg(test)]
320mod tests {
321 use anyhow::Result;
322
323 use crate::mochow::{TESTDATABSE, TESTTABLE, UTCLIENT};
324
325 use super::*;
326 #[tokio::test]
327 async fn test_rebuild_index() -> Result<()> {
328 let ret = UTCLIENT
329 .rebuild_index(&TESTDATABSE, &TESTTABLE, "vector_idx")
330 .await?;
331 println!("rebuild index: {:?}", ret);
332 Ok(())
333 }
334
335 #[tokio::test]
336 async fn test_desc_index() -> Result<()> {
337 let ret = UTCLIENT
338 .desc_index(&TESTDATABSE, &TESTTABLE, "vector_idx_hnswpq")
339 .await?;
340 println!("desc index: {:?}", ret);
341 Ok(())
342 }
343
344 #[tokio::test]
345 async fn test_delete_index() -> Result<()> {
346 let ret = UTCLIENT
347 .delete_index(&TESTDATABSE, &TESTTABLE, "vector_idx_hnswpq")
348 .await?;
349 println!("delete index: {:?}", ret);
350 Ok(())
351 }
352
353 #[tokio::test]
354 async fn test_create_index_flat() -> Result<()> {
355 let indexes = vec![IndexSchemaBuilder::default()
356 .index_name("vector_idx_flat")
357 .field("vector")
358 .index_type(IndexType::FLAT)
359 .metric_type(MetricType::L2)
360 .build()?];
361 let args = CreateIndexArgsBuilder::default()
362 .database(TESTDATABSE.to_string())
363 .table(TESTTABLE.to_string())
364 .indexes(indexes)
365 .build()?;
366 let ret = UTCLIENT.create_index(&args).await?;
367 println!("create index: {:?}", ret);
368 Ok(())
369 }
370
371 #[tokio::test]
373 async fn test_create_index_hnsw() -> Result<()> {
374 let indexes = vec![IndexSchemaBuilder::default()
375 .index_name("vector_idx_hnsw")
376 .field("vector")
377 .index_type(IndexType::HNSW)
378 .metric_type(MetricType::L2)
379 .params(VectorIndexParams::HNSW(HNSWIndexParam {
380 m: 16,
381 ef_construction: 200,
382 }))
383 .build()?];
384 let args = CreateIndexArgsBuilder::default()
385 .database(TESTDATABSE.to_string())
386 .table(TESTTABLE.to_string())
387 .indexes(indexes)
388 .build()?;
389 let ret = UTCLIENT.create_index(&args).await?;
390 println!("create index: {:?}", ret);
391 Ok(())
392 }
393
394 #[tokio::test]
395 async fn test_create_index_hnswpq() -> Result<()> {
396 let indexes = vec![IndexSchemaBuilder::default()
397 .index_name("vector_idx_hnswpq")
398 .field("vector")
399 .index_type(IndexType::HNSWPQ)
400 .metric_type(MetricType::L2)
401 .params(VectorIndexParams::HNSWPQ(HNSWPQIndexParam {
402 m: 16,
403 ef_construction: 200,
404 nsq: 3,
405 sample_rate: 1.0,
406 }))
407 .build()?];
408 let args = CreateIndexArgsBuilder::default()
409 .database(TESTDATABSE.to_string())
410 .table(TESTTABLE.to_string())
411 .indexes(indexes)
412 .build()?;
413 let ret = UTCLIENT.create_index(&args).await?;
414 println!("create index: {:?}", ret);
415 Ok(())
416 }
417
418 #[tokio::test]
419 async fn test_create_index_puck() -> Result<()> {
420 let indexes = vec![IndexSchemaBuilder::default()
421 .index_name("vector_idx_puck")
422 .field("vector")
423 .index_type(IndexType::PUCK)
424 .metric_type(MetricType::L2)
425 .params(VectorIndexParams::PUCK(PUCKIndexParam {
426 coarse_cluster_count: 5,
427 fine_cluster_count: 5,
428 }))
429 .build()?];
430 let args = CreateIndexArgsBuilder::default()
431 .database(TESTDATABSE.to_string())
432 .table(TESTTABLE.to_string())
433 .indexes(indexes)
434 .build()?;
435 let ret = UTCLIENT.create_index(&args).await?;
436 println!("create index: {:?}", ret);
437 Ok(())
438 }
439
440 #[tokio::test]
441 async fn test_modify_index() -> Result<()> {
442 let index = IndexSchemaBuilder::default()
443 .index_name("vector_idx")
444 .auto_build(true)
445 .auto_build_policy(
446 AutoBuildPolicyBuilder::default()
447 .policy_type(AutoBuildPolicyType::PERIODICAL)
448 .period_in_second(5000 as u64)
449 .build()?,
450 )
451 .build()?;
452 let args = ModifyIndexArgsBuilder::default()
453 .database(TESTDATABSE.to_string())
454 .table(TESTTABLE.to_string())
455 .index(index)
456 .build()?;
457 let ret = UTCLIENT.modify_index(&args).await?;
460 println!("modify index: {:?}", ret);
461 Ok(())
462 }
463}