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)]
582pub struct HybridSearchRequest {
583 #[serde(skip_serializing_if = "Option::is_none")]
585 pub vector: Option<Vec<f32>>,
586 pub text: String,
588 pub top_k: u32,
590 #[serde(default = "default_vector_weight")]
592 pub vector_weight: f32,
593 #[serde(skip_serializing_if = "Option::is_none")]
595 pub filter: Option<serde_json::Value>,
596}
597
598fn default_vector_weight() -> f32 {
599 0.5
600}
601
602impl HybridSearchRequest {
603 pub fn new(vector: Vec<f32>, text: impl Into<String>, top_k: u32) -> Self {
605 Self {
606 vector: Some(vector),
607 text: text.into(),
608 top_k,
609 vector_weight: 0.5,
610 filter: None,
611 }
612 }
613
614 pub fn text_only(text: impl Into<String>, top_k: u32) -> Self {
616 Self {
617 vector: None,
618 text: text.into(),
619 top_k,
620 vector_weight: 0.5,
621 filter: None,
622 }
623 }
624
625 pub fn with_vector_weight(mut self, weight: f32) -> Self {
627 self.vector_weight = weight.clamp(0.0, 1.0);
628 self
629 }
630
631 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
633 self.filter = Some(filter);
634 self
635 }
636}
637
638#[derive(Debug, Clone, Serialize, Deserialize)]
640pub struct HybridSearchResponse {
641 pub matches: Vec<Match>,
643}
644
645#[derive(Debug, Clone, Serialize, Deserialize)]
651pub struct SystemDiagnostics {
652 pub system: SystemInfo,
654 pub resources: ResourceUsage,
656 pub components: ComponentHealth,
658 pub active_jobs: u64,
660}
661
662#[derive(Debug, Clone, Serialize, Deserialize)]
664pub struct SystemInfo {
665 pub version: String,
667 pub rust_version: String,
669 pub uptime_seconds: u64,
671 pub pid: u32,
673}
674
675#[derive(Debug, Clone, Serialize, Deserialize)]
677pub struct ResourceUsage {
678 pub memory_bytes: u64,
680 pub thread_count: u64,
682 pub open_fds: u64,
684 pub cpu_percent: Option<f64>,
686}
687
688#[derive(Debug, Clone, Serialize, Deserialize)]
690pub struct ComponentHealth {
691 pub storage: HealthStatus,
693 pub search_engine: HealthStatus,
695 pub cache: HealthStatus,
697 pub grpc: HealthStatus,
699}
700
701#[derive(Debug, Clone, Serialize, Deserialize)]
703pub struct HealthStatus {
704 pub healthy: bool,
706 pub message: String,
708 pub last_check: u64,
710}
711
712#[derive(Debug, Clone, Serialize, Deserialize)]
714pub struct JobInfo {
715 pub id: String,
717 pub job_type: String,
719 pub status: String,
721 pub created_at: u64,
723 pub started_at: Option<u64>,
725 pub completed_at: Option<u64>,
727 pub progress: u8,
729 pub message: Option<String>,
731}
732
733#[derive(Debug, Clone, Serialize, Deserialize)]
735pub struct CompactionRequest {
736 #[serde(skip_serializing_if = "Option::is_none")]
738 pub namespace: Option<String>,
739 #[serde(default)]
741 pub force: bool,
742}
743
744#[derive(Debug, Clone, Serialize, Deserialize)]
746pub struct CompactionResponse {
747 pub job_id: String,
749 pub message: String,
751}
752
753#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
759#[serde(rename_all = "snake_case")]
760pub enum WarmingPriority {
761 Critical,
763 High,
765 #[default]
767 Normal,
768 Low,
770 Background,
772}
773
774#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
776#[serde(rename_all = "snake_case")]
777pub enum WarmingTargetTier {
778 L1,
780 #[default]
782 L2,
783 Both,
785}
786
787#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
789#[serde(rename_all = "snake_case")]
790pub enum AccessPatternHint {
791 #[default]
793 Random,
794 Sequential,
796 Temporal,
798 Spatial,
800}
801
802#[derive(Debug, Clone, Serialize, Deserialize)]
804pub struct WarmCacheRequest {
805 pub namespace: String,
807 #[serde(skip_serializing_if = "Option::is_none")]
809 pub vector_ids: Option<Vec<String>>,
810 #[serde(default)]
812 pub priority: WarmingPriority,
813 #[serde(default)]
815 pub target_tier: WarmingTargetTier,
816 #[serde(default)]
818 pub background: bool,
819 #[serde(skip_serializing_if = "Option::is_none")]
821 pub ttl_hint_seconds: Option<u64>,
822 #[serde(default)]
824 pub access_pattern: AccessPatternHint,
825 #[serde(skip_serializing_if = "Option::is_none")]
827 pub max_vectors: Option<usize>,
828}
829
830impl WarmCacheRequest {
831 pub fn new(namespace: impl Into<String>) -> Self {
833 Self {
834 namespace: namespace.into(),
835 vector_ids: None,
836 priority: WarmingPriority::default(),
837 target_tier: WarmingTargetTier::default(),
838 background: false,
839 ttl_hint_seconds: None,
840 access_pattern: AccessPatternHint::default(),
841 max_vectors: None,
842 }
843 }
844
845 pub fn with_vector_ids(mut self, ids: Vec<String>) -> Self {
847 self.vector_ids = Some(ids);
848 self
849 }
850
851 pub fn with_priority(mut self, priority: WarmingPriority) -> Self {
853 self.priority = priority;
854 self
855 }
856
857 pub fn with_target_tier(mut self, tier: WarmingTargetTier) -> Self {
859 self.target_tier = tier;
860 self
861 }
862
863 pub fn in_background(mut self) -> Self {
865 self.background = true;
866 self
867 }
868
869 pub fn with_ttl(mut self, seconds: u64) -> Self {
871 self.ttl_hint_seconds = Some(seconds);
872 self
873 }
874
875 pub fn with_access_pattern(mut self, pattern: AccessPatternHint) -> Self {
877 self.access_pattern = pattern;
878 self
879 }
880
881 pub fn with_max_vectors(mut self, max: usize) -> Self {
883 self.max_vectors = Some(max);
884 self
885 }
886}
887
888#[derive(Debug, Clone, Serialize, Deserialize)]
890pub struct WarmCacheResponse {
891 pub success: bool,
893 pub entries_warmed: u64,
895 pub entries_skipped: u64,
897 #[serde(skip_serializing_if = "Option::is_none")]
899 pub job_id: Option<String>,
900 pub message: String,
902 #[serde(skip_serializing_if = "Option::is_none")]
904 pub estimated_completion: Option<String>,
905 pub target_tier: WarmingTargetTier,
907 pub priority: WarmingPriority,
909 #[serde(skip_serializing_if = "Option::is_none")]
911 pub bytes_warmed: Option<u64>,
912}
913
914#[derive(Debug, Clone, Serialize, Deserialize)]
920pub struct ExportRequest {
921 #[serde(default = "default_export_top_k")]
923 pub top_k: usize,
924 #[serde(skip_serializing_if = "Option::is_none")]
926 pub cursor: Option<String>,
927 #[serde(default = "default_true")]
929 pub include_vectors: bool,
930 #[serde(default = "default_true")]
932 pub include_metadata: bool,
933}
934
935fn default_export_top_k() -> usize {
936 1000
937}
938
939impl Default for ExportRequest {
940 fn default() -> Self {
941 Self {
942 top_k: 1000,
943 cursor: None,
944 include_vectors: true,
945 include_metadata: true,
946 }
947 }
948}
949
950impl ExportRequest {
951 pub fn new() -> Self {
953 Self::default()
954 }
955
956 pub fn with_top_k(mut self, top_k: usize) -> Self {
958 self.top_k = top_k;
959 self
960 }
961
962 pub fn with_cursor(mut self, cursor: impl Into<String>) -> Self {
964 self.cursor = Some(cursor.into());
965 self
966 }
967
968 pub fn include_vectors(mut self, include: bool) -> Self {
970 self.include_vectors = include;
971 self
972 }
973
974 pub fn include_metadata(mut self, include: bool) -> Self {
976 self.include_metadata = include;
977 self
978 }
979}
980
981#[derive(Debug, Clone, Serialize, Deserialize)]
983pub struct ExportedVector {
984 pub id: String,
986 #[serde(skip_serializing_if = "Option::is_none")]
988 pub values: Option<Vec<f32>>,
989 #[serde(skip_serializing_if = "Option::is_none")]
991 pub metadata: Option<serde_json::Value>,
992 #[serde(skip_serializing_if = "Option::is_none")]
994 pub ttl_seconds: Option<u64>,
995}
996
997#[derive(Debug, Clone, Serialize, Deserialize)]
999pub struct ExportResponse {
1000 pub vectors: Vec<ExportedVector>,
1002 #[serde(skip_serializing_if = "Option::is_none")]
1004 pub next_cursor: Option<String>,
1005 pub total_count: usize,
1007 pub returned_count: usize,
1009}
1010
1011#[derive(Debug, Clone, Serialize, Deserialize)]
1017pub struct BatchQueryItem {
1018 #[serde(skip_serializing_if = "Option::is_none")]
1020 pub id: Option<String>,
1021 pub vector: Vec<f32>,
1023 #[serde(default = "default_batch_top_k")]
1025 pub top_k: u32,
1026 #[serde(skip_serializing_if = "Option::is_none")]
1028 pub filter: Option<serde_json::Value>,
1029 #[serde(default)]
1031 pub include_metadata: bool,
1032 #[serde(default)]
1034 pub consistency: ReadConsistency,
1035 #[serde(skip_serializing_if = "Option::is_none")]
1037 pub staleness_config: Option<StalenessConfig>,
1038}
1039
1040fn default_batch_top_k() -> u32 {
1041 10
1042}
1043
1044impl BatchQueryItem {
1045 pub fn new(vector: Vec<f32>, top_k: u32) -> Self {
1047 Self {
1048 id: None,
1049 vector,
1050 top_k,
1051 filter: None,
1052 include_metadata: true,
1053 consistency: ReadConsistency::default(),
1054 staleness_config: None,
1055 }
1056 }
1057
1058 pub fn with_id(mut self, id: impl Into<String>) -> Self {
1060 self.id = Some(id.into());
1061 self
1062 }
1063
1064 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1066 self.filter = Some(filter);
1067 self
1068 }
1069
1070 pub fn include_metadata(mut self, include: bool) -> Self {
1072 self.include_metadata = include;
1073 self
1074 }
1075
1076 pub fn with_consistency(mut self, consistency: ReadConsistency) -> Self {
1078 self.consistency = consistency;
1079 self
1080 }
1081
1082 pub fn with_bounded_staleness(mut self, max_staleness_ms: u64) -> Self {
1084 self.consistency = ReadConsistency::BoundedStaleness;
1085 self.staleness_config = Some(StalenessConfig::new(max_staleness_ms));
1086 self
1087 }
1088}
1089
1090#[derive(Debug, Clone, Serialize, Deserialize)]
1092pub struct BatchQueryRequest {
1093 pub queries: Vec<BatchQueryItem>,
1095}
1096
1097impl BatchQueryRequest {
1098 pub fn new(queries: Vec<BatchQueryItem>) -> Self {
1100 Self { queries }
1101 }
1102
1103 pub fn single(query: BatchQueryItem) -> Self {
1105 Self {
1106 queries: vec![query],
1107 }
1108 }
1109}
1110
1111#[derive(Debug, Clone, Serialize, Deserialize)]
1113pub struct BatchQueryResult {
1114 #[serde(skip_serializing_if = "Option::is_none")]
1116 pub id: Option<String>,
1117 pub results: Vec<Match>,
1119 pub latency_ms: f64,
1121 #[serde(skip_serializing_if = "Option::is_none")]
1123 pub error: Option<String>,
1124}
1125
1126#[derive(Debug, Clone, Serialize, Deserialize)]
1128pub struct BatchQueryResponse {
1129 pub results: Vec<BatchQueryResult>,
1131 pub total_latency_ms: f64,
1133 pub query_count: usize,
1135}
1136
1137#[derive(Debug, Clone, Serialize, Deserialize)]
1143pub struct MultiVectorSearchRequest {
1144 pub positive_vectors: Vec<Vec<f32>>,
1146 #[serde(skip_serializing_if = "Option::is_none")]
1148 pub positive_weights: Option<Vec<f32>>,
1149 #[serde(skip_serializing_if = "Option::is_none")]
1151 pub negative_vectors: Option<Vec<Vec<f32>>>,
1152 #[serde(skip_serializing_if = "Option::is_none")]
1154 pub negative_weights: Option<Vec<f32>>,
1155 #[serde(default = "default_multi_vector_top_k")]
1157 pub top_k: u32,
1158 #[serde(default)]
1160 pub distance_metric: DistanceMetric,
1161 #[serde(skip_serializing_if = "Option::is_none")]
1163 pub score_threshold: Option<f32>,
1164 #[serde(default)]
1166 pub enable_mmr: bool,
1167 #[serde(default = "default_mmr_lambda")]
1169 pub mmr_lambda: f32,
1170 #[serde(default = "default_true")]
1172 pub include_metadata: bool,
1173 #[serde(default)]
1175 pub include_vectors: bool,
1176 #[serde(skip_serializing_if = "Option::is_none")]
1178 pub filter: Option<serde_json::Value>,
1179 #[serde(default)]
1181 pub consistency: ReadConsistency,
1182 #[serde(skip_serializing_if = "Option::is_none")]
1184 pub staleness_config: Option<StalenessConfig>,
1185}
1186
1187fn default_multi_vector_top_k() -> u32 {
1188 10
1189}
1190
1191fn default_mmr_lambda() -> f32 {
1192 0.5
1193}
1194
1195impl MultiVectorSearchRequest {
1196 pub fn new(positive_vectors: Vec<Vec<f32>>) -> Self {
1198 Self {
1199 positive_vectors,
1200 positive_weights: None,
1201 negative_vectors: None,
1202 negative_weights: None,
1203 top_k: 10,
1204 distance_metric: DistanceMetric::default(),
1205 score_threshold: None,
1206 enable_mmr: false,
1207 mmr_lambda: 0.5,
1208 include_metadata: true,
1209 include_vectors: false,
1210 filter: None,
1211 consistency: ReadConsistency::default(),
1212 staleness_config: None,
1213 }
1214 }
1215
1216 pub fn with_top_k(mut self, top_k: u32) -> Self {
1218 self.top_k = top_k;
1219 self
1220 }
1221
1222 pub fn with_positive_weights(mut self, weights: Vec<f32>) -> Self {
1224 self.positive_weights = Some(weights);
1225 self
1226 }
1227
1228 pub fn with_negative_vectors(mut self, vectors: Vec<Vec<f32>>) -> Self {
1230 self.negative_vectors = Some(vectors);
1231 self
1232 }
1233
1234 pub fn with_negative_weights(mut self, weights: Vec<f32>) -> Self {
1236 self.negative_weights = Some(weights);
1237 self
1238 }
1239
1240 pub fn with_distance_metric(mut self, metric: DistanceMetric) -> Self {
1242 self.distance_metric = metric;
1243 self
1244 }
1245
1246 pub fn with_score_threshold(mut self, threshold: f32) -> Self {
1248 self.score_threshold = Some(threshold);
1249 self
1250 }
1251
1252 pub fn with_mmr(mut self, lambda: f32) -> Self {
1254 self.enable_mmr = true;
1255 self.mmr_lambda = lambda.clamp(0.0, 1.0);
1256 self
1257 }
1258
1259 pub fn include_metadata(mut self, include: bool) -> Self {
1261 self.include_metadata = include;
1262 self
1263 }
1264
1265 pub fn include_vectors(mut self, include: bool) -> Self {
1267 self.include_vectors = include;
1268 self
1269 }
1270
1271 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1273 self.filter = Some(filter);
1274 self
1275 }
1276
1277 pub fn with_consistency(mut self, consistency: ReadConsistency) -> Self {
1279 self.consistency = consistency;
1280 self
1281 }
1282}
1283
1284#[derive(Debug, Clone, Serialize, Deserialize)]
1286pub struct MultiVectorSearchResult {
1287 pub id: String,
1289 pub score: f32,
1291 #[serde(skip_serializing_if = "Option::is_none")]
1293 pub mmr_score: Option<f32>,
1294 #[serde(skip_serializing_if = "Option::is_none")]
1296 pub original_rank: Option<usize>,
1297 #[serde(skip_serializing_if = "Option::is_none")]
1299 pub metadata: Option<HashMap<String, serde_json::Value>>,
1300 #[serde(skip_serializing_if = "Option::is_none")]
1302 pub vector: Option<Vec<f32>>,
1303}
1304
1305#[derive(Debug, Clone, Serialize, Deserialize)]
1307pub struct MultiVectorSearchResponse {
1308 pub results: Vec<MultiVectorSearchResult>,
1310 #[serde(skip_serializing_if = "Option::is_none")]
1312 pub computed_query_vector: Option<Vec<f32>>,
1313}
1314
1315#[derive(Debug, Clone, Serialize, Deserialize)]
1321#[serde(untagged)]
1322pub enum AggregateFunction {
1323 Count,
1325 Sum { field: String },
1327 Avg { field: String },
1329 Min { field: String },
1331 Max { field: String },
1333}
1334
1335#[derive(Debug, Clone, Serialize, Deserialize)]
1337pub struct AggregationRequest {
1338 pub aggregate_by: HashMap<String, serde_json::Value>,
1341 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1344 pub group_by: Vec<String>,
1345 #[serde(skip_serializing_if = "Option::is_none")]
1347 pub filter: Option<serde_json::Value>,
1348 #[serde(default = "default_agg_limit")]
1350 pub limit: usize,
1351}
1352
1353fn default_agg_limit() -> usize {
1354 100
1355}
1356
1357impl AggregationRequest {
1358 pub fn new() -> Self {
1360 Self {
1361 aggregate_by: HashMap::new(),
1362 group_by: Vec::new(),
1363 filter: None,
1364 limit: 100,
1365 }
1366 }
1367
1368 pub fn with_count(mut self, name: impl Into<String>) -> Self {
1370 self.aggregate_by
1371 .insert(name.into(), serde_json::json!(["Count"]));
1372 self
1373 }
1374
1375 pub fn with_sum(mut self, name: impl Into<String>, field: impl Into<String>) -> Self {
1377 self.aggregate_by
1378 .insert(name.into(), serde_json::json!(["Sum", field.into()]));
1379 self
1380 }
1381
1382 pub fn with_avg(mut self, name: impl Into<String>, field: impl Into<String>) -> Self {
1384 self.aggregate_by
1385 .insert(name.into(), serde_json::json!(["Avg", field.into()]));
1386 self
1387 }
1388
1389 pub fn with_min(mut self, name: impl Into<String>, field: impl Into<String>) -> Self {
1391 self.aggregate_by
1392 .insert(name.into(), serde_json::json!(["Min", field.into()]));
1393 self
1394 }
1395
1396 pub fn with_max(mut self, name: impl Into<String>, field: impl Into<String>) -> Self {
1398 self.aggregate_by
1399 .insert(name.into(), serde_json::json!(["Max", field.into()]));
1400 self
1401 }
1402
1403 pub fn group_by(mut self, fields: Vec<String>) -> Self {
1405 self.group_by = fields;
1406 self
1407 }
1408
1409 pub fn with_group_by(mut self, field: impl Into<String>) -> Self {
1411 self.group_by.push(field.into());
1412 self
1413 }
1414
1415 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1417 self.filter = Some(filter);
1418 self
1419 }
1420
1421 pub fn with_limit(mut self, limit: usize) -> Self {
1423 self.limit = limit;
1424 self
1425 }
1426}
1427
1428impl Default for AggregationRequest {
1429 fn default() -> Self {
1430 Self::new()
1431 }
1432}
1433
1434#[derive(Debug, Clone, Serialize, Deserialize)]
1436pub struct AggregationResponse {
1437 #[serde(skip_serializing_if = "Option::is_none")]
1439 pub aggregations: Option<HashMap<String, serde_json::Value>>,
1440 #[serde(skip_serializing_if = "Option::is_none")]
1442 pub aggregation_groups: Option<Vec<AggregationGroup>>,
1443}
1444
1445#[derive(Debug, Clone, Serialize, Deserialize)]
1447pub struct AggregationGroup {
1448 #[serde(flatten)]
1450 pub group_key: HashMap<String, serde_json::Value>,
1451 #[serde(flatten)]
1453 pub aggregations: HashMap<String, serde_json::Value>,
1454}
1455
1456#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
1462pub enum VectorSearchMethod {
1463 #[default]
1465 ANN,
1466 #[serde(rename = "kNN")]
1468 KNN,
1469}
1470
1471#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
1473#[serde(rename_all = "lowercase")]
1474pub enum SortDirection {
1475 Asc,
1477 #[default]
1479 Desc,
1480}
1481
1482#[derive(Debug, Clone, Serialize, Deserialize)]
1485#[serde(untagged)]
1486pub enum RankBy {
1487 VectorSearch {
1489 field: String,
1490 method: VectorSearchMethod,
1491 query_vector: Vec<f32>,
1492 },
1493 FullTextSearch {
1495 field: String,
1496 method: String, query: String,
1498 },
1499 AttributeOrder {
1501 field: String,
1502 direction: SortDirection,
1503 },
1504 Sum(Vec<RankBy>),
1506 Max(Vec<RankBy>),
1508 Product { weight: f32, ranking: Box<RankBy> },
1510}
1511
1512impl RankBy {
1513 pub fn vector_ann(field: impl Into<String>, query_vector: Vec<f32>) -> Self {
1515 RankBy::VectorSearch {
1516 field: field.into(),
1517 method: VectorSearchMethod::ANN,
1518 query_vector,
1519 }
1520 }
1521
1522 pub fn ann(query_vector: Vec<f32>) -> Self {
1524 Self::vector_ann("vector", query_vector)
1525 }
1526
1527 pub fn vector_knn(field: impl Into<String>, query_vector: Vec<f32>) -> Self {
1529 RankBy::VectorSearch {
1530 field: field.into(),
1531 method: VectorSearchMethod::KNN,
1532 query_vector,
1533 }
1534 }
1535
1536 pub fn knn(query_vector: Vec<f32>) -> Self {
1538 Self::vector_knn("vector", query_vector)
1539 }
1540
1541 pub fn bm25(field: impl Into<String>, query: impl Into<String>) -> Self {
1543 RankBy::FullTextSearch {
1544 field: field.into(),
1545 method: "BM25".to_string(),
1546 query: query.into(),
1547 }
1548 }
1549
1550 pub fn asc(field: impl Into<String>) -> Self {
1552 RankBy::AttributeOrder {
1553 field: field.into(),
1554 direction: SortDirection::Asc,
1555 }
1556 }
1557
1558 pub fn desc(field: impl Into<String>) -> Self {
1560 RankBy::AttributeOrder {
1561 field: field.into(),
1562 direction: SortDirection::Desc,
1563 }
1564 }
1565
1566 pub fn sum(rankings: Vec<RankBy>) -> Self {
1568 RankBy::Sum(rankings)
1569 }
1570
1571 pub fn max(rankings: Vec<RankBy>) -> Self {
1573 RankBy::Max(rankings)
1574 }
1575
1576 pub fn product(weight: f32, ranking: RankBy) -> Self {
1578 RankBy::Product {
1579 weight,
1580 ranking: Box::new(ranking),
1581 }
1582 }
1583}
1584
1585#[derive(Debug, Clone, Serialize, Deserialize)]
1603pub struct UnifiedQueryRequest {
1604 pub rank_by: serde_json::Value,
1606 #[serde(default = "default_unified_top_k")]
1608 pub top_k: usize,
1609 #[serde(skip_serializing_if = "Option::is_none")]
1611 pub filter: Option<serde_json::Value>,
1612 #[serde(default = "default_true")]
1614 pub include_metadata: bool,
1615 #[serde(default)]
1617 pub include_vectors: bool,
1618 #[serde(default)]
1620 pub distance_metric: DistanceMetric,
1621}
1622
1623fn default_unified_top_k() -> usize {
1624 10
1625}
1626
1627impl UnifiedQueryRequest {
1628 pub fn vector_search(query_vector: Vec<f32>, top_k: usize) -> Self {
1630 Self {
1631 rank_by: serde_json::json!(["ANN", query_vector]),
1632 top_k,
1633 filter: None,
1634 include_metadata: true,
1635 include_vectors: false,
1636 distance_metric: DistanceMetric::default(),
1637 }
1638 }
1639
1640 pub fn vector_knn_search(query_vector: Vec<f32>, top_k: usize) -> Self {
1642 Self {
1643 rank_by: serde_json::json!(["kNN", query_vector]),
1644 top_k,
1645 filter: None,
1646 include_metadata: true,
1647 include_vectors: false,
1648 distance_metric: DistanceMetric::default(),
1649 }
1650 }
1651
1652 pub fn fulltext_search(
1654 field: impl Into<String>,
1655 query: impl Into<String>,
1656 top_k: usize,
1657 ) -> Self {
1658 Self {
1659 rank_by: serde_json::json!([field.into(), "BM25", query.into()]),
1660 top_k,
1661 filter: None,
1662 include_metadata: true,
1663 include_vectors: false,
1664 distance_metric: DistanceMetric::default(),
1665 }
1666 }
1667
1668 pub fn attribute_order(
1670 field: impl Into<String>,
1671 direction: SortDirection,
1672 top_k: usize,
1673 ) -> Self {
1674 let dir = match direction {
1675 SortDirection::Asc => "asc",
1676 SortDirection::Desc => "desc",
1677 };
1678 Self {
1679 rank_by: serde_json::json!([field.into(), dir]),
1680 top_k,
1681 filter: None,
1682 include_metadata: true,
1683 include_vectors: false,
1684 distance_metric: DistanceMetric::default(),
1685 }
1686 }
1687
1688 pub fn with_rank_by(rank_by: serde_json::Value, top_k: usize) -> Self {
1690 Self {
1691 rank_by,
1692 top_k,
1693 filter: None,
1694 include_metadata: true,
1695 include_vectors: false,
1696 distance_metric: DistanceMetric::default(),
1697 }
1698 }
1699
1700 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1702 self.filter = Some(filter);
1703 self
1704 }
1705
1706 pub fn include_metadata(mut self, include: bool) -> Self {
1708 self.include_metadata = include;
1709 self
1710 }
1711
1712 pub fn include_vectors(mut self, include: bool) -> Self {
1714 self.include_vectors = include;
1715 self
1716 }
1717
1718 pub fn with_distance_metric(mut self, metric: DistanceMetric) -> Self {
1720 self.distance_metric = metric;
1721 self
1722 }
1723
1724 pub fn with_top_k(mut self, top_k: usize) -> Self {
1726 self.top_k = top_k;
1727 self
1728 }
1729}
1730
1731#[derive(Debug, Clone, Serialize, Deserialize)]
1733pub struct UnifiedSearchResult {
1734 pub id: String,
1736 #[serde(rename = "$dist", skip_serializing_if = "Option::is_none")]
1739 pub dist: Option<f32>,
1740 #[serde(skip_serializing_if = "Option::is_none")]
1742 pub metadata: Option<serde_json::Value>,
1743 #[serde(skip_serializing_if = "Option::is_none")]
1745 pub vector: Option<Vec<f32>>,
1746}
1747
1748#[derive(Debug, Clone, Serialize, Deserialize)]
1750pub struct UnifiedQueryResponse {
1751 pub results: Vec<UnifiedSearchResult>,
1753 #[serde(skip_serializing_if = "Option::is_none")]
1755 pub next_cursor: Option<String>,
1756}
1757
1758fn default_explain_top_k() -> usize {
1763 10
1764}
1765
1766#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1768#[serde(rename_all = "snake_case")]
1769#[derive(Default)]
1770pub enum ExplainQueryType {
1771 #[default]
1773 VectorSearch,
1774 FullTextSearch,
1776 HybridSearch,
1778 MultiVector,
1780 BatchQuery,
1782}
1783
1784#[derive(Debug, Clone, Serialize, Deserialize)]
1786pub struct QueryExplainRequest {
1787 #[serde(default)]
1789 pub query_type: ExplainQueryType,
1790 #[serde(skip_serializing_if = "Option::is_none")]
1792 pub vector: Option<Vec<f32>>,
1793 #[serde(default = "default_explain_top_k")]
1795 pub top_k: usize,
1796 #[serde(skip_serializing_if = "Option::is_none")]
1798 pub filter: Option<serde_json::Value>,
1799 #[serde(skip_serializing_if = "Option::is_none")]
1801 pub text_query: Option<String>,
1802 #[serde(default = "default_distance_metric")]
1804 pub distance_metric: String,
1805 #[serde(default)]
1807 pub execute: bool,
1808 #[serde(default)]
1810 pub verbose: bool,
1811}
1812
1813fn default_distance_metric() -> String {
1814 "cosine".to_string()
1815}
1816
1817impl QueryExplainRequest {
1818 pub fn vector_search(vector: Vec<f32>, top_k: usize) -> Self {
1820 Self {
1821 query_type: ExplainQueryType::VectorSearch,
1822 vector: Some(vector),
1823 top_k,
1824 filter: None,
1825 text_query: None,
1826 distance_metric: "cosine".to_string(),
1827 execute: false,
1828 verbose: false,
1829 }
1830 }
1831
1832 pub fn fulltext_search(text_query: impl Into<String>, top_k: usize) -> Self {
1834 Self {
1835 query_type: ExplainQueryType::FullTextSearch,
1836 vector: None,
1837 top_k,
1838 filter: None,
1839 text_query: Some(text_query.into()),
1840 distance_metric: "bm25".to_string(),
1841 execute: false,
1842 verbose: false,
1843 }
1844 }
1845
1846 pub fn hybrid_search(vector: Vec<f32>, text_query: impl Into<String>, top_k: usize) -> Self {
1848 Self {
1849 query_type: ExplainQueryType::HybridSearch,
1850 vector: Some(vector),
1851 top_k,
1852 filter: None,
1853 text_query: Some(text_query.into()),
1854 distance_metric: "hybrid".to_string(),
1855 execute: false,
1856 verbose: false,
1857 }
1858 }
1859
1860 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
1862 self.filter = Some(filter);
1863 self
1864 }
1865
1866 pub fn with_distance_metric(mut self, metric: impl Into<String>) -> Self {
1868 self.distance_metric = metric.into();
1869 self
1870 }
1871
1872 pub fn with_execution(mut self) -> Self {
1874 self.execute = true;
1875 self
1876 }
1877
1878 pub fn with_verbose(mut self) -> Self {
1880 self.verbose = true;
1881 self
1882 }
1883}
1884
1885#[derive(Debug, Clone, Serialize, Deserialize)]
1887pub struct ExecutionStage {
1888 pub name: String,
1890 pub description: String,
1892 pub order: u32,
1894 pub estimated_input: u64,
1896 pub estimated_output: u64,
1898 pub estimated_cost: f64,
1900 #[serde(default)]
1902 pub details: HashMap<String, serde_json::Value>,
1903}
1904
1905#[derive(Debug, Clone, Serialize, Deserialize)]
1907pub struct CostEstimate {
1908 pub total_cost: f64,
1910 pub estimated_time_ms: u64,
1912 pub estimated_memory_bytes: u64,
1914 pub estimated_io_ops: u64,
1916 #[serde(default)]
1918 pub cost_breakdown: HashMap<String, f64>,
1919 pub confidence: f64,
1921}
1922
1923#[derive(Debug, Clone, Serialize, Deserialize)]
1925pub struct ActualStats {
1926 pub execution_time_ms: u64,
1928 pub results_returned: usize,
1930 pub vectors_scanned: u64,
1932 pub vectors_after_filter: u64,
1934 pub index_lookups: u64,
1936 pub cache_hits: u64,
1938 pub cache_misses: u64,
1940 pub memory_used_bytes: u64,
1942}
1943
1944#[derive(Debug, Clone, Serialize, Deserialize)]
1946pub struct Recommendation {
1947 pub recommendation_type: String,
1949 pub priority: String,
1951 pub description: String,
1953 pub expected_improvement: String,
1955 pub implementation: String,
1957}
1958
1959#[derive(Debug, Clone, Serialize, Deserialize)]
1961pub struct IndexSelection {
1962 pub index_type: String,
1964 pub selection_reason: String,
1966 #[serde(default)]
1968 pub alternatives_considered: Vec<IndexAlternative>,
1969 #[serde(default)]
1971 pub index_config: HashMap<String, serde_json::Value>,
1972 pub index_stats: IndexStatistics,
1974}
1975
1976#[derive(Debug, Clone, Serialize, Deserialize)]
1978pub struct IndexAlternative {
1979 pub index_type: String,
1981 pub rejection_reason: String,
1983 pub estimated_cost: f64,
1985}
1986
1987#[derive(Debug, Clone, Serialize, Deserialize)]
1989pub struct IndexStatistics {
1990 pub vector_count: u64,
1992 pub dimension: usize,
1994 pub memory_bytes: u64,
1996 #[serde(skip_serializing_if = "Option::is_none")]
1998 pub build_time_ms: Option<u64>,
1999 #[serde(skip_serializing_if = "Option::is_none")]
2001 pub last_updated: Option<u64>,
2002}
2003
2004#[derive(Debug, Clone, Serialize, Deserialize)]
2006pub struct QueryParams {
2007 pub top_k: usize,
2009 pub has_filter: bool,
2011 pub filter_complexity: String,
2013 #[serde(skip_serializing_if = "Option::is_none")]
2015 pub vector_dimension: Option<usize>,
2016 pub distance_metric: String,
2018 #[serde(skip_serializing_if = "Option::is_none")]
2020 pub text_query_length: Option<usize>,
2021}
2022
2023#[derive(Debug, Clone, Serialize, Deserialize)]
2025pub struct QueryExplainResponse {
2026 pub query_type: ExplainQueryType,
2028 pub namespace: String,
2030 pub index_selection: IndexSelection,
2032 pub stages: Vec<ExecutionStage>,
2034 pub cost_estimate: CostEstimate,
2036 #[serde(skip_serializing_if = "Option::is_none")]
2038 pub actual_stats: Option<ActualStats>,
2039 #[serde(default)]
2041 pub recommendations: Vec<Recommendation>,
2042 pub summary: String,
2044 pub query_params: QueryParams,
2046}
2047
2048#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
2054#[serde(rename_all = "kebab-case")]
2055pub enum EmbeddingModel {
2056 #[default]
2058 Minilm,
2059 BgeSmall,
2061 E5Small,
2063}
2064
2065#[derive(Debug, Clone, Serialize, Deserialize)]
2067pub struct TextDocument {
2068 pub id: String,
2070 pub text: String,
2072 #[serde(skip_serializing_if = "Option::is_none")]
2074 pub metadata: Option<HashMap<String, serde_json::Value>>,
2075 #[serde(skip_serializing_if = "Option::is_none")]
2077 pub ttl_seconds: Option<u64>,
2078}
2079
2080impl TextDocument {
2081 pub fn new(id: impl Into<String>, text: impl Into<String>) -> Self {
2083 Self {
2084 id: id.into(),
2085 text: text.into(),
2086 metadata: None,
2087 ttl_seconds: None,
2088 }
2089 }
2090
2091 pub fn with_metadata(mut self, metadata: HashMap<String, serde_json::Value>) -> Self {
2093 self.metadata = Some(metadata);
2094 self
2095 }
2096
2097 pub fn with_ttl(mut self, ttl_seconds: u64) -> Self {
2099 self.ttl_seconds = Some(ttl_seconds);
2100 self
2101 }
2102}
2103
2104#[derive(Debug, Clone, Serialize, Deserialize)]
2106pub struct UpsertTextRequest {
2107 pub documents: Vec<TextDocument>,
2109 #[serde(skip_serializing_if = "Option::is_none")]
2111 pub model: Option<EmbeddingModel>,
2112}
2113
2114impl UpsertTextRequest {
2115 pub fn new(documents: Vec<TextDocument>) -> Self {
2117 Self {
2118 documents,
2119 model: None,
2120 }
2121 }
2122
2123 pub fn with_model(mut self, model: EmbeddingModel) -> Self {
2125 self.model = Some(model);
2126 self
2127 }
2128}
2129
2130#[derive(Debug, Clone, Serialize, Deserialize)]
2132pub struct TextUpsertResponse {
2133 pub upserted_count: u64,
2135 pub tokens_processed: u64,
2137 pub model: EmbeddingModel,
2139 pub embedding_time_ms: u64,
2141}
2142
2143#[derive(Debug, Clone, Serialize, Deserialize)]
2145pub struct TextSearchResult {
2146 pub id: String,
2148 pub score: f32,
2150 #[serde(skip_serializing_if = "Option::is_none")]
2152 pub text: Option<String>,
2153 #[serde(skip_serializing_if = "Option::is_none")]
2155 pub metadata: Option<HashMap<String, serde_json::Value>>,
2156 #[serde(skip_serializing_if = "Option::is_none")]
2158 pub vector: Option<Vec<f32>>,
2159}
2160
2161#[derive(Debug, Clone, Serialize, Deserialize)]
2163pub struct QueryTextRequest {
2164 pub text: String,
2166 pub top_k: u32,
2168 #[serde(skip_serializing_if = "Option::is_none")]
2170 pub filter: Option<serde_json::Value>,
2171 pub include_text: bool,
2173 pub include_vectors: bool,
2175 #[serde(skip_serializing_if = "Option::is_none")]
2177 pub model: Option<EmbeddingModel>,
2178}
2179
2180impl QueryTextRequest {
2181 pub fn new(text: impl Into<String>, top_k: u32) -> Self {
2183 Self {
2184 text: text.into(),
2185 top_k,
2186 filter: None,
2187 include_text: true,
2188 include_vectors: false,
2189 model: None,
2190 }
2191 }
2192
2193 pub fn with_filter(mut self, filter: serde_json::Value) -> Self {
2195 self.filter = Some(filter);
2196 self
2197 }
2198
2199 pub fn include_text(mut self, include: bool) -> Self {
2201 self.include_text = include;
2202 self
2203 }
2204
2205 pub fn include_vectors(mut self, include: bool) -> Self {
2207 self.include_vectors = include;
2208 self
2209 }
2210
2211 pub fn with_model(mut self, model: EmbeddingModel) -> Self {
2213 self.model = Some(model);
2214 self
2215 }
2216}
2217
2218#[derive(Debug, Clone, Serialize, Deserialize)]
2220pub struct TextQueryResponse {
2221 pub results: Vec<TextSearchResult>,
2223 pub model: EmbeddingModel,
2225 pub embedding_time_ms: u64,
2227 pub search_time_ms: u64,
2229}
2230
2231#[derive(Debug, Clone, Serialize, Deserialize)]
2233pub struct BatchQueryTextRequest {
2234 pub queries: Vec<String>,
2236 pub top_k: u32,
2238 #[serde(skip_serializing_if = "Option::is_none")]
2240 pub filter: Option<serde_json::Value>,
2241 pub include_vectors: bool,
2243 #[serde(skip_serializing_if = "Option::is_none")]
2245 pub model: Option<EmbeddingModel>,
2246}
2247
2248impl BatchQueryTextRequest {
2249 pub fn new(queries: Vec<String>, top_k: u32) -> Self {
2251 Self {
2252 queries,
2253 top_k,
2254 filter: None,
2255 include_vectors: false,
2256 model: None,
2257 }
2258 }
2259}
2260
2261#[derive(Debug, Clone, Serialize, Deserialize)]
2263pub struct BatchQueryTextResponse {
2264 pub results: Vec<Vec<TextSearchResult>>,
2266 pub model: EmbeddingModel,
2268 pub embedding_time_ms: u64,
2270 pub search_time_ms: u64,
2272}
2273
2274#[derive(Debug, Clone, Serialize, Deserialize)]
2280pub struct FetchRequest {
2281 pub ids: Vec<String>,
2283 pub include_values: bool,
2285 pub include_metadata: bool,
2287}
2288
2289impl FetchRequest {
2290 pub fn new(ids: Vec<String>) -> Self {
2292 Self {
2293 ids,
2294 include_values: true,
2295 include_metadata: true,
2296 }
2297 }
2298}
2299
2300#[derive(Debug, Clone, Serialize, Deserialize)]
2302pub struct FetchResponse {
2303 pub vectors: Vec<Vector>,
2305}
2306
2307#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2313pub struct CreateNamespaceRequest {
2314 #[serde(skip_serializing_if = "Option::is_none")]
2316 pub dimensions: Option<u32>,
2317 #[serde(skip_serializing_if = "Option::is_none")]
2319 pub index_type: Option<String>,
2320 #[serde(skip_serializing_if = "Option::is_none")]
2322 pub metadata: Option<HashMap<String, serde_json::Value>>,
2323}
2324
2325impl CreateNamespaceRequest {
2326 pub fn new() -> Self {
2328 Self::default()
2329 }
2330
2331 pub fn with_dimensions(mut self, dimensions: u32) -> Self {
2333 self.dimensions = Some(dimensions);
2334 self
2335 }
2336
2337 pub fn with_index_type(mut self, index_type: impl Into<String>) -> Self {
2339 self.index_type = Some(index_type.into());
2340 self
2341 }
2342}
2343
2344#[derive(Debug, Clone, Serialize, Deserialize)]
2349pub struct ConfigureNamespaceRequest {
2350 pub dimension: usize,
2352 #[serde(skip_serializing_if = "Option::is_none")]
2354 pub distance: Option<DistanceMetric>,
2355}
2356
2357impl ConfigureNamespaceRequest {
2358 pub fn new(dimension: usize) -> Self {
2360 Self {
2361 dimension,
2362 distance: None,
2363 }
2364 }
2365
2366 pub fn with_distance(mut self, distance: DistanceMetric) -> Self {
2368 self.distance = Some(distance);
2369 self
2370 }
2371}
2372
2373#[derive(Debug, Clone, Serialize, Deserialize)]
2375pub struct ConfigureNamespaceResponse {
2376 pub namespace: String,
2378 pub dimension: usize,
2380 pub distance: DistanceMetric,
2382 pub created: bool,
2384}