1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct HealthResponse {
13 pub healthy: bool,
15 pub version: Option<String>,
17 pub uptime_seconds: Option<u64>,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct ReadinessResponse {
24 pub ready: bool,
26 pub components: Option<HashMap<String, bool>>,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct NamespaceInfo {
37 #[serde(alias = "namespace")]
39 pub name: String,
40 pub vector_count: u64,
42 #[serde(alias = "dimension")]
44 pub dimensions: Option<u32>,
45 pub index_type: Option<String>,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct ListNamespacesResponse {
52 pub namespaces: Vec<String>,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct Vector {
63 pub id: String,
65 pub values: Vec<f32>,
67 #[serde(skip_serializing_if = "Option::is_none")]
69 pub metadata: Option<HashMap<String, serde_json::Value>>,
70}
71
72impl Vector {
73 pub fn new(id: impl Into<String>, values: Vec<f32>) -> Self {
75 Self {
76 id: id.into(),
77 values,
78 metadata: None,
79 }
80 }
81
82 pub fn with_metadata(
84 id: impl Into<String>,
85 values: Vec<f32>,
86 metadata: HashMap<String, serde_json::Value>,
87 ) -> Self {
88 Self {
89 id: id.into(),
90 values,
91 metadata: Some(metadata),
92 }
93 }
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct UpsertRequest {
99 pub vectors: Vec<Vector>,
101}
102
103impl UpsertRequest {
104 pub fn single(vector: Vector) -> Self {
106 Self {
107 vectors: vec![vector],
108 }
109 }
110
111 pub fn batch(vectors: Vec<Vector>) -> Self {
113 Self { vectors }
114 }
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct UpsertResponse {
120 pub upserted_count: u64,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct ColumnUpsertRequest {
142 pub ids: Vec<String>,
144 pub vectors: Vec<Vec<f32>>,
146 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
149 pub attributes: HashMap<String, Vec<serde_json::Value>>,
150 #[serde(skip_serializing_if = "Option::is_none")]
152 pub ttl_seconds: Option<u64>,
153 #[serde(skip_serializing_if = "Option::is_none")]
155 pub dimension: Option<usize>,
156}
157
158impl ColumnUpsertRequest {
159 pub fn new(ids: Vec<String>, vectors: Vec<Vec<f32>>) -> Self {
161 Self {
162 ids,
163 vectors,
164 attributes: HashMap::new(),
165 ttl_seconds: None,
166 dimension: None,
167 }
168 }
169
170 pub fn with_attribute(
172 mut self,
173 name: impl Into<String>,
174 values: Vec<serde_json::Value>,
175 ) -> Self {
176 self.attributes.insert(name.into(), values);
177 self
178 }
179
180 pub fn with_ttl(mut self, seconds: u64) -> Self {
182 self.ttl_seconds = Some(seconds);
183 self
184 }
185
186 pub fn with_dimension(mut self, dim: usize) -> Self {
188 self.dimension = Some(dim);
189 self
190 }
191
192 pub fn len(&self) -> usize {
194 self.ids.len()
195 }
196
197 pub fn is_empty(&self) -> bool {
199 self.ids.is_empty()
200 }
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize)]
205pub struct DeleteRequest {
206 pub ids: Vec<String>,
208}
209
210impl DeleteRequest {
211 pub fn single(id: impl Into<String>) -> Self {
213 Self {
214 ids: vec![id.into()],
215 }
216 }
217
218 pub fn batch(ids: Vec<String>) -> Self {
220 Self { ids }
221 }
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct DeleteResponse {
227 pub deleted_count: u64,
229}
230
231#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
237#[serde(rename_all = "snake_case")]
238pub enum ReadConsistency {
239 Strong,
241 #[default]
243 Eventual,
244 #[serde(rename = "bounded_staleness")]
246 BoundedStaleness,
247}
248
249#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
251pub struct StalenessConfig {
252 #[serde(default = "default_max_staleness_ms")]
254 pub max_staleness_ms: u64,
255}
256
257fn default_max_staleness_ms() -> u64 {
258 5000 }
260
261impl StalenessConfig {
262 pub fn new(max_staleness_ms: u64) -> Self {
264 Self { max_staleness_ms }
265 }
266}
267
268#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
270#[serde(rename_all = "snake_case")]
271pub enum DistanceMetric {
272 #[default]
274 Cosine,
275 Euclidean,
277 DotProduct,
279}
280
281#[derive(Debug, Clone, Serialize, Deserialize)]
283pub struct QueryRequest {
284 pub vector: Vec<f32>,
286 pub top_k: u32,
288 #[serde(default)]
290 pub distance_metric: DistanceMetric,
291 #[serde(skip_serializing_if = "Option::is_none")]
293 pub filter: Option<serde_json::Value>,
294 #[serde(default = "default_true")]
296 pub include_metadata: bool,
297 #[serde(default)]
299 pub include_vectors: bool,
300 #[serde(default)]
302 pub consistency: ReadConsistency,
303 #[serde(skip_serializing_if = "Option::is_none")]
305 pub staleness_config: Option<StalenessConfig>,
306}
307
308fn default_true() -> bool {
309 true
310}
311
312impl QueryRequest {
313 pub fn new(vector: Vec<f32>, top_k: u32) -> Self {
315 Self {
316 vector,
317 top_k,
318 distance_metric: DistanceMetric::default(),
319 filter: None,
320 include_metadata: true,
321 include_vectors: false,
322 consistency: ReadConsistency::default(),
323 staleness_config: None,
324 }
325 }
326
327 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
329 self.filter = Some(filter);
330 self
331 }
332
333 pub fn include_metadata(mut self, include: bool) -> Self {
335 self.include_metadata = include;
336 self
337 }
338
339 pub fn include_vectors(mut self, include: bool) -> Self {
341 self.include_vectors = include;
342 self
343 }
344
345 pub fn with_distance_metric(mut self, metric: DistanceMetric) -> Self {
347 self.distance_metric = metric;
348 self
349 }
350
351 pub fn with_consistency(mut self, consistency: ReadConsistency) -> Self {
353 self.consistency = consistency;
354 self
355 }
356
357 pub fn with_bounded_staleness(mut self, max_staleness_ms: u64) -> Self {
359 self.consistency = ReadConsistency::BoundedStaleness;
360 self.staleness_config = Some(StalenessConfig::new(max_staleness_ms));
361 self
362 }
363
364 pub fn with_strong_consistency(mut self) -> Self {
366 self.consistency = ReadConsistency::Strong;
367 self
368 }
369}
370
371#[derive(Debug, Clone, Serialize, Deserialize)]
373pub struct Match {
374 pub id: String,
376 pub score: f32,
378 #[serde(skip_serializing_if = "Option::is_none")]
380 pub metadata: Option<HashMap<String, serde_json::Value>>,
381}
382
383#[derive(Debug, Clone, Serialize, Deserialize)]
385pub struct QueryResponse {
386 pub matches: Vec<Match>,
388}
389
390#[derive(Debug, Clone, Serialize, Deserialize)]
396pub struct Document {
397 pub id: String,
399 pub text: String,
401 #[serde(skip_serializing_if = "Option::is_none")]
403 pub metadata: Option<HashMap<String, serde_json::Value>>,
404}
405
406impl Document {
407 pub fn new(id: impl Into<String>, text: impl Into<String>) -> Self {
409 Self {
410 id: id.into(),
411 text: text.into(),
412 metadata: None,
413 }
414 }
415
416 pub fn with_metadata(
418 id: impl Into<String>,
419 text: impl Into<String>,
420 metadata: HashMap<String, serde_json::Value>,
421 ) -> Self {
422 Self {
423 id: id.into(),
424 text: text.into(),
425 metadata: Some(metadata),
426 }
427 }
428}
429
430#[derive(Debug, Clone, Serialize, Deserialize)]
432pub struct IndexDocumentsRequest {
433 pub documents: Vec<Document>,
435}
436
437#[derive(Debug, Clone, Serialize, Deserialize)]
439pub struct IndexDocumentsResponse {
440 pub indexed_count: u64,
442}
443
444#[derive(Debug, Clone, Serialize, Deserialize)]
446pub struct FullTextSearchRequest {
447 pub query: String,
449 pub top_k: u32,
451 #[serde(skip_serializing_if = "Option::is_none")]
453 pub filter: Option<serde_json::Value>,
454}
455
456impl FullTextSearchRequest {
457 pub fn new(query: impl Into<String>, top_k: u32) -> Self {
459 Self {
460 query: query.into(),
461 top_k,
462 filter: None,
463 }
464 }
465
466 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
468 self.filter = Some(filter);
469 self
470 }
471}
472
473#[derive(Debug, Clone, Serialize, Deserialize)]
475pub struct FullTextMatch {
476 pub id: String,
478 pub score: f32,
480 #[serde(skip_serializing_if = "Option::is_none")]
482 pub text: Option<String>,
483 #[serde(skip_serializing_if = "Option::is_none")]
485 pub metadata: Option<HashMap<String, serde_json::Value>>,
486}
487
488#[derive(Debug, Clone, Serialize, Deserialize)]
490pub struct FullTextSearchResponse {
491 pub matches: Vec<FullTextMatch>,
493}
494
495#[derive(Debug, Clone, Serialize, Deserialize)]
497pub struct FullTextStats {
498 pub document_count: u64,
500 pub term_count: u64,
502}
503
504#[derive(Debug, Clone, Serialize, Deserialize)]
510pub struct HybridSearchRequest {
511 pub vector: Vec<f32>,
513 pub text: String,
515 pub top_k: u32,
517 #[serde(default = "default_vector_weight")]
519 pub vector_weight: f32,
520 #[serde(skip_serializing_if = "Option::is_none")]
522 pub filter: Option<serde_json::Value>,
523}
524
525fn default_vector_weight() -> f32 {
526 0.5
527}
528
529impl HybridSearchRequest {
530 pub fn new(vector: Vec<f32>, text: impl Into<String>, top_k: u32) -> Self {
532 Self {
533 vector,
534 text: text.into(),
535 top_k,
536 vector_weight: 0.5,
537 filter: None,
538 }
539 }
540
541 pub fn with_vector_weight(mut self, weight: f32) -> Self {
543 self.vector_weight = weight.clamp(0.0, 1.0);
544 self
545 }
546
547 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
549 self.filter = Some(filter);
550 self
551 }
552}
553
554#[derive(Debug, Clone, Serialize, Deserialize)]
556pub struct HybridSearchResponse {
557 pub matches: Vec<Match>,
559}
560
561#[derive(Debug, Clone, Serialize, Deserialize)]
567pub struct SystemDiagnostics {
568 pub system: SystemInfo,
570 pub resources: ResourceUsage,
572 pub components: ComponentHealth,
574 pub active_jobs: u64,
576}
577
578#[derive(Debug, Clone, Serialize, Deserialize)]
580pub struct SystemInfo {
581 pub version: String,
583 pub rust_version: String,
585 pub uptime_seconds: u64,
587 pub pid: u32,
589}
590
591#[derive(Debug, Clone, Serialize, Deserialize)]
593pub struct ResourceUsage {
594 pub memory_bytes: u64,
596 pub thread_count: u64,
598 pub open_fds: u64,
600 pub cpu_percent: Option<f64>,
602}
603
604#[derive(Debug, Clone, Serialize, Deserialize)]
606pub struct ComponentHealth {
607 pub storage: HealthStatus,
609 pub search_engine: HealthStatus,
611 pub cache: HealthStatus,
613 pub grpc: HealthStatus,
615}
616
617#[derive(Debug, Clone, Serialize, Deserialize)]
619pub struct HealthStatus {
620 pub healthy: bool,
622 pub message: String,
624 pub last_check: u64,
626}
627
628#[derive(Debug, Clone, Serialize, Deserialize)]
630pub struct JobInfo {
631 pub id: String,
633 pub job_type: String,
635 pub status: String,
637 pub created_at: u64,
639 pub started_at: Option<u64>,
641 pub completed_at: Option<u64>,
643 pub progress: u8,
645 pub message: Option<String>,
647}
648
649#[derive(Debug, Clone, Serialize, Deserialize)]
651pub struct CompactionRequest {
652 #[serde(skip_serializing_if = "Option::is_none")]
654 pub namespace: Option<String>,
655 #[serde(default)]
657 pub force: bool,
658}
659
660#[derive(Debug, Clone, Serialize, Deserialize)]
662pub struct CompactionResponse {
663 pub job_id: String,
665 pub message: String,
667}
668
669#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
675#[serde(rename_all = "snake_case")]
676pub enum WarmingPriority {
677 Critical,
679 High,
681 #[default]
683 Normal,
684 Low,
686 Background,
688}
689
690#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
692#[serde(rename_all = "snake_case")]
693pub enum WarmingTargetTier {
694 L1,
696 #[default]
698 L2,
699 Both,
701}
702
703#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
705#[serde(rename_all = "snake_case")]
706pub enum AccessPatternHint {
707 #[default]
709 Random,
710 Sequential,
712 Temporal,
714 Spatial,
716}
717
718#[derive(Debug, Clone, Serialize, Deserialize)]
720pub struct WarmCacheRequest {
721 pub namespace: String,
723 #[serde(skip_serializing_if = "Option::is_none")]
725 pub vector_ids: Option<Vec<String>>,
726 #[serde(default)]
728 pub priority: WarmingPriority,
729 #[serde(default)]
731 pub target_tier: WarmingTargetTier,
732 #[serde(default)]
734 pub background: bool,
735 #[serde(skip_serializing_if = "Option::is_none")]
737 pub ttl_hint_seconds: Option<u64>,
738 #[serde(default)]
740 pub access_pattern: AccessPatternHint,
741 #[serde(skip_serializing_if = "Option::is_none")]
743 pub max_vectors: Option<usize>,
744}
745
746impl WarmCacheRequest {
747 pub fn new(namespace: impl Into<String>) -> Self {
749 Self {
750 namespace: namespace.into(),
751 vector_ids: None,
752 priority: WarmingPriority::default(),
753 target_tier: WarmingTargetTier::default(),
754 background: false,
755 ttl_hint_seconds: None,
756 access_pattern: AccessPatternHint::default(),
757 max_vectors: None,
758 }
759 }
760
761 pub fn with_vector_ids(mut self, ids: Vec<String>) -> Self {
763 self.vector_ids = Some(ids);
764 self
765 }
766
767 pub fn with_priority(mut self, priority: WarmingPriority) -> Self {
769 self.priority = priority;
770 self
771 }
772
773 pub fn with_target_tier(mut self, tier: WarmingTargetTier) -> Self {
775 self.target_tier = tier;
776 self
777 }
778
779 pub fn in_background(mut self) -> Self {
781 self.background = true;
782 self
783 }
784
785 pub fn with_ttl(mut self, seconds: u64) -> Self {
787 self.ttl_hint_seconds = Some(seconds);
788 self
789 }
790
791 pub fn with_access_pattern(mut self, pattern: AccessPatternHint) -> Self {
793 self.access_pattern = pattern;
794 self
795 }
796
797 pub fn with_max_vectors(mut self, max: usize) -> Self {
799 self.max_vectors = Some(max);
800 self
801 }
802}
803
804#[derive(Debug, Clone, Serialize, Deserialize)]
806pub struct WarmCacheResponse {
807 pub success: bool,
809 pub entries_warmed: u64,
811 pub entries_skipped: u64,
813 #[serde(skip_serializing_if = "Option::is_none")]
815 pub job_id: Option<String>,
816 pub message: String,
818 #[serde(skip_serializing_if = "Option::is_none")]
820 pub estimated_completion: Option<String>,
821 pub target_tier: WarmingTargetTier,
823 pub priority: WarmingPriority,
825 #[serde(skip_serializing_if = "Option::is_none")]
827 pub bytes_warmed: Option<u64>,
828}
829
830#[derive(Debug, Clone, Serialize, Deserialize)]
836pub struct ExportRequest {
837 #[serde(default = "default_export_top_k")]
839 pub top_k: usize,
840 #[serde(skip_serializing_if = "Option::is_none")]
842 pub cursor: Option<String>,
843 #[serde(default = "default_true")]
845 pub include_vectors: bool,
846 #[serde(default = "default_true")]
848 pub include_metadata: bool,
849}
850
851fn default_export_top_k() -> usize {
852 1000
853}
854
855impl Default for ExportRequest {
856 fn default() -> Self {
857 Self {
858 top_k: 1000,
859 cursor: None,
860 include_vectors: true,
861 include_metadata: true,
862 }
863 }
864}
865
866impl ExportRequest {
867 pub fn new() -> Self {
869 Self::default()
870 }
871
872 pub fn with_top_k(mut self, top_k: usize) -> Self {
874 self.top_k = top_k;
875 self
876 }
877
878 pub fn with_cursor(mut self, cursor: impl Into<String>) -> Self {
880 self.cursor = Some(cursor.into());
881 self
882 }
883
884 pub fn include_vectors(mut self, include: bool) -> Self {
886 self.include_vectors = include;
887 self
888 }
889
890 pub fn include_metadata(mut self, include: bool) -> Self {
892 self.include_metadata = include;
893 self
894 }
895}
896
897#[derive(Debug, Clone, Serialize, Deserialize)]
899pub struct ExportedVector {
900 pub id: String,
902 #[serde(skip_serializing_if = "Option::is_none")]
904 pub values: Option<Vec<f32>>,
905 #[serde(skip_serializing_if = "Option::is_none")]
907 pub metadata: Option<serde_json::Value>,
908 #[serde(skip_serializing_if = "Option::is_none")]
910 pub ttl_seconds: Option<u64>,
911}
912
913#[derive(Debug, Clone, Serialize, Deserialize)]
915pub struct ExportResponse {
916 pub vectors: Vec<ExportedVector>,
918 #[serde(skip_serializing_if = "Option::is_none")]
920 pub next_cursor: Option<String>,
921 pub total_count: usize,
923 pub returned_count: usize,
925}
926
927#[derive(Debug, Clone, Serialize, Deserialize)]
933pub struct BatchQueryItem {
934 #[serde(skip_serializing_if = "Option::is_none")]
936 pub id: Option<String>,
937 pub vector: Vec<f32>,
939 #[serde(default = "default_batch_top_k")]
941 pub top_k: u32,
942 #[serde(skip_serializing_if = "Option::is_none")]
944 pub filter: Option<serde_json::Value>,
945 #[serde(default)]
947 pub include_metadata: bool,
948 #[serde(default)]
950 pub consistency: ReadConsistency,
951 #[serde(skip_serializing_if = "Option::is_none")]
953 pub staleness_config: Option<StalenessConfig>,
954}
955
956fn default_batch_top_k() -> u32 {
957 10
958}
959
960impl BatchQueryItem {
961 pub fn new(vector: Vec<f32>, top_k: u32) -> Self {
963 Self {
964 id: None,
965 vector,
966 top_k,
967 filter: None,
968 include_metadata: true,
969 consistency: ReadConsistency::default(),
970 staleness_config: None,
971 }
972 }
973
974 pub fn with_id(mut self, id: impl Into<String>) -> Self {
976 self.id = Some(id.into());
977 self
978 }
979
980 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
982 self.filter = Some(filter);
983 self
984 }
985
986 pub fn include_metadata(mut self, include: bool) -> Self {
988 self.include_metadata = include;
989 self
990 }
991
992 pub fn with_consistency(mut self, consistency: ReadConsistency) -> Self {
994 self.consistency = consistency;
995 self
996 }
997
998 pub fn with_bounded_staleness(mut self, max_staleness_ms: u64) -> Self {
1000 self.consistency = ReadConsistency::BoundedStaleness;
1001 self.staleness_config = Some(StalenessConfig::new(max_staleness_ms));
1002 self
1003 }
1004}
1005
1006#[derive(Debug, Clone, Serialize, Deserialize)]
1008pub struct BatchQueryRequest {
1009 pub queries: Vec<BatchQueryItem>,
1011}
1012
1013impl BatchQueryRequest {
1014 pub fn new(queries: Vec<BatchQueryItem>) -> Self {
1016 Self { queries }
1017 }
1018
1019 pub fn single(query: BatchQueryItem) -> Self {
1021 Self {
1022 queries: vec![query],
1023 }
1024 }
1025}
1026
1027#[derive(Debug, Clone, Serialize, Deserialize)]
1029pub struct BatchQueryResult {
1030 #[serde(skip_serializing_if = "Option::is_none")]
1032 pub id: Option<String>,
1033 pub results: Vec<Match>,
1035 pub latency_ms: f64,
1037 #[serde(skip_serializing_if = "Option::is_none")]
1039 pub error: Option<String>,
1040}
1041
1042#[derive(Debug, Clone, Serialize, Deserialize)]
1044pub struct BatchQueryResponse {
1045 pub results: Vec<BatchQueryResult>,
1047 pub total_latency_ms: f64,
1049 pub query_count: usize,
1051}
1052
1053#[derive(Debug, Clone, Serialize, Deserialize)]
1059pub struct MultiVectorSearchRequest {
1060 pub positive_vectors: Vec<Vec<f32>>,
1062 #[serde(skip_serializing_if = "Option::is_none")]
1064 pub positive_weights: Option<Vec<f32>>,
1065 #[serde(skip_serializing_if = "Option::is_none")]
1067 pub negative_vectors: Option<Vec<Vec<f32>>>,
1068 #[serde(skip_serializing_if = "Option::is_none")]
1070 pub negative_weights: Option<Vec<f32>>,
1071 #[serde(default = "default_multi_vector_top_k")]
1073 pub top_k: u32,
1074 #[serde(default)]
1076 pub distance_metric: DistanceMetric,
1077 #[serde(skip_serializing_if = "Option::is_none")]
1079 pub score_threshold: Option<f32>,
1080 #[serde(default)]
1082 pub enable_mmr: bool,
1083 #[serde(default = "default_mmr_lambda")]
1085 pub mmr_lambda: f32,
1086 #[serde(default = "default_true")]
1088 pub include_metadata: bool,
1089 #[serde(default)]
1091 pub include_vectors: bool,
1092 #[serde(skip_serializing_if = "Option::is_none")]
1094 pub filter: Option<serde_json::Value>,
1095 #[serde(default)]
1097 pub consistency: ReadConsistency,
1098 #[serde(skip_serializing_if = "Option::is_none")]
1100 pub staleness_config: Option<StalenessConfig>,
1101}
1102
1103fn default_multi_vector_top_k() -> u32 {
1104 10
1105}
1106
1107fn default_mmr_lambda() -> f32 {
1108 0.5
1109}
1110
1111impl MultiVectorSearchRequest {
1112 pub fn new(positive_vectors: Vec<Vec<f32>>) -> Self {
1114 Self {
1115 positive_vectors,
1116 positive_weights: None,
1117 negative_vectors: None,
1118 negative_weights: None,
1119 top_k: 10,
1120 distance_metric: DistanceMetric::default(),
1121 score_threshold: None,
1122 enable_mmr: false,
1123 mmr_lambda: 0.5,
1124 include_metadata: true,
1125 include_vectors: false,
1126 filter: None,
1127 consistency: ReadConsistency::default(),
1128 staleness_config: None,
1129 }
1130 }
1131
1132 pub fn with_top_k(mut self, top_k: u32) -> Self {
1134 self.top_k = top_k;
1135 self
1136 }
1137
1138 pub fn with_positive_weights(mut self, weights: Vec<f32>) -> Self {
1140 self.positive_weights = Some(weights);
1141 self
1142 }
1143
1144 pub fn with_negative_vectors(mut self, vectors: Vec<Vec<f32>>) -> Self {
1146 self.negative_vectors = Some(vectors);
1147 self
1148 }
1149
1150 pub fn with_negative_weights(mut self, weights: Vec<f32>) -> Self {
1152 self.negative_weights = Some(weights);
1153 self
1154 }
1155
1156 pub fn with_distance_metric(mut self, metric: DistanceMetric) -> Self {
1158 self.distance_metric = metric;
1159 self
1160 }
1161
1162 pub fn with_score_threshold(mut self, threshold: f32) -> Self {
1164 self.score_threshold = Some(threshold);
1165 self
1166 }
1167
1168 pub fn with_mmr(mut self, lambda: f32) -> Self {
1170 self.enable_mmr = true;
1171 self.mmr_lambda = lambda.clamp(0.0, 1.0);
1172 self
1173 }
1174
1175 pub fn include_metadata(mut self, include: bool) -> Self {
1177 self.include_metadata = include;
1178 self
1179 }
1180
1181 pub fn include_vectors(mut self, include: bool) -> Self {
1183 self.include_vectors = include;
1184 self
1185 }
1186
1187 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1189 self.filter = Some(filter);
1190 self
1191 }
1192
1193 pub fn with_consistency(mut self, consistency: ReadConsistency) -> Self {
1195 self.consistency = consistency;
1196 self
1197 }
1198}
1199
1200#[derive(Debug, Clone, Serialize, Deserialize)]
1202pub struct MultiVectorSearchResult {
1203 pub id: String,
1205 pub score: f32,
1207 #[serde(skip_serializing_if = "Option::is_none")]
1209 pub mmr_score: Option<f32>,
1210 #[serde(skip_serializing_if = "Option::is_none")]
1212 pub original_rank: Option<usize>,
1213 #[serde(skip_serializing_if = "Option::is_none")]
1215 pub metadata: Option<HashMap<String, serde_json::Value>>,
1216 #[serde(skip_serializing_if = "Option::is_none")]
1218 pub vector: Option<Vec<f32>>,
1219}
1220
1221#[derive(Debug, Clone, Serialize, Deserialize)]
1223pub struct MultiVectorSearchResponse {
1224 pub results: Vec<MultiVectorSearchResult>,
1226 #[serde(skip_serializing_if = "Option::is_none")]
1228 pub computed_query_vector: Option<Vec<f32>>,
1229}
1230
1231#[derive(Debug, Clone, Serialize, Deserialize)]
1237#[serde(untagged)]
1238pub enum AggregateFunction {
1239 Count,
1241 Sum { field: String },
1243 Avg { field: String },
1245 Min { field: String },
1247 Max { field: String },
1249}
1250
1251#[derive(Debug, Clone, Serialize, Deserialize)]
1253pub struct AggregationRequest {
1254 pub aggregate_by: HashMap<String, serde_json::Value>,
1257 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1260 pub group_by: Vec<String>,
1261 #[serde(skip_serializing_if = "Option::is_none")]
1263 pub filter: Option<serde_json::Value>,
1264 #[serde(default = "default_agg_limit")]
1266 pub limit: usize,
1267}
1268
1269fn default_agg_limit() -> usize {
1270 100
1271}
1272
1273impl AggregationRequest {
1274 pub fn new() -> Self {
1276 Self {
1277 aggregate_by: HashMap::new(),
1278 group_by: Vec::new(),
1279 filter: None,
1280 limit: 100,
1281 }
1282 }
1283
1284 pub fn with_count(mut self, name: impl Into<String>) -> Self {
1286 self.aggregate_by
1287 .insert(name.into(), serde_json::json!(["Count"]));
1288 self
1289 }
1290
1291 pub fn with_sum(mut self, name: impl Into<String>, field: impl Into<String>) -> Self {
1293 self.aggregate_by
1294 .insert(name.into(), serde_json::json!(["Sum", field.into()]));
1295 self
1296 }
1297
1298 pub fn with_avg(mut self, name: impl Into<String>, field: impl Into<String>) -> Self {
1300 self.aggregate_by
1301 .insert(name.into(), serde_json::json!(["Avg", field.into()]));
1302 self
1303 }
1304
1305 pub fn with_min(mut self, name: impl Into<String>, field: impl Into<String>) -> Self {
1307 self.aggregate_by
1308 .insert(name.into(), serde_json::json!(["Min", field.into()]));
1309 self
1310 }
1311
1312 pub fn with_max(mut self, name: impl Into<String>, field: impl Into<String>) -> Self {
1314 self.aggregate_by
1315 .insert(name.into(), serde_json::json!(["Max", field.into()]));
1316 self
1317 }
1318
1319 pub fn group_by(mut self, fields: Vec<String>) -> Self {
1321 self.group_by = fields;
1322 self
1323 }
1324
1325 pub fn with_group_by(mut self, field: impl Into<String>) -> Self {
1327 self.group_by.push(field.into());
1328 self
1329 }
1330
1331 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1333 self.filter = Some(filter);
1334 self
1335 }
1336
1337 pub fn with_limit(mut self, limit: usize) -> Self {
1339 self.limit = limit;
1340 self
1341 }
1342}
1343
1344impl Default for AggregationRequest {
1345 fn default() -> Self {
1346 Self::new()
1347 }
1348}
1349
1350#[derive(Debug, Clone, Serialize, Deserialize)]
1352pub struct AggregationResponse {
1353 #[serde(skip_serializing_if = "Option::is_none")]
1355 pub aggregations: Option<HashMap<String, serde_json::Value>>,
1356 #[serde(skip_serializing_if = "Option::is_none")]
1358 pub aggregation_groups: Option<Vec<AggregationGroup>>,
1359}
1360
1361#[derive(Debug, Clone, Serialize, Deserialize)]
1363pub struct AggregationGroup {
1364 #[serde(flatten)]
1366 pub group_key: HashMap<String, serde_json::Value>,
1367 #[serde(flatten)]
1369 pub aggregations: HashMap<String, serde_json::Value>,
1370}
1371
1372#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
1378pub enum VectorSearchMethod {
1379 #[default]
1381 ANN,
1382 #[serde(rename = "kNN")]
1384 KNN,
1385}
1386
1387#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
1389#[serde(rename_all = "lowercase")]
1390pub enum SortDirection {
1391 Asc,
1393 #[default]
1395 Desc,
1396}
1397
1398#[derive(Debug, Clone, Serialize, Deserialize)]
1401#[serde(untagged)]
1402pub enum RankBy {
1403 VectorSearch {
1405 field: String,
1406 method: VectorSearchMethod,
1407 query_vector: Vec<f32>,
1408 },
1409 FullTextSearch {
1411 field: String,
1412 method: String, query: String,
1414 },
1415 AttributeOrder {
1417 field: String,
1418 direction: SortDirection,
1419 },
1420 Sum(Vec<RankBy>),
1422 Max(Vec<RankBy>),
1424 Product { weight: f32, ranking: Box<RankBy> },
1426}
1427
1428impl RankBy {
1429 pub fn vector_ann(field: impl Into<String>, query_vector: Vec<f32>) -> Self {
1431 RankBy::VectorSearch {
1432 field: field.into(),
1433 method: VectorSearchMethod::ANN,
1434 query_vector,
1435 }
1436 }
1437
1438 pub fn ann(query_vector: Vec<f32>) -> Self {
1440 Self::vector_ann("vector", query_vector)
1441 }
1442
1443 pub fn vector_knn(field: impl Into<String>, query_vector: Vec<f32>) -> Self {
1445 RankBy::VectorSearch {
1446 field: field.into(),
1447 method: VectorSearchMethod::KNN,
1448 query_vector,
1449 }
1450 }
1451
1452 pub fn knn(query_vector: Vec<f32>) -> Self {
1454 Self::vector_knn("vector", query_vector)
1455 }
1456
1457 pub fn bm25(field: impl Into<String>, query: impl Into<String>) -> Self {
1459 RankBy::FullTextSearch {
1460 field: field.into(),
1461 method: "BM25".to_string(),
1462 query: query.into(),
1463 }
1464 }
1465
1466 pub fn asc(field: impl Into<String>) -> Self {
1468 RankBy::AttributeOrder {
1469 field: field.into(),
1470 direction: SortDirection::Asc,
1471 }
1472 }
1473
1474 pub fn desc(field: impl Into<String>) -> Self {
1476 RankBy::AttributeOrder {
1477 field: field.into(),
1478 direction: SortDirection::Desc,
1479 }
1480 }
1481
1482 pub fn sum(rankings: Vec<RankBy>) -> Self {
1484 RankBy::Sum(rankings)
1485 }
1486
1487 pub fn max(rankings: Vec<RankBy>) -> Self {
1489 RankBy::Max(rankings)
1490 }
1491
1492 pub fn product(weight: f32, ranking: RankBy) -> Self {
1494 RankBy::Product {
1495 weight,
1496 ranking: Box::new(ranking),
1497 }
1498 }
1499}
1500
1501#[derive(Debug, Clone, Serialize, Deserialize)]
1519pub struct UnifiedQueryRequest {
1520 pub rank_by: serde_json::Value,
1522 #[serde(default = "default_unified_top_k")]
1524 pub top_k: usize,
1525 #[serde(skip_serializing_if = "Option::is_none")]
1527 pub filter: Option<serde_json::Value>,
1528 #[serde(default = "default_true")]
1530 pub include_metadata: bool,
1531 #[serde(default)]
1533 pub include_vectors: bool,
1534 #[serde(default)]
1536 pub distance_metric: DistanceMetric,
1537}
1538
1539fn default_unified_top_k() -> usize {
1540 10
1541}
1542
1543impl UnifiedQueryRequest {
1544 pub fn vector_search(query_vector: Vec<f32>, top_k: usize) -> Self {
1546 Self {
1547 rank_by: serde_json::json!(["ANN", query_vector]),
1548 top_k,
1549 filter: None,
1550 include_metadata: true,
1551 include_vectors: false,
1552 distance_metric: DistanceMetric::default(),
1553 }
1554 }
1555
1556 pub fn vector_knn_search(query_vector: Vec<f32>, top_k: usize) -> Self {
1558 Self {
1559 rank_by: serde_json::json!(["kNN", query_vector]),
1560 top_k,
1561 filter: None,
1562 include_metadata: true,
1563 include_vectors: false,
1564 distance_metric: DistanceMetric::default(),
1565 }
1566 }
1567
1568 pub fn fulltext_search(
1570 field: impl Into<String>,
1571 query: impl Into<String>,
1572 top_k: usize,
1573 ) -> Self {
1574 Self {
1575 rank_by: serde_json::json!([field.into(), "BM25", query.into()]),
1576 top_k,
1577 filter: None,
1578 include_metadata: true,
1579 include_vectors: false,
1580 distance_metric: DistanceMetric::default(),
1581 }
1582 }
1583
1584 pub fn attribute_order(
1586 field: impl Into<String>,
1587 direction: SortDirection,
1588 top_k: usize,
1589 ) -> Self {
1590 let dir = match direction {
1591 SortDirection::Asc => "asc",
1592 SortDirection::Desc => "desc",
1593 };
1594 Self {
1595 rank_by: serde_json::json!([field.into(), dir]),
1596 top_k,
1597 filter: None,
1598 include_metadata: true,
1599 include_vectors: false,
1600 distance_metric: DistanceMetric::default(),
1601 }
1602 }
1603
1604 pub fn with_rank_by(rank_by: serde_json::Value, top_k: usize) -> Self {
1606 Self {
1607 rank_by,
1608 top_k,
1609 filter: None,
1610 include_metadata: true,
1611 include_vectors: false,
1612 distance_metric: DistanceMetric::default(),
1613 }
1614 }
1615
1616 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1618 self.filter = Some(filter);
1619 self
1620 }
1621
1622 pub fn include_metadata(mut self, include: bool) -> Self {
1624 self.include_metadata = include;
1625 self
1626 }
1627
1628 pub fn include_vectors(mut self, include: bool) -> Self {
1630 self.include_vectors = include;
1631 self
1632 }
1633
1634 pub fn with_distance_metric(mut self, metric: DistanceMetric) -> Self {
1636 self.distance_metric = metric;
1637 self
1638 }
1639
1640 pub fn with_top_k(mut self, top_k: usize) -> Self {
1642 self.top_k = top_k;
1643 self
1644 }
1645}
1646
1647#[derive(Debug, Clone, Serialize, Deserialize)]
1649pub struct UnifiedSearchResult {
1650 pub id: String,
1652 #[serde(rename = "$dist", skip_serializing_if = "Option::is_none")]
1655 pub dist: Option<f32>,
1656 #[serde(skip_serializing_if = "Option::is_none")]
1658 pub metadata: Option<serde_json::Value>,
1659 #[serde(skip_serializing_if = "Option::is_none")]
1661 pub vector: Option<Vec<f32>>,
1662}
1663
1664#[derive(Debug, Clone, Serialize, Deserialize)]
1666pub struct UnifiedQueryResponse {
1667 pub results: Vec<UnifiedSearchResult>,
1669 #[serde(skip_serializing_if = "Option::is_none")]
1671 pub next_cursor: Option<String>,
1672}
1673
1674fn default_explain_top_k() -> usize {
1679 10
1680}
1681
1682#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1684#[serde(rename_all = "snake_case")]
1685#[derive(Default)]
1686pub enum ExplainQueryType {
1687 #[default]
1689 VectorSearch,
1690 FullTextSearch,
1692 HybridSearch,
1694 MultiVector,
1696 BatchQuery,
1698}
1699
1700#[derive(Debug, Clone, Serialize, Deserialize)]
1702pub struct QueryExplainRequest {
1703 #[serde(default)]
1705 pub query_type: ExplainQueryType,
1706 #[serde(skip_serializing_if = "Option::is_none")]
1708 pub vector: Option<Vec<f32>>,
1709 #[serde(default = "default_explain_top_k")]
1711 pub top_k: usize,
1712 #[serde(skip_serializing_if = "Option::is_none")]
1714 pub filter: Option<serde_json::Value>,
1715 #[serde(skip_serializing_if = "Option::is_none")]
1717 pub text_query: Option<String>,
1718 #[serde(default = "default_distance_metric")]
1720 pub distance_metric: String,
1721 #[serde(default)]
1723 pub execute: bool,
1724 #[serde(default)]
1726 pub verbose: bool,
1727}
1728
1729fn default_distance_metric() -> String {
1730 "cosine".to_string()
1731}
1732
1733impl QueryExplainRequest {
1734 pub fn vector_search(vector: Vec<f32>, top_k: usize) -> Self {
1736 Self {
1737 query_type: ExplainQueryType::VectorSearch,
1738 vector: Some(vector),
1739 top_k,
1740 filter: None,
1741 text_query: None,
1742 distance_metric: "cosine".to_string(),
1743 execute: false,
1744 verbose: false,
1745 }
1746 }
1747
1748 pub fn fulltext_search(text_query: impl Into<String>, top_k: usize) -> Self {
1750 Self {
1751 query_type: ExplainQueryType::FullTextSearch,
1752 vector: None,
1753 top_k,
1754 filter: None,
1755 text_query: Some(text_query.into()),
1756 distance_metric: "bm25".to_string(),
1757 execute: false,
1758 verbose: false,
1759 }
1760 }
1761
1762 pub fn hybrid_search(vector: Vec<f32>, text_query: impl Into<String>, top_k: usize) -> Self {
1764 Self {
1765 query_type: ExplainQueryType::HybridSearch,
1766 vector: Some(vector),
1767 top_k,
1768 filter: None,
1769 text_query: Some(text_query.into()),
1770 distance_metric: "hybrid".to_string(),
1771 execute: false,
1772 verbose: false,
1773 }
1774 }
1775
1776 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1778 self.filter = Some(filter);
1779 self
1780 }
1781
1782 pub fn with_distance_metric(mut self, metric: impl Into<String>) -> Self {
1784 self.distance_metric = metric.into();
1785 self
1786 }
1787
1788 pub fn with_execution(mut self) -> Self {
1790 self.execute = true;
1791 self
1792 }
1793
1794 pub fn with_verbose(mut self) -> Self {
1796 self.verbose = true;
1797 self
1798 }
1799}
1800
1801#[derive(Debug, Clone, Serialize, Deserialize)]
1803pub struct ExecutionStage {
1804 pub name: String,
1806 pub description: String,
1808 pub order: u32,
1810 pub estimated_input: u64,
1812 pub estimated_output: u64,
1814 pub estimated_cost: f64,
1816 #[serde(default)]
1818 pub details: HashMap<String, serde_json::Value>,
1819}
1820
1821#[derive(Debug, Clone, Serialize, Deserialize)]
1823pub struct CostEstimate {
1824 pub total_cost: f64,
1826 pub estimated_time_ms: u64,
1828 pub estimated_memory_bytes: u64,
1830 pub estimated_io_ops: u64,
1832 #[serde(default)]
1834 pub cost_breakdown: HashMap<String, f64>,
1835 pub confidence: f64,
1837}
1838
1839#[derive(Debug, Clone, Serialize, Deserialize)]
1841pub struct ActualStats {
1842 pub execution_time_ms: u64,
1844 pub results_returned: usize,
1846 pub vectors_scanned: u64,
1848 pub vectors_after_filter: u64,
1850 pub index_lookups: u64,
1852 pub cache_hits: u64,
1854 pub cache_misses: u64,
1856 pub memory_used_bytes: u64,
1858}
1859
1860#[derive(Debug, Clone, Serialize, Deserialize)]
1862pub struct Recommendation {
1863 pub recommendation_type: String,
1865 pub priority: String,
1867 pub description: String,
1869 pub expected_improvement: String,
1871 pub implementation: String,
1873}
1874
1875#[derive(Debug, Clone, Serialize, Deserialize)]
1877pub struct IndexSelection {
1878 pub index_type: String,
1880 pub selection_reason: String,
1882 #[serde(default)]
1884 pub alternatives_considered: Vec<IndexAlternative>,
1885 #[serde(default)]
1887 pub index_config: HashMap<String, serde_json::Value>,
1888 pub index_stats: IndexStatistics,
1890}
1891
1892#[derive(Debug, Clone, Serialize, Deserialize)]
1894pub struct IndexAlternative {
1895 pub index_type: String,
1897 pub rejection_reason: String,
1899 pub estimated_cost: f64,
1901}
1902
1903#[derive(Debug, Clone, Serialize, Deserialize)]
1905pub struct IndexStatistics {
1906 pub vector_count: u64,
1908 pub dimension: usize,
1910 pub memory_bytes: u64,
1912 #[serde(skip_serializing_if = "Option::is_none")]
1914 pub build_time_ms: Option<u64>,
1915 #[serde(skip_serializing_if = "Option::is_none")]
1917 pub last_updated: Option<u64>,
1918}
1919
1920#[derive(Debug, Clone, Serialize, Deserialize)]
1922pub struct QueryParams {
1923 pub top_k: usize,
1925 pub has_filter: bool,
1927 pub filter_complexity: String,
1929 #[serde(skip_serializing_if = "Option::is_none")]
1931 pub vector_dimension: Option<usize>,
1932 pub distance_metric: String,
1934 #[serde(skip_serializing_if = "Option::is_none")]
1936 pub text_query_length: Option<usize>,
1937}
1938
1939#[derive(Debug, Clone, Serialize, Deserialize)]
1941pub struct QueryExplainResponse {
1942 pub query_type: ExplainQueryType,
1944 pub namespace: String,
1946 pub index_selection: IndexSelection,
1948 pub stages: Vec<ExecutionStage>,
1950 pub cost_estimate: CostEstimate,
1952 #[serde(skip_serializing_if = "Option::is_none")]
1954 pub actual_stats: Option<ActualStats>,
1955 #[serde(default)]
1957 pub recommendations: Vec<Recommendation>,
1958 pub summary: String,
1960 pub query_params: QueryParams,
1962}
1963
1964#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1970#[serde(rename_all = "kebab-case")]
1971pub enum EmbeddingModel {
1972 #[default]
1974 Minilm,
1975 BgeSmall,
1977 E5Small,
1979}
1980
1981#[derive(Debug, Clone, Serialize, Deserialize)]
1983pub struct TextDocument {
1984 pub id: String,
1986 pub text: String,
1988 #[serde(skip_serializing_if = "Option::is_none")]
1990 pub metadata: Option<HashMap<String, serde_json::Value>>,
1991 #[serde(skip_serializing_if = "Option::is_none")]
1993 pub ttl_seconds: Option<u64>,
1994}
1995
1996impl TextDocument {
1997 pub fn new(id: impl Into<String>, text: impl Into<String>) -> Self {
1999 Self {
2000 id: id.into(),
2001 text: text.into(),
2002 metadata: None,
2003 ttl_seconds: None,
2004 }
2005 }
2006
2007 pub fn with_metadata(mut self, metadata: HashMap<String, serde_json::Value>) -> Self {
2009 self.metadata = Some(metadata);
2010 self
2011 }
2012
2013 pub fn with_ttl(mut self, ttl_seconds: u64) -> Self {
2015 self.ttl_seconds = Some(ttl_seconds);
2016 self
2017 }
2018}
2019
2020#[derive(Debug, Clone, Serialize, Deserialize)]
2022pub struct UpsertTextRequest {
2023 pub documents: Vec<TextDocument>,
2025 #[serde(skip_serializing_if = "Option::is_none")]
2027 pub model: Option<EmbeddingModel>,
2028}
2029
2030impl UpsertTextRequest {
2031 pub fn new(documents: Vec<TextDocument>) -> Self {
2033 Self {
2034 documents,
2035 model: None,
2036 }
2037 }
2038
2039 pub fn with_model(mut self, model: EmbeddingModel) -> Self {
2041 self.model = Some(model);
2042 self
2043 }
2044}
2045
2046#[derive(Debug, Clone, Serialize, Deserialize)]
2048pub struct TextUpsertResponse {
2049 pub upserted_count: u64,
2051 pub tokens_processed: u64,
2053 pub model: String,
2055 pub embedding_time_ms: u64,
2057}
2058
2059#[derive(Debug, Clone, Serialize, Deserialize)]
2061pub struct TextSearchResult {
2062 pub id: String,
2064 pub score: f32,
2066 #[serde(skip_serializing_if = "Option::is_none")]
2068 pub text: Option<String>,
2069 #[serde(skip_serializing_if = "Option::is_none")]
2071 pub metadata: Option<HashMap<String, serde_json::Value>>,
2072 #[serde(skip_serializing_if = "Option::is_none")]
2074 pub vector: Option<Vec<f32>>,
2075}
2076
2077#[derive(Debug, Clone, Serialize, Deserialize)]
2079pub struct QueryTextRequest {
2080 pub text: String,
2082 pub top_k: u32,
2084 #[serde(skip_serializing_if = "Option::is_none")]
2086 pub filter: Option<serde_json::Value>,
2087 pub include_text: bool,
2089 pub include_vectors: bool,
2091 #[serde(skip_serializing_if = "Option::is_none")]
2093 pub model: Option<EmbeddingModel>,
2094}
2095
2096impl QueryTextRequest {
2097 pub fn new(text: impl Into<String>, top_k: u32) -> Self {
2099 Self {
2100 text: text.into(),
2101 top_k,
2102 filter: None,
2103 include_text: true,
2104 include_vectors: false,
2105 model: None,
2106 }
2107 }
2108
2109 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
2111 self.filter = Some(filter);
2112 self
2113 }
2114
2115 pub fn include_text(mut self, include: bool) -> Self {
2117 self.include_text = include;
2118 self
2119 }
2120
2121 pub fn include_vectors(mut self, include: bool) -> Self {
2123 self.include_vectors = include;
2124 self
2125 }
2126
2127 pub fn with_model(mut self, model: EmbeddingModel) -> Self {
2129 self.model = Some(model);
2130 self
2131 }
2132}
2133
2134#[derive(Debug, Clone, Serialize, Deserialize)]
2136pub struct TextQueryResponse {
2137 pub results: Vec<TextSearchResult>,
2139 pub model: String,
2141 pub embedding_time_ms: u64,
2143 pub search_time_ms: u64,
2145}
2146
2147#[derive(Debug, Clone, Serialize, Deserialize)]
2149pub struct BatchQueryTextRequest {
2150 pub queries: Vec<String>,
2152 pub top_k: u32,
2154 #[serde(skip_serializing_if = "Option::is_none")]
2156 pub filter: Option<serde_json::Value>,
2157 pub include_vectors: bool,
2159 #[serde(skip_serializing_if = "Option::is_none")]
2161 pub model: Option<EmbeddingModel>,
2162}
2163
2164impl BatchQueryTextRequest {
2165 pub fn new(queries: Vec<String>, top_k: u32) -> Self {
2167 Self {
2168 queries,
2169 top_k,
2170 filter: None,
2171 include_vectors: false,
2172 model: None,
2173 }
2174 }
2175}
2176
2177#[derive(Debug, Clone, Serialize, Deserialize)]
2179pub struct BatchQueryTextResponse {
2180 pub results: Vec<Vec<TextSearchResult>>,
2182 pub model: String,
2184 pub embedding_time_ms: u64,
2186 pub search_time_ms: u64,
2188}
2189
2190#[derive(Debug, Clone, Serialize, Deserialize)]
2196pub struct FetchRequest {
2197 pub ids: Vec<String>,
2199 pub include_values: bool,
2201 pub include_metadata: bool,
2203}
2204
2205impl FetchRequest {
2206 pub fn new(ids: Vec<String>) -> Self {
2208 Self {
2209 ids,
2210 include_values: true,
2211 include_metadata: true,
2212 }
2213 }
2214}
2215
2216#[derive(Debug, Clone, Serialize, Deserialize)]
2218pub struct FetchResponse {
2219 pub vectors: Vec<Vector>,
2221}
2222
2223#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2229pub struct CreateNamespaceRequest {
2230 #[serde(skip_serializing_if = "Option::is_none")]
2232 pub dimensions: Option<u32>,
2233 #[serde(skip_serializing_if = "Option::is_none")]
2235 pub index_type: Option<String>,
2236 #[serde(skip_serializing_if = "Option::is_none")]
2238 pub metadata: Option<HashMap<String, serde_json::Value>>,
2239}
2240
2241impl CreateNamespaceRequest {
2242 pub fn new() -> Self {
2244 Self::default()
2245 }
2246
2247 pub fn with_dimensions(mut self, dimensions: u32) -> Self {
2249 self.dimensions = Some(dimensions);
2250 self
2251 }
2252
2253 pub fn with_index_type(mut self, index_type: impl Into<String>) -> Self {
2255 self.index_type = Some(index_type.into());
2256 self
2257 }
2258}