Skip to main content

qail_qdrant/
point.rs

1//! Point and payload types for Qdrant.
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6/// Point ID - either UUID string or integer.
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub enum PointId {
9    /// UUID string identifier.
10    Uuid(String),
11    /// Numeric identifier.
12    Num(u64),
13}
14
15impl From<&str> for PointId {
16    fn from(s: &str) -> Self {
17        PointId::Uuid(s.to_string())
18    }
19}
20
21impl From<String> for PointId {
22    fn from(s: String) -> Self {
23        PointId::Uuid(s)
24    }
25}
26
27impl From<u64> for PointId {
28    fn from(n: u64) -> Self {
29        PointId::Num(n)
30    }
31}
32
33/// Payload value types.
34#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
35#[serde(untagged)]
36pub enum PayloadValue {
37    /// UTF-8 string value.
38    String(String),
39    /// Signed 64-bit integer.
40    Integer(i64),
41    /// 64-bit floating-point number.
42    Float(f64),
43    /// Boolean value.
44    Bool(bool),
45    /// Ordered list of nested payload values.
46    List(Vec<PayloadValue>),
47    /// Nested key-value object.
48    Object(HashMap<String, PayloadValue>),
49    /// Explicit null / absent value.
50    Null,
51}
52
53/// Payload - key-value metadata attached to points.
54pub type Payload = HashMap<String, PayloadValue>;
55
56/// A point in Qdrant - vector + payload + id.
57#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
58pub struct Point {
59    /// Unique point identifier (UUID string or integer).
60    pub id: PointId,
61    /// Dense embedding vector.
62    pub vector: Vec<f32>,
63    /// Key-value metadata payload.
64    #[serde(default)]
65    pub payload: Payload,
66}
67
68impl Point {
69    /// Create a new point with a string/UUID ID.
70    pub fn new(id: impl Into<PointId>, vector: Vec<f32>) -> Self {
71        Self {
72            id: id.into(),
73            vector,
74            payload: HashMap::new(),
75        }
76    }
77
78    /// Create a new point with a numeric ID.
79    pub fn new_num(id: u64, vector: Vec<f32>) -> Self {
80        Self {
81            id: PointId::Num(id),
82            vector,
83            payload: HashMap::new(),
84        }
85    }
86
87    /// Add payload field.
88    pub fn with_payload(mut self, key: impl Into<String>, value: impl Into<PayloadValue>) -> Self {
89        self.payload.insert(key.into(), value.into());
90        self
91    }
92}
93
94/// Sparse vector - only non-zero indices and their values.
95#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
96pub struct SparseVector {
97    /// Indices of non-zero elements.
98    pub indices: Vec<u32>,
99    /// Values at those indices.
100    pub values: Vec<f32>,
101}
102
103impl SparseVector {
104    /// Create a sparse vector from indices and values.
105    pub fn new(indices: Vec<u32>, values: Vec<f32>) -> Self {
106        Self { indices, values }
107    }
108
109    /// Create from a dense vector (only keeps non-zero elements).
110    pub fn from_dense(dense: &[f32], threshold: f32) -> Self {
111        let mut indices = Vec::new();
112        let mut values = Vec::new();
113        for (i, &v) in dense.iter().enumerate() {
114            if v.abs() > threshold {
115                indices.push(i as u32);
116                values.push(v);
117            }
118        }
119        Self { indices, values }
120    }
121}
122
123/// Vector type that can be named or anonymous.
124#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
125#[serde(untagged)]
126pub enum VectorData {
127    /// Single unnamed vector.
128    Single(Vec<f32>),
129    /// Named vectors (for multi-vector collections).
130    Named(HashMap<String, Vec<f32>>),
131    /// Sparse vector.
132    Sparse {
133        /// Indices of non-zero elements.
134        indices: Vec<u32>,
135        /// Values at those indices.
136        values: Vec<f32>,
137    },
138}
139
140/// A point with named vector support (for multi-vector collections).
141#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
142pub struct MultiVectorPoint {
143    /// Unique point identifier.
144    pub id: PointId,
145    /// Named vectors — key is vector name, value is the embedding.
146    pub vectors: HashMap<String, Vec<f32>>,
147    /// Key-value metadata payload.
148    #[serde(default)]
149    pub payload: Payload,
150}
151
152impl MultiVectorPoint {
153    /// Create a new multi-vector point.
154    pub fn new(id: impl Into<PointId>) -> Self {
155        Self {
156            id: id.into(),
157            vectors: HashMap::new(),
158            payload: HashMap::new(),
159        }
160    }
161
162    /// Add a named vector.
163    pub fn with_vector(mut self, name: impl Into<String>, vector: Vec<f32>) -> Self {
164        self.vectors.insert(name.into(), vector);
165        self
166    }
167
168    /// Add payload field.
169    pub fn with_payload(mut self, key: impl Into<String>, value: impl Into<PayloadValue>) -> Self {
170        self.payload.insert(key.into(), value.into());
171        self
172    }
173}
174
175/// Search result - point with similarity score.
176#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
177pub struct ScoredPoint {
178    /// Point identifier.
179    pub id: PointId,
180    /// Similarity score (higher = more similar for cosine/dot, lower for euclidean).
181    pub score: f32,
182    /// Key-value metadata payload.
183    #[serde(default)]
184    pub payload: Payload,
185    /// Optional dense vector (returned when `with_vectors = true`).
186    #[serde(default)]
187    pub vector: Option<Vec<f32>>,
188}
189
190// Convenient From implementations for PayloadValue
191impl From<String> for PayloadValue {
192    fn from(s: String) -> Self {
193        PayloadValue::String(s)
194    }
195}
196
197impl From<&str> for PayloadValue {
198    fn from(s: &str) -> Self {
199        PayloadValue::String(s.to_string())
200    }
201}
202
203impl From<i64> for PayloadValue {
204    fn from(n: i64) -> Self {
205        PayloadValue::Integer(n)
206    }
207}
208
209impl From<f64> for PayloadValue {
210    fn from(n: f64) -> Self {
211        PayloadValue::Float(n)
212    }
213}
214
215impl From<bool> for PayloadValue {
216    fn from(b: bool) -> Self {
217        PayloadValue::Bool(b)
218    }
219}