qdrant_client/qdrant_client/search.rs
1use crate::qdrant::{
2 DiscoverBatchPoints, DiscoverBatchResponse, DiscoverPoints, DiscoverResponse,
3 RecommendBatchPoints, RecommendBatchResponse, RecommendGroupsResponse, RecommendPointGroups,
4 RecommendPoints, RecommendResponse, SearchBatchPoints, SearchBatchResponse,
5 SearchGroupsResponse, SearchPointGroups, SearchPoints, SearchResponse,
6};
7use crate::qdrant_client::{Qdrant, QdrantResult};
8
9/// # Search operations
10///
11/// <div class="warning">
12/// For searching, please switch to the more fully featured <a href="#query-operations">Query API</a> instead. The search API will be removed in the future.
13/// </div>
14///
15/// Search and explore points.
16///
17/// Documentation: <https://qdrant.tech/documentation/concepts/search/>
18impl Qdrant {
19 /// Search points in a collection.
20 ///
21 /// ```no_run
22 ///# use qdrant_client::{Qdrant, QdrantError};
23 /// use qdrant_client::qdrant::{Condition, Filter, SearchParamsBuilder, SearchPointsBuilder};
24 ///
25 ///# async fn search_points(client: &Qdrant)
26 ///# -> Result<(), QdrantError> {
27 /// client
28 /// .search_points(
29 /// SearchPointsBuilder::new("my_collection", vec![0.2, 0.1, 0.9, 0.7], 3)
30 /// .filter(Filter::must([Condition::matches(
31 /// "city",
32 /// "London".to_string(),
33 /// )]))
34 /// .params(SearchParamsBuilder::default().hnsw_ef(128).exact(false)),
35 /// )
36 /// .await?;
37 ///# Ok(())
38 ///# }
39 /// ```
40 ///
41 /// Documentation: <https://qdrant.tech/documentation/concepts/search/#search-api>
42 pub async fn search_points(
43 &self,
44 request: impl Into<SearchPoints>,
45 ) -> QdrantResult<SearchResponse> {
46 let request = &request.into();
47
48 self.with_points_client(|mut points_api| async move {
49 let result = points_api.search(request.clone()).await?;
50 Ok(result.into_inner())
51 })
52 .await
53 }
54
55 /// Batch multiple points searches in a collection.
56 ///
57 /// ```no_run
58 ///# use qdrant_client::{Qdrant, QdrantError};
59 /// use qdrant_client::qdrant::{Condition, Filter, SearchBatchPointsBuilder, SearchPointsBuilder,};
60 ///
61 ///# async fn search_batch_points(client: &Qdrant)
62 ///# -> Result<(), QdrantError> {
63 /// let filter = Filter::must([Condition::matches("city", "London".to_string())]);
64 ///
65 /// let searches = vec![
66 /// SearchPointsBuilder::new("my_collection", vec![0.2, 0.1, 0.9, 0.7], 3)
67 /// .filter(filter.clone())
68 /// .build(),
69 /// SearchPointsBuilder::new("my_collection", vec![0.5, 0.3, 0.2, 0.3], 3)
70 /// .filter(filter)
71 /// .build(),
72 /// ];
73 ///
74 /// client
75 /// .search_batch_points(SearchBatchPointsBuilder::new("my_collection", searches))
76 /// .await?;
77 ///# Ok(())
78 ///# }
79 /// ```
80 ///
81 /// Documentation: <https://qdrant.tech/documentation/concepts/search/#batch-search-api>
82 pub async fn search_batch_points(
83 &self,
84 request: impl Into<SearchBatchPoints>,
85 ) -> QdrantResult<SearchBatchResponse> {
86 let request = &request.into();
87
88 self.with_points_client(|mut points_api| async move {
89 let result = points_api.search_batch(request.clone()).await?;
90 Ok(result.into_inner())
91 })
92 .await
93 }
94
95 /// Search points in a collection and group results by a payload field.
96 ///
97 /// ```no_run
98 ///# use qdrant_client::{Qdrant, QdrantError};
99 /// use qdrant_client::qdrant::SearchPointGroupsBuilder;
100 ///
101 ///# async fn search_points(client: &Qdrant)
102 ///# -> Result<(), QdrantError> {
103 /// client
104 /// .search_groups(SearchPointGroupsBuilder::new(
105 /// "my_collection", // Collection name
106 /// vec![1.1], // Search vector
107 /// 4, // Search limit
108 /// "document_id", // Group by field
109 /// 2, // Group size
110 /// ))
111 /// .await?;
112 ///# Ok(())
113 ///# }
114 /// ```
115 ///
116 /// Documentation: <https://qdrant.tech/documentation/concepts/search/#search-groups>
117 pub async fn search_groups(
118 &self,
119 request: impl Into<SearchPointGroups>,
120 ) -> QdrantResult<SearchGroupsResponse> {
121 let request = &request.into();
122
123 self.with_points_client(|mut points_api| async move {
124 let result = points_api.search_groups(request.clone()).await?;
125 Ok(result.into_inner())
126 })
127 .await
128 }
129
130 /// Recommend points in a collection.
131 ///
132 /// ```no_run
133 ///# use qdrant_client::{Qdrant, QdrantError};
134 /// use qdrant_client::qdrant::{Condition, Filter, RecommendPointsBuilder, RecommendStrategy};
135 ///
136 ///# async fn recommend(client: &Qdrant)
137 ///# -> Result<(), QdrantError> {
138 /// client
139 /// .recommend(
140 /// RecommendPointsBuilder::new("my_collection", 3)
141 /// .add_positive(100)
142 /// .add_positive(200)
143 /// .add_positive(vec![100.0, 231.0])
144 /// .add_negative(718)
145 /// .add_negative(vec![0.2, 0.3, 0.4, 0.5])
146 /// .strategy(RecommendStrategy::AverageVector)
147 /// .filter(Filter::must([Condition::matches(
148 /// "city",
149 /// "London".to_string(),
150 /// )])),
151 /// )
152 /// .await?;
153 ///# Ok(())
154 ///# }
155 /// ```
156 ///
157 /// Documentation: <https://qdrant.tech/documentation/concepts/explore/#recommendation-api>
158 pub async fn recommend(
159 &self,
160 request: impl Into<RecommendPoints>,
161 ) -> QdrantResult<RecommendResponse> {
162 let request = &request.into();
163
164 self.with_points_client(|mut points_api| async move {
165 let result = points_api.recommend(request.clone()).await?;
166 Ok(result.into_inner())
167 })
168 .await
169 }
170
171 /// Batch multiple points recommendations in a collection.
172 ///
173 /// ```no_run
174 ///# use qdrant_client::{Qdrant, QdrantError};
175 /// use qdrant_client::qdrant::{Condition, Filter, RecommendBatchPointsBuilder, RecommendPointsBuilder};
176 ///
177 ///# async fn recommend_batch(client: &Qdrant)
178 ///# -> Result<(), QdrantError> {
179 /// let filter = Filter::must([Condition::matches("city", "London".to_string())]);
180 ///
181 /// let recommend_queries = vec![
182 /// RecommendPointsBuilder::new("my_collection", 3)
183 /// .add_positive(100)
184 /// .add_positive(231)
185 /// .add_negative(718)
186 /// .filter(filter.clone())
187 /// .build(),
188 /// RecommendPointsBuilder::new("my_collection", 3)
189 /// .add_positive(200)
190 /// .add_positive(67)
191 /// .add_negative(300)
192 /// .filter(filter.clone())
193 /// .build(),
194 /// ];
195 ///
196 /// client
197 /// .recommend_batch(RecommendBatchPointsBuilder::new(
198 /// "my_collection",
199 /// recommend_queries,
200 /// ))
201 /// .await?;
202 ///# Ok(())
203 ///# }
204 /// ```
205 ///
206 /// Documentation: <https://qdrant.tech/documentation/concepts/explore/#batch-recommendation-api>
207 pub async fn recommend_batch(
208 &self,
209 request: impl Into<RecommendBatchPoints>,
210 ) -> QdrantResult<RecommendBatchResponse> {
211 let request = &request.into();
212
213 self.with_points_client(|mut points_api| async move {
214 let result = points_api.recommend_batch(request.clone()).await?;
215 Ok(result.into_inner())
216 })
217 .await
218 }
219
220 /// Recommend points in a collection and group results by a payload field.
221 ///
222 /// ```no_run
223 ///# use qdrant_client::{Qdrant, QdrantError};
224 /// use qdrant_client::qdrant::{RecommendPointGroupsBuilder, RecommendStrategy};
225 ///
226 ///# async fn recommend_groups(client: &Qdrant)
227 ///# -> Result<(), QdrantError> {
228 /// client
229 /// .recommend_groups(
230 /// RecommendPointGroupsBuilder::new(
231 /// "my_collection", // Collection name
232 /// "document_id", // Group by field
233 /// 2, // Group size
234 /// 3, // Search limit
235 /// )
236 /// .add_positive(100)
237 /// .add_positive(200)
238 /// .add_negative(718)
239 /// .strategy(RecommendStrategy::AverageVector),
240 /// )
241 /// .await?;
242 ///# Ok(())
243 ///# }
244 /// ```
245 ///
246 /// Documentation: <https://qdrant.tech/documentation/concepts/explore/#recommendation-api>
247 pub async fn recommend_groups(
248 &self,
249 request: impl Into<RecommendPointGroups>,
250 ) -> QdrantResult<RecommendGroupsResponse> {
251 let request = &request.into();
252
253 self.with_points_client(|mut points_api| async move {
254 let result = points_api.recommend_groups(request.clone()).await?;
255 Ok(result.into_inner())
256 })
257 .await
258 }
259
260 /// Discover points in a collection.
261 ///
262 /// ```no_run
263 ///# use qdrant_client::{Qdrant, QdrantError};
264 /// use qdrant_client::qdrant::{
265 /// target_vector::Target, vector_example::Example, ContextExamplePairBuilder,
266 /// DiscoverPointsBuilder, VectorExample,
267 /// };
268 ///
269 ///# async fn discover(client: &Qdrant)
270 ///# -> Result<(), QdrantError> {
271 /// client
272 /// .discover(
273 /// DiscoverPointsBuilder::new(
274 /// "my_collection", // Collection name
275 /// vec![
276 /// ContextExamplePairBuilder::default()
277 /// .positive(Example::Id(100.into()))
278 /// .negative(Example::Id(718.into()))
279 /// .build(),
280 /// ContextExamplePairBuilder::default()
281 /// .positive(Example::Id(200.into()))
282 /// .negative(Example::Id(300.into()))
283 /// .build(),
284 /// ],
285 /// 10, // Search limit
286 /// )
287 /// .target(Target::Single(VectorExample {
288 /// example: Some(Example::Vector(vec![0.2, 0.1, 0.9, 0.7].into())),
289 /// })),
290 /// )
291 /// .await?;
292 ///# Ok(())
293 ///# }
294 /// ```
295 ///
296 /// Documentation: <https://qdrant.tech/documentation/concepts/explore/#discovery-api>
297 pub async fn discover(
298 &self,
299 request: impl Into<DiscoverPoints>,
300 ) -> QdrantResult<DiscoverResponse> {
301 let request = &request.into();
302
303 self.with_points_client(|mut points_api| async move {
304 let result = points_api.discover(request.clone()).await?;
305 Ok(result.into_inner())
306 })
307 .await
308 }
309
310 /// Batch multiple point discoveries in a collection.
311 ///
312 /// ```no_run
313 ///# use qdrant_client::{Qdrant, QdrantError};
314 /// use qdrant_client::qdrant::{
315 /// vector_example::Example, ContextExamplePairBuilder, DiscoverBatchPointsBuilder,
316 /// DiscoverPointsBuilder,
317 /// };
318 ///
319 ///# async fn discover_batch(client: &Qdrant)
320 ///# -> Result<(), QdrantError> {
321 /// let discover_points = DiscoverBatchPointsBuilder::new(
322 /// "my_collection",
323 /// vec![
324 /// DiscoverPointsBuilder::new(
325 /// "my_collection",
326 /// vec![
327 /// ContextExamplePairBuilder::default()
328 /// .positive(Example::Id(100.into()))
329 /// .negative(Example::Id(718.into()))
330 /// .build(),
331 /// ContextExamplePairBuilder::default()
332 /// .positive(Example::Id(200.into()))
333 /// .negative(Example::Id(300.into()))
334 /// .build(),
335 /// ],
336 /// 10,
337 /// )
338 /// .build(),
339 /// DiscoverPointsBuilder::new(
340 /// "my_collection",
341 /// vec![
342 /// ContextExamplePairBuilder::default()
343 /// .positive(Example::Id(342.into()))
344 /// .negative(Example::Id(213.into()))
345 /// .build(),
346 /// ContextExamplePairBuilder::default()
347 /// .positive(Example::Id(100.into()))
348 /// .negative(Example::Id(200.into()))
349 /// .build(),
350 /// ],
351 /// 10,
352 /// )
353 /// .build(),
354 /// ],
355 /// );
356 ///
357 /// client.discover_batch(&discover_points.build()).await?;
358 ///# Ok(())
359 ///# }
360 /// ```
361 ///
362 /// Documentation: <https://qdrant.tech/documentation/concepts/explore/#discovery-api>
363 pub async fn discover_batch(
364 &self,
365 request: &DiscoverBatchPoints,
366 ) -> QdrantResult<DiscoverBatchResponse> {
367 self.with_points_client(|mut points_api| async move {
368 let result = points_api.discover_batch(request.clone()).await?;
369 Ok(result.into_inner())
370 })
371 .await
372 }
373}