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