distx_core/
point.rs

1use serde::{Deserialize, Serialize};
2use uuid::Uuid;
3use crate::vector::Vector;
4use crate::multivector::MultiVector;
5
6/// Vector data - can be a single dense vector or a multivector (ColBERT-style)
7#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
8#[serde(untagged)]
9pub enum VectorData {
10    /// Single dense vector
11    Single(Vector),
12    /// Multiple vectors per point (ColBERT-style late interaction)
13    Multi(MultiVector),
14}
15
16impl VectorData {
17    /// Get dimension of the vector(s)
18    pub fn dim(&self) -> usize {
19        match self {
20            VectorData::Single(v) => v.dim(),
21            VectorData::Multi(mv) => mv.dim(),
22        }
23    }
24    
25    /// Check if this is a multivector
26    pub fn is_multi(&self) -> bool {
27        matches!(self, VectorData::Multi(_))
28    }
29    
30    /// Get as single vector (for backwards compatibility)
31    /// For multivector, returns the first sub-vector
32    pub fn as_single(&self) -> Vector {
33        match self {
34            VectorData::Single(v) => v.clone(),
35            VectorData::Multi(mv) => mv.to_single_vector(),
36        }
37    }
38    
39    /// Get as slice (for single vectors only)
40    pub fn as_slice(&self) -> &[f32] {
41        match self {
42            VectorData::Single(v) => v.as_slice(),
43            VectorData::Multi(mv) => mv.vectors().first().map(|v| v.as_slice()).unwrap_or(&[]),
44        }
45    }
46}
47
48impl From<Vector> for VectorData {
49    fn from(v: Vector) -> Self {
50        VectorData::Single(v)
51    }
52}
53
54impl From<MultiVector> for VectorData {
55    fn from(mv: MultiVector) -> Self {
56        VectorData::Multi(mv)
57    }
58}
59
60/// A point in the vector space with optional payload
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct Point {
63    pub id: PointId,
64    /// Vector data - backwards compatible field name
65    #[serde(alias = "vectors")]
66    pub vector: Vector,
67    /// Optional multivector data for ColBERT-style search
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub multivector: Option<MultiVector>,
70    pub payload: Option<serde_json::Value>,
71}
72
73#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
74#[serde(untagged)]
75pub enum PointId {
76    String(String),
77    Uuid(Uuid),
78    Integer(u64),
79}
80
81impl std::fmt::Display for PointId {
82    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83        match self {
84            PointId::String(s) => write!(f, "{}", s),
85            PointId::Uuid(u) => write!(f, "{}", u),
86            PointId::Integer(i) => write!(f, "{}", i),
87        }
88    }
89}
90
91impl From<String> for PointId {
92    fn from(s: String) -> Self {
93        PointId::String(s)
94    }
95}
96
97impl From<u64> for PointId {
98    fn from(i: u64) -> Self {
99        PointId::Integer(i)
100    }
101}
102
103impl From<Uuid> for PointId {
104    fn from(u: Uuid) -> Self {
105        PointId::Uuid(u)
106    }
107}
108
109impl Point {
110    /// Create a new point with a single dense vector
111    #[inline]
112    #[must_use]
113    pub fn new(id: PointId, vector: Vector, payload: Option<serde_json::Value>) -> Self {
114        Self {
115            id,
116            vector,
117            multivector: None,
118            payload,
119        }
120    }
121    
122    /// Create a new point with a multivector (ColBERT-style)
123    #[inline]
124    #[must_use]
125    pub fn new_multi(id: PointId, multivector: MultiVector, payload: Option<serde_json::Value>) -> Self {
126        // Store first sub-vector as the primary vector for backwards compatibility
127        let vector = multivector.to_single_vector();
128        Self {
129            id,
130            vector,
131            multivector: Some(multivector),
132            payload,
133        }
134    }
135    
136    /// Check if this point has multivector data
137    #[inline]
138    pub fn has_multivector(&self) -> bool {
139        self.multivector.is_some()
140    }
141    
142    /// Get the multivector if present
143    #[inline]
144    pub fn get_multivector(&self) -> Option<&MultiVector> {
145        self.multivector.as_ref()
146    }
147
148    #[inline]
149    #[must_use]
150    pub fn with_payload(mut self, payload: serde_json::Value) -> Self {
151        self.payload = Some(payload);
152        self
153    }
154    
155    #[inline]
156    #[must_use]
157    pub fn with_multivector(mut self, multivector: MultiVector) -> Self {
158        self.multivector = Some(multivector);
159        self
160    }
161}
162