fred/commands/interfaces/
redisearch.rs

1use crate::{
2  commands,
3  interfaces::{ClientLike, FredResult},
4  prelude::Error,
5  types::{
6    redisearch::{
7      FtAggregateOptions,
8      FtAlterOptions,
9      FtCreateOptions,
10      FtSearchOptions,
11      SearchSchema,
12      SpellcheckTerms,
13    },
14    FromValue,
15    Key,
16    MultipleStrings,
17    Value,
18  },
19};
20use bytes::Bytes;
21use bytes_utils::Str;
22use fred_macros::rm_send_if;
23use std::future::Future;
24
25/// A [RediSearch](https://github.com/RediSearch/RediSearch) interface.
26#[cfg_attr(docsrs, doc(cfg(feature = "i-redisearch")))]
27#[rm_send_if(feature = "glommio")]
28pub trait RediSearchInterface: ClientLike + Sized {
29  /// Returns a list of all existing indexes.
30  ///
31  /// <https://redis.io/docs/latest/commands/ft._list/>
32  fn ft_list<R>(&self) -> impl Future<Output = FredResult<R>> + Send
33  where
34    R: FromValue,
35  {
36    async move { commands::redisearch::ft_list(self).await?.convert() }
37  }
38
39  /// Run a search query on an index, and perform aggregate transformations on the results.
40  ///
41  /// <https://redis.io/docs/latest/commands/ft.aggregate/>
42  fn ft_aggregate<R, I, Q>(
43    &self,
44    index: I,
45    query: Q,
46    options: FtAggregateOptions,
47  ) -> impl Future<Output = FredResult<R>> + Send
48  where
49    R: FromValue,
50    I: Into<Str> + Send,
51    Q: Into<Str> + Send,
52  {
53    async move {
54      into!(index, query);
55      commands::redisearch::ft_aggregate(self, index, query, options)
56        .await?
57        .convert()
58    }
59  }
60
61  /// Search the index with a textual query, returning either documents or just ids.
62  ///
63  /// <https://redis.io/docs/latest/commands/ft.search/>
64  ///
65  /// Note: `FT.SEARCH` uses a different format in RESP3 mode.
66  fn ft_search<R, I, Q>(
67    &self,
68    index: I,
69    query: Q,
70    options: FtSearchOptions,
71  ) -> impl Future<Output = FredResult<R>> + Send
72  where
73    R: FromValue,
74    I: Into<Str> + Send,
75    Q: Into<Str> + Send,
76  {
77    async move {
78      into!(index, query);
79      commands::redisearch::ft_search(self, index, query, options)
80        .await?
81        .convert()
82    }
83  }
84
85  /// Create an index with the given specification.
86  ///
87  /// <https://redis.io/docs/latest/commands/ft.create/>
88  fn ft_create<R, I>(
89    &self,
90    index: I,
91    options: FtCreateOptions,
92    schema: Vec<SearchSchema>,
93  ) -> impl Future<Output = FredResult<R>> + Send
94  where
95    R: FromValue,
96    I: Into<Str> + Send,
97  {
98    async move {
99      into!(index);
100      commands::redisearch::ft_create(self, index, options, schema)
101        .await?
102        .convert()
103    }
104  }
105
106  /// Add a new attribute to the index.
107  ///
108  /// <https://redis.io/docs/latest/commands/ft.alter/>
109  fn ft_alter<R, I>(&self, index: I, options: FtAlterOptions) -> impl Future<Output = FredResult<R>> + Send
110  where
111    R: FromValue,
112    I: Into<Str> + Send,
113  {
114    async move {
115      into!(index);
116      commands::redisearch::ft_alter(self, index, options).await?.convert()
117    }
118  }
119
120  /// Add an alias to an index.
121  ///
122  /// <https://redis.io/docs/latest/commands/ft.aliasadd/>
123  fn ft_aliasadd<R, A, I>(&self, alias: A, index: I) -> impl Future<Output = FredResult<R>> + Send
124  where
125    R: FromValue,
126    A: Into<Str> + Send,
127    I: Into<Str> + Send,
128  {
129    async move {
130      into!(alias, index);
131      commands::redisearch::ft_aliasadd(self, alias, index).await?.convert()
132    }
133  }
134
135  /// Remove an alias from an index.
136  ///
137  /// <https://redis.io/docs/latest/commands/ft.aliasdel/>
138  fn ft_aliasdel<R, A>(&self, alias: A) -> impl Future<Output = FredResult<R>> + Send
139  where
140    R: FromValue,
141    A: Into<Str> + Send,
142  {
143    async move {
144      into!(alias);
145      commands::redisearch::ft_aliasdel(self, alias).await?.convert()
146    }
147  }
148
149  /// Add an alias to an index. If the alias is already associated with another index, FT.ALIASUPDATE removes the
150  /// alias association with the previous index.
151  ///
152  /// <https://redis.io/docs/latest/commands/ft.aliasupdate/>
153  fn ft_aliasupdate<R, A, I>(&self, alias: A, index: I) -> impl Future<Output = FredResult<R>> + Send
154  where
155    R: FromValue,
156    A: Into<Str> + Send,
157    I: Into<Str> + Send,
158  {
159    async move {
160      into!(alias, index);
161      commands::redisearch::ft_aliasupdate(self, alias, index)
162        .await?
163        .convert()
164    }
165  }
166
167  /// Retrieve configuration options.
168  ///
169  /// <https://redis.io/docs/latest/commands/ft.config-get/>
170  fn ft_config_get<R, S>(&self, option: S) -> impl Future<Output = FredResult<R>> + Send
171  where
172    R: FromValue,
173    S: Into<Str> + Send,
174  {
175    async move {
176      into!(option);
177      commands::redisearch::ft_config_get(self, option).await?.convert()
178    }
179  }
180
181  /// Set the value of a RediSearch configuration parameter.
182  ///
183  /// <https://redis.io/docs/latest/commands/ft.config-set/>
184  fn ft_config_set<R, S, V>(&self, option: S, value: V) -> impl Future<Output = FredResult<R>> + Send
185  where
186    R: FromValue,
187    S: Into<Str> + Send,
188    V: TryInto<Value> + Send,
189    V::Error: Into<Error> + Send,
190  {
191    async move {
192      into!(option);
193      try_into!(value);
194      commands::redisearch::ft_config_set(self, option, value)
195        .await?
196        .convert()
197    }
198  }
199
200  /// Delete a cursor.
201  ///
202  /// <https://redis.io/docs/latest/commands/ft.cursor-del/>
203  fn ft_cursor_del<R, I, C>(&self, index: I, cursor: C) -> impl Future<Output = FredResult<R>> + Send
204  where
205    R: FromValue,
206    I: Into<Str> + Send,
207    C: TryInto<Value> + Send,
208    C::Error: Into<Error> + Send,
209  {
210    async move {
211      into!(index);
212      try_into!(cursor);
213      commands::redisearch::ft_cursor_del(self, index, cursor)
214        .await?
215        .convert()
216    }
217  }
218
219  /// Read next results from an existing cursor.
220  ///
221  /// <https://redis.io/docs/latest/commands/ft.cursor-read/>
222  fn ft_cursor_read<R, I, C>(
223    &self,
224    index: I,
225    cursor: C,
226    count: Option<u64>,
227  ) -> impl Future<Output = FredResult<R>> + Send
228  where
229    R: FromValue,
230    I: Into<Str> + Send,
231    C: TryInto<Value> + Send,
232    C::Error: Into<Error> + Send,
233  {
234    async move {
235      into!(index);
236      try_into!(cursor);
237      commands::redisearch::ft_cursor_read(self, index, cursor, count)
238        .await?
239        .convert()
240    }
241  }
242
243  /// Add terms to a dictionary.
244  ///
245  /// <https://redis.io/docs/latest/commands/ft.dictadd/>
246  fn ft_dictadd<R, D, S>(&self, dict: D, terms: S) -> impl Future<Output = FredResult<R>>
247  where
248    R: FromValue,
249    D: Into<Str> + Send,
250    S: Into<MultipleStrings> + Send,
251  {
252    async move {
253      into!(dict, terms);
254      commands::redisearch::ft_dictadd(self, dict, terms).await?.convert()
255    }
256  }
257
258  /// Remove terms from a dictionary.
259  ///
260  /// <https://redis.io/docs/latest/commands/ft.dictdel/>
261  fn ft_dictdel<R, D, S>(&self, dict: D, terms: S) -> impl Future<Output = FredResult<R>>
262  where
263    R: FromValue,
264    D: Into<Str> + Send,
265    S: Into<MultipleStrings> + Send,
266  {
267    async move {
268      into!(dict, terms);
269      commands::redisearch::ft_dictdel(self, dict, terms).await?.convert()
270    }
271  }
272
273  /// Dump all terms in the given dictionary.
274  ///
275  /// <https://redis.io/docs/latest/commands/ft.dictdump/>
276  fn ft_dictdump<R, D>(&self, dict: D) -> impl Future<Output = FredResult<R>>
277  where
278    R: FromValue,
279    D: Into<Str> + Send,
280  {
281    async move {
282      into!(dict);
283      commands::redisearch::ft_dictdump(self, dict).await?.convert()
284    }
285  }
286
287  /// Delete an index.
288  ///
289  /// <https://redis.io/docs/latest/commands/ft.dropindex/>
290  fn ft_dropindex<R, I>(&self, index: I, dd: bool) -> impl Future<Output = FredResult<R>> + Send
291  where
292    R: FromValue,
293    I: Into<Str> + Send,
294  {
295    async move {
296      into!(index);
297      commands::redisearch::ft_dropindex(self, index, dd).await?.convert()
298    }
299  }
300
301  /// Return the execution plan for a complex query.
302  ///
303  /// <https://redis.io/docs/latest/commands/ft.explain/>
304  fn ft_explain<R, I, Q>(
305    &self,
306    index: I,
307    query: Q,
308    dialect: Option<i64>,
309  ) -> impl Future<Output = FredResult<R>> + Send
310  where
311    R: FromValue,
312    I: Into<Str> + Send,
313    Q: Into<Str> + Send,
314  {
315    async move {
316      into!(index, query);
317      commands::redisearch::ft_explain(self, index, query, dialect)
318        .await?
319        .convert()
320    }
321  }
322
323  /// Return information and statistics on the index.
324  ///
325  /// <https://redis.io/docs/latest/commands/ft.info/>
326  fn ft_info<R, I>(&self, index: I) -> impl Future<Output = FredResult<R>> + Send
327  where
328    R: FromValue,
329    I: Into<Str> + Send,
330  {
331    async move {
332      into!(index);
333      commands::redisearch::ft_info(self, index).await?.convert()
334    }
335  }
336
337  /// Perform spelling correction on a query, returning suggestions for misspelled terms.
338  ///
339  /// <https://redis.io/docs/latest/commands/ft.spellcheck/>
340  fn ft_spellcheck<R, I, Q>(
341    &self,
342    index: I,
343    query: Q,
344    distance: Option<u8>,
345    terms: Option<SpellcheckTerms>,
346    dialect: Option<i64>,
347  ) -> impl Future<Output = FredResult<R>> + Send
348  where
349    R: FromValue,
350    I: Into<Str> + Send,
351    Q: Into<Str> + Send,
352  {
353    async move {
354      into!(index, query);
355      commands::redisearch::ft_spellcheck(self, index, query, distance, terms, dialect)
356        .await?
357        .convert()
358    }
359  }
360
361  /// Add a suggestion string to an auto-complete suggestion dictionary.
362  ///
363  /// <https://redis.io/docs/latest/commands/ft.sugadd/>
364  fn ft_sugadd<R, K, S>(
365    &self,
366    key: K,
367    string: S,
368    score: f64,
369    incr: bool,
370    payload: Option<Bytes>,
371  ) -> impl Future<Output = FredResult<R>> + Send
372  where
373    R: FromValue,
374    K: Into<Key> + Send,
375    S: Into<Str> + Send,
376  {
377    async move {
378      into!(key, string);
379      commands::redisearch::ft_sugadd(self, key, string, score, incr, payload)
380        .await?
381        .convert()
382    }
383  }
384
385  /// Delete a string from a suggestion index.
386  ///
387  /// <https://redis.io/docs/latest/commands/ft.sugdel/>
388  fn ft_sugdel<R, K, S>(&self, key: K, string: S) -> impl Future<Output = FredResult<R>> + Send
389  where
390    R: FromValue,
391    K: Into<Key> + Send,
392    S: Into<Str> + Send,
393  {
394    async move {
395      into!(key, string);
396      commands::redisearch::ft_sugdel(self, key, string).await?.convert()
397    }
398  }
399
400  /// Get completion suggestions for a prefix.
401  ///
402  /// <https://redis.io/docs/latest/commands/ft.sugget/>
403  fn ft_sugget<R, K, P>(
404    &self,
405    key: K,
406    prefix: P,
407    fuzzy: bool,
408    withscores: bool,
409    withpayloads: bool,
410    max: Option<u64>,
411  ) -> impl Future<Output = FredResult<R>> + Send
412  where
413    R: FromValue,
414    K: Into<Key> + Send,
415    P: Into<Str> + Send,
416  {
417    async move {
418      into!(key, prefix);
419      commands::redisearch::ft_sugget(self, key, prefix, fuzzy, withscores, withpayloads, max)
420        .await?
421        .convert()
422    }
423  }
424
425  /// Get the size of an auto-complete suggestion dictionary.
426  ///
427  /// <https://redis.io/docs/latest/commands/ft.suglen/>
428  fn ft_suglen<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
429  where
430    R: FromValue,
431    K: Into<Key> + Send,
432  {
433    async move {
434      into!(key);
435      commands::redisearch::ft_suglen(self, key).await?.convert()
436    }
437  }
438
439  /// Dump the contents of a synonym group.
440  ///
441  /// <https://redis.io/docs/latest/commands/ft.syndump/>
442  fn ft_syndump<R, I>(&self, index: I) -> impl Future<Output = FredResult<R>> + Send
443  where
444    R: FromValue,
445    I: Into<Str> + Send,
446  {
447    async move {
448      into!(index);
449      commands::redisearch::ft_syndump(self, index).await?.convert()
450    }
451  }
452
453  /// Update a synonym group.
454  ///
455  /// <https://redis.io/docs/latest/commands/ft.synupdate/>
456  fn ft_synupdate<R, I, S, T>(
457    &self,
458    index: I,
459    synonym_group_id: S,
460    skipinitialscan: bool,
461    terms: T,
462  ) -> impl Future<Output = FredResult<R>> + Send
463  where
464    R: FromValue,
465    I: Into<Str> + Send,
466    S: Into<Str> + Send,
467    T: Into<MultipleStrings> + Send,
468  {
469    async move {
470      into!(index, synonym_group_id, terms);
471      commands::redisearch::ft_synupdate(self, index, synonym_group_id, skipinitialscan, terms)
472        .await?
473        .convert()
474    }
475  }
476
477  /// Return a distinct set of values indexed in a Tag field.
478  ///
479  /// <https://redis.io/docs/latest/commands/ft.tagvals/>
480  fn ft_tagvals<R, I, F>(&self, index: I, field_name: F) -> impl Future<Output = FredResult<R>> + Send
481  where
482    R: FromValue,
483    I: Into<Str> + Send,
484    F: Into<Str> + Send,
485  {
486    async move {
487      into!(index, field_name);
488      commands::redisearch::ft_tagvals(self, index, field_name)
489        .await?
490        .convert()
491    }
492  }
493}