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}