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")]
217 pub soar: Option<crate::structures::SoarConfig>,
218}
219
220fn default_nprobe() -> usize {
221 32
222}
223
224fn default_unit_norm() -> bool {
225 true
226}
227
228impl DenseVectorConfig {
229 pub fn new(dim: usize) -> Self {
230 Self {
231 dim,
232 index_type: VectorIndexType::RaBitQ,
233 quantization: DenseVectorQuantization::F32,
234 num_clusters: None,
235 nprobe: 32,
236 build_threshold: None,
237 unit_norm: true,
238 soar: None,
239 }
240 }
241
242 pub fn with_ivf(dim: usize, num_clusters: Option<usize>, nprobe: usize) -> Self {
244 Self {
245 dim,
246 index_type: VectorIndexType::IvfRaBitQ,
247 quantization: DenseVectorQuantization::F32,
248 num_clusters,
249 nprobe,
250 build_threshold: None,
251 unit_norm: true,
252 soar: None,
253 }
254 }
255
256 pub fn with_scann(dim: usize, num_clusters: Option<usize>, nprobe: usize) -> Self {
258 Self {
259 dim,
260 index_type: VectorIndexType::ScaNN,
261 quantization: DenseVectorQuantization::F32,
262 num_clusters,
263 nprobe,
264 build_threshold: None,
265 unit_norm: true,
266 soar: None,
267 }
268 }
269
270 pub fn flat(dim: usize) -> Self {
272 Self {
273 dim,
274 index_type: VectorIndexType::Flat,
275 quantization: DenseVectorQuantization::F32,
276 num_clusters: None,
277 nprobe: 0,
278 build_threshold: None,
279 unit_norm: true,
280 soar: None,
281 }
282 }
283
284 pub fn with_quantization(mut self, quantization: DenseVectorQuantization) -> Self {
286 self.quantization = quantization;
287 self
288 }
289
290 pub fn with_build_threshold(mut self, threshold: usize) -> Self {
292 self.build_threshold = Some(threshold);
293 self
294 }
295
296 pub fn with_unit_norm(mut self) -> Self {
298 self.unit_norm = true;
299 self
300 }
301
302 pub fn with_num_clusters(mut self, num_clusters: usize) -> Self {
304 self.num_clusters = Some(num_clusters);
305 self
306 }
307
308 pub fn with_soar(mut self, soar: crate::structures::SoarConfig) -> Self {
310 self.soar = Some(soar);
311 self
312 }
313
314 pub fn uses_ivf(&self) -> bool {
316 matches!(
317 self.index_type,
318 VectorIndexType::IvfRaBitQ | VectorIndexType::ScaNN
319 )
320 }
321
322 pub fn uses_scann(&self) -> bool {
324 self.index_type == VectorIndexType::ScaNN
325 }
326
327 pub fn is_flat(&self) -> bool {
329 self.index_type == VectorIndexType::Flat
330 }
331
332 pub fn default_build_threshold(&self) -> usize {
334 self.build_threshold.unwrap_or(match self.index_type {
335 VectorIndexType::Flat => usize::MAX, VectorIndexType::RaBitQ => 1000,
337 VectorIndexType::IvfRaBitQ | VectorIndexType::ScaNN => 10000,
338 })
339 }
340
341 pub fn optimal_num_clusters(&self, num_vectors: usize) -> usize {
343 self.num_clusters.unwrap_or_else(|| {
344 let optimal = (num_vectors as f64).sqrt() as usize;
346 optimal.clamp(16, 4096)
347 })
348 }
349}
350
351#[derive(Debug, Clone, Serialize, Deserialize)]
357pub struct BinaryDenseVectorConfig {
358 pub dim: usize,
360}
361
362impl BinaryDenseVectorConfig {
363 pub fn new(dim: usize) -> Self {
364 assert!(
365 dim.is_multiple_of(8),
366 "BinaryDenseVector dimension must be a multiple of 8, got {dim}"
367 );
368 Self { dim }
369 }
370
371 pub fn byte_len(&self) -> usize {
373 self.dim.div_ceil(8)
374 }
375}
376
377use super::query_field_router::QueryRouterRule;
378
379#[derive(Debug, Clone, Default, Serialize, Deserialize)]
381pub struct Schema {
382 fields: Vec<FieldEntry>,
383 name_to_field: HashMap<String, Field>,
384 #[serde(default)]
386 default_fields: Vec<Field>,
387 #[serde(default)]
389 query_routers: Vec<QueryRouterRule>,
390}
391
392impl Schema {
393 pub fn builder() -> SchemaBuilder {
394 SchemaBuilder::default()
395 }
396
397 pub fn get_field(&self, name: &str) -> Option<Field> {
398 self.name_to_field.get(name).copied()
399 }
400
401 pub fn get_field_entry(&self, field: Field) -> Option<&FieldEntry> {
402 self.fields.get(field.0 as usize)
403 }
404
405 pub fn get_field_name(&self, field: Field) -> Option<&str> {
406 self.fields.get(field.0 as usize).map(|e| e.name.as_str())
407 }
408
409 pub fn fields(&self) -> impl Iterator<Item = (Field, &FieldEntry)> {
410 self.fields
411 .iter()
412 .enumerate()
413 .map(|(i, e)| (Field(i as u32), e))
414 }
415
416 pub fn num_fields(&self) -> usize {
417 self.fields.len()
418 }
419
420 pub fn has_reorder_fields(&self) -> bool {
423 self.fields.iter().any(|e| e.reorder)
424 }
425
426 pub fn default_fields(&self) -> &[Field] {
428 &self.default_fields
429 }
430
431 pub fn set_default_fields(&mut self, fields: Vec<Field>) {
433 self.default_fields = fields;
434 }
435
436 pub fn query_routers(&self) -> &[QueryRouterRule] {
438 &self.query_routers
439 }
440
441 pub fn set_query_routers(&mut self, rules: Vec<QueryRouterRule>) {
443 self.query_routers = rules;
444 }
445
446 pub fn primary_field(&self) -> Option<Field> {
448 self.fields
449 .iter()
450 .enumerate()
451 .find(|(_, e)| e.primary_key)
452 .map(|(i, _)| Field(i as u32))
453 }
454}
455
456#[derive(Debug, Default)]
458pub struct SchemaBuilder {
459 fields: Vec<FieldEntry>,
460 default_fields: Vec<String>,
461 query_routers: Vec<QueryRouterRule>,
462}
463
464impl SchemaBuilder {
465 pub fn add_text_field(&mut self, name: &str, indexed: bool, stored: bool) -> Field {
466 self.add_field_with_tokenizer(
467 name,
468 FieldType::Text,
469 indexed,
470 stored,
471 Some("simple".to_string()),
472 )
473 }
474
475 pub fn add_text_field_with_tokenizer(
476 &mut self,
477 name: &str,
478 indexed: bool,
479 stored: bool,
480 tokenizer: &str,
481 ) -> Field {
482 self.add_field_with_tokenizer(
483 name,
484 FieldType::Text,
485 indexed,
486 stored,
487 Some(tokenizer.to_string()),
488 )
489 }
490
491 pub fn add_u64_field(&mut self, name: &str, indexed: bool, stored: bool) -> Field {
492 self.add_field(name, FieldType::U64, indexed, stored)
493 }
494
495 pub fn add_i64_field(&mut self, name: &str, indexed: bool, stored: bool) -> Field {
496 self.add_field(name, FieldType::I64, indexed, stored)
497 }
498
499 pub fn add_f64_field(&mut self, name: &str, indexed: bool, stored: bool) -> Field {
500 self.add_field(name, FieldType::F64, indexed, stored)
501 }
502
503 pub fn add_bytes_field(&mut self, name: &str, stored: bool) -> Field {
504 self.add_field(name, FieldType::Bytes, false, stored)
505 }
506
507 pub fn add_json_field(&mut self, name: &str, stored: bool) -> Field {
512 self.add_field(name, FieldType::Json, false, stored)
513 }
514
515 pub fn add_sparse_vector_field(&mut self, name: &str, indexed: bool, stored: bool) -> Field {
520 self.add_sparse_vector_field_with_config(
521 name,
522 indexed,
523 stored,
524 crate::structures::SparseVectorConfig::default(),
525 )
526 }
527
528 pub fn add_sparse_vector_field_with_config(
533 &mut self,
534 name: &str,
535 indexed: bool,
536 stored: bool,
537 config: crate::structures::SparseVectorConfig,
538 ) -> Field {
539 let field = Field(self.fields.len() as u32);
540 self.fields.push(FieldEntry {
541 name: name.to_string(),
542 field_type: FieldType::SparseVector,
543 indexed,
544 stored,
545 tokenizer: None,
546 multi: false,
547 positions: None,
548 sparse_vector_config: Some(config),
549 dense_vector_config: None,
550 binary_dense_vector_config: None,
551 fast: false,
552 primary_key: false,
553 reorder: false,
554 });
555 field
556 }
557
558 pub fn set_sparse_vector_config(
560 &mut self,
561 field: Field,
562 config: crate::structures::SparseVectorConfig,
563 ) {
564 if let Some(entry) = self.fields.get_mut(field.0 as usize) {
565 entry.sparse_vector_config = Some(config);
566 }
567 }
568
569 pub fn add_dense_vector_field(
574 &mut self,
575 name: &str,
576 dim: usize,
577 indexed: bool,
578 stored: bool,
579 ) -> Field {
580 self.add_dense_vector_field_with_config(name, indexed, stored, DenseVectorConfig::new(dim))
581 }
582
583 pub fn add_dense_vector_field_with_config(
585 &mut self,
586 name: &str,
587 indexed: bool,
588 stored: bool,
589 config: DenseVectorConfig,
590 ) -> Field {
591 let field = Field(self.fields.len() as u32);
592 self.fields.push(FieldEntry {
593 name: name.to_string(),
594 field_type: FieldType::DenseVector,
595 indexed,
596 stored,
597 tokenizer: None,
598 multi: false,
599 positions: None,
600 sparse_vector_config: None,
601 dense_vector_config: Some(config),
602 binary_dense_vector_config: None,
603 fast: false,
604 primary_key: false,
605 reorder: false,
606 });
607 field
608 }
609
610 pub fn add_binary_dense_vector_field(
615 &mut self,
616 name: &str,
617 dim: usize,
618 indexed: bool,
619 stored: bool,
620 ) -> Field {
621 self.add_binary_dense_vector_field_with_config(
622 name,
623 indexed,
624 stored,
625 BinaryDenseVectorConfig::new(dim),
626 )
627 }
628
629 pub fn add_binary_dense_vector_field_with_config(
631 &mut self,
632 name: &str,
633 indexed: bool,
634 stored: bool,
635 config: BinaryDenseVectorConfig,
636 ) -> Field {
637 let field = Field(self.fields.len() as u32);
638 self.fields.push(FieldEntry {
639 name: name.to_string(),
640 field_type: FieldType::BinaryDenseVector,
641 indexed,
642 stored,
643 tokenizer: None,
644 multi: false,
645 positions: None,
646 sparse_vector_config: None,
647 dense_vector_config: None,
648 binary_dense_vector_config: Some(config),
649 fast: false,
650 primary_key: false,
651 reorder: false,
652 });
653 field
654 }
655
656 fn add_field(
657 &mut self,
658 name: &str,
659 field_type: FieldType,
660 indexed: bool,
661 stored: bool,
662 ) -> Field {
663 self.add_field_with_tokenizer(name, field_type, indexed, stored, None)
664 }
665
666 fn add_field_with_tokenizer(
667 &mut self,
668 name: &str,
669 field_type: FieldType,
670 indexed: bool,
671 stored: bool,
672 tokenizer: Option<String>,
673 ) -> Field {
674 self.add_field_full(name, field_type, indexed, stored, tokenizer, false)
675 }
676
677 fn add_field_full(
678 &mut self,
679 name: &str,
680 field_type: FieldType,
681 indexed: bool,
682 stored: bool,
683 tokenizer: Option<String>,
684 multi: bool,
685 ) -> Field {
686 let field = Field(self.fields.len() as u32);
687 self.fields.push(FieldEntry {
688 name: name.to_string(),
689 field_type,
690 indexed,
691 stored,
692 tokenizer,
693 multi,
694 positions: None,
695 sparse_vector_config: None,
696 dense_vector_config: None,
697 binary_dense_vector_config: None,
698 fast: false,
699 primary_key: false,
700 reorder: false,
701 });
702 field
703 }
704
705 pub fn set_multi(&mut self, field: Field, multi: bool) {
707 if let Some(entry) = self.fields.get_mut(field.0 as usize) {
708 entry.multi = multi;
709 }
710 }
711
712 pub fn set_fast(&mut self, field: Field, fast: bool) {
715 if let Some(entry) = self.fields.get_mut(field.0 as usize) {
716 entry.fast = fast;
717 }
718 }
719
720 pub fn set_primary_key(&mut self, field: Field) {
722 if let Some(entry) = self.fields.get_mut(field.0 as usize) {
723 entry.primary_key = true;
724 }
725 }
726
727 pub fn set_reorder(&mut self, field: Field, reorder: bool) {
729 if let Some(entry) = self.fields.get_mut(field.0 as usize) {
730 entry.reorder = reorder;
731 }
732 }
733
734 pub fn set_positions(&mut self, field: Field, mode: PositionMode) {
736 if let Some(entry) = self.fields.get_mut(field.0 as usize) {
737 entry.positions = Some(mode);
738 }
739 }
740
741 pub fn set_default_fields(&mut self, field_names: Vec<String>) {
743 self.default_fields = field_names;
744 }
745
746 pub fn set_query_routers(&mut self, rules: Vec<QueryRouterRule>) {
748 self.query_routers = rules;
749 }
750
751 pub fn build(self) -> Schema {
752 let mut name_to_field = HashMap::new();
753 for (i, entry) in self.fields.iter().enumerate() {
754 name_to_field.insert(entry.name.clone(), Field(i as u32));
755 }
756
757 let default_fields: Vec<Field> = self
759 .default_fields
760 .iter()
761 .filter_map(|name| name_to_field.get(name).copied())
762 .collect();
763
764 Schema {
765 fields: self.fields,
766 name_to_field,
767 default_fields,
768 query_routers: self.query_routers,
769 }
770 }
771}
772
773#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
775pub enum FieldValue {
776 #[serde(rename = "text")]
777 Text(String),
778 #[serde(rename = "u64")]
779 U64(u64),
780 #[serde(rename = "i64")]
781 I64(i64),
782 #[serde(rename = "f64")]
783 F64(f64),
784 #[serde(rename = "bytes")]
785 Bytes(Vec<u8>),
786 #[serde(rename = "sparse_vector")]
788 SparseVector(Vec<(u32, f32)>),
789 #[serde(rename = "dense_vector")]
791 DenseVector(Vec<f32>),
792 #[serde(rename = "json")]
794 Json(serde_json::Value),
795 #[serde(rename = "binary_dense_vector")]
797 BinaryDenseVector(Vec<u8>),
798}
799
800impl FieldValue {
801 pub fn as_text(&self) -> Option<&str> {
802 match self {
803 FieldValue::Text(s) => Some(s),
804 _ => None,
805 }
806 }
807
808 pub fn as_u64(&self) -> Option<u64> {
809 match self {
810 FieldValue::U64(v) => Some(*v),
811 _ => None,
812 }
813 }
814
815 pub fn as_i64(&self) -> Option<i64> {
816 match self {
817 FieldValue::I64(v) => Some(*v),
818 _ => None,
819 }
820 }
821
822 pub fn as_f64(&self) -> Option<f64> {
823 match self {
824 FieldValue::F64(v) => Some(*v),
825 _ => None,
826 }
827 }
828
829 pub fn as_bytes(&self) -> Option<&[u8]> {
830 match self {
831 FieldValue::Bytes(b) => Some(b),
832 _ => None,
833 }
834 }
835
836 pub fn as_sparse_vector(&self) -> Option<&[(u32, f32)]> {
837 match self {
838 FieldValue::SparseVector(entries) => Some(entries),
839 _ => None,
840 }
841 }
842
843 pub fn as_dense_vector(&self) -> Option<&[f32]> {
844 match self {
845 FieldValue::DenseVector(v) => Some(v),
846 _ => None,
847 }
848 }
849
850 pub fn as_json(&self) -> Option<&serde_json::Value> {
851 match self {
852 FieldValue::Json(v) => Some(v),
853 _ => None,
854 }
855 }
856
857 pub fn as_binary_dense_vector(&self) -> Option<&[u8]> {
858 match self {
859 FieldValue::BinaryDenseVector(v) => Some(v),
860 _ => None,
861 }
862 }
863}
864
865#[derive(Debug, Clone, Default, Serialize, Deserialize)]
867pub struct Document {
868 field_values: Vec<(Field, FieldValue)>,
869}
870
871impl Document {
872 pub fn new() -> Self {
873 Self::default()
874 }
875
876 pub fn add_text(&mut self, field: Field, value: impl Into<String>) {
877 self.field_values
878 .push((field, FieldValue::Text(value.into())));
879 }
880
881 pub fn add_u64(&mut self, field: Field, value: u64) {
882 self.field_values.push((field, FieldValue::U64(value)));
883 }
884
885 pub fn add_i64(&mut self, field: Field, value: i64) {
886 self.field_values.push((field, FieldValue::I64(value)));
887 }
888
889 pub fn add_f64(&mut self, field: Field, value: f64) {
890 self.field_values.push((field, FieldValue::F64(value)));
891 }
892
893 pub fn add_bytes(&mut self, field: Field, value: Vec<u8>) {
894 self.field_values.push((field, FieldValue::Bytes(value)));
895 }
896
897 pub fn add_sparse_vector(&mut self, field: Field, entries: Vec<(u32, f32)>) {
898 self.field_values
899 .push((field, FieldValue::SparseVector(entries)));
900 }
901
902 pub fn add_dense_vector(&mut self, field: Field, values: Vec<f32>) {
903 self.field_values
904 .push((field, FieldValue::DenseVector(values)));
905 }
906
907 pub fn add_json(&mut self, field: Field, value: serde_json::Value) {
908 self.field_values.push((field, FieldValue::Json(value)));
909 }
910
911 pub fn add_binary_dense_vector(&mut self, field: Field, values: Vec<u8>) {
912 self.field_values
913 .push((field, FieldValue::BinaryDenseVector(values)));
914 }
915
916 pub fn get_first(&self, field: Field) -> Option<&FieldValue> {
917 self.field_values
918 .iter()
919 .find(|(f, _)| *f == field)
920 .map(|(_, v)| v)
921 }
922
923 pub fn get_all(&self, field: Field) -> impl Iterator<Item = &FieldValue> {
924 self.field_values
925 .iter()
926 .filter(move |(f, _)| *f == field)
927 .map(|(_, v)| v)
928 }
929
930 pub fn field_values(&self) -> &[(Field, FieldValue)] {
931 &self.field_values
932 }
933
934 pub fn filter_stored(&self, schema: &Schema) -> Document {
936 Document {
937 field_values: self
938 .field_values
939 .iter()
940 .filter(|(field, _)| {
941 schema
942 .get_field_entry(*field)
943 .is_some_and(|entry| entry.stored)
944 })
945 .cloned()
946 .collect(),
947 }
948 }
949
950 pub fn to_json(&self, schema: &Schema) -> serde_json::Value {
956 use std::collections::HashMap;
957
958 let mut field_values_map: HashMap<Field, (String, bool, Vec<serde_json::Value>)> =
960 HashMap::new();
961
962 for (field, value) in &self.field_values {
963 if let Some(entry) = schema.get_field_entry(*field) {
964 let json_value = match value {
965 FieldValue::Text(s) => serde_json::Value::String(s.clone()),
966 FieldValue::U64(n) => serde_json::Value::Number((*n).into()),
967 FieldValue::I64(n) => serde_json::Value::Number((*n).into()),
968 FieldValue::F64(n) => serde_json::json!(n),
969 FieldValue::Bytes(b) => {
970 use base64::Engine;
971 serde_json::Value::String(
972 base64::engine::general_purpose::STANDARD.encode(b),
973 )
974 }
975 FieldValue::SparseVector(entries) => {
976 let indices: Vec<u32> = entries.iter().map(|(i, _)| *i).collect();
977 let values: Vec<f32> = entries.iter().map(|(_, v)| *v).collect();
978 serde_json::json!({
979 "indices": indices,
980 "values": values
981 })
982 }
983 FieldValue::DenseVector(values) => {
984 serde_json::json!(values)
985 }
986 FieldValue::Json(v) => v.clone(),
987 FieldValue::BinaryDenseVector(b) => {
988 use base64::Engine;
989 serde_json::Value::String(
990 base64::engine::general_purpose::STANDARD.encode(b),
991 )
992 }
993 };
994 field_values_map
995 .entry(*field)
996 .or_insert_with(|| (entry.name.clone(), entry.multi, Vec::new()))
997 .2
998 .push(json_value);
999 }
1000 }
1001
1002 let mut map = serde_json::Map::new();
1004 for (_field, (name, is_multi, values)) in field_values_map {
1005 let json_value = if is_multi || values.len() > 1 {
1006 serde_json::Value::Array(values)
1007 } else {
1008 values.into_iter().next().unwrap()
1009 };
1010 map.insert(name, json_value);
1011 }
1012
1013 serde_json::Value::Object(map)
1014 }
1015
1016 pub fn from_json(json: &serde_json::Value, schema: &Schema) -> Option<Self> {
1025 let obj = json.as_object()?;
1026 let mut doc = Document::new();
1027
1028 for (key, value) in obj {
1029 if let Some(field) = schema.get_field(key) {
1030 let field_entry = schema.get_field_entry(field)?;
1031 Self::add_json_value(&mut doc, field, &field_entry.field_type, value);
1032 }
1033 }
1034
1035 Some(doc)
1036 }
1037
1038 fn add_json_value(
1040 doc: &mut Document,
1041 field: Field,
1042 field_type: &FieldType,
1043 value: &serde_json::Value,
1044 ) {
1045 match value {
1046 serde_json::Value::String(s) => {
1047 if matches!(field_type, FieldType::Text) {
1048 doc.add_text(field, s.clone());
1049 }
1050 }
1051 serde_json::Value::Number(n) => {
1052 match field_type {
1053 FieldType::I64 => {
1054 if let Some(i) = n.as_i64() {
1055 doc.add_i64(field, i);
1056 }
1057 }
1058 FieldType::U64 => {
1059 if let Some(u) = n.as_u64() {
1060 doc.add_u64(field, u);
1061 } else if let Some(i) = n.as_i64() {
1062 if i >= 0 {
1064 doc.add_u64(field, i as u64);
1065 }
1066 }
1067 }
1068 FieldType::F64 => {
1069 if let Some(f) = n.as_f64() {
1070 doc.add_f64(field, f);
1071 }
1072 }
1073 _ => {}
1074 }
1075 }
1076 serde_json::Value::Array(arr) => {
1078 for item in arr {
1079 Self::add_json_value(doc, field, field_type, item);
1080 }
1081 }
1082 serde_json::Value::Object(obj) if matches!(field_type, FieldType::SparseVector) => {
1084 if let (Some(indices_val), Some(values_val)) =
1085 (obj.get("indices"), obj.get("values"))
1086 {
1087 let indices: Vec<u32> = indices_val
1088 .as_array()
1089 .map(|arr| {
1090 arr.iter()
1091 .filter_map(|v| v.as_u64().map(|n| n as u32))
1092 .collect()
1093 })
1094 .unwrap_or_default();
1095 let values: Vec<f32> = values_val
1096 .as_array()
1097 .map(|arr| {
1098 arr.iter()
1099 .filter_map(|v| v.as_f64().map(|n| n as f32))
1100 .collect()
1101 })
1102 .unwrap_or_default();
1103 if indices.len() == values.len() {
1104 let entries: Vec<(u32, f32)> = indices.into_iter().zip(values).collect();
1105 doc.add_sparse_vector(field, entries);
1106 }
1107 }
1108 }
1109 _ if matches!(field_type, FieldType::Json) => {
1111 doc.add_json(field, value.clone());
1112 }
1113 serde_json::Value::Object(_) => {}
1114 _ => {}
1115 }
1116 }
1117}
1118
1119#[cfg(test)]
1120mod tests {
1121 use super::*;
1122
1123 #[test]
1124 fn test_schema_builder() {
1125 let mut builder = Schema::builder();
1126 let title = builder.add_text_field("title", true, true);
1127 let body = builder.add_text_field("body", true, false);
1128 let count = builder.add_u64_field("count", true, true);
1129 let schema = builder.build();
1130
1131 assert_eq!(schema.get_field("title"), Some(title));
1132 assert_eq!(schema.get_field("body"), Some(body));
1133 assert_eq!(schema.get_field("count"), Some(count));
1134 assert_eq!(schema.get_field("nonexistent"), None);
1135 }
1136
1137 #[test]
1138 fn test_document() {
1139 let mut builder = Schema::builder();
1140 let title = builder.add_text_field("title", true, true);
1141 let count = builder.add_u64_field("count", true, true);
1142 let _schema = builder.build();
1143
1144 let mut doc = Document::new();
1145 doc.add_text(title, "Hello World");
1146 doc.add_u64(count, 42);
1147
1148 assert_eq!(doc.get_first(title).unwrap().as_text(), Some("Hello World"));
1149 assert_eq!(doc.get_first(count).unwrap().as_u64(), Some(42));
1150 }
1151
1152 #[test]
1153 fn test_document_serialization() {
1154 let mut builder = Schema::builder();
1155 let title = builder.add_text_field("title", true, true);
1156 let count = builder.add_u64_field("count", true, true);
1157 let _schema = builder.build();
1158
1159 let mut doc = Document::new();
1160 doc.add_text(title, "Hello World");
1161 doc.add_u64(count, 42);
1162
1163 let json = serde_json::to_string(&doc).unwrap();
1165 println!("Serialized doc: {}", json);
1166
1167 let doc2: Document = serde_json::from_str(&json).unwrap();
1169 assert_eq!(
1170 doc2.field_values().len(),
1171 2,
1172 "Should have 2 field values after deserialization"
1173 );
1174 assert_eq!(
1175 doc2.get_first(title).unwrap().as_text(),
1176 Some("Hello World")
1177 );
1178 assert_eq!(doc2.get_first(count).unwrap().as_u64(), Some(42));
1179 }
1180
1181 #[test]
1182 fn test_multivalue_field() {
1183 let mut builder = Schema::builder();
1184 let uris = builder.add_text_field("uris", true, true);
1185 let title = builder.add_text_field("title", true, true);
1186 let schema = builder.build();
1187
1188 let mut doc = Document::new();
1190 doc.add_text(uris, "one");
1191 doc.add_text(uris, "two");
1192 doc.add_text(title, "Test Document");
1193
1194 assert_eq!(doc.get_first(uris).unwrap().as_text(), Some("one"));
1196
1197 let all_uris: Vec<_> = doc.get_all(uris).collect();
1199 assert_eq!(all_uris.len(), 2);
1200 assert_eq!(all_uris[0].as_text(), Some("one"));
1201 assert_eq!(all_uris[1].as_text(), Some("two"));
1202
1203 let json = doc.to_json(&schema);
1205 let uris_json = json.get("uris").unwrap();
1206 assert!(uris_json.is_array(), "Multi-value field should be an array");
1207 let uris_arr = uris_json.as_array().unwrap();
1208 assert_eq!(uris_arr.len(), 2);
1209 assert_eq!(uris_arr[0].as_str(), Some("one"));
1210 assert_eq!(uris_arr[1].as_str(), Some("two"));
1211
1212 let title_json = json.get("title").unwrap();
1214 assert!(
1215 title_json.is_string(),
1216 "Single-value field should be a string"
1217 );
1218 assert_eq!(title_json.as_str(), Some("Test Document"));
1219 }
1220
1221 #[test]
1222 fn test_multivalue_from_json() {
1223 let mut builder = Schema::builder();
1224 let uris = builder.add_text_field("uris", true, true);
1225 let title = builder.add_text_field("title", true, true);
1226 let schema = builder.build();
1227
1228 let json = serde_json::json!({
1230 "uris": ["one", "two"],
1231 "title": "Test Document"
1232 });
1233
1234 let doc = Document::from_json(&json, &schema).unwrap();
1236
1237 let all_uris: Vec<_> = doc.get_all(uris).collect();
1239 assert_eq!(all_uris.len(), 2);
1240 assert_eq!(all_uris[0].as_text(), Some("one"));
1241 assert_eq!(all_uris[1].as_text(), Some("two"));
1242
1243 assert_eq!(
1245 doc.get_first(title).unwrap().as_text(),
1246 Some("Test Document")
1247 );
1248
1249 let json_out = doc.to_json(&schema);
1251 let uris_out = json_out.get("uris").unwrap().as_array().unwrap();
1252 assert_eq!(uris_out.len(), 2);
1253 assert_eq!(uris_out[0].as_str(), Some("one"));
1254 assert_eq!(uris_out[1].as_str(), Some("two"));
1255 }
1256
1257 #[test]
1258 fn test_multi_attribute_forces_array() {
1259 let mut builder = Schema::builder();
1262 let uris = builder.add_text_field("uris", true, true);
1263 builder.set_multi(uris, true); let title = builder.add_text_field("title", true, true);
1265 let schema = builder.build();
1266
1267 assert!(schema.get_field_entry(uris).unwrap().multi);
1269 assert!(!schema.get_field_entry(title).unwrap().multi);
1270
1271 let mut doc = Document::new();
1273 doc.add_text(uris, "only_one");
1274 doc.add_text(title, "Test Document");
1275
1276 let json = doc.to_json(&schema);
1278
1279 let uris_json = json.get("uris").unwrap();
1280 assert!(
1281 uris_json.is_array(),
1282 "Multi field should be array even with single value"
1283 );
1284 let uris_arr = uris_json.as_array().unwrap();
1285 assert_eq!(uris_arr.len(), 1);
1286 assert_eq!(uris_arr[0].as_str(), Some("only_one"));
1287
1288 let title_json = json.get("title").unwrap();
1290 assert!(
1291 title_json.is_string(),
1292 "Non-multi 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_sparse_vector_field() {
1299 let mut builder = Schema::builder();
1300 let embedding = builder.add_sparse_vector_field("embedding", true, true);
1301 let title = builder.add_text_field("title", true, true);
1302 let schema = builder.build();
1303
1304 assert_eq!(schema.get_field("embedding"), Some(embedding));
1305 assert_eq!(
1306 schema.get_field_entry(embedding).unwrap().field_type,
1307 FieldType::SparseVector
1308 );
1309
1310 let mut doc = Document::new();
1312 doc.add_sparse_vector(embedding, vec![(0, 1.0), (5, 2.5), (10, 0.5)]);
1313 doc.add_text(title, "Test Document");
1314
1315 let entries = doc
1317 .get_first(embedding)
1318 .unwrap()
1319 .as_sparse_vector()
1320 .unwrap();
1321 assert_eq!(entries, &[(0, 1.0), (5, 2.5), (10, 0.5)]);
1322
1323 let json = doc.to_json(&schema);
1325 let embedding_json = json.get("embedding").unwrap();
1326 assert!(embedding_json.is_object());
1327 assert_eq!(
1328 embedding_json
1329 .get("indices")
1330 .unwrap()
1331 .as_array()
1332 .unwrap()
1333 .len(),
1334 3
1335 );
1336
1337 let doc2 = Document::from_json(&json, &schema).unwrap();
1339 let entries2 = doc2
1340 .get_first(embedding)
1341 .unwrap()
1342 .as_sparse_vector()
1343 .unwrap();
1344 assert_eq!(entries2[0].0, 0);
1345 assert!((entries2[0].1 - 1.0).abs() < 1e-6);
1346 assert_eq!(entries2[1].0, 5);
1347 assert!((entries2[1].1 - 2.5).abs() < 1e-6);
1348 assert_eq!(entries2[2].0, 10);
1349 assert!((entries2[2].1 - 0.5).abs() < 1e-6);
1350 }
1351
1352 #[test]
1353 fn test_json_field() {
1354 let mut builder = Schema::builder();
1355 let metadata = builder.add_json_field("metadata", true);
1356 let title = builder.add_text_field("title", true, true);
1357 let schema = builder.build();
1358
1359 assert_eq!(schema.get_field("metadata"), Some(metadata));
1360 assert_eq!(
1361 schema.get_field_entry(metadata).unwrap().field_type,
1362 FieldType::Json
1363 );
1364 assert!(!schema.get_field_entry(metadata).unwrap().indexed);
1366 assert!(schema.get_field_entry(metadata).unwrap().stored);
1367
1368 let json_value = serde_json::json!({
1370 "author": "John Doe",
1371 "tags": ["rust", "search"],
1372 "nested": {"key": "value"}
1373 });
1374 let mut doc = Document::new();
1375 doc.add_json(metadata, json_value.clone());
1376 doc.add_text(title, "Test Document");
1377
1378 let stored_json = doc.get_first(metadata).unwrap().as_json().unwrap();
1380 assert_eq!(stored_json, &json_value);
1381 assert_eq!(
1382 stored_json.get("author").unwrap().as_str(),
1383 Some("John Doe")
1384 );
1385
1386 let doc_json = doc.to_json(&schema);
1388 let metadata_out = doc_json.get("metadata").unwrap();
1389 assert_eq!(metadata_out, &json_value);
1390
1391 let doc2 = Document::from_json(&doc_json, &schema).unwrap();
1393 let stored_json2 = doc2.get_first(metadata).unwrap().as_json().unwrap();
1394 assert_eq!(stored_json2, &json_value);
1395 }
1396
1397 #[test]
1398 fn test_json_field_various_types() {
1399 let mut builder = Schema::builder();
1400 let data = builder.add_json_field("data", true);
1401 let _schema = builder.build();
1402
1403 let arr_value = serde_json::json!([1, 2, 3, "four", null]);
1405 let mut doc = Document::new();
1406 doc.add_json(data, arr_value.clone());
1407 assert_eq!(doc.get_first(data).unwrap().as_json().unwrap(), &arr_value);
1408
1409 let str_value = serde_json::json!("just a string");
1411 let mut doc2 = Document::new();
1412 doc2.add_json(data, str_value.clone());
1413 assert_eq!(doc2.get_first(data).unwrap().as_json().unwrap(), &str_value);
1414
1415 let num_value = serde_json::json!(42.5);
1417 let mut doc3 = Document::new();
1418 doc3.add_json(data, num_value.clone());
1419 assert_eq!(doc3.get_first(data).unwrap().as_json().unwrap(), &num_value);
1420
1421 let null_value = serde_json::Value::Null;
1423 let mut doc4 = Document::new();
1424 doc4.add_json(data, null_value.clone());
1425 assert_eq!(
1426 doc4.get_first(data).unwrap().as_json().unwrap(),
1427 &null_value
1428 );
1429
1430 let bool_value = serde_json::json!(true);
1432 let mut doc5 = Document::new();
1433 doc5.add_json(data, bool_value.clone());
1434 assert_eq!(
1435 doc5.get_first(data).unwrap().as_json().unwrap(),
1436 &bool_value
1437 );
1438 }
1439}