1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
8pub struct Field(pub u32);
9
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
12pub enum FieldType {
13 #[serde(rename = "text")]
15 Text,
16 #[serde(rename = "u64")]
18 U64,
19 #[serde(rename = "i64")]
21 I64,
22 #[serde(rename = "f64")]
24 F64,
25 #[serde(rename = "bytes")]
27 Bytes,
28 #[serde(rename = "sparse_vector")]
30 SparseVector,
31 #[serde(rename = "dense_vector")]
33 DenseVector,
34 #[serde(rename = "json")]
36 Json,
37 #[serde(rename = "binary_dense_vector")]
39 BinaryDenseVector,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct FieldEntry {
45 pub name: String,
46 pub field_type: FieldType,
47 pub indexed: bool,
48 pub stored: bool,
49 pub tokenizer: Option<String>,
51 #[serde(default)]
53 pub multi: bool,
54 #[serde(default, skip_serializing_if = "Option::is_none")]
56 pub positions: Option<PositionMode>,
57 #[serde(default, skip_serializing_if = "Option::is_none")]
59 pub sparse_vector_config: Option<crate::structures::SparseVectorConfig>,
60 #[serde(default, skip_serializing_if = "Option::is_none")]
62 pub dense_vector_config: Option<DenseVectorConfig>,
63 #[serde(default, skip_serializing_if = "Option::is_none")]
65 pub binary_dense_vector_config: Option<BinaryDenseVectorConfig>,
66 #[serde(default)]
69 pub fast: bool,
70 #[serde(default)]
72 pub primary_key: bool,
73 #[serde(default)]
77 pub reorder: bool,
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
82#[serde(rename_all = "snake_case")]
83pub enum PositionMode {
84 Ordinal,
87 TokenPosition,
90 Full,
93}
94
95impl PositionMode {
96 pub fn tracks_ordinal(&self) -> bool {
98 matches!(self, PositionMode::Ordinal | PositionMode::Full)
99 }
100
101 pub fn tracks_token_position(&self) -> bool {
103 matches!(self, PositionMode::TokenPosition | PositionMode::Full)
104 }
105}
106
107#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
109#[serde(rename_all = "snake_case")]
110pub enum VectorIndexType {
111 Flat,
113 #[default]
115 RaBitQ,
116 IvfRaBitQ,
118 ScaNN,
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
128#[serde(rename_all = "snake_case")]
129pub enum DenseVectorQuantization {
130 #[default]
132 F32,
133 F16,
135 UInt8,
137 Binary,
140}
141
142impl DenseVectorQuantization {
143 pub fn element_size(self) -> usize {
146 match self {
147 Self::F32 => 4,
148 Self::F16 => 2,
149 Self::UInt8 => 1,
150 Self::Binary => panic!("element_size() not valid for Binary; use dim.div_ceil(8)"),
151 }
152 }
153
154 pub fn tag(self) -> u8 {
156 match self {
157 Self::F32 => 0,
158 Self::F16 => 1,
159 Self::UInt8 => 2,
160 Self::Binary => 3,
161 }
162 }
163
164 pub fn from_tag(tag: u8) -> Option<Self> {
166 match tag {
167 0 => Some(Self::F32),
168 1 => Some(Self::F16),
169 2 => Some(Self::UInt8),
170 3 => Some(Self::Binary),
171 _ => None,
172 }
173 }
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
184pub struct DenseVectorConfig {
185 pub dim: usize,
187 #[serde(default)]
190 pub index_type: VectorIndexType,
191 #[serde(default)]
193 pub quantization: DenseVectorQuantization,
194 #[serde(default, skip_serializing_if = "Option::is_none")]
197 pub num_clusters: Option<usize>,
198 #[serde(default = "default_nprobe")]
200 pub nprobe: usize,
201 #[serde(default, skip_serializing_if = "Option::is_none")]
205 pub build_threshold: Option<usize>,
206 #[serde(default = "default_unit_norm")]
211 pub unit_norm: bool,
212 #[serde(default, skip_serializing_if = "Option::is_none")]
218 pub rabitq_bits: Option<u8>,
219 #[serde(default, skip_serializing_if = "Option::is_none")]
224 pub soar: Option<crate::structures::SoarConfig>,
225}
226
227fn default_nprobe() -> usize {
228 32
229}
230
231fn default_unit_norm() -> bool {
232 true
233}
234
235impl DenseVectorConfig {
236 pub fn new(dim: usize) -> Self {
237 Self {
238 dim,
239 index_type: VectorIndexType::RaBitQ,
240 quantization: DenseVectorQuantization::F32,
241 num_clusters: None,
242 nprobe: 32,
243 build_threshold: None,
244 unit_norm: true,
245 soar: None,
246 rabitq_bits: None,
247 }
248 }
249
250 pub fn with_ivf(dim: usize, num_clusters: Option<usize>, nprobe: usize) -> Self {
252 Self {
253 dim,
254 index_type: VectorIndexType::IvfRaBitQ,
255 quantization: DenseVectorQuantization::F32,
256 num_clusters,
257 nprobe,
258 build_threshold: None,
259 unit_norm: true,
260 soar: None,
261 rabitq_bits: None,
262 }
263 }
264
265 pub fn with_scann(dim: usize, num_clusters: Option<usize>, nprobe: usize) -> Self {
267 Self {
268 dim,
269 index_type: VectorIndexType::ScaNN,
270 quantization: DenseVectorQuantization::F32,
271 num_clusters,
272 nprobe,
273 build_threshold: None,
274 unit_norm: true,
275 soar: None,
276 rabitq_bits: None,
277 }
278 }
279
280 pub fn flat(dim: usize) -> Self {
282 Self {
283 dim,
284 index_type: VectorIndexType::Flat,
285 quantization: DenseVectorQuantization::F32,
286 num_clusters: None,
287 nprobe: 0,
288 build_threshold: None,
289 unit_norm: true,
290 soar: None,
291 rabitq_bits: None,
292 }
293 }
294
295 pub fn with_quantization(mut self, quantization: DenseVectorQuantization) -> Self {
297 self.quantization = quantization;
298 self
299 }
300
301 pub fn with_build_threshold(mut self, threshold: usize) -> Self {
303 self.build_threshold = Some(threshold);
304 self
305 }
306
307 pub fn with_unit_norm(mut self) -> Self {
309 self.unit_norm = true;
310 self
311 }
312
313 pub fn with_num_clusters(mut self, num_clusters: usize) -> Self {
315 self.num_clusters = Some(num_clusters);
316 self
317 }
318
319 pub fn with_rabitq_bits(mut self, bits: u8) -> Self {
321 self.rabitq_bits = Some(bits.clamp(1, 8));
322 self
323 }
324
325 pub fn with_soar(mut self, soar: crate::structures::SoarConfig) -> Self {
327 self.soar = Some(soar);
328 self
329 }
330
331 pub fn uses_ivf(&self) -> bool {
333 matches!(
334 self.index_type,
335 VectorIndexType::IvfRaBitQ | VectorIndexType::ScaNN
336 )
337 }
338
339 pub fn uses_scann(&self) -> bool {
341 self.index_type == VectorIndexType::ScaNN
342 }
343
344 pub fn is_flat(&self) -> bool {
346 self.index_type == VectorIndexType::Flat
347 }
348
349 pub fn default_build_threshold(&self) -> usize {
351 self.build_threshold.unwrap_or(match self.index_type {
352 VectorIndexType::Flat => usize::MAX, VectorIndexType::RaBitQ => 1000,
354 VectorIndexType::IvfRaBitQ | VectorIndexType::ScaNN => 10000,
355 })
356 }
357
358 pub fn optimal_num_clusters(&self, num_vectors: usize) -> usize {
360 self.num_clusters.unwrap_or_else(|| {
361 let optimal = (num_vectors as f64).sqrt() as usize;
363 optimal.clamp(16, 4096)
364 })
365 }
366}
367
368#[derive(Debug, Clone, Serialize, Deserialize)]
374pub struct BinaryDenseVectorConfig {
375 pub dim: usize,
377 #[serde(default)]
381 pub index_type: BinaryIndexType,
382 #[serde(default, skip_serializing_if = "Option::is_none")]
384 pub num_clusters: Option<usize>,
385 #[serde(default = "default_nprobe")]
387 pub nprobe: usize,
388 #[serde(default, skip_serializing_if = "Option::is_none")]
391 pub build_threshold: Option<usize>,
392}
393
394#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
396#[serde(rename_all = "snake_case")]
397pub enum BinaryIndexType {
398 #[default]
400 Flat,
401 Ivf,
403}
404
405impl BinaryDenseVectorConfig {
406 pub fn new(dim: usize) -> Self {
407 assert!(
408 dim.is_multiple_of(8),
409 "BinaryDenseVector dimension must be a multiple of 8, got {dim}"
410 );
411 Self {
412 dim,
413 index_type: BinaryIndexType::Flat,
414 num_clusters: None,
415 nprobe: 32,
416 build_threshold: None,
417 }
418 }
419
420 pub fn with_ivf(mut self, num_clusters: Option<usize>, nprobe: usize) -> Self {
422 self.index_type = BinaryIndexType::Ivf;
423 self.num_clusters = num_clusters;
424 self.nprobe = nprobe;
425 self
426 }
427
428 pub fn with_build_threshold(mut self, threshold: usize) -> Self {
430 self.build_threshold = Some(threshold);
431 self
432 }
433
434 pub fn default_build_threshold(&self) -> usize {
436 self.build_threshold.unwrap_or(100_000)
437 }
438
439 pub fn optimal_num_clusters(&self, num_vectors: usize) -> usize {
441 self.num_clusters.unwrap_or_else(|| {
442 let optimal = (num_vectors as f64).sqrt() as usize;
443 optimal.clamp(16, 4096)
444 })
445 }
446
447 pub fn byte_len(&self) -> usize {
449 self.dim.div_ceil(8)
450 }
451}
452
453use super::query_field_router::QueryRouterRule;
454
455#[derive(Debug, Clone, Default, Serialize, Deserialize)]
457pub struct Schema {
458 fields: Vec<FieldEntry>,
459 name_to_field: HashMap<String, Field>,
460 #[serde(default)]
462 default_fields: Vec<Field>,
463 #[serde(default)]
465 query_routers: Vec<QueryRouterRule>,
466}
467
468impl Schema {
469 pub fn builder() -> SchemaBuilder {
470 SchemaBuilder::default()
471 }
472
473 pub fn get_field(&self, name: &str) -> Option<Field> {
474 self.name_to_field.get(name).copied()
475 }
476
477 pub fn get_field_entry(&self, field: Field) -> Option<&FieldEntry> {
478 self.fields.get(field.0 as usize)
479 }
480
481 pub fn get_field_name(&self, field: Field) -> Option<&str> {
482 self.fields.get(field.0 as usize).map(|e| e.name.as_str())
483 }
484
485 pub fn fields(&self) -> impl Iterator<Item = (Field, &FieldEntry)> {
486 self.fields
487 .iter()
488 .enumerate()
489 .map(|(i, e)| (Field(i as u32), e))
490 }
491
492 pub fn num_fields(&self) -> usize {
493 self.fields.len()
494 }
495
496 pub fn has_reorder_fields(&self) -> bool {
499 self.fields.iter().any(|e| e.reorder)
500 }
501
502 pub fn default_fields(&self) -> &[Field] {
504 &self.default_fields
505 }
506
507 pub fn set_default_fields(&mut self, fields: Vec<Field>) {
509 self.default_fields = fields;
510 }
511
512 pub fn query_routers(&self) -> &[QueryRouterRule] {
514 &self.query_routers
515 }
516
517 pub fn set_query_routers(&mut self, rules: Vec<QueryRouterRule>) {
519 self.query_routers = rules;
520 }
521
522 pub fn primary_field(&self) -> Option<Field> {
524 self.fields
525 .iter()
526 .enumerate()
527 .find(|(_, e)| e.primary_key)
528 .map(|(i, _)| Field(i as u32))
529 }
530}
531
532#[derive(Debug, Default)]
534pub struct SchemaBuilder {
535 fields: Vec<FieldEntry>,
536 default_fields: Vec<String>,
537 query_routers: Vec<QueryRouterRule>,
538}
539
540impl SchemaBuilder {
541 pub fn add_text_field(&mut self, name: &str, indexed: bool, stored: bool) -> Field {
542 self.add_field_with_tokenizer(
543 name,
544 FieldType::Text,
545 indexed,
546 stored,
547 Some("simple".to_string()),
548 )
549 }
550
551 pub fn add_text_field_with_tokenizer(
552 &mut self,
553 name: &str,
554 indexed: bool,
555 stored: bool,
556 tokenizer: &str,
557 ) -> Field {
558 self.add_field_with_tokenizer(
559 name,
560 FieldType::Text,
561 indexed,
562 stored,
563 Some(tokenizer.to_string()),
564 )
565 }
566
567 pub fn add_u64_field(&mut self, name: &str, indexed: bool, stored: bool) -> Field {
568 self.add_field(name, FieldType::U64, indexed, stored)
569 }
570
571 pub fn add_i64_field(&mut self, name: &str, indexed: bool, stored: bool) -> Field {
572 self.add_field(name, FieldType::I64, indexed, stored)
573 }
574
575 pub fn add_f64_field(&mut self, name: &str, indexed: bool, stored: bool) -> Field {
576 self.add_field(name, FieldType::F64, indexed, stored)
577 }
578
579 pub fn add_bytes_field(&mut self, name: &str, stored: bool) -> Field {
580 self.add_field(name, FieldType::Bytes, false, stored)
581 }
582
583 pub fn add_json_field(&mut self, name: &str, stored: bool) -> Field {
588 self.add_field(name, FieldType::Json, false, stored)
589 }
590
591 pub fn add_sparse_vector_field(&mut self, name: &str, indexed: bool, stored: bool) -> Field {
596 self.add_sparse_vector_field_with_config(
597 name,
598 indexed,
599 stored,
600 crate::structures::SparseVectorConfig::default(),
601 )
602 }
603
604 pub fn add_sparse_vector_field_with_config(
609 &mut self,
610 name: &str,
611 indexed: bool,
612 stored: bool,
613 config: crate::structures::SparseVectorConfig,
614 ) -> Field {
615 let field = Field(self.fields.len() as u32);
616 self.fields.push(FieldEntry {
617 name: name.to_string(),
618 field_type: FieldType::SparseVector,
619 indexed,
620 stored,
621 tokenizer: None,
622 multi: false,
623 positions: None,
624 sparse_vector_config: Some(config),
625 dense_vector_config: None,
626 binary_dense_vector_config: None,
627 fast: false,
628 primary_key: false,
629 reorder: false,
630 });
631 field
632 }
633
634 pub fn set_sparse_vector_config(
636 &mut self,
637 field: Field,
638 config: crate::structures::SparseVectorConfig,
639 ) {
640 if let Some(entry) = self.fields.get_mut(field.0 as usize) {
641 entry.sparse_vector_config = Some(config);
642 }
643 }
644
645 pub fn add_dense_vector_field(
650 &mut self,
651 name: &str,
652 dim: usize,
653 indexed: bool,
654 stored: bool,
655 ) -> Field {
656 self.add_dense_vector_field_with_config(name, indexed, stored, DenseVectorConfig::new(dim))
657 }
658
659 pub fn add_dense_vector_field_with_config(
661 &mut self,
662 name: &str,
663 indexed: bool,
664 stored: bool,
665 config: DenseVectorConfig,
666 ) -> Field {
667 let field = Field(self.fields.len() as u32);
668 self.fields.push(FieldEntry {
669 name: name.to_string(),
670 field_type: FieldType::DenseVector,
671 indexed,
672 stored,
673 tokenizer: None,
674 multi: false,
675 positions: None,
676 sparse_vector_config: None,
677 dense_vector_config: Some(config),
678 binary_dense_vector_config: None,
679 fast: false,
680 primary_key: false,
681 reorder: false,
682 });
683 field
684 }
685
686 pub fn add_binary_dense_vector_field(
691 &mut self,
692 name: &str,
693 dim: usize,
694 indexed: bool,
695 stored: bool,
696 ) -> Field {
697 self.add_binary_dense_vector_field_with_config(
698 name,
699 indexed,
700 stored,
701 BinaryDenseVectorConfig::new(dim),
702 )
703 }
704
705 pub fn add_binary_dense_vector_field_with_config(
707 &mut self,
708 name: &str,
709 indexed: bool,
710 stored: bool,
711 config: BinaryDenseVectorConfig,
712 ) -> Field {
713 let field = Field(self.fields.len() as u32);
714 self.fields.push(FieldEntry {
715 name: name.to_string(),
716 field_type: FieldType::BinaryDenseVector,
717 indexed,
718 stored,
719 tokenizer: None,
720 multi: false,
721 positions: None,
722 sparse_vector_config: None,
723 dense_vector_config: None,
724 binary_dense_vector_config: Some(config),
725 fast: false,
726 primary_key: false,
727 reorder: false,
728 });
729 field
730 }
731
732 fn add_field(
733 &mut self,
734 name: &str,
735 field_type: FieldType,
736 indexed: bool,
737 stored: bool,
738 ) -> Field {
739 self.add_field_with_tokenizer(name, field_type, indexed, stored, None)
740 }
741
742 fn add_field_with_tokenizer(
743 &mut self,
744 name: &str,
745 field_type: FieldType,
746 indexed: bool,
747 stored: bool,
748 tokenizer: Option<String>,
749 ) -> Field {
750 self.add_field_full(name, field_type, indexed, stored, tokenizer, false)
751 }
752
753 fn add_field_full(
754 &mut self,
755 name: &str,
756 field_type: FieldType,
757 indexed: bool,
758 stored: bool,
759 tokenizer: Option<String>,
760 multi: bool,
761 ) -> Field {
762 let field = Field(self.fields.len() as u32);
763 self.fields.push(FieldEntry {
764 name: name.to_string(),
765 field_type,
766 indexed,
767 stored,
768 tokenizer,
769 multi,
770 positions: None,
771 sparse_vector_config: None,
772 dense_vector_config: None,
773 binary_dense_vector_config: None,
774 fast: false,
775 primary_key: false,
776 reorder: false,
777 });
778 field
779 }
780
781 pub fn set_multi(&mut self, field: Field, multi: bool) {
783 if let Some(entry) = self.fields.get_mut(field.0 as usize) {
784 entry.multi = multi;
785 }
786 }
787
788 pub fn set_fast(&mut self, field: Field, fast: bool) {
791 if let Some(entry) = self.fields.get_mut(field.0 as usize) {
792 entry.fast = fast;
793 }
794 }
795
796 pub fn set_primary_key(&mut self, field: Field) {
798 if let Some(entry) = self.fields.get_mut(field.0 as usize) {
799 entry.primary_key = true;
800 }
801 }
802
803 pub fn set_reorder(&mut self, field: Field, reorder: bool) {
805 if let Some(entry) = self.fields.get_mut(field.0 as usize) {
806 entry.reorder = reorder;
807 }
808 }
809
810 pub fn set_positions(&mut self, field: Field, mode: PositionMode) {
812 if let Some(entry) = self.fields.get_mut(field.0 as usize) {
813 entry.positions = Some(mode);
814 }
815 }
816
817 pub fn set_default_fields(&mut self, field_names: Vec<String>) {
819 self.default_fields = field_names;
820 }
821
822 pub fn set_query_routers(&mut self, rules: Vec<QueryRouterRule>) {
824 self.query_routers = rules;
825 }
826
827 pub fn build(self) -> Schema {
828 let mut name_to_field = HashMap::new();
829 for (i, entry) in self.fields.iter().enumerate() {
830 name_to_field.insert(entry.name.clone(), Field(i as u32));
831 }
832
833 let default_fields: Vec<Field> = self
835 .default_fields
836 .iter()
837 .filter_map(|name| name_to_field.get(name).copied())
838 .collect();
839
840 Schema {
841 fields: self.fields,
842 name_to_field,
843 default_fields,
844 query_routers: self.query_routers,
845 }
846 }
847}
848
849#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
851pub enum FieldValue {
852 #[serde(rename = "text")]
853 Text(String),
854 #[serde(rename = "u64")]
855 U64(u64),
856 #[serde(rename = "i64")]
857 I64(i64),
858 #[serde(rename = "f64")]
859 F64(f64),
860 #[serde(rename = "bytes")]
861 Bytes(Vec<u8>),
862 #[serde(rename = "sparse_vector")]
864 SparseVector(Vec<(u32, f32)>),
865 #[serde(rename = "dense_vector")]
867 DenseVector(Vec<f32>),
868 #[serde(rename = "json")]
870 Json(serde_json::Value),
871 #[serde(rename = "binary_dense_vector")]
873 BinaryDenseVector(Vec<u8>),
874}
875
876impl FieldValue {
877 pub fn as_text(&self) -> Option<&str> {
878 match self {
879 FieldValue::Text(s) => Some(s),
880 _ => None,
881 }
882 }
883
884 pub fn as_u64(&self) -> Option<u64> {
885 match self {
886 FieldValue::U64(v) => Some(*v),
887 _ => None,
888 }
889 }
890
891 pub fn as_i64(&self) -> Option<i64> {
892 match self {
893 FieldValue::I64(v) => Some(*v),
894 _ => None,
895 }
896 }
897
898 pub fn as_f64(&self) -> Option<f64> {
899 match self {
900 FieldValue::F64(v) => Some(*v),
901 _ => None,
902 }
903 }
904
905 pub fn as_bytes(&self) -> Option<&[u8]> {
906 match self {
907 FieldValue::Bytes(b) => Some(b),
908 _ => None,
909 }
910 }
911
912 pub fn as_sparse_vector(&self) -> Option<&[(u32, f32)]> {
913 match self {
914 FieldValue::SparseVector(entries) => Some(entries),
915 _ => None,
916 }
917 }
918
919 pub fn as_dense_vector(&self) -> Option<&[f32]> {
920 match self {
921 FieldValue::DenseVector(v) => Some(v),
922 _ => None,
923 }
924 }
925
926 pub fn as_json(&self) -> Option<&serde_json::Value> {
927 match self {
928 FieldValue::Json(v) => Some(v),
929 _ => None,
930 }
931 }
932
933 pub fn as_binary_dense_vector(&self) -> Option<&[u8]> {
934 match self {
935 FieldValue::BinaryDenseVector(v) => Some(v),
936 _ => None,
937 }
938 }
939}
940
941#[derive(Debug, Clone, Default, Serialize, Deserialize)]
943pub struct Document {
944 field_values: Vec<(Field, FieldValue)>,
945}
946
947impl Document {
948 pub fn new() -> Self {
949 Self::default()
950 }
951
952 pub fn add_text(&mut self, field: Field, value: impl Into<String>) {
953 self.field_values
954 .push((field, FieldValue::Text(value.into())));
955 }
956
957 pub fn add_u64(&mut self, field: Field, value: u64) {
958 self.field_values.push((field, FieldValue::U64(value)));
959 }
960
961 pub fn add_i64(&mut self, field: Field, value: i64) {
962 self.field_values.push((field, FieldValue::I64(value)));
963 }
964
965 pub fn add_f64(&mut self, field: Field, value: f64) {
966 self.field_values.push((field, FieldValue::F64(value)));
967 }
968
969 pub fn add_bytes(&mut self, field: Field, value: Vec<u8>) {
970 self.field_values.push((field, FieldValue::Bytes(value)));
971 }
972
973 pub fn add_sparse_vector(&mut self, field: Field, entries: Vec<(u32, f32)>) {
974 self.field_values
975 .push((field, FieldValue::SparseVector(entries)));
976 }
977
978 pub fn add_dense_vector(&mut self, field: Field, values: Vec<f32>) {
979 self.field_values
980 .push((field, FieldValue::DenseVector(values)));
981 }
982
983 pub fn add_json(&mut self, field: Field, value: serde_json::Value) {
984 self.field_values.push((field, FieldValue::Json(value)));
985 }
986
987 pub fn add_binary_dense_vector(&mut self, field: Field, values: Vec<u8>) {
988 self.field_values
989 .push((field, FieldValue::BinaryDenseVector(values)));
990 }
991
992 pub fn get_first(&self, field: Field) -> Option<&FieldValue> {
993 self.field_values
994 .iter()
995 .find(|(f, _)| *f == field)
996 .map(|(_, v)| v)
997 }
998
999 pub fn get_all(&self, field: Field) -> impl Iterator<Item = &FieldValue> {
1000 self.field_values
1001 .iter()
1002 .filter(move |(f, _)| *f == field)
1003 .map(|(_, v)| v)
1004 }
1005
1006 pub fn field_values(&self) -> &[(Field, FieldValue)] {
1007 &self.field_values
1008 }
1009
1010 pub fn filter_stored(&self, schema: &Schema) -> Document {
1012 Document {
1013 field_values: self
1014 .field_values
1015 .iter()
1016 .filter(|(field, _)| {
1017 schema
1018 .get_field_entry(*field)
1019 .is_some_and(|entry| entry.stored)
1020 })
1021 .cloned()
1022 .collect(),
1023 }
1024 }
1025
1026 pub fn to_json(&self, schema: &Schema) -> serde_json::Value {
1032 use std::collections::HashMap;
1033
1034 let mut field_values_map: HashMap<Field, (String, bool, Vec<serde_json::Value>)> =
1036 HashMap::new();
1037
1038 for (field, value) in &self.field_values {
1039 if let Some(entry) = schema.get_field_entry(*field) {
1040 let json_value = match value {
1041 FieldValue::Text(s) => serde_json::Value::String(s.clone()),
1042 FieldValue::U64(n) => serde_json::Value::Number((*n).into()),
1043 FieldValue::I64(n) => serde_json::Value::Number((*n).into()),
1044 FieldValue::F64(n) => serde_json::json!(n),
1045 FieldValue::Bytes(b) => {
1046 use base64::Engine;
1047 serde_json::Value::String(
1048 base64::engine::general_purpose::STANDARD.encode(b),
1049 )
1050 }
1051 FieldValue::SparseVector(entries) => {
1052 let indices: Vec<u32> = entries.iter().map(|(i, _)| *i).collect();
1053 let values: Vec<f32> = entries.iter().map(|(_, v)| *v).collect();
1054 serde_json::json!({
1055 "indices": indices,
1056 "values": values
1057 })
1058 }
1059 FieldValue::DenseVector(values) => {
1060 serde_json::json!(values)
1061 }
1062 FieldValue::Json(v) => v.clone(),
1063 FieldValue::BinaryDenseVector(b) => {
1064 use base64::Engine;
1065 serde_json::Value::String(
1066 base64::engine::general_purpose::STANDARD.encode(b),
1067 )
1068 }
1069 };
1070 field_values_map
1071 .entry(*field)
1072 .or_insert_with(|| (entry.name.clone(), entry.multi, Vec::new()))
1073 .2
1074 .push(json_value);
1075 }
1076 }
1077
1078 let mut map = serde_json::Map::new();
1080 for (_field, (name, is_multi, values)) in field_values_map {
1081 let json_value = if is_multi || values.len() > 1 {
1082 serde_json::Value::Array(values)
1083 } else {
1084 values.into_iter().next().unwrap()
1085 };
1086 map.insert(name, json_value);
1087 }
1088
1089 serde_json::Value::Object(map)
1090 }
1091
1092 pub fn from_json(json: &serde_json::Value, schema: &Schema) -> Option<Self> {
1101 let obj = json.as_object()?;
1102 let mut doc = Document::new();
1103
1104 for (key, value) in obj {
1105 if let Some(field) = schema.get_field(key) {
1106 let field_entry = schema.get_field_entry(field)?;
1107 Self::add_json_value(&mut doc, field, &field_entry.field_type, value);
1108 }
1109 }
1110
1111 Some(doc)
1112 }
1113
1114 fn add_json_value(
1116 doc: &mut Document,
1117 field: Field,
1118 field_type: &FieldType,
1119 value: &serde_json::Value,
1120 ) {
1121 match value {
1122 serde_json::Value::String(s) => {
1123 if matches!(field_type, FieldType::Text) {
1124 doc.add_text(field, s.clone());
1125 }
1126 }
1127 serde_json::Value::Number(n) => {
1128 match field_type {
1129 FieldType::I64 => {
1130 if let Some(i) = n.as_i64() {
1131 doc.add_i64(field, i);
1132 }
1133 }
1134 FieldType::U64 => {
1135 if let Some(u) = n.as_u64() {
1136 doc.add_u64(field, u);
1137 } else if let Some(i) = n.as_i64() {
1138 if i >= 0 {
1140 doc.add_u64(field, i as u64);
1141 }
1142 }
1143 }
1144 FieldType::F64 => {
1145 if let Some(f) = n.as_f64() {
1146 doc.add_f64(field, f);
1147 }
1148 }
1149 _ => {}
1150 }
1151 }
1152 serde_json::Value::Array(arr) => {
1154 for item in arr {
1155 Self::add_json_value(doc, field, field_type, item);
1156 }
1157 }
1158 serde_json::Value::Object(obj) if matches!(field_type, FieldType::SparseVector) => {
1160 if let (Some(indices_val), Some(values_val)) =
1161 (obj.get("indices"), obj.get("values"))
1162 {
1163 let indices: Vec<u32> = indices_val
1164 .as_array()
1165 .map(|arr| {
1166 arr.iter()
1167 .filter_map(|v| v.as_u64().map(|n| n as u32))
1168 .collect()
1169 })
1170 .unwrap_or_default();
1171 let values: Vec<f32> = values_val
1172 .as_array()
1173 .map(|arr| {
1174 arr.iter()
1175 .filter_map(|v| v.as_f64().map(|n| n as f32))
1176 .collect()
1177 })
1178 .unwrap_or_default();
1179 if indices.len() == values.len() {
1180 let entries: Vec<(u32, f32)> = indices.into_iter().zip(values).collect();
1181 doc.add_sparse_vector(field, entries);
1182 }
1183 }
1184 }
1185 _ if matches!(field_type, FieldType::Json) => {
1187 doc.add_json(field, value.clone());
1188 }
1189 serde_json::Value::Object(_) => {}
1190 _ => {}
1191 }
1192 }
1193}
1194
1195#[cfg(test)]
1196mod tests {
1197 use super::*;
1198
1199 #[test]
1200 fn test_schema_builder() {
1201 let mut builder = Schema::builder();
1202 let title = builder.add_text_field("title", true, true);
1203 let body = builder.add_text_field("body", true, false);
1204 let count = builder.add_u64_field("count", true, true);
1205 let schema = builder.build();
1206
1207 assert_eq!(schema.get_field("title"), Some(title));
1208 assert_eq!(schema.get_field("body"), Some(body));
1209 assert_eq!(schema.get_field("count"), Some(count));
1210 assert_eq!(schema.get_field("nonexistent"), None);
1211 }
1212
1213 #[test]
1214 fn test_document() {
1215 let mut builder = Schema::builder();
1216 let title = builder.add_text_field("title", true, true);
1217 let count = builder.add_u64_field("count", true, true);
1218 let _schema = builder.build();
1219
1220 let mut doc = Document::new();
1221 doc.add_text(title, "Hello World");
1222 doc.add_u64(count, 42);
1223
1224 assert_eq!(doc.get_first(title).unwrap().as_text(), Some("Hello World"));
1225 assert_eq!(doc.get_first(count).unwrap().as_u64(), Some(42));
1226 }
1227
1228 #[test]
1229 fn test_document_serialization() {
1230 let mut builder = Schema::builder();
1231 let title = builder.add_text_field("title", true, true);
1232 let count = builder.add_u64_field("count", true, true);
1233 let _schema = builder.build();
1234
1235 let mut doc = Document::new();
1236 doc.add_text(title, "Hello World");
1237 doc.add_u64(count, 42);
1238
1239 let json = serde_json::to_string(&doc).unwrap();
1241 println!("Serialized doc: {}", json);
1242
1243 let doc2: Document = serde_json::from_str(&json).unwrap();
1245 assert_eq!(
1246 doc2.field_values().len(),
1247 2,
1248 "Should have 2 field values after deserialization"
1249 );
1250 assert_eq!(
1251 doc2.get_first(title).unwrap().as_text(),
1252 Some("Hello World")
1253 );
1254 assert_eq!(doc2.get_first(count).unwrap().as_u64(), Some(42));
1255 }
1256
1257 #[test]
1258 fn test_multivalue_field() {
1259 let mut builder = Schema::builder();
1260 let uris = builder.add_text_field("uris", true, true);
1261 let title = builder.add_text_field("title", true, true);
1262 let schema = builder.build();
1263
1264 let mut doc = Document::new();
1266 doc.add_text(uris, "one");
1267 doc.add_text(uris, "two");
1268 doc.add_text(title, "Test Document");
1269
1270 assert_eq!(doc.get_first(uris).unwrap().as_text(), Some("one"));
1272
1273 let all_uris: Vec<_> = doc.get_all(uris).collect();
1275 assert_eq!(all_uris.len(), 2);
1276 assert_eq!(all_uris[0].as_text(), Some("one"));
1277 assert_eq!(all_uris[1].as_text(), Some("two"));
1278
1279 let json = doc.to_json(&schema);
1281 let uris_json = json.get("uris").unwrap();
1282 assert!(uris_json.is_array(), "Multi-value field should be an array");
1283 let uris_arr = uris_json.as_array().unwrap();
1284 assert_eq!(uris_arr.len(), 2);
1285 assert_eq!(uris_arr[0].as_str(), Some("one"));
1286 assert_eq!(uris_arr[1].as_str(), Some("two"));
1287
1288 let title_json = json.get("title").unwrap();
1290 assert!(
1291 title_json.is_string(),
1292 "Single-value field should be a string"
1293 );
1294 assert_eq!(title_json.as_str(), Some("Test Document"));
1295 }
1296
1297 #[test]
1298 fn test_multivalue_from_json() {
1299 let mut builder = Schema::builder();
1300 let uris = builder.add_text_field("uris", true, true);
1301 let title = builder.add_text_field("title", true, true);
1302 let schema = builder.build();
1303
1304 let json = serde_json::json!({
1306 "uris": ["one", "two"],
1307 "title": "Test Document"
1308 });
1309
1310 let doc = Document::from_json(&json, &schema).unwrap();
1312
1313 let all_uris: Vec<_> = doc.get_all(uris).collect();
1315 assert_eq!(all_uris.len(), 2);
1316 assert_eq!(all_uris[0].as_text(), Some("one"));
1317 assert_eq!(all_uris[1].as_text(), Some("two"));
1318
1319 assert_eq!(
1321 doc.get_first(title).unwrap().as_text(),
1322 Some("Test Document")
1323 );
1324
1325 let json_out = doc.to_json(&schema);
1327 let uris_out = json_out.get("uris").unwrap().as_array().unwrap();
1328 assert_eq!(uris_out.len(), 2);
1329 assert_eq!(uris_out[0].as_str(), Some("one"));
1330 assert_eq!(uris_out[1].as_str(), Some("two"));
1331 }
1332
1333 #[test]
1334 fn test_multi_attribute_forces_array() {
1335 let mut builder = Schema::builder();
1338 let uris = builder.add_text_field("uris", true, true);
1339 builder.set_multi(uris, true); let title = builder.add_text_field("title", true, true);
1341 let schema = builder.build();
1342
1343 assert!(schema.get_field_entry(uris).unwrap().multi);
1345 assert!(!schema.get_field_entry(title).unwrap().multi);
1346
1347 let mut doc = Document::new();
1349 doc.add_text(uris, "only_one");
1350 doc.add_text(title, "Test Document");
1351
1352 let json = doc.to_json(&schema);
1354
1355 let uris_json = json.get("uris").unwrap();
1356 assert!(
1357 uris_json.is_array(),
1358 "Multi field should be array even with single value"
1359 );
1360 let uris_arr = uris_json.as_array().unwrap();
1361 assert_eq!(uris_arr.len(), 1);
1362 assert_eq!(uris_arr[0].as_str(), Some("only_one"));
1363
1364 let title_json = json.get("title").unwrap();
1366 assert!(
1367 title_json.is_string(),
1368 "Non-multi single-value field should be a string"
1369 );
1370 assert_eq!(title_json.as_str(), Some("Test Document"));
1371 }
1372
1373 #[test]
1374 fn test_sparse_vector_field() {
1375 let mut builder = Schema::builder();
1376 let embedding = builder.add_sparse_vector_field("embedding", true, true);
1377 let title = builder.add_text_field("title", true, true);
1378 let schema = builder.build();
1379
1380 assert_eq!(schema.get_field("embedding"), Some(embedding));
1381 assert_eq!(
1382 schema.get_field_entry(embedding).unwrap().field_type,
1383 FieldType::SparseVector
1384 );
1385
1386 let mut doc = Document::new();
1388 doc.add_sparse_vector(embedding, vec![(0, 1.0), (5, 2.5), (10, 0.5)]);
1389 doc.add_text(title, "Test Document");
1390
1391 let entries = doc
1393 .get_first(embedding)
1394 .unwrap()
1395 .as_sparse_vector()
1396 .unwrap();
1397 assert_eq!(entries, &[(0, 1.0), (5, 2.5), (10, 0.5)]);
1398
1399 let json = doc.to_json(&schema);
1401 let embedding_json = json.get("embedding").unwrap();
1402 assert!(embedding_json.is_object());
1403 assert_eq!(
1404 embedding_json
1405 .get("indices")
1406 .unwrap()
1407 .as_array()
1408 .unwrap()
1409 .len(),
1410 3
1411 );
1412
1413 let doc2 = Document::from_json(&json, &schema).unwrap();
1415 let entries2 = doc2
1416 .get_first(embedding)
1417 .unwrap()
1418 .as_sparse_vector()
1419 .unwrap();
1420 assert_eq!(entries2[0].0, 0);
1421 assert!((entries2[0].1 - 1.0).abs() < 1e-6);
1422 assert_eq!(entries2[1].0, 5);
1423 assert!((entries2[1].1 - 2.5).abs() < 1e-6);
1424 assert_eq!(entries2[2].0, 10);
1425 assert!((entries2[2].1 - 0.5).abs() < 1e-6);
1426 }
1427
1428 #[test]
1429 fn test_json_field() {
1430 let mut builder = Schema::builder();
1431 let metadata = builder.add_json_field("metadata", true);
1432 let title = builder.add_text_field("title", true, true);
1433 let schema = builder.build();
1434
1435 assert_eq!(schema.get_field("metadata"), Some(metadata));
1436 assert_eq!(
1437 schema.get_field_entry(metadata).unwrap().field_type,
1438 FieldType::Json
1439 );
1440 assert!(!schema.get_field_entry(metadata).unwrap().indexed);
1442 assert!(schema.get_field_entry(metadata).unwrap().stored);
1443
1444 let json_value = serde_json::json!({
1446 "author": "John Doe",
1447 "tags": ["rust", "search"],
1448 "nested": {"key": "value"}
1449 });
1450 let mut doc = Document::new();
1451 doc.add_json(metadata, json_value.clone());
1452 doc.add_text(title, "Test Document");
1453
1454 let stored_json = doc.get_first(metadata).unwrap().as_json().unwrap();
1456 assert_eq!(stored_json, &json_value);
1457 assert_eq!(
1458 stored_json.get("author").unwrap().as_str(),
1459 Some("John Doe")
1460 );
1461
1462 let doc_json = doc.to_json(&schema);
1464 let metadata_out = doc_json.get("metadata").unwrap();
1465 assert_eq!(metadata_out, &json_value);
1466
1467 let doc2 = Document::from_json(&doc_json, &schema).unwrap();
1469 let stored_json2 = doc2.get_first(metadata).unwrap().as_json().unwrap();
1470 assert_eq!(stored_json2, &json_value);
1471 }
1472
1473 #[test]
1474 fn test_json_field_various_types() {
1475 let mut builder = Schema::builder();
1476 let data = builder.add_json_field("data", true);
1477 let _schema = builder.build();
1478
1479 let arr_value = serde_json::json!([1, 2, 3, "four", null]);
1481 let mut doc = Document::new();
1482 doc.add_json(data, arr_value.clone());
1483 assert_eq!(doc.get_first(data).unwrap().as_json().unwrap(), &arr_value);
1484
1485 let str_value = serde_json::json!("just a string");
1487 let mut doc2 = Document::new();
1488 doc2.add_json(data, str_value.clone());
1489 assert_eq!(doc2.get_first(data).unwrap().as_json().unwrap(), &str_value);
1490
1491 let num_value = serde_json::json!(42.5);
1493 let mut doc3 = Document::new();
1494 doc3.add_json(data, num_value.clone());
1495 assert_eq!(doc3.get_first(data).unwrap().as_json().unwrap(), &num_value);
1496
1497 let null_value = serde_json::Value::Null;
1499 let mut doc4 = Document::new();
1500 doc4.add_json(data, null_value.clone());
1501 assert_eq!(
1502 doc4.get_first(data).unwrap().as_json().unwrap(),
1503 &null_value
1504 );
1505
1506 let bool_value = serde_json::json!(true);
1508 let mut doc5 = Document::new();
1509 doc5.add_json(data, bool_value.clone());
1510 assert_eq!(
1511 doc5.get_first(data).unwrap().as_json().unwrap(),
1512 &bool_value
1513 );
1514 }
1515}