1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Debug, Clone)]
12pub struct RetryConfig {
13 pub max_retries: u32,
15 pub base_delay: std::time::Duration,
17 pub max_delay: std::time::Duration,
19 pub jitter: bool,
21}
22
23impl Default for RetryConfig {
24 fn default() -> Self {
25 Self {
26 max_retries: 3,
27 base_delay: std::time::Duration::from_millis(100),
28 max_delay: std::time::Duration::from_secs(60),
29 jitter: true,
30 }
31 }
32}
33
34#[derive(Debug, Clone, Default)]
43pub struct RateLimitHeaders {
44 pub limit: Option<u64>,
46 pub remaining: Option<u64>,
48 pub reset: Option<u64>,
50 pub quota_used: Option<u64>,
52 pub quota_limit: Option<u64>,
54}
55
56impl RateLimitHeaders {
57 pub fn from_response(response: &reqwest::Response) -> Self {
59 let headers = response.headers();
60 fn parse(h: &reqwest::header::HeaderMap, name: &str) -> Option<u64> {
61 h.get(name)
62 .and_then(|v| v.to_str().ok())
63 .and_then(|s| s.parse().ok())
64 }
65 Self {
66 limit: parse(headers, "X-RateLimit-Limit"),
67 remaining: parse(headers, "X-RateLimit-Remaining"),
68 reset: parse(headers, "X-RateLimit-Reset"),
69 quota_used: parse(headers, "X-Quota-Used"),
70 quota_limit: parse(headers, "X-Quota-Limit"),
71 }
72 }
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct HealthResponse {
82 pub healthy: bool,
84 pub version: Option<String>,
86 pub uptime_seconds: Option<u64>,
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize)]
92pub struct ReadinessResponse {
93 pub ready: bool,
95 pub components: Option<HashMap<String, bool>>,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
105pub struct NamespaceInfo {
106 #[serde(alias = "namespace")]
108 pub name: String,
109 pub vector_count: u64,
111 #[serde(alias = "dimension")]
113 pub dimensions: Option<u32>,
114 pub index_type: Option<String>,
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct ListNamespacesResponse {
121 pub namespaces: Vec<String>,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct Vector {
132 pub id: String,
134 pub values: Vec<f32>,
136 #[serde(skip_serializing_if = "Option::is_none")]
138 pub metadata: Option<HashMap<String, serde_json::Value>>,
139}
140
141impl Vector {
142 pub fn new(id: impl Into<String>, values: Vec<f32>) -> Self {
144 Self {
145 id: id.into(),
146 values,
147 metadata: None,
148 }
149 }
150
151 pub fn with_metadata(
153 id: impl Into<String>,
154 values: Vec<f32>,
155 metadata: HashMap<String, serde_json::Value>,
156 ) -> Self {
157 Self {
158 id: id.into(),
159 values,
160 metadata: Some(metadata),
161 }
162 }
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct UpsertRequest {
168 pub vectors: Vec<Vector>,
170}
171
172impl UpsertRequest {
173 pub fn single(vector: Vector) -> Self {
175 Self {
176 vectors: vec![vector],
177 }
178 }
179
180 pub fn batch(vectors: Vec<Vector>) -> Self {
182 Self { vectors }
183 }
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct UpsertResponse {
189 pub upserted_count: u64,
191}
192
193#[derive(Debug, Clone, Serialize, Deserialize)]
210pub struct ColumnUpsertRequest {
211 pub ids: Vec<String>,
213 pub vectors: Vec<Vec<f32>>,
215 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
218 pub attributes: HashMap<String, Vec<serde_json::Value>>,
219 #[serde(skip_serializing_if = "Option::is_none")]
221 pub ttl_seconds: Option<u64>,
222 #[serde(skip_serializing_if = "Option::is_none")]
224 pub dimension: Option<usize>,
225}
226
227impl ColumnUpsertRequest {
228 pub fn new(ids: Vec<String>, vectors: Vec<Vec<f32>>) -> Self {
230 Self {
231 ids,
232 vectors,
233 attributes: HashMap::new(),
234 ttl_seconds: None,
235 dimension: None,
236 }
237 }
238
239 pub fn with_attribute(
241 mut self,
242 name: impl Into<String>,
243 values: Vec<serde_json::Value>,
244 ) -> Self {
245 self.attributes.insert(name.into(), values);
246 self
247 }
248
249 pub fn with_ttl(mut self, seconds: u64) -> Self {
251 self.ttl_seconds = Some(seconds);
252 self
253 }
254
255 pub fn with_dimension(mut self, dim: usize) -> Self {
257 self.dimension = Some(dim);
258 self
259 }
260
261 pub fn len(&self) -> usize {
263 self.ids.len()
264 }
265
266 pub fn is_empty(&self) -> bool {
268 self.ids.is_empty()
269 }
270}
271
272#[derive(Debug, Clone, Serialize, Deserialize)]
274pub struct DeleteRequest {
275 pub ids: Vec<String>,
277}
278
279impl DeleteRequest {
280 pub fn single(id: impl Into<String>) -> Self {
282 Self {
283 ids: vec![id.into()],
284 }
285 }
286
287 pub fn batch(ids: Vec<String>) -> Self {
289 Self { ids }
290 }
291}
292
293#[derive(Debug, Clone, Serialize, Deserialize)]
295pub struct DeleteResponse {
296 pub deleted_count: u64,
298}
299
300#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
306#[serde(rename_all = "snake_case")]
307pub enum ReadConsistency {
308 Strong,
310 #[default]
312 Eventual,
313 #[serde(rename = "bounded_staleness")]
315 BoundedStaleness,
316}
317
318#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
320pub struct StalenessConfig {
321 #[serde(default = "default_max_staleness_ms")]
323 pub max_staleness_ms: u64,
324}
325
326fn default_max_staleness_ms() -> u64 {
327 5000 }
329
330impl StalenessConfig {
331 pub fn new(max_staleness_ms: u64) -> Self {
333 Self { max_staleness_ms }
334 }
335}
336
337#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
339#[serde(rename_all = "snake_case")]
340pub enum DistanceMetric {
341 #[default]
343 Cosine,
344 Euclidean,
346 DotProduct,
348}
349
350#[derive(Debug, Clone, Serialize, Deserialize)]
352pub struct QueryRequest {
353 pub vector: Vec<f32>,
355 pub top_k: u32,
357 #[serde(default)]
359 pub distance_metric: DistanceMetric,
360 #[serde(skip_serializing_if = "Option::is_none")]
362 pub filter: Option<serde_json::Value>,
363 #[serde(default = "default_true")]
365 pub include_metadata: bool,
366 #[serde(default)]
368 pub include_vectors: bool,
369 #[serde(default)]
371 pub consistency: ReadConsistency,
372 #[serde(skip_serializing_if = "Option::is_none")]
374 pub staleness_config: Option<StalenessConfig>,
375}
376
377fn default_true() -> bool {
378 true
379}
380
381impl QueryRequest {
382 pub fn new(vector: Vec<f32>, top_k: u32) -> Self {
384 Self {
385 vector,
386 top_k,
387 distance_metric: DistanceMetric::default(),
388 filter: None,
389 include_metadata: true,
390 include_vectors: false,
391 consistency: ReadConsistency::default(),
392 staleness_config: None,
393 }
394 }
395
396 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
398 self.filter = Some(filter);
399 self
400 }
401
402 pub fn include_metadata(mut self, include: bool) -> Self {
404 self.include_metadata = include;
405 self
406 }
407
408 pub fn include_vectors(mut self, include: bool) -> Self {
410 self.include_vectors = include;
411 self
412 }
413
414 pub fn with_distance_metric(mut self, metric: DistanceMetric) -> Self {
416 self.distance_metric = metric;
417 self
418 }
419
420 pub fn with_consistency(mut self, consistency: ReadConsistency) -> Self {
422 self.consistency = consistency;
423 self
424 }
425
426 pub fn with_bounded_staleness(mut self, max_staleness_ms: u64) -> Self {
428 self.consistency = ReadConsistency::BoundedStaleness;
429 self.staleness_config = Some(StalenessConfig::new(max_staleness_ms));
430 self
431 }
432
433 pub fn with_strong_consistency(mut self) -> Self {
435 self.consistency = ReadConsistency::Strong;
436 self
437 }
438}
439
440#[derive(Debug, Clone, Serialize, Deserialize)]
442pub struct Match {
443 pub id: String,
445 pub score: f32,
447 #[serde(skip_serializing_if = "Option::is_none")]
449 pub metadata: Option<HashMap<String, serde_json::Value>>,
450}
451
452#[derive(Debug, Clone, Serialize, Deserialize)]
454pub struct QueryResponse {
455 pub matches: Vec<Match>,
457}
458
459#[derive(Debug, Clone, Serialize, Deserialize)]
465pub struct Document {
466 pub id: String,
468 pub text: String,
470 #[serde(skip_serializing_if = "Option::is_none")]
472 pub metadata: Option<HashMap<String, serde_json::Value>>,
473}
474
475impl Document {
476 pub fn new(id: impl Into<String>, text: impl Into<String>) -> Self {
478 Self {
479 id: id.into(),
480 text: text.into(),
481 metadata: None,
482 }
483 }
484
485 pub fn with_metadata(
487 id: impl Into<String>,
488 text: impl Into<String>,
489 metadata: HashMap<String, serde_json::Value>,
490 ) -> Self {
491 Self {
492 id: id.into(),
493 text: text.into(),
494 metadata: Some(metadata),
495 }
496 }
497}
498
499#[derive(Debug, Clone, Serialize, Deserialize)]
501pub struct IndexDocumentsRequest {
502 pub documents: Vec<Document>,
504}
505
506#[derive(Debug, Clone, Serialize, Deserialize)]
508pub struct IndexDocumentsResponse {
509 pub indexed_count: u64,
511}
512
513#[derive(Debug, Clone, Serialize, Deserialize)]
515pub struct FullTextSearchRequest {
516 pub query: String,
518 pub top_k: u32,
520 #[serde(skip_serializing_if = "Option::is_none")]
522 pub filter: Option<serde_json::Value>,
523}
524
525impl FullTextSearchRequest {
526 pub fn new(query: impl Into<String>, top_k: u32) -> Self {
528 Self {
529 query: query.into(),
530 top_k,
531 filter: None,
532 }
533 }
534
535 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
537 self.filter = Some(filter);
538 self
539 }
540}
541
542#[derive(Debug, Clone, Serialize, Deserialize)]
544pub struct FullTextMatch {
545 pub id: String,
547 pub score: f32,
549 #[serde(skip_serializing_if = "Option::is_none")]
551 pub text: Option<String>,
552 #[serde(skip_serializing_if = "Option::is_none")]
554 pub metadata: Option<HashMap<String, serde_json::Value>>,
555}
556
557#[derive(Debug, Clone, Serialize, Deserialize)]
559pub struct FullTextSearchResponse {
560 pub matches: Vec<FullTextMatch>,
562}
563
564#[derive(Debug, Clone, Serialize, Deserialize)]
566pub struct FullTextStats {
567 pub document_count: u64,
569 pub term_count: u64,
571}
572
573#[derive(Debug, Clone, Serialize, Deserialize)]
579pub struct HybridSearchRequest {
580 pub vector: Vec<f32>,
582 pub text: String,
584 pub top_k: u32,
586 #[serde(default = "default_vector_weight")]
588 pub vector_weight: f32,
589 #[serde(skip_serializing_if = "Option::is_none")]
591 pub filter: Option<serde_json::Value>,
592}
593
594fn default_vector_weight() -> f32 {
595 0.5
596}
597
598impl HybridSearchRequest {
599 pub fn new(vector: Vec<f32>, text: impl Into<String>, top_k: u32) -> Self {
601 Self {
602 vector,
603 text: text.into(),
604 top_k,
605 vector_weight: 0.5,
606 filter: None,
607 }
608 }
609
610 pub fn with_vector_weight(mut self, weight: f32) -> Self {
612 self.vector_weight = weight.clamp(0.0, 1.0);
613 self
614 }
615
616 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
618 self.filter = Some(filter);
619 self
620 }
621}
622
623#[derive(Debug, Clone, Serialize, Deserialize)]
625pub struct HybridSearchResponse {
626 pub matches: Vec<Match>,
628}
629
630#[derive(Debug, Clone, Serialize, Deserialize)]
636pub struct SystemDiagnostics {
637 pub system: SystemInfo,
639 pub resources: ResourceUsage,
641 pub components: ComponentHealth,
643 pub active_jobs: u64,
645}
646
647#[derive(Debug, Clone, Serialize, Deserialize)]
649pub struct SystemInfo {
650 pub version: String,
652 pub rust_version: String,
654 pub uptime_seconds: u64,
656 pub pid: u32,
658}
659
660#[derive(Debug, Clone, Serialize, Deserialize)]
662pub struct ResourceUsage {
663 pub memory_bytes: u64,
665 pub thread_count: u64,
667 pub open_fds: u64,
669 pub cpu_percent: Option<f64>,
671}
672
673#[derive(Debug, Clone, Serialize, Deserialize)]
675pub struct ComponentHealth {
676 pub storage: HealthStatus,
678 pub search_engine: HealthStatus,
680 pub cache: HealthStatus,
682 pub grpc: HealthStatus,
684}
685
686#[derive(Debug, Clone, Serialize, Deserialize)]
688pub struct HealthStatus {
689 pub healthy: bool,
691 pub message: String,
693 pub last_check: u64,
695}
696
697#[derive(Debug, Clone, Serialize, Deserialize)]
699pub struct JobInfo {
700 pub id: String,
702 pub job_type: String,
704 pub status: String,
706 pub created_at: u64,
708 pub started_at: Option<u64>,
710 pub completed_at: Option<u64>,
712 pub progress: u8,
714 pub message: Option<String>,
716}
717
718#[derive(Debug, Clone, Serialize, Deserialize)]
720pub struct CompactionRequest {
721 #[serde(skip_serializing_if = "Option::is_none")]
723 pub namespace: Option<String>,
724 #[serde(default)]
726 pub force: bool,
727}
728
729#[derive(Debug, Clone, Serialize, Deserialize)]
731pub struct CompactionResponse {
732 pub job_id: String,
734 pub message: String,
736}
737
738#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
744#[serde(rename_all = "snake_case")]
745pub enum WarmingPriority {
746 Critical,
748 High,
750 #[default]
752 Normal,
753 Low,
755 Background,
757}
758
759#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
761#[serde(rename_all = "snake_case")]
762pub enum WarmingTargetTier {
763 L1,
765 #[default]
767 L2,
768 Both,
770}
771
772#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
774#[serde(rename_all = "snake_case")]
775pub enum AccessPatternHint {
776 #[default]
778 Random,
779 Sequential,
781 Temporal,
783 Spatial,
785}
786
787#[derive(Debug, Clone, Serialize, Deserialize)]
789pub struct WarmCacheRequest {
790 pub namespace: String,
792 #[serde(skip_serializing_if = "Option::is_none")]
794 pub vector_ids: Option<Vec<String>>,
795 #[serde(default)]
797 pub priority: WarmingPriority,
798 #[serde(default)]
800 pub target_tier: WarmingTargetTier,
801 #[serde(default)]
803 pub background: bool,
804 #[serde(skip_serializing_if = "Option::is_none")]
806 pub ttl_hint_seconds: Option<u64>,
807 #[serde(default)]
809 pub access_pattern: AccessPatternHint,
810 #[serde(skip_serializing_if = "Option::is_none")]
812 pub max_vectors: Option<usize>,
813}
814
815impl WarmCacheRequest {
816 pub fn new(namespace: impl Into<String>) -> Self {
818 Self {
819 namespace: namespace.into(),
820 vector_ids: None,
821 priority: WarmingPriority::default(),
822 target_tier: WarmingTargetTier::default(),
823 background: false,
824 ttl_hint_seconds: None,
825 access_pattern: AccessPatternHint::default(),
826 max_vectors: None,
827 }
828 }
829
830 pub fn with_vector_ids(mut self, ids: Vec<String>) -> Self {
832 self.vector_ids = Some(ids);
833 self
834 }
835
836 pub fn with_priority(mut self, priority: WarmingPriority) -> Self {
838 self.priority = priority;
839 self
840 }
841
842 pub fn with_target_tier(mut self, tier: WarmingTargetTier) -> Self {
844 self.target_tier = tier;
845 self
846 }
847
848 pub fn in_background(mut self) -> Self {
850 self.background = true;
851 self
852 }
853
854 pub fn with_ttl(mut self, seconds: u64) -> Self {
856 self.ttl_hint_seconds = Some(seconds);
857 self
858 }
859
860 pub fn with_access_pattern(mut self, pattern: AccessPatternHint) -> Self {
862 self.access_pattern = pattern;
863 self
864 }
865
866 pub fn with_max_vectors(mut self, max: usize) -> Self {
868 self.max_vectors = Some(max);
869 self
870 }
871}
872
873#[derive(Debug, Clone, Serialize, Deserialize)]
875pub struct WarmCacheResponse {
876 pub success: bool,
878 pub entries_warmed: u64,
880 pub entries_skipped: u64,
882 #[serde(skip_serializing_if = "Option::is_none")]
884 pub job_id: Option<String>,
885 pub message: String,
887 #[serde(skip_serializing_if = "Option::is_none")]
889 pub estimated_completion: Option<String>,
890 pub target_tier: WarmingTargetTier,
892 pub priority: WarmingPriority,
894 #[serde(skip_serializing_if = "Option::is_none")]
896 pub bytes_warmed: Option<u64>,
897}
898
899#[derive(Debug, Clone, Serialize, Deserialize)]
905pub struct ExportRequest {
906 #[serde(default = "default_export_top_k")]
908 pub top_k: usize,
909 #[serde(skip_serializing_if = "Option::is_none")]
911 pub cursor: Option<String>,
912 #[serde(default = "default_true")]
914 pub include_vectors: bool,
915 #[serde(default = "default_true")]
917 pub include_metadata: bool,
918}
919
920fn default_export_top_k() -> usize {
921 1000
922}
923
924impl Default for ExportRequest {
925 fn default() -> Self {
926 Self {
927 top_k: 1000,
928 cursor: None,
929 include_vectors: true,
930 include_metadata: true,
931 }
932 }
933}
934
935impl ExportRequest {
936 pub fn new() -> Self {
938 Self::default()
939 }
940
941 pub fn with_top_k(mut self, top_k: usize) -> Self {
943 self.top_k = top_k;
944 self
945 }
946
947 pub fn with_cursor(mut self, cursor: impl Into<String>) -> Self {
949 self.cursor = Some(cursor.into());
950 self
951 }
952
953 pub fn include_vectors(mut self, include: bool) -> Self {
955 self.include_vectors = include;
956 self
957 }
958
959 pub fn include_metadata(mut self, include: bool) -> Self {
961 self.include_metadata = include;
962 self
963 }
964}
965
966#[derive(Debug, Clone, Serialize, Deserialize)]
968pub struct ExportedVector {
969 pub id: String,
971 #[serde(skip_serializing_if = "Option::is_none")]
973 pub values: Option<Vec<f32>>,
974 #[serde(skip_serializing_if = "Option::is_none")]
976 pub metadata: Option<serde_json::Value>,
977 #[serde(skip_serializing_if = "Option::is_none")]
979 pub ttl_seconds: Option<u64>,
980}
981
982#[derive(Debug, Clone, Serialize, Deserialize)]
984pub struct ExportResponse {
985 pub vectors: Vec<ExportedVector>,
987 #[serde(skip_serializing_if = "Option::is_none")]
989 pub next_cursor: Option<String>,
990 pub total_count: usize,
992 pub returned_count: usize,
994}
995
996#[derive(Debug, Clone, Serialize, Deserialize)]
1002pub struct BatchQueryItem {
1003 #[serde(skip_serializing_if = "Option::is_none")]
1005 pub id: Option<String>,
1006 pub vector: Vec<f32>,
1008 #[serde(default = "default_batch_top_k")]
1010 pub top_k: u32,
1011 #[serde(skip_serializing_if = "Option::is_none")]
1013 pub filter: Option<serde_json::Value>,
1014 #[serde(default)]
1016 pub include_metadata: bool,
1017 #[serde(default)]
1019 pub consistency: ReadConsistency,
1020 #[serde(skip_serializing_if = "Option::is_none")]
1022 pub staleness_config: Option<StalenessConfig>,
1023}
1024
1025fn default_batch_top_k() -> u32 {
1026 10
1027}
1028
1029impl BatchQueryItem {
1030 pub fn new(vector: Vec<f32>, top_k: u32) -> Self {
1032 Self {
1033 id: None,
1034 vector,
1035 top_k,
1036 filter: None,
1037 include_metadata: true,
1038 consistency: ReadConsistency::default(),
1039 staleness_config: None,
1040 }
1041 }
1042
1043 pub fn with_id(mut self, id: impl Into<String>) -> Self {
1045 self.id = Some(id.into());
1046 self
1047 }
1048
1049 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1051 self.filter = Some(filter);
1052 self
1053 }
1054
1055 pub fn include_metadata(mut self, include: bool) -> Self {
1057 self.include_metadata = include;
1058 self
1059 }
1060
1061 pub fn with_consistency(mut self, consistency: ReadConsistency) -> Self {
1063 self.consistency = consistency;
1064 self
1065 }
1066
1067 pub fn with_bounded_staleness(mut self, max_staleness_ms: u64) -> Self {
1069 self.consistency = ReadConsistency::BoundedStaleness;
1070 self.staleness_config = Some(StalenessConfig::new(max_staleness_ms));
1071 self
1072 }
1073}
1074
1075#[derive(Debug, Clone, Serialize, Deserialize)]
1077pub struct BatchQueryRequest {
1078 pub queries: Vec<BatchQueryItem>,
1080}
1081
1082impl BatchQueryRequest {
1083 pub fn new(queries: Vec<BatchQueryItem>) -> Self {
1085 Self { queries }
1086 }
1087
1088 pub fn single(query: BatchQueryItem) -> Self {
1090 Self {
1091 queries: vec![query],
1092 }
1093 }
1094}
1095
1096#[derive(Debug, Clone, Serialize, Deserialize)]
1098pub struct BatchQueryResult {
1099 #[serde(skip_serializing_if = "Option::is_none")]
1101 pub id: Option<String>,
1102 pub results: Vec<Match>,
1104 pub latency_ms: f64,
1106 #[serde(skip_serializing_if = "Option::is_none")]
1108 pub error: Option<String>,
1109}
1110
1111#[derive(Debug, Clone, Serialize, Deserialize)]
1113pub struct BatchQueryResponse {
1114 pub results: Vec<BatchQueryResult>,
1116 pub total_latency_ms: f64,
1118 pub query_count: usize,
1120}
1121
1122#[derive(Debug, Clone, Serialize, Deserialize)]
1128pub struct MultiVectorSearchRequest {
1129 pub positive_vectors: Vec<Vec<f32>>,
1131 #[serde(skip_serializing_if = "Option::is_none")]
1133 pub positive_weights: Option<Vec<f32>>,
1134 #[serde(skip_serializing_if = "Option::is_none")]
1136 pub negative_vectors: Option<Vec<Vec<f32>>>,
1137 #[serde(skip_serializing_if = "Option::is_none")]
1139 pub negative_weights: Option<Vec<f32>>,
1140 #[serde(default = "default_multi_vector_top_k")]
1142 pub top_k: u32,
1143 #[serde(default)]
1145 pub distance_metric: DistanceMetric,
1146 #[serde(skip_serializing_if = "Option::is_none")]
1148 pub score_threshold: Option<f32>,
1149 #[serde(default)]
1151 pub enable_mmr: bool,
1152 #[serde(default = "default_mmr_lambda")]
1154 pub mmr_lambda: f32,
1155 #[serde(default = "default_true")]
1157 pub include_metadata: bool,
1158 #[serde(default)]
1160 pub include_vectors: bool,
1161 #[serde(skip_serializing_if = "Option::is_none")]
1163 pub filter: Option<serde_json::Value>,
1164 #[serde(default)]
1166 pub consistency: ReadConsistency,
1167 #[serde(skip_serializing_if = "Option::is_none")]
1169 pub staleness_config: Option<StalenessConfig>,
1170}
1171
1172fn default_multi_vector_top_k() -> u32 {
1173 10
1174}
1175
1176fn default_mmr_lambda() -> f32 {
1177 0.5
1178}
1179
1180impl MultiVectorSearchRequest {
1181 pub fn new(positive_vectors: Vec<Vec<f32>>) -> Self {
1183 Self {
1184 positive_vectors,
1185 positive_weights: None,
1186 negative_vectors: None,
1187 negative_weights: None,
1188 top_k: 10,
1189 distance_metric: DistanceMetric::default(),
1190 score_threshold: None,
1191 enable_mmr: false,
1192 mmr_lambda: 0.5,
1193 include_metadata: true,
1194 include_vectors: false,
1195 filter: None,
1196 consistency: ReadConsistency::default(),
1197 staleness_config: None,
1198 }
1199 }
1200
1201 pub fn with_top_k(mut self, top_k: u32) -> Self {
1203 self.top_k = top_k;
1204 self
1205 }
1206
1207 pub fn with_positive_weights(mut self, weights: Vec<f32>) -> Self {
1209 self.positive_weights = Some(weights);
1210 self
1211 }
1212
1213 pub fn with_negative_vectors(mut self, vectors: Vec<Vec<f32>>) -> Self {
1215 self.negative_vectors = Some(vectors);
1216 self
1217 }
1218
1219 pub fn with_negative_weights(mut self, weights: Vec<f32>) -> Self {
1221 self.negative_weights = Some(weights);
1222 self
1223 }
1224
1225 pub fn with_distance_metric(mut self, metric: DistanceMetric) -> Self {
1227 self.distance_metric = metric;
1228 self
1229 }
1230
1231 pub fn with_score_threshold(mut self, threshold: f32) -> Self {
1233 self.score_threshold = Some(threshold);
1234 self
1235 }
1236
1237 pub fn with_mmr(mut self, lambda: f32) -> Self {
1239 self.enable_mmr = true;
1240 self.mmr_lambda = lambda.clamp(0.0, 1.0);
1241 self
1242 }
1243
1244 pub fn include_metadata(mut self, include: bool) -> Self {
1246 self.include_metadata = include;
1247 self
1248 }
1249
1250 pub fn include_vectors(mut self, include: bool) -> Self {
1252 self.include_vectors = include;
1253 self
1254 }
1255
1256 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1258 self.filter = Some(filter);
1259 self
1260 }
1261
1262 pub fn with_consistency(mut self, consistency: ReadConsistency) -> Self {
1264 self.consistency = consistency;
1265 self
1266 }
1267}
1268
1269#[derive(Debug, Clone, Serialize, Deserialize)]
1271pub struct MultiVectorSearchResult {
1272 pub id: String,
1274 pub score: f32,
1276 #[serde(skip_serializing_if = "Option::is_none")]
1278 pub mmr_score: Option<f32>,
1279 #[serde(skip_serializing_if = "Option::is_none")]
1281 pub original_rank: Option<usize>,
1282 #[serde(skip_serializing_if = "Option::is_none")]
1284 pub metadata: Option<HashMap<String, serde_json::Value>>,
1285 #[serde(skip_serializing_if = "Option::is_none")]
1287 pub vector: Option<Vec<f32>>,
1288}
1289
1290#[derive(Debug, Clone, Serialize, Deserialize)]
1292pub struct MultiVectorSearchResponse {
1293 pub results: Vec<MultiVectorSearchResult>,
1295 #[serde(skip_serializing_if = "Option::is_none")]
1297 pub computed_query_vector: Option<Vec<f32>>,
1298}
1299
1300#[derive(Debug, Clone, Serialize, Deserialize)]
1306#[serde(untagged)]
1307pub enum AggregateFunction {
1308 Count,
1310 Sum { field: String },
1312 Avg { field: String },
1314 Min { field: String },
1316 Max { field: String },
1318}
1319
1320#[derive(Debug, Clone, Serialize, Deserialize)]
1322pub struct AggregationRequest {
1323 pub aggregate_by: HashMap<String, serde_json::Value>,
1326 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1329 pub group_by: Vec<String>,
1330 #[serde(skip_serializing_if = "Option::is_none")]
1332 pub filter: Option<serde_json::Value>,
1333 #[serde(default = "default_agg_limit")]
1335 pub limit: usize,
1336}
1337
1338fn default_agg_limit() -> usize {
1339 100
1340}
1341
1342impl AggregationRequest {
1343 pub fn new() -> Self {
1345 Self {
1346 aggregate_by: HashMap::new(),
1347 group_by: Vec::new(),
1348 filter: None,
1349 limit: 100,
1350 }
1351 }
1352
1353 pub fn with_count(mut self, name: impl Into<String>) -> Self {
1355 self.aggregate_by
1356 .insert(name.into(), serde_json::json!(["Count"]));
1357 self
1358 }
1359
1360 pub fn with_sum(mut self, name: impl Into<String>, field: impl Into<String>) -> Self {
1362 self.aggregate_by
1363 .insert(name.into(), serde_json::json!(["Sum", field.into()]));
1364 self
1365 }
1366
1367 pub fn with_avg(mut self, name: impl Into<String>, field: impl Into<String>) -> Self {
1369 self.aggregate_by
1370 .insert(name.into(), serde_json::json!(["Avg", field.into()]));
1371 self
1372 }
1373
1374 pub fn with_min(mut self, name: impl Into<String>, field: impl Into<String>) -> Self {
1376 self.aggregate_by
1377 .insert(name.into(), serde_json::json!(["Min", field.into()]));
1378 self
1379 }
1380
1381 pub fn with_max(mut self, name: impl Into<String>, field: impl Into<String>) -> Self {
1383 self.aggregate_by
1384 .insert(name.into(), serde_json::json!(["Max", field.into()]));
1385 self
1386 }
1387
1388 pub fn group_by(mut self, fields: Vec<String>) -> Self {
1390 self.group_by = fields;
1391 self
1392 }
1393
1394 pub fn with_group_by(mut self, field: impl Into<String>) -> Self {
1396 self.group_by.push(field.into());
1397 self
1398 }
1399
1400 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1402 self.filter = Some(filter);
1403 self
1404 }
1405
1406 pub fn with_limit(mut self, limit: usize) -> Self {
1408 self.limit = limit;
1409 self
1410 }
1411}
1412
1413impl Default for AggregationRequest {
1414 fn default() -> Self {
1415 Self::new()
1416 }
1417}
1418
1419#[derive(Debug, Clone, Serialize, Deserialize)]
1421pub struct AggregationResponse {
1422 #[serde(skip_serializing_if = "Option::is_none")]
1424 pub aggregations: Option<HashMap<String, serde_json::Value>>,
1425 #[serde(skip_serializing_if = "Option::is_none")]
1427 pub aggregation_groups: Option<Vec<AggregationGroup>>,
1428}
1429
1430#[derive(Debug, Clone, Serialize, Deserialize)]
1432pub struct AggregationGroup {
1433 #[serde(flatten)]
1435 pub group_key: HashMap<String, serde_json::Value>,
1436 #[serde(flatten)]
1438 pub aggregations: HashMap<String, serde_json::Value>,
1439}
1440
1441#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
1447pub enum VectorSearchMethod {
1448 #[default]
1450 ANN,
1451 #[serde(rename = "kNN")]
1453 KNN,
1454}
1455
1456#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
1458#[serde(rename_all = "lowercase")]
1459pub enum SortDirection {
1460 Asc,
1462 #[default]
1464 Desc,
1465}
1466
1467#[derive(Debug, Clone, Serialize, Deserialize)]
1470#[serde(untagged)]
1471pub enum RankBy {
1472 VectorSearch {
1474 field: String,
1475 method: VectorSearchMethod,
1476 query_vector: Vec<f32>,
1477 },
1478 FullTextSearch {
1480 field: String,
1481 method: String, query: String,
1483 },
1484 AttributeOrder {
1486 field: String,
1487 direction: SortDirection,
1488 },
1489 Sum(Vec<RankBy>),
1491 Max(Vec<RankBy>),
1493 Product { weight: f32, ranking: Box<RankBy> },
1495}
1496
1497impl RankBy {
1498 pub fn vector_ann(field: impl Into<String>, query_vector: Vec<f32>) -> Self {
1500 RankBy::VectorSearch {
1501 field: field.into(),
1502 method: VectorSearchMethod::ANN,
1503 query_vector,
1504 }
1505 }
1506
1507 pub fn ann(query_vector: Vec<f32>) -> Self {
1509 Self::vector_ann("vector", query_vector)
1510 }
1511
1512 pub fn vector_knn(field: impl Into<String>, query_vector: Vec<f32>) -> Self {
1514 RankBy::VectorSearch {
1515 field: field.into(),
1516 method: VectorSearchMethod::KNN,
1517 query_vector,
1518 }
1519 }
1520
1521 pub fn knn(query_vector: Vec<f32>) -> Self {
1523 Self::vector_knn("vector", query_vector)
1524 }
1525
1526 pub fn bm25(field: impl Into<String>, query: impl Into<String>) -> Self {
1528 RankBy::FullTextSearch {
1529 field: field.into(),
1530 method: "BM25".to_string(),
1531 query: query.into(),
1532 }
1533 }
1534
1535 pub fn asc(field: impl Into<String>) -> Self {
1537 RankBy::AttributeOrder {
1538 field: field.into(),
1539 direction: SortDirection::Asc,
1540 }
1541 }
1542
1543 pub fn desc(field: impl Into<String>) -> Self {
1545 RankBy::AttributeOrder {
1546 field: field.into(),
1547 direction: SortDirection::Desc,
1548 }
1549 }
1550
1551 pub fn sum(rankings: Vec<RankBy>) -> Self {
1553 RankBy::Sum(rankings)
1554 }
1555
1556 pub fn max(rankings: Vec<RankBy>) -> Self {
1558 RankBy::Max(rankings)
1559 }
1560
1561 pub fn product(weight: f32, ranking: RankBy) -> Self {
1563 RankBy::Product {
1564 weight,
1565 ranking: Box::new(ranking),
1566 }
1567 }
1568}
1569
1570#[derive(Debug, Clone, Serialize, Deserialize)]
1588pub struct UnifiedQueryRequest {
1589 pub rank_by: serde_json::Value,
1591 #[serde(default = "default_unified_top_k")]
1593 pub top_k: usize,
1594 #[serde(skip_serializing_if = "Option::is_none")]
1596 pub filter: Option<serde_json::Value>,
1597 #[serde(default = "default_true")]
1599 pub include_metadata: bool,
1600 #[serde(default)]
1602 pub include_vectors: bool,
1603 #[serde(default)]
1605 pub distance_metric: DistanceMetric,
1606}
1607
1608fn default_unified_top_k() -> usize {
1609 10
1610}
1611
1612impl UnifiedQueryRequest {
1613 pub fn vector_search(query_vector: Vec<f32>, top_k: usize) -> Self {
1615 Self {
1616 rank_by: serde_json::json!(["ANN", query_vector]),
1617 top_k,
1618 filter: None,
1619 include_metadata: true,
1620 include_vectors: false,
1621 distance_metric: DistanceMetric::default(),
1622 }
1623 }
1624
1625 pub fn vector_knn_search(query_vector: Vec<f32>, top_k: usize) -> Self {
1627 Self {
1628 rank_by: serde_json::json!(["kNN", query_vector]),
1629 top_k,
1630 filter: None,
1631 include_metadata: true,
1632 include_vectors: false,
1633 distance_metric: DistanceMetric::default(),
1634 }
1635 }
1636
1637 pub fn fulltext_search(
1639 field: impl Into<String>,
1640 query: impl Into<String>,
1641 top_k: usize,
1642 ) -> Self {
1643 Self {
1644 rank_by: serde_json::json!([field.into(), "BM25", query.into()]),
1645 top_k,
1646 filter: None,
1647 include_metadata: true,
1648 include_vectors: false,
1649 distance_metric: DistanceMetric::default(),
1650 }
1651 }
1652
1653 pub fn attribute_order(
1655 field: impl Into<String>,
1656 direction: SortDirection,
1657 top_k: usize,
1658 ) -> Self {
1659 let dir = match direction {
1660 SortDirection::Asc => "asc",
1661 SortDirection::Desc => "desc",
1662 };
1663 Self {
1664 rank_by: serde_json::json!([field.into(), dir]),
1665 top_k,
1666 filter: None,
1667 include_metadata: true,
1668 include_vectors: false,
1669 distance_metric: DistanceMetric::default(),
1670 }
1671 }
1672
1673 pub fn with_rank_by(rank_by: serde_json::Value, top_k: usize) -> Self {
1675 Self {
1676 rank_by,
1677 top_k,
1678 filter: None,
1679 include_metadata: true,
1680 include_vectors: false,
1681 distance_metric: DistanceMetric::default(),
1682 }
1683 }
1684
1685 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1687 self.filter = Some(filter);
1688 self
1689 }
1690
1691 pub fn include_metadata(mut self, include: bool) -> Self {
1693 self.include_metadata = include;
1694 self
1695 }
1696
1697 pub fn include_vectors(mut self, include: bool) -> Self {
1699 self.include_vectors = include;
1700 self
1701 }
1702
1703 pub fn with_distance_metric(mut self, metric: DistanceMetric) -> Self {
1705 self.distance_metric = metric;
1706 self
1707 }
1708
1709 pub fn with_top_k(mut self, top_k: usize) -> Self {
1711 self.top_k = top_k;
1712 self
1713 }
1714}
1715
1716#[derive(Debug, Clone, Serialize, Deserialize)]
1718pub struct UnifiedSearchResult {
1719 pub id: String,
1721 #[serde(rename = "$dist", skip_serializing_if = "Option::is_none")]
1724 pub dist: Option<f32>,
1725 #[serde(skip_serializing_if = "Option::is_none")]
1727 pub metadata: Option<serde_json::Value>,
1728 #[serde(skip_serializing_if = "Option::is_none")]
1730 pub vector: Option<Vec<f32>>,
1731}
1732
1733#[derive(Debug, Clone, Serialize, Deserialize)]
1735pub struct UnifiedQueryResponse {
1736 pub results: Vec<UnifiedSearchResult>,
1738 #[serde(skip_serializing_if = "Option::is_none")]
1740 pub next_cursor: Option<String>,
1741}
1742
1743fn default_explain_top_k() -> usize {
1748 10
1749}
1750
1751#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1753#[serde(rename_all = "snake_case")]
1754#[derive(Default)]
1755pub enum ExplainQueryType {
1756 #[default]
1758 VectorSearch,
1759 FullTextSearch,
1761 HybridSearch,
1763 MultiVector,
1765 BatchQuery,
1767}
1768
1769#[derive(Debug, Clone, Serialize, Deserialize)]
1771pub struct QueryExplainRequest {
1772 #[serde(default)]
1774 pub query_type: ExplainQueryType,
1775 #[serde(skip_serializing_if = "Option::is_none")]
1777 pub vector: Option<Vec<f32>>,
1778 #[serde(default = "default_explain_top_k")]
1780 pub top_k: usize,
1781 #[serde(skip_serializing_if = "Option::is_none")]
1783 pub filter: Option<serde_json::Value>,
1784 #[serde(skip_serializing_if = "Option::is_none")]
1786 pub text_query: Option<String>,
1787 #[serde(default = "default_distance_metric")]
1789 pub distance_metric: String,
1790 #[serde(default)]
1792 pub execute: bool,
1793 #[serde(default)]
1795 pub verbose: bool,
1796}
1797
1798fn default_distance_metric() -> String {
1799 "cosine".to_string()
1800}
1801
1802impl QueryExplainRequest {
1803 pub fn vector_search(vector: Vec<f32>, top_k: usize) -> Self {
1805 Self {
1806 query_type: ExplainQueryType::VectorSearch,
1807 vector: Some(vector),
1808 top_k,
1809 filter: None,
1810 text_query: None,
1811 distance_metric: "cosine".to_string(),
1812 execute: false,
1813 verbose: false,
1814 }
1815 }
1816
1817 pub fn fulltext_search(text_query: impl Into<String>, top_k: usize) -> Self {
1819 Self {
1820 query_type: ExplainQueryType::FullTextSearch,
1821 vector: None,
1822 top_k,
1823 filter: None,
1824 text_query: Some(text_query.into()),
1825 distance_metric: "bm25".to_string(),
1826 execute: false,
1827 verbose: false,
1828 }
1829 }
1830
1831 pub fn hybrid_search(vector: Vec<f32>, text_query: impl Into<String>, top_k: usize) -> Self {
1833 Self {
1834 query_type: ExplainQueryType::HybridSearch,
1835 vector: Some(vector),
1836 top_k,
1837 filter: None,
1838 text_query: Some(text_query.into()),
1839 distance_metric: "hybrid".to_string(),
1840 execute: false,
1841 verbose: false,
1842 }
1843 }
1844
1845 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1847 self.filter = Some(filter);
1848 self
1849 }
1850
1851 pub fn with_distance_metric(mut self, metric: impl Into<String>) -> Self {
1853 self.distance_metric = metric.into();
1854 self
1855 }
1856
1857 pub fn with_execution(mut self) -> Self {
1859 self.execute = true;
1860 self
1861 }
1862
1863 pub fn with_verbose(mut self) -> Self {
1865 self.verbose = true;
1866 self
1867 }
1868}
1869
1870#[derive(Debug, Clone, Serialize, Deserialize)]
1872pub struct ExecutionStage {
1873 pub name: String,
1875 pub description: String,
1877 pub order: u32,
1879 pub estimated_input: u64,
1881 pub estimated_output: u64,
1883 pub estimated_cost: f64,
1885 #[serde(default)]
1887 pub details: HashMap<String, serde_json::Value>,
1888}
1889
1890#[derive(Debug, Clone, Serialize, Deserialize)]
1892pub struct CostEstimate {
1893 pub total_cost: f64,
1895 pub estimated_time_ms: u64,
1897 pub estimated_memory_bytes: u64,
1899 pub estimated_io_ops: u64,
1901 #[serde(default)]
1903 pub cost_breakdown: HashMap<String, f64>,
1904 pub confidence: f64,
1906}
1907
1908#[derive(Debug, Clone, Serialize, Deserialize)]
1910pub struct ActualStats {
1911 pub execution_time_ms: u64,
1913 pub results_returned: usize,
1915 pub vectors_scanned: u64,
1917 pub vectors_after_filter: u64,
1919 pub index_lookups: u64,
1921 pub cache_hits: u64,
1923 pub cache_misses: u64,
1925 pub memory_used_bytes: u64,
1927}
1928
1929#[derive(Debug, Clone, Serialize, Deserialize)]
1931pub struct Recommendation {
1932 pub recommendation_type: String,
1934 pub priority: String,
1936 pub description: String,
1938 pub expected_improvement: String,
1940 pub implementation: String,
1942}
1943
1944#[derive(Debug, Clone, Serialize, Deserialize)]
1946pub struct IndexSelection {
1947 pub index_type: String,
1949 pub selection_reason: String,
1951 #[serde(default)]
1953 pub alternatives_considered: Vec<IndexAlternative>,
1954 #[serde(default)]
1956 pub index_config: HashMap<String, serde_json::Value>,
1957 pub index_stats: IndexStatistics,
1959}
1960
1961#[derive(Debug, Clone, Serialize, Deserialize)]
1963pub struct IndexAlternative {
1964 pub index_type: String,
1966 pub rejection_reason: String,
1968 pub estimated_cost: f64,
1970}
1971
1972#[derive(Debug, Clone, Serialize, Deserialize)]
1974pub struct IndexStatistics {
1975 pub vector_count: u64,
1977 pub dimension: usize,
1979 pub memory_bytes: u64,
1981 #[serde(skip_serializing_if = "Option::is_none")]
1983 pub build_time_ms: Option<u64>,
1984 #[serde(skip_serializing_if = "Option::is_none")]
1986 pub last_updated: Option<u64>,
1987}
1988
1989#[derive(Debug, Clone, Serialize, Deserialize)]
1991pub struct QueryParams {
1992 pub top_k: usize,
1994 pub has_filter: bool,
1996 pub filter_complexity: String,
1998 #[serde(skip_serializing_if = "Option::is_none")]
2000 pub vector_dimension: Option<usize>,
2001 pub distance_metric: String,
2003 #[serde(skip_serializing_if = "Option::is_none")]
2005 pub text_query_length: Option<usize>,
2006}
2007
2008#[derive(Debug, Clone, Serialize, Deserialize)]
2010pub struct QueryExplainResponse {
2011 pub query_type: ExplainQueryType,
2013 pub namespace: String,
2015 pub index_selection: IndexSelection,
2017 pub stages: Vec<ExecutionStage>,
2019 pub cost_estimate: CostEstimate,
2021 #[serde(skip_serializing_if = "Option::is_none")]
2023 pub actual_stats: Option<ActualStats>,
2024 #[serde(default)]
2026 pub recommendations: Vec<Recommendation>,
2027 pub summary: String,
2029 pub query_params: QueryParams,
2031}
2032
2033#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
2039#[serde(rename_all = "kebab-case")]
2040pub enum EmbeddingModel {
2041 #[default]
2043 Minilm,
2044 BgeSmall,
2046 E5Small,
2048}
2049
2050#[derive(Debug, Clone, Serialize, Deserialize)]
2052pub struct TextDocument {
2053 pub id: String,
2055 pub text: String,
2057 #[serde(skip_serializing_if = "Option::is_none")]
2059 pub metadata: Option<HashMap<String, serde_json::Value>>,
2060 #[serde(skip_serializing_if = "Option::is_none")]
2062 pub ttl_seconds: Option<u64>,
2063}
2064
2065impl TextDocument {
2066 pub fn new(id: impl Into<String>, text: impl Into<String>) -> Self {
2068 Self {
2069 id: id.into(),
2070 text: text.into(),
2071 metadata: None,
2072 ttl_seconds: None,
2073 }
2074 }
2075
2076 pub fn with_metadata(mut self, metadata: HashMap<String, serde_json::Value>) -> Self {
2078 self.metadata = Some(metadata);
2079 self
2080 }
2081
2082 pub fn with_ttl(mut self, ttl_seconds: u64) -> Self {
2084 self.ttl_seconds = Some(ttl_seconds);
2085 self
2086 }
2087}
2088
2089#[derive(Debug, Clone, Serialize, Deserialize)]
2091pub struct UpsertTextRequest {
2092 pub documents: Vec<TextDocument>,
2094 #[serde(skip_serializing_if = "Option::is_none")]
2096 pub model: Option<EmbeddingModel>,
2097}
2098
2099impl UpsertTextRequest {
2100 pub fn new(documents: Vec<TextDocument>) -> Self {
2102 Self {
2103 documents,
2104 model: None,
2105 }
2106 }
2107
2108 pub fn with_model(mut self, model: EmbeddingModel) -> Self {
2110 self.model = Some(model);
2111 self
2112 }
2113}
2114
2115#[derive(Debug, Clone, Serialize, Deserialize)]
2117pub struct TextUpsertResponse {
2118 pub upserted_count: u64,
2120 pub tokens_processed: u64,
2122 pub model: EmbeddingModel,
2124 pub embedding_time_ms: u64,
2126}
2127
2128#[derive(Debug, Clone, Serialize, Deserialize)]
2130pub struct TextSearchResult {
2131 pub id: String,
2133 pub score: f32,
2135 #[serde(skip_serializing_if = "Option::is_none")]
2137 pub text: Option<String>,
2138 #[serde(skip_serializing_if = "Option::is_none")]
2140 pub metadata: Option<HashMap<String, serde_json::Value>>,
2141 #[serde(skip_serializing_if = "Option::is_none")]
2143 pub vector: Option<Vec<f32>>,
2144}
2145
2146#[derive(Debug, Clone, Serialize, Deserialize)]
2148pub struct QueryTextRequest {
2149 pub text: String,
2151 pub top_k: u32,
2153 #[serde(skip_serializing_if = "Option::is_none")]
2155 pub filter: Option<serde_json::Value>,
2156 pub include_text: bool,
2158 pub include_vectors: bool,
2160 #[serde(skip_serializing_if = "Option::is_none")]
2162 pub model: Option<EmbeddingModel>,
2163}
2164
2165impl QueryTextRequest {
2166 pub fn new(text: impl Into<String>, top_k: u32) -> Self {
2168 Self {
2169 text: text.into(),
2170 top_k,
2171 filter: None,
2172 include_text: true,
2173 include_vectors: false,
2174 model: None,
2175 }
2176 }
2177
2178 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
2180 self.filter = Some(filter);
2181 self
2182 }
2183
2184 pub fn include_text(mut self, include: bool) -> Self {
2186 self.include_text = include;
2187 self
2188 }
2189
2190 pub fn include_vectors(mut self, include: bool) -> Self {
2192 self.include_vectors = include;
2193 self
2194 }
2195
2196 pub fn with_model(mut self, model: EmbeddingModel) -> Self {
2198 self.model = Some(model);
2199 self
2200 }
2201}
2202
2203#[derive(Debug, Clone, Serialize, Deserialize)]
2205pub struct TextQueryResponse {
2206 pub results: Vec<TextSearchResult>,
2208 pub model: EmbeddingModel,
2210 pub embedding_time_ms: u64,
2212 pub search_time_ms: u64,
2214}
2215
2216#[derive(Debug, Clone, Serialize, Deserialize)]
2218pub struct BatchQueryTextRequest {
2219 pub queries: Vec<String>,
2221 pub top_k: u32,
2223 #[serde(skip_serializing_if = "Option::is_none")]
2225 pub filter: Option<serde_json::Value>,
2226 pub include_vectors: bool,
2228 #[serde(skip_serializing_if = "Option::is_none")]
2230 pub model: Option<EmbeddingModel>,
2231}
2232
2233impl BatchQueryTextRequest {
2234 pub fn new(queries: Vec<String>, top_k: u32) -> Self {
2236 Self {
2237 queries,
2238 top_k,
2239 filter: None,
2240 include_vectors: false,
2241 model: None,
2242 }
2243 }
2244}
2245
2246#[derive(Debug, Clone, Serialize, Deserialize)]
2248pub struct BatchQueryTextResponse {
2249 pub results: Vec<Vec<TextSearchResult>>,
2251 pub model: EmbeddingModel,
2253 pub embedding_time_ms: u64,
2255 pub search_time_ms: u64,
2257}
2258
2259#[derive(Debug, Clone, Serialize, Deserialize)]
2265pub struct FetchRequest {
2266 pub ids: Vec<String>,
2268 pub include_values: bool,
2270 pub include_metadata: bool,
2272}
2273
2274impl FetchRequest {
2275 pub fn new(ids: Vec<String>) -> Self {
2277 Self {
2278 ids,
2279 include_values: true,
2280 include_metadata: true,
2281 }
2282 }
2283}
2284
2285#[derive(Debug, Clone, Serialize, Deserialize)]
2287pub struct FetchResponse {
2288 pub vectors: Vec<Vector>,
2290}
2291
2292#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2298pub struct CreateNamespaceRequest {
2299 #[serde(skip_serializing_if = "Option::is_none")]
2301 pub dimensions: Option<u32>,
2302 #[serde(skip_serializing_if = "Option::is_none")]
2304 pub index_type: Option<String>,
2305 #[serde(skip_serializing_if = "Option::is_none")]
2307 pub metadata: Option<HashMap<String, serde_json::Value>>,
2308}
2309
2310impl CreateNamespaceRequest {
2311 pub fn new() -> Self {
2313 Self::default()
2314 }
2315
2316 pub fn with_dimensions(mut self, dimensions: u32) -> Self {
2318 self.dimensions = Some(dimensions);
2319 self
2320 }
2321
2322 pub fn with_index_type(mut self, index_type: impl Into<String>) -> Self {
2324 self.index_type = Some(index_type.into());
2325 self
2326 }
2327}
2328
2329#[derive(Debug, Clone, Serialize, Deserialize)]
2334pub struct ConfigureNamespaceRequest {
2335 pub dimension: usize,
2337 #[serde(skip_serializing_if = "Option::is_none")]
2339 pub distance: Option<DistanceMetric>,
2340}
2341
2342impl ConfigureNamespaceRequest {
2343 pub fn new(dimension: usize) -> Self {
2345 Self {
2346 dimension,
2347 distance: None,
2348 }
2349 }
2350
2351 pub fn with_distance(mut self, distance: DistanceMetric) -> Self {
2353 self.distance = Some(distance);
2354 self
2355 }
2356}
2357
2358#[derive(Debug, Clone, Serialize, Deserialize)]
2360pub struct ConfigureNamespaceResponse {
2361 pub namespace: String,
2363 pub dimension: usize,
2365 pub distance: DistanceMetric,
2367 pub created: bool,
2369}