nexus_common/db/kv/traits.rs
1use super::index::*;
2use crate::types::DynError;
3use async_trait::async_trait;
4use json::JsonAction;
5use serde::{de::DeserializeOwned, Serialize};
6use sorted_sets::{ScoreAction, SortOrder, SORTED_PREFIX};
7
8/// A trait for operations involving Redis storage. Implement this trait for types that need to be stored
9/// and retrieved from Redis with serialization and deserialization capabilities.
10#[async_trait]
11pub trait RedisOps: Serialize + DeserializeOwned + Send + Sync {
12 /// Provides a prefix string for the Redis key.
13 ///
14 /// This method should return a prefix string that helps namespace the keys in Redis,
15 /// preventing key collisions. The prefix is typically derived from the struct name.
16 ///
17 /// # Returns
18 ///
19 /// A `String` representing the prefix for Redis keys.
20 async fn prefix() -> String {
21 let type_name = std::any::type_name::<Self>();
22 let struct_name = type_name.split("::").last().unwrap_or_default();
23
24 // Insert ":" before each uppercase letter except the first one
25 let mut prefixed_name = String::new();
26 let chars = struct_name.chars().peekable();
27
28 for c in chars {
29 if c.is_uppercase() && !prefixed_name.is_empty() {
30 prefixed_name.push(':');
31 }
32 prefixed_name.push(c);
33 }
34
35 prefixed_name
36 }
37
38 // ############################################################
39 // ################# JSON related functions ###################
40 // ############################################################
41
42 /// Sets the data in Redis using the provided key parts.
43 ///
44 /// This method serializes the data and stores it in Redis under the key generated
45 /// from the provided `key_parts`. It can also set an expiration time for the key if required.
46 ///
47 /// # Arguments
48 ///
49 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the value is stored
50 /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
51 /// * `expiration` - An optional `i64` specifying the TTL (in seconds) for the set. If `None`, no TTL will be set.
52 ///
53 /// # Errors
54 ///
55 /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
56 async fn put_index_json(
57 &self,
58 key_parts: &[&str],
59 prefix: Option<String>,
60 expiration: Option<i64>,
61 ) -> Result<(), DynError> {
62 let prefix = prefix.unwrap_or(Self::prefix().await);
63 json::put(&prefix, &key_parts.join(":"), self, None, expiration).await
64 }
65
66 /// Retrieves data from Redis using the provided key parts.
67 ///
68 /// This method deserializes the data stored under the key generated from the provided `key_parts` in Redis.
69 /// If the key is not found, it returns `None`.
70 ///
71 /// # Arguments
72 ///
73 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the value is stored.
74 /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
75 ///
76 /// # Returns
77 ///
78 /// An `Option<Self>` containing the deserialized data if found, or `None` if the key does not exist.
79 ///
80 /// # Errors
81 ///
82 /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
83 async fn try_from_index_json(
84 key_parts: &[&str],
85 prefix: Option<String>,
86 ) -> Result<Option<Self>, DynError> {
87 let prefix = prefix.unwrap_or(Self::prefix().await);
88 json::get(&prefix, &key_parts.join(":"), None).await
89 }
90
91 /// Retrieves multiple JSON objects from Redis using the provided key parts.
92 ///
93 /// This method deserializes the data stored under the keys generated from the provided `key_parts_list` in Redis.
94 /// It returns a vector of options, where each option corresponds to the existence of the key in Redis.
95 ///
96 /// # Arguments
97 ///
98 /// * `key_parts_list` - A slice of slices, where each inner slice contains string slices representing
99 /// the parts used to form the key under which the corresponding value is stored.
100 ///
101 /// # Returns
102 ///
103 /// A `Vec<Option<Self>>` containing the deserialized data if found, or `None` if a key does not exist.
104 async fn try_from_index_multiple_json(
105 key_parts_list: &[&[&str]],
106 ) -> Result<Vec<Option<Self>>, DynError> {
107 let prefix = Self::prefix().await;
108 let keys: Vec<String> = key_parts_list
109 .iter()
110 .map(|key_parts| key_parts.join(":"))
111 .collect();
112
113 json::get_multiple(&prefix, &keys, None).await
114 }
115
116 /// Stores multiple key-value pairs in Redis, where each key is constructed from the provided key parts
117 /// and each value is an item from the given collection.
118 ///
119 /// This method serializes each item in the collection and stores it in Redis under keys generated
120 /// by joining the elements of the corresponding slices in `key_parts_list`. It efficiently handles
121 /// the setting of multiple key-value pairs in a single operation.
122 ///
123 /// # Arguments
124 ///
125 /// * `key_parts_list` - A slice of slices, where each inner slice is a list of string slices representing
126 /// the components used to generate the Redis key for the corresponding value in the `collection`.
127 /// Each slice in this list must align with the corresponding index in `collection`.
128 ///
129 /// * `collection` - A vector of `Option<Self>` representing the values to be stored in Redis. Each value is serialized
130 /// before being stored, and the vector should be of the same length as `key_parts_list`.
131 ///
132 /// # Returns
133 ///
134 /// This function returns a `Result` indicating success or failure. A successful result means that
135 /// all key-value pairs were successfully stored in Redis.
136 async fn put_multiple_json_indexes(
137 key_parts_list: &[&[&str]],
138 collection: Vec<Option<Self>>,
139 ) -> Result<(), DynError> // The items in the collection must be serializable
140 {
141 let mut data = Vec::with_capacity(key_parts_list.len());
142 for (i, key_parts) in key_parts_list.iter().enumerate() {
143 let key = key_parts.join(":");
144 data.push((key, &collection[i]));
145 }
146
147 json::put_multiple(&Self::prefix().await, &data).await
148 }
149
150 /// Removes multiple JSON objects from Redis using the provided key parts.
151 ///
152 /// This method deletes the data stored under the keys generated from the provided `key_parts_list` in Redis.
153 /// It returns a result indicating success or failure.
154 ///
155 /// # Arguments
156 ///
157 /// * `key_parts_list` - A slice of slices, where each inner slice contains string slices representing
158 /// the parts used to form the key under which the corresponding value is stored.
159 ///
160 /// # Returns
161 ///
162 /// A `Result` indicating success or failure. If successful, all keys are removed from Redis.
163 ///
164 /// # Errors
165 ///
166 /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
167 async fn remove_from_index_multiple_json(key_parts_list: &[&[&str]]) -> Result<(), DynError> {
168 let prefix = Self::prefix().await;
169 let keys: Vec<String> = key_parts_list
170 .iter()
171 .map(|key_parts| key_parts.join(":"))
172 .collect();
173
174 json::del_multiple(&prefix, &keys).await
175 }
176
177 /// Modifies a numeric field in a Redis JSON object by either incrementing or decrementing it.
178 ///
179 /// This method performs an operation on a numeric field in Redis JSON at the given path,
180 /// either incrementing or decrementing it based on the `JsonAction` provided.
181 ///
182 /// # Arguments
183 ///
184 /// * `key_parts` - A slice of string slices representing the parts used to form the key under which the JSON object is stored.
185 /// * `field` - A string slice representing the field to be modified in the JSON object.
186 /// * `action` - A `JsonAction` enum that specifies whether to increment or decrement the field.
187 ///
188 /// # Returns
189 ///
190 /// Returns a result indicating success or failure.
191 ///
192 /// # Errors
193 ///
194 /// Returns an error if the operation fails, such as if the Redis connection is unavailable or the field is not numeric.
195 async fn modify_json_field(
196 key_parts: &[&str],
197 field: &str,
198 action: JsonAction,
199 ) -> Result<(), DynError> {
200 let prefix = Self::prefix().await;
201 let key = key_parts.join(":");
202 json::modify_json_field(&prefix, &key, field, action, None).await
203 }
204
205 // ############################################################
206 // ################# List related functions ###################
207 // ############################################################
208
209 /// Adds elements to a Redis list using the provided key parts.
210 ///
211 /// This method serializes the data and appends it to a Redis list under the key generated
212 /// from the provided `key_parts`.
213 ///
214 /// # Arguments
215 ///
216 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the list is stored.
217 ///
218 /// # Errors
219 ///
220 /// Returns an error if the operation fails, such as if the Redis connection is unavailable or
221 /// if there is an issue with serialization.
222 async fn put_index_list<T>(&self, key_parts: &[&str]) -> Result<(), DynError>
223 where
224 Self: AsRef<[T]>, // Self can be dereferenced into a slice of T
225 T: AsRef<str> + Send + Sync, // The items must be convertible to &str
226 {
227 let prefix = Self::prefix().await;
228 let key = key_parts.join(":");
229
230 // TODO: Unsafe. If re-indexed it will duplicate follower/following list entries.
231 // Need reading, matching out the duplicates then storing. Inneficient.
232 // Needs mode safety for double-write.
233
234 // Directly use the string representations of items without additional serialization
235 let collection = self.as_ref();
236 let values: Vec<&str> = collection.iter().map(|item| item.as_ref()).collect();
237
238 // Store the values in the Redis list
239 lists::put(&prefix, &key, &values).await
240 }
241
242 /// Retrieves a range of elements from a Redis list using the provided key parts.
243 ///
244 /// This method fetches elements from a Redis list stored under the key generated from the provided `key_parts`.
245 /// The range is defined by `skip` and `limit` parameters.
246 ///
247 /// # Arguments
248 ///
249 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the list is stored.
250 /// * `skip` - An optional number of elements to skip (useful for pagination).
251 /// * `limit` - An optional number of elements to return (useful for pagination).
252 ///
253 /// # Returns
254 ///
255 /// Returns a vector of deserialized elements if they exist, or an empty vector if no matching elements are found.
256 ///
257 /// # Errors
258 ///
259 /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
260 async fn try_from_index_list(
261 key_parts: &[&str],
262 skip: Option<usize>,
263 limit: Option<usize>,
264 ) -> Result<Option<Vec<String>>, DynError> {
265 let prefix = Self::prefix().await;
266 let key = key_parts.join(":");
267 lists::get_range(&prefix, &key, skip, limit).await
268 }
269
270 // ############################################################
271 // ################# SET related functions ###################
272 // ############################################################
273
274 /// Adds elements to a Redis set using the provided key parts.
275 ///
276 /// This method adds elements to a Redis set under the key generated from the provided `key_parts`.
277 /// It ensures that each element in the set is unique.
278 ///
279 /// # Arguments
280 ///
281 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the set is stored.
282 /// * `values` - A list of string that represents the value to add in the index
283 /// * `expiration` - An optional `i64` specifying the TTL (in seconds) for the set. If `None`, no TTL will be set.
284 /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
285 /// # Errors
286 ///
287 /// Returns an error if the operation fails, such as if the Redis connection is unavailable or
288 /// if there is an issue with serialization.
289 async fn put_index_set(
290 key_parts: &[&str],
291 values: &[&str],
292 expiration: Option<i64>,
293 prefix: Option<String>,
294 ) -> Result<(), DynError> {
295 let prefix = prefix.unwrap_or(Self::prefix().await);
296 let key = key_parts.join(":");
297 // Store the values in the Redis set
298 sets::put(&prefix, &key, values, expiration).await
299 }
300
301 /// Removes elements from a Redis set using the provided key parts.
302 ///
303 /// This method removes elements from a Redis set stored under the key generated from the provided `key_parts`.
304 ///
305 /// # Arguments
306 ///
307 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the set is stored.
308 /// * `values` - A slice of string slices representing the elements to be removed from the set.
309 ///
310 /// # Errors
311 ///
312 /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
313 async fn remove_from_index_set<T>(&self, key_parts: &[&str]) -> Result<(), DynError>
314 where
315 Self: AsRef<[T]>, // Self can be dereferenced into a slice of T
316 T: AsRef<str> + Send + Sync, // The items must be convertible to &str
317 {
318 let prefix = Self::prefix().await;
319 let key = key_parts.join(":");
320
321 // Directly use the string representations of items without additional serialization
322 let collection = self.as_ref();
323 let values: Vec<&str> = collection.iter().map(|item| item.as_ref()).collect();
324
325 // Remove the values from the Redis set
326 sets::del(&prefix, &key, &values).await
327 }
328
329 /// Retrieves a range of elements from a Redis set using the provided key parts.
330 ///
331 /// This method fetches elements from a Redis set stored under the key generated from the provided `key_parts`.
332 /// The range is defined by `skip` and `limit` parameters.
333 ///
334 /// # Arguments
335 ///
336 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the set is stored.
337 /// * `skip` - An optional number of elements to skip (useful for pagination).
338 /// * `limit` - An optional number of elements to return (useful for pagination).
339 /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
340 /// # Returns
341 ///
342 /// Returns a vector of deserialized elements if they exist, or an empty vector if no matching elements are found.
343 ///
344 /// # Errors
345 ///
346 /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
347 async fn try_from_index_set(
348 key_parts: &[&str],
349 skip: Option<usize>,
350 limit: Option<usize>,
351 prefix: Option<String>,
352 ) -> Result<Option<Vec<String>>, DynError> {
353 let combined_prefix = match prefix {
354 Some(p) => format!("{}:{}", p, Self::prefix().await),
355 None => Self::prefix().await,
356 };
357 let key = key_parts.join(":");
358 sets::get_range(&combined_prefix, &key, skip, limit).await
359 }
360
361 /// Checks if a member exists in a Redis set and if the set exists using the provided key parts.
362 ///
363 /// This method checks if a specific member is present in the Redis set stored under the key
364 /// generated from the provided `key_parts`. It also determines if the set itself exists.
365 ///
366 /// # Arguments
367 ///
368 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the set is stored.
369 /// * `member` - A string slice representing the member to check for existence in the set.
370 ///
371 /// # Returns
372 ///
373 /// Returns `Ok((true, true))` if the set exists and the member is in the set,
374 /// `Ok((true, false))` if the set exists but the member is not in the set,
375 /// `Ok((false, false))` if the set does not exist.
376 ///
377 /// # Errors
378 ///
379 /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
380 async fn check_set_member(key_parts: &[&str], member: &str) -> Result<(bool, bool), DynError> {
381 let prefix = Self::prefix().await;
382 let key = key_parts.join(":");
383 sets::check_member(&prefix, &key, member).await
384 }
385
386 /// Retrieves the size of a Redis set using the provided key parts.
387 ///
388 /// This method retrieves the number of elements in a Redis set stored under the key generated from the provided `key_parts`.
389 /// It returns `Ok(Some(size))` if the set exists, or `Ok(None)` if the set does not exist.
390 ///
391 /// # Arguments
392 ///
393 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the set is stored.
394 ///
395 /// # Returns
396 ///
397 /// Returns `Ok(Some(size))` where `size` is the number of elements in the set, or `Ok(None)` if the set does not exist.
398 ///
399 /// # Errors
400 ///
401 /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
402 async fn get_set_size(key_parts: &[&str]) -> Result<Option<usize>, DynError> {
403 let prefix = Self::prefix().await;
404 let key = key_parts.join(":");
405 sets::get_size(&prefix, &key).await
406 }
407
408 /// Fetches multiple sets from Redis using the specified key components.
409 ///
410 /// # Arguments
411 /// * `key_parts_list` - A slice of string slices, where each inner slice represents the components
412 /// used to construct the Redis keys.
413 /// * `prefix` - An optional string representing the prefix for the Redis keys
414 /// * `member` - An optional string reference representing a specific element to check for member in each SET
415 /// * `limit` - An optional parameter specifying the maximum number of elements to fetch from each SET
416 /// If `None`, all elements will be retrieved.
417 async fn try_from_multiple_sets(
418 key_parts_list: &[&str],
419 prefix: Option<String>,
420 member: Option<&str>,
421 limit: Option<usize>,
422 ) -> Result<Vec<Option<(Vec<String>, usize, bool)>>, DynError> {
423 let combined_prefix = match prefix {
424 Some(p) => format!("{}:{}", p, Self::prefix().await),
425 None => Self::prefix().await,
426 };
427 sets::get_multiple_sets(&combined_prefix, key_parts_list, member, limit).await
428 }
429
430 /// Adds elements to multiple Redis sets using the provided keys and collections.
431 ///
432 /// This asynchronous function allows you to add elements to multiple Redis sets,
433 /// with each set identified by a key generated from the `common_key` and `index_ref`.
434 /// The function ensures that each element in each set is unique.
435 ///
436 /// # Arguments
437 ///
438 /// * `common_key` - A slice of string slices representing the common part of the Redis keys.
439 /// This will be combined with each element in `index` to generate the full Redis key.
440 /// * `index` - A slice of string slices representing the unique identifiers to append to the `common_key` to form the full Redis keys.
441 /// * `collections_refs` - A slice of vectors, where each inner vector contains elements to be added to the corresponding Redis set
442 /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
443 /// * `expiration` - An optional `i64` specifying the TTL (in seconds) for the set. If `None`, no TTL will be set.
444 ///
445 /// # Returns
446 ///
447 /// This function returns a `Result` indicating success or failure. A successful result means that
448 /// all elements were successfully added to their respective Redis sets.
449 ///
450 /// # Errors
451 ///
452 /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
453 async fn put_multiple_set_indexes(
454 common_key: &[&str],
455 index: &[&str],
456 collections_refs: &[Vec<&str>],
457 prefix: Option<String>,
458 expiration: Option<i64>,
459 ) -> Result<(), DynError> {
460 // Ensure the lengths of keys_refs and collections_refs match
461 if index.len() != collections_refs.len() {
462 // TODO: Maybe create redis related errors
463 return Err("Keys refs and collections refs length mismatch".into());
464 }
465 let combined_prefix = match prefix {
466 Some(p) => format!("{}:{}", p, Self::prefix().await),
467 None => Self::prefix().await,
468 };
469
470 let refs: Vec<&[&str]> = collections_refs
471 .iter()
472 .map(|inner_vec| inner_vec.as_slice())
473 .collect();
474 let slice: &[&[&str]] = refs.as_slice();
475
476 sets::put_multiple_sets(&combined_prefix, common_key, index, slice, expiration).await
477 }
478
479 /// Retrieves random elements from a Redis set using the provided key parts.
480 ///
481 /// This method fetches random elements from a Redis set stored under the key generated from the provided `key_parts`.
482 /// The number of elements retrieved is defined by the `count` parameter.
483 /// # Arguments
484 ///
485 /// * `key_parts` - Components of the key under which the set is stored.
486 /// * `count` - The number of random elements to retrieve.
487 /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
488 ///
489 /// # Returns
490 ///
491 /// Returns `Ok(Some(Vec<String>))` if the set exists and random elements are retrieved.
492 /// Returns `Ok(None)` if the set does not exist.
493 ///
494 /// # Errors
495 ///
496 /// Returns an error if the Redis operation fails.
497 async fn try_get_random_from_index_set(
498 key_parts: &[&str],
499 count: isize,
500 prefix: Option<String>,
501 ) -> Result<Option<Vec<String>>, DynError> {
502 let prefix = prefix.unwrap_or(Self::prefix().await);
503 let key = key_parts.join(":");
504 sets::get_random_members(&prefix, &key, count).await
505 }
506
507 // ############################################################
508 // ########### SORTED SET related functions ###################
509 // ############################################################
510
511 /// Checks if a member exists in a Redis sorted set and retrieves its score if it exists.
512 ///
513 /// This method checks if a specific member is present in the Redis sorted set stored under the key
514 /// generated from the provided `key_parts`. If the member is found, it returns its score.
515 ///
516 /// # Arguments
517 ///
518 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the sorted set is stored.
519 /// * `member` - A slice of string slices that represent the parts used to form the key identifying the member within the sorted set.
520 async fn check_sorted_set_member(
521 prefix: Option<&str>,
522 key_parts: &[&str],
523 member: &[&str],
524 ) -> Result<Option<isize>, DynError> {
525 let prefix = prefix.unwrap_or(SORTED_PREFIX);
526 let key = key_parts.join(":");
527 let member_key = member.join(":");
528 sorted_sets::check_member(prefix, &key, &member_key).await
529 }
530
531 /// Adds elements to a Redis sorted set using the provided key parts.
532 ///
533 /// This method adds elements to a Redis sorted set under the key generated from the provided `key_parts`.
534 /// The elements are associated with scores, which determine their order in the set.
535 ///
536 /// # Arguments
537 ///
538 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the sorted set is stored.
539 /// * `elements` - A slice of tuples where each tuple contains a reference to a string slice representing
540 /// the element and a f64 representing the score of the element.
541 /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
542 /// * `expiration` - An optional `i64` specifying the TTL (in seconds) for the set. If `None`, no TTL will be set.
543 ///
544 /// # Errors
545 ///
546 /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
547 async fn put_index_sorted_set(
548 key_parts: &[&str],
549 elements: &[(f64, &str)],
550 prefix: Option<&str>,
551 expiration: Option<i64>,
552 ) -> Result<(), DynError> {
553 let prefix = prefix.unwrap_or(SORTED_PREFIX);
554 let key = key_parts.join(":");
555 // Store the elements in the Redis sorted set
556 sorted_sets::put(prefix, &key, elements, expiration).await
557 }
558
559 /// Updates the score of a member in a Redis sorted set.
560 ///
561 /// This method updates the score associated with a specific member in a Redis sorted set
562 /// identified by the provided key parts. The score can be mutated (incremented, decremented, or set) based on the `score_mutation` parameter.
563 ///
564 /// # Arguments
565 ///
566 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the sorted set is stored.
567 /// * `member` - A slice of string slices that represent the parts used to form the key identifying the member within the sorted set.
568 /// * `score_mutation` - A `ScoreAction` that defines how the score should be modified (e.g., incremented or decremented).
569 async fn put_score_index_sorted_set(
570 key_parts: &[&str],
571 member: &[&str],
572 score_mutation: ScoreAction,
573 ) -> Result<(), DynError> {
574 let key = key_parts.join(":");
575 let member_key = member.join(":");
576 sorted_sets::put_score(SORTED_PREFIX, &key, &member_key, score_mutation).await
577 }
578
579 /// Removes elements from a Redis sorted set using the provided key parts.
580 ///
581 /// This method removes the specified elements from the Redis sorted set identified by the key generated
582 /// from the provided `key_parts`.
583 ///
584 /// # Arguments
585 ///
586 /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
587 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the sorted set is stored.
588 /// * `items` - A slice of string slices representing the elements to be removed from the sorted set.
589 ///
590 /// # Errors
591 ///
592 /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
593 async fn remove_from_index_sorted_set(
594 prefix: Option<&str>,
595 key_parts: &[&str],
596 items: &[&str],
597 ) -> Result<(), DynError> {
598 if items.is_empty() {
599 return Ok(());
600 }
601
602 let prefix = prefix.unwrap_or(SORTED_PREFIX);
603 // Create the key by joining the key parts
604 let key = key_parts.join(":");
605 // Call the sorted_sets::del function to remove the items from the sorted set
606 sorted_sets::del(prefix, &key, items).await
607 }
608
609 /// Retrieves a range of elements from a Redis sorted set using the provided key parts.
610 ///
611 /// This method fetches elements from a Redis sorted set stored under the key generated from the provided `key_parts`.
612 /// The range is defined by `skip` and `limit` parameters.
613 ///
614 /// # Arguments
615 ///
616 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the sorted set is stored.
617 /// * `start` - An optional value representing the beginning of the stream timeframe or score. If `None`, no lower bound is applied.
618 /// * `end` - An optional value representing the end of the stream timeframe or score. If `None`, no upper bound is applied.
619 /// * `skip` - An optional number of elements to skip (useful for pagination).
620 /// * `limit` - An optional number of elements to return (useful for pagination).
621 /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
622 ///
623 /// # Returns
624 ///
625 /// Returns a vector of tuples containing the elements and their scores if they exist, or an empty vector if no matching elements are found.
626 ///
627 /// # Errors
628 ///
629 /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
630 async fn try_from_index_sorted_set(
631 key_parts: &[&str],
632 start: Option<f64>,
633 end: Option<f64>,
634 skip: Option<usize>,
635 limit: Option<usize>,
636 sorting: SortOrder,
637 prefix: Option<&str>,
638 ) -> Result<Option<Vec<(String, f64)>>, DynError> {
639 let key = key_parts.join(":");
640 let prefix = prefix.unwrap_or("Sorted");
641
642 sorted_sets::get_range(prefix, &key, end, start, skip, limit, sorting).await
643 }
644
645 /// Retrieves a lexicographical range of elements from a Redis sorted set using the provided key parts.
646 ///
647 /// This method fetches elements from a Redis sorted set stored under the key generated from the provided `key_parts`.
648 /// The range is defined by `min` and `max` lexicographical bounds.
649 ///
650 /// # Arguments
651 ///
652 /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the sorted set is stored.
653 /// * `min` - The minimum lexicographical bound (inclusive).
654 /// * `max` - The maximum lexicographical bound (exclusive).
655 /// * `skip` - An optional number of elements to skip (useful for pagination).
656 /// * `limit` - An optional number of elements to return (useful for pagination).
657 ///
658 /// # Returns
659 ///
660 /// Returns a vector of elements if they exist, or an empty vector if no matching elements are found.
661 ///
662 /// # Errors
663 ///
664 /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
665 async fn try_from_index_sorted_set_lex(
666 key_parts: &[&str],
667 min: &str,
668 max: &str,
669 skip: Option<usize>,
670 limit: Option<usize>,
671 ) -> Result<Option<Vec<String>>, DynError> {
672 let key = key_parts.join(":");
673 sorted_sets::get_lex_range("Sorted", &key, min, max, skip, limit).await
674 }
675}