qail_core/ast/cmd/vector.rs
1//! Vector database builder methods for Qdrant.
2
3use crate::ast::{Action, Qail};
4
5impl Qail {
6 /// Create a vector similarity search command.
7 ///
8 /// # Example
9 /// ```ignore
10 /// use qail_core::prelude::*;
11 ///
12 /// let cmd = Qail::search("products")
13 /// .vector(vec![0.1, 0.2, 0.3])
14 /// .limit(10);
15 /// ```
16 pub fn search(collection: &str) -> Self {
17 Self {
18 action: Action::Search,
19 table: collection.to_string(),
20 ..Default::default()
21 }
22 }
23
24 /// Create a vector upsert command (insert or update points).
25 ///
26 /// # Example
27 /// ```ignore
28 /// let cmd = Qail::upsert("products");
29 /// ```
30 pub fn upsert(collection: &str) -> Self {
31 Self {
32 action: Action::Upsert,
33 table: collection.to_string(),
34 ..Default::default()
35 }
36 }
37
38 /// Create a scroll command for paginated iteration.
39 ///
40 /// # Example
41 /// ```ignore
42 /// let cmd = Qail::scroll("products").limit(100);
43 /// ```
44 pub fn scroll(collection: &str) -> Self {
45 Self {
46 action: Action::Scroll,
47 table: collection.to_string(),
48 ..Default::default()
49 }
50 }
51
52 /// Set the query vector for similarity search.
53 ///
54 /// # Example
55 /// ```
56 /// use qail_core::prelude::*;
57 ///
58 /// let embedding = vec![0.1, 0.2, 0.3, 0.4];
59 /// let cmd = Qail::search("products").vector(embedding);
60 /// assert!(cmd.vector.is_some());
61 /// ```
62 pub fn vector(mut self, embedding: Vec<f32>) -> Self {
63 self.vector = Some(embedding);
64 self
65 }
66
67 /// Set minimum similarity score threshold.
68 ///
69 /// Points with similarity below this threshold will be filtered out.
70 ///
71 /// # Example
72 /// ```
73 /// use qail_core::prelude::*;
74 ///
75 /// let cmd = Qail::search("products")
76 /// .vector(vec![0.1, 0.2])
77 /// .score_threshold(0.8);
78 /// assert_eq!(cmd.score_threshold, Some(0.8));
79 /// ```
80 pub fn score_threshold(mut self, threshold: f32) -> Self {
81 self.score_threshold = Some(threshold);
82 self
83 }
84
85 /// Specify which named vector to search (for multi-vector collections).
86 ///
87 /// # Example
88 /// ```
89 /// use qail_core::prelude::*;
90 ///
91 /// // Collection with separate "title" and "content" vectors
92 /// let title_embedding = vec![0.1, 0.2, 0.3];
93 /// let cmd = Qail::search("articles")
94 /// .vector_name("title")
95 /// .vector(title_embedding);
96 /// ```
97 pub fn vector_name(mut self, name: &str) -> Self {
98 self.vector_name = Some(name.to_string());
99 self
100 }
101
102 /// Include vectors in search results.
103 ///
104 /// # Example
105 /// ```
106 /// use qail_core::prelude::*;
107 ///
108 /// let embedding = vec![0.1, 0.2, 0.3];
109 /// let cmd = Qail::search("products")
110 /// .vector(embedding)
111 /// .with_vectors();
112 /// assert!(cmd.with_vector);
113 /// ```
114 pub fn with_vectors(mut self) -> Self {
115 self.with_vector = true;
116 self
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 #[test]
125 fn test_search_builder() {
126 let cmd = Qail::search("products")
127 .vector(vec![0.1, 0.2, 0.3])
128 .score_threshold(0.8)
129 .limit(10);
130
131 assert_eq!(cmd.action, Action::Search);
132 assert_eq!(cmd.table, "products");
133 assert_eq!(cmd.vector, Some(vec![0.1, 0.2, 0.3]));
134 assert_eq!(cmd.score_threshold, Some(0.8));
135 }
136
137 #[test]
138 fn test_vector_name() {
139 let cmd = Qail::search("articles")
140 .vector_name("title")
141 .vector(vec![0.5, 0.5]);
142
143 assert_eq!(cmd.vector_name, Some("title".to_string()));
144 }
145
146 #[test]
147 fn test_with_vectors() {
148 let cmd = Qail::search("products")
149 .vector(vec![0.1])
150 .with_vectors();
151
152 assert!(cmd.with_vector);
153 }
154}