rustis/commands/
sorted_set_commands.rs

1use crate::{
2    client::{prepare_command, PreparedCommand},
3    resp::{
4        cmd, deserialize_vec_of_pairs, CommandArgs, MultipleArgsCollection, PrimitiveResponse,
5        SingleArg, SingleArgCollection, ToArgs,
6    },
7};
8use serde::{de::DeserializeOwned, Deserialize};
9
10/// A group of Redis commands related to [`Sorted Sets`](https://redis.io/docs/data-types/sorted-sets/)
11///
12/// # See Also
13/// [Redis Sorted Set Commands](https://redis.io/commands/?group=sorted-set)
14pub trait SortedSetCommands<'a> {
15    /// Adds all the specified members with the specified scores
16    /// to the sorted set stored at key.
17    ///
18    /// # Return
19    /// * When used without optional arguments, the number of elements added to the sorted set (excluding score updates).
20    /// * If the `change` option is specified, the number of elements that were changed (added or updated).
21    ///
22    /// # See Also
23    /// [<https://redis.io/commands/zadd/>](https://redis.io/commands/zadd/)
24    #[must_use]
25    fn zadd<K, M, I>(
26        self,
27        key: K,
28        items: I,
29        options: ZAddOptions,
30    ) -> PreparedCommand<'a, Self, usize>
31    where
32        Self: Sized,
33        K: SingleArg,
34        M: SingleArg,
35        I: MultipleArgsCollection<(f64, M)>,
36    {
37        prepare_command(self, cmd("ZADD").arg(key).arg(options).arg(items))
38    }
39
40    /// In this mode ZADD acts like ZINCRBY.
41    /// Only one score-element pair can be specified in this mode.
42    ///
43    /// # Return
44    /// The new score of member (a double precision floating point number),
45    /// or nil if the operation was aborted (when called with either the XX or the NX option).
46    ///
47    /// # See Also
48    /// [<https://redis.io/commands/zadd/>](https://redis.io/commands/zadd/)
49    #[must_use]
50    fn zadd_incr<K, M>(
51        self,
52        key: K,
53        condition: ZAddCondition,
54        comparison: ZAddComparison,
55        change: bool,
56        score: f64,
57        member: M,
58    ) -> PreparedCommand<'a, Self, Option<f64>>
59    where
60        Self: Sized,
61        K: SingleArg,
62        M: SingleArg,
63    {
64        prepare_command(
65            self,
66            cmd("ZADD")
67                .arg(key)
68                .arg(condition)
69                .arg(comparison)
70                .arg_if(change, "CH")
71                .arg(score)
72                .arg(member),
73        )
74    }
75
76    /// Returns the sorted set cardinality (number of elements)
77    /// of the sorted set stored at key.
78    ///
79    /// # Return
80    /// The cardinality (number of elements) of the sorted set, or 0 if key does not exist.
81    ///
82    /// # See Also
83    /// [<https://redis.io/commands/zcard/>](https://redis.io/commands/zcard/)
84    #[must_use]
85    fn zcard<K>(self, key: K) -> PreparedCommand<'a, Self, usize>
86    where
87        Self: Sized,
88        K: SingleArg,
89    {
90        prepare_command(self, cmd("ZCARD").arg(key))
91    }
92
93    /// Returns the number of elements in the sorted set at key with a score between min and max.
94    ///
95    /// # Return
96    /// The number of elements in the specified score range.
97    ///
98    /// # See Also
99    /// [<https://redis.io/commands/zcount/>](https://redis.io/commands/zcount/)
100    #[must_use]
101    fn zcount<K, M1, M2>(self, key: K, min: M1, max: M2) -> PreparedCommand<'a, Self, usize>
102    where
103        Self: Sized,
104        K: SingleArg,
105        M1: SingleArg,
106        M2: SingleArg,
107    {
108        prepare_command(self, cmd("ZCOUNT").arg(key).arg(min).arg(max))
109    }
110
111    /// This command is similar to [zdiffstore](SortedSetCommands::zdiffstore), but instead of storing the resulting sorted set,
112    /// it is returned to the client.
113    ///
114    /// # Return
115    /// The result of the difference
116    ///
117    /// # See Also
118    /// [<https://redis.io/commands/zdiff/>](https://redis.io/commands/zdiff/)
119    #[must_use]
120    fn zdiff<K, C, E>(self, keys: C) -> PreparedCommand<'a, Self, Vec<E>>
121    where
122        Self: Sized,
123        K: SingleArg,
124        C: SingleArgCollection<K>,
125        E: PrimitiveResponse + DeserializeOwned,
126    {
127        prepare_command(self, cmd("ZDIFF").arg(keys.num_args()).arg(keys))
128    }
129
130    /// This command is similar to [zdiffstore](SortedSetCommands::zdiffstore), but instead of storing the resulting sorted set,
131    /// it is returned to the client.
132    ///
133    /// # Return
134    /// The result of the difference with their scores
135    ///
136    /// # See Also
137    /// [<https://redis.io/commands/zdiff/>](https://redis.io/commands/zdiff/)
138    #[must_use]
139    fn zdiff_with_scores<K, C, E>(self, keys: C) -> PreparedCommand<'a, Self, Vec<(E, f64)>>
140    where
141        Self: Sized,
142        K: SingleArg,
143        C: SingleArgCollection<K>,
144        E: PrimitiveResponse + DeserializeOwned,
145    {
146        prepare_command(
147            self,
148            cmd("ZDIFF")
149                .arg(keys.num_args())
150                .arg(keys)
151                .arg("WITHSCORES"),
152        )
153    }
154
155    /// Computes the difference between the first and all successive
156    /// input sorted sets and stores the result in destination.
157    ///
158    /// # Return
159    /// The number of elements in the resulting sorted set at destination.
160    ///
161    /// # See Also
162    /// [<https://redis.io/commands/zdiffstore/>](https://redis.io/commands/zdiffstore/)
163    #[must_use]
164    fn zdiffstore<D, K, C>(self, destination: D, keys: C) -> PreparedCommand<'a, Self, usize>
165    where
166        Self: Sized,
167        D: SingleArg,
168        K: SingleArg,
169        C: SingleArgCollection<K>,
170    {
171        prepare_command(
172            self,
173            cmd("ZDIFFSTORE")
174                .arg(destination)
175                .arg(keys.num_args())
176                .arg(keys),
177        )
178    }
179
180    /// Increments the score of member in the sorted set stored at key by increment.
181    ///
182    /// # Return
183    /// the new score of member
184    ///
185    /// # See Also
186    /// [<https://redis.io/commands/zincrby/>](https://redis.io/commands/zincrby/)
187    #[must_use]
188    fn zincrby<K, M>(self, key: K, increment: f64, member: M) -> PreparedCommand<'a, Self, f64>
189    where
190        Self: Sized,
191        K: SingleArg,
192        M: SingleArg,
193    {
194        prepare_command(self, cmd("ZINCRBY").arg(key).arg(increment).arg(member))
195    }
196
197    /// This command is similar to [zinterstore](SortedSetCommands::zinterstore),
198    /// but instead of storing the resulting sorted set, it is returned to the client.
199    ///
200    /// # Return
201    /// The result of the intersection as an array of members
202    ///
203    /// # See Also
204    /// [<https://redis.io/commands/zinter/>](https://redis.io/commands/zinter/)
205    #[must_use]
206    fn zinter<K, C, W, E>(
207        self,
208        keys: C,
209        weights: Option<W>,
210        aggregate: ZAggregate,
211    ) -> PreparedCommand<'a, Self, Vec<E>>
212    where
213        Self: Sized,
214        K: SingleArg,
215        C: SingleArgCollection<K>,
216        W: SingleArgCollection<f64>,
217        E: PrimitiveResponse + DeserializeOwned,
218    {
219        prepare_command(
220            self,
221            cmd("ZINTER")
222                .arg(keys.num_args())
223                .arg(keys)
224                .arg(weights.map(|w| ("WEIGHTS", w)))
225                .arg(aggregate),
226        )
227    }
228
229    /// This command is similar to [zinterstore](SortedSetCommands::zinterstore),
230    /// but instead of storing the resulting sorted set, it is returned to the client.
231    ///
232    /// # Return
233    /// The result of the intersection as an array of members with their scores
234    ///
235    /// # See Also
236    /// [<https://redis.io/commands/zinter/>](https://redis.io/commands/zinter/)
237    #[must_use]
238    fn zinter_with_scores<K, C, W, E>(
239        self,
240        keys: C,
241        weights: Option<W>,
242        aggregate: ZAggregate,
243    ) -> PreparedCommand<'a, Self, Vec<(E, f64)>>
244    where
245        Self: Sized,
246        K: SingleArg,
247        C: SingleArgCollection<K>,
248        W: SingleArgCollection<f64>,
249        E: PrimitiveResponse + DeserializeOwned,
250    {
251        prepare_command(
252            self,
253            cmd("ZINTER")
254                .arg(keys.num_args())
255                .arg(keys)
256                .arg(weights.map(|w| ("WEIGHTS", w)))
257                .arg(aggregate)
258                .arg("WITHSCORES"),
259        )
260    }
261
262    /// This command is similar to [zinter](SortedSetCommands::zinter),
263    /// but instead of returning the result set, it returns just the cardinality of the result.
264    ///
265    //// limit: if the intersection cardinality reaches limit partway through the computation,
266    /// the algorithm will exit and yield limit as the cardinality. 0 means unlimited
267    ///
268    /// # See Also
269    /// [<https://redis.io/commands/zintercard/>](https://redis.io/commands/zintercard/)
270    #[must_use]
271    fn zintercard<K, C>(self, keys: C, limit: usize) -> PreparedCommand<'a, Self, usize>
272    where
273        Self: Sized,
274        K: SingleArg,
275        C: SingleArgCollection<K>,
276    {
277        prepare_command(
278            self,
279            cmd("ZINTERCARD")
280                .arg(keys.num_args())
281                .arg(keys)
282                .arg("LIMIT")
283                .arg(limit),
284        )
285    }
286
287    /// Computes the intersection of numkeys sorted sets given by the specified keys,
288    /// and stores the result in destination.
289    ///
290    /// # Return
291    /// The number of elements in the resulting sorted set at destination.
292    ///
293    /// # See Also
294    /// [<https://redis.io/commands/zinterstore/>](https://redis.io/commands/zinterstore/)
295    #[must_use]
296    fn zinterstore<D, K, C, W>(
297        self,
298        destination: D,
299        keys: C,
300        weights: Option<W>,
301        aggregate: ZAggregate,
302    ) -> PreparedCommand<'a, Self, usize>
303    where
304        Self: Sized,
305        D: SingleArg,
306        K: SingleArg,
307        C: SingleArgCollection<K>,
308        W: SingleArgCollection<f64>,
309    {
310        prepare_command(
311            self,
312            cmd("ZINTERSTORE")
313                .arg(destination)
314                .arg(keys.num_args())
315                .arg(keys)
316                .arg(weights.map(|w| ("WEIGHTS", w)))
317                .arg(aggregate),
318        )
319    }
320
321    /// When all the elements in a sorted set are inserted with the same score,
322    /// in order to force lexicographical ordering, this command returns the number
323    /// of elements in the sorted set at key with a value between min and max.
324    ///
325    /// # Return
326    /// the number of elements in the specified score range.
327    ///
328    /// # See Also
329    /// [<https://redis.io/commands/zlexcount/>](https://redis.io/commands/zlexcount/)
330    #[must_use]
331    fn zlexcount<K, M1, M2>(self, key: K, min: M1, max: M2) -> PreparedCommand<'a, Self, usize>
332    where
333        Self: Sized,
334        K: SingleArg,
335        M1: SingleArg,
336        M2: SingleArg,
337    {
338        prepare_command(self, cmd("ZLEXCOUNT").arg(key).arg(min).arg(max))
339    }
340
341    /// Pops one or more elements, that are member-score pairs,
342    /// from the first non-empty sorted set in the provided list of key names.
343    ///
344    /// # Return
345    /// * None if no element could be popped
346    /// * A tuple made up of
347    ///     * The name of the key from which elements were popped
348    ///     * An array of tuples with all the popped members and their scores
349    ///
350    /// # See Also
351    /// [<https://redis.io/commands/zmpop/>](https://redis.io/commands/zmpop/)
352    #[must_use]
353    fn zmpop<K, C, E>(
354        self,
355        keys: C,
356        where_: ZWhere,
357        count: usize,
358    ) -> PreparedCommand<'a, Self, Option<ZMPopResult<E>>>
359    where
360        Self: Sized,
361        K: SingleArg,
362        C: SingleArgCollection<K>,
363        E: PrimitiveResponse + DeserializeOwned,
364    {
365        prepare_command(
366            self,
367            cmd("ZMPOP")
368                .arg(keys.num_args())
369                .arg(keys)
370                .arg(where_)
371                .arg("COUNT")
372                .arg(count),
373        )
374    }
375
376    /// Returns the scores associated with the specified members in the sorted set stored at key.
377    ///
378    /// For every member that does not exist in the sorted set, a nil value is returned.
379    ///
380    /// # Return
381    /// The list of scores or nil associated with the specified member value
382    ///
383    /// # See Also
384    /// [<https://redis.io/commands/zmscore/>](https://redis.io/commands/zmscore/)
385    #[must_use]
386    fn zmscore<K, M, C>(self, key: K, members: C) -> PreparedCommand<'a, Self, Vec<Option<f64>>>
387    where
388        Self: Sized,
389        K: SingleArg,
390        M: SingleArg,
391        C: SingleArgCollection<M>,
392    {
393        prepare_command(self, cmd("ZMSCORE").arg(key).arg(members))
394    }
395
396    /// Removes and returns up to count members with the highest scores in the sorted set stored at key.
397    ///
398    /// # Return
399    /// The list of popped elements and scores.
400    ///
401    /// # See Also
402    /// [<https://redis.io/commands/zpopmax/>](https://redis.io/commands/zpopmax/)
403    #[must_use]
404    fn zpopmax<K, M>(self, key: K, count: usize) -> PreparedCommand<'a, Self, Vec<(M, f64)>>
405    where
406        Self: Sized,
407        K: SingleArg,
408        M: PrimitiveResponse + DeserializeOwned,
409    {
410        prepare_command(self, cmd("ZPOPMAX").arg(key).arg(count))
411    }
412
413    /// Removes and returns up to count members with the lowest scores in the sorted set stored at key.
414    ///
415    /// # Return
416    /// The list of popped elements and scores.
417    ///
418    /// # See Also
419    /// [<https://redis.io/commands/zpopmin/>](https://redis.io/commands/zpopmin/)
420    #[must_use]
421    fn zpopmin<K, M>(self, key: K, count: usize) -> PreparedCommand<'a, Self, Vec<(M, f64)>>
422    where
423        Self: Sized,
424        K: SingleArg,
425        M: PrimitiveResponse + DeserializeOwned,
426    {
427        prepare_command(self, cmd("ZPOPMIN").arg(key).arg(count))
428    }
429
430    /// Return a random element from the sorted set value stored at key.
431    ///
432    /// # Return
433    /// The randomly selected element, or nil when key does not exist.
434    ///
435    /// # See Also
436    /// [<https://redis.io/commands/zrandmember/>](https://redis.io/commands/zrandmember/)
437    #[must_use]
438    fn zrandmember<K, E>(self, key: K) -> PreparedCommand<'a, Self, E>
439    where
440        Self: Sized,
441        K: SingleArg,
442        E: PrimitiveResponse,
443    {
444        prepare_command(self, cmd("ZRANDMEMBER").arg(key))
445    }
446
447    /// Return random elements from the sorted set value stored at key.
448    ///
449    /// # Return
450    /// * If the provided count argument is positive, return an array of distinct elements.
451    /// The array's length is either count or the sorted set's cardinality (ZCARD), whichever is lower.
452    /// * If called with a negative count, the behavior changes and the command is allowed
453    /// to return the same element multiple times. In this case, the number of returned elements
454    /// is the absolute value of the specified count.
455    ///
456    /// # See Also
457    /// [<https://redis.io/commands/zrandmember/>](https://redis.io/commands/zrandmember/)
458    #[must_use]
459    fn zrandmembers<K, E>(self, key: K, count: isize) -> PreparedCommand<'a, Self, Vec<E>>
460    where
461        Self: Sized,
462        K: SingleArg,
463        E: PrimitiveResponse + DeserializeOwned,
464    {
465        prepare_command(self, cmd("ZRANDMEMBER").arg(key).arg(count))
466    }
467
468    /// Return random elements with their scores from the sorted set value stored at key.
469    ///
470    /// # Return
471    /// * If the provided count argument is positive, return an array of distinct elements with their scores.
472    /// The array's length is either count or the sorted set's cardinality (ZCARD), whichever is lower.
473    /// * If called with a negative count, the behavior changes and the command is allowed
474    /// to return the same element multiple times. In this case, the number of returned elements
475    /// is the absolute value of the specified count.
476    ///
477    /// # See Also
478    /// [<https://redis.io/commands/zrandmember/>](https://redis.io/commands/zrandmember/)
479    #[must_use]
480    fn zrandmembers_with_scores<K, E>(
481        self,
482        key: K,
483        count: isize,
484    ) -> PreparedCommand<'a, Self, Vec<E>>
485    where
486        Self: Sized,
487        K: SingleArg,
488        E: DeserializeOwned,
489    {
490        prepare_command(
491            self,
492            cmd("ZRANDMEMBER").arg(key).arg(count).arg("WITHSCORES"),
493        )
494    }
495
496    /// Returns the specified range of elements in the sorted set stored at `key`.
497    ///
498    /// # Return
499    /// A collection of elements in the specified range
500    ///
501    /// # See Also
502    /// [<https://redis.io/commands/zrange/>](https://redis.io/commands/zrange/)
503    #[must_use]
504    fn zrange<K, S, E>(
505        self,
506        key: K,
507        start: S,
508        stop: S,
509        options: ZRangeOptions,
510    ) -> PreparedCommand<'a, Self, Vec<E>>
511    where
512        Self: Sized,
513        K: SingleArg,
514        S: SingleArg,
515        E: PrimitiveResponse + DeserializeOwned,
516    {
517        prepare_command(
518            self,
519            cmd("ZRANGE").arg(key).arg(start).arg(stop).arg(options),
520        )
521    }
522
523    /// Returns the specified range of elements in the sorted set stored at `key`.
524    ///
525    /// # Return
526    /// A collection of elements and their scores in the specified range
527    ///
528    /// # See Also
529    /// [<https://redis.io/commands/zrange/>](https://redis.io/commands/zrange/)
530    #[must_use]
531    fn zrange_with_scores<K, S, E>(
532        self,
533        key: K,
534        start: S,
535        stop: S,
536        options: ZRangeOptions,
537    ) -> PreparedCommand<'a, Self, Vec<(E, f64)>>
538    where
539        Self: Sized,
540        K: SingleArg,
541        S: SingleArg,
542        E: PrimitiveResponse + DeserializeOwned,
543    {
544        prepare_command(
545            self,
546            cmd("ZRANGE")
547                .arg(key)
548                .arg(start)
549                .arg(stop)
550                .arg(options)
551                .arg("WITHSCORES"),
552        )
553    }
554
555    /// This command is like [zrange](SortedSetCommands::zrange),
556    /// but stores the result in the `dst` destination key.
557    ///
558    /// # Return
559    /// The number of elements in the resulting sorted set.
560    ///
561    /// # See Also
562    /// [<https://redis.io/commands/zrangestore/>](https://redis.io/commands/zrangestore/)
563    #[must_use]
564    fn zrangestore<D, S, SS>(
565        self,
566        dst: D,
567        src: S,
568        start: SS,
569        stop: SS,
570        options: ZRangeOptions,
571    ) -> PreparedCommand<'a, Self, usize>
572    where
573        Self: Sized,
574        D: SingleArg,
575        S: SingleArg,
576        SS: SingleArg,
577    {
578        prepare_command(
579            self,
580            cmd("ZRANGESTORE")
581                .arg(dst)
582                .arg(src)
583                .arg(start)
584                .arg(stop)
585                .arg(options),
586        )
587    }
588
589    /// Returns the rank of member in the sorted set stored at key,
590    /// with the scores ordered from low to high.
591    ///
592    /// # Return
593    /// * If member exists in the sorted set, the rank of member.
594    /// * If member does not exist in the sorted set or key does not exist, None.
595    ///
596    /// # See Also
597    /// [<https://redis.io/commands/zrank/>](https://redis.io/commands/zrank/)
598    #[must_use]
599    fn zrank<K, M>(self, key: K, member: M) -> PreparedCommand<'a, Self, Option<usize>>
600    where
601        Self: Sized,
602        K: SingleArg,
603        M: SingleArg,
604    {
605        prepare_command(self, cmd("ZRANK").arg(key).arg(member))
606    }
607
608    /// Removes the specified members from the sorted set stored at key.
609    ///
610    /// # Return
611    /// The number of members removed from the sorted set, not including non existing members.
612    ///
613    /// # See Also
614    /// [<https://redis.io/commands/zrem/>](https://redis.io/commands/zrem/)
615    #[must_use]
616    fn zrem<K, M, C>(self, key: K, members: C) -> PreparedCommand<'a, Self, usize>
617    where
618        Self: Sized,
619        K: SingleArg,
620        M: SingleArg,
621        C: SingleArgCollection<M>,
622    {
623        prepare_command(self, cmd("ZREM").arg(key).arg(members))
624    }
625
626    /// When all the elements in a sorted set are inserted with the same score,
627    /// in order to force lexicographical ordering,
628    /// this command removes all elements in the sorted set stored at key
629    /// between the lexicographical range specified by min and max.
630    ///
631    /// # Return
632    /// the number of elements removed.
633    ///
634    /// # See Also
635    /// [<https://redis.io/commands/zremrangebylex/>](https://redis.io/commands/zremrangebylex/)
636    #[must_use]
637    fn zremrangebylex<K, S>(self, key: K, start: S, stop: S) -> PreparedCommand<'a, Self, usize>
638    where
639        Self: Sized,
640        K: SingleArg,
641        S: SingleArg,
642    {
643        prepare_command(self, cmd("ZREMRANGEBYLEX").arg(key).arg(start).arg(stop))
644    }
645
646    /// Removes all elements in the sorted set stored at key with rank between start and stop.
647    ///
648    /// # Return
649    /// the number of elements removed.
650    ///
651    /// # See Also
652    /// [<https://redis.io/commands/zremrangebyrank/>](https://redis.io/commands/zremrangebyrank/)
653    #[must_use]
654    fn zremrangebyrank<K>(
655        self,
656        key: K,
657        start: isize,
658        stop: isize,
659    ) -> PreparedCommand<'a, Self, usize>
660    where
661        Self: Sized,
662        K: SingleArg,
663    {
664        prepare_command(self, cmd("ZREMRANGEBYRANK").arg(key).arg(start).arg(stop))
665    }
666
667    /// Removes all elements in the sorted set stored at key with a score between min and max (inclusive).
668    ///
669    /// # Return
670    /// the number of elements removed.
671    ///
672    /// # See Also
673    /// [<https://redis.io/commands/zremrangebyscore/>](https://redis.io/commands/zremrangebyscore/)
674    #[must_use]
675    fn zremrangebyscore<K, S>(self, key: K, start: S, stop: S) -> PreparedCommand<'a, Self, usize>
676    where
677        Self: Sized,
678        K: SingleArg,
679        S: SingleArg,
680    {
681        prepare_command(self, cmd("ZREMRANGEBYSCORE").arg(key).arg(start).arg(stop))
682    }
683
684    /// Returns the rank of member in the sorted set stored at key, with the scores ordered from high to low.
685    ///
686    /// # Return
687    /// * If member exists in the sorted set, the rank of member.
688    /// * If member does not exist in the sorted set or key does not exist, None.
689    ///
690    /// # See Also
691    /// [<https://redis.io/commands/zrevrank/>](https://redis.io/commands/zrevrank/)
692    #[must_use]
693    fn zrevrank<K, M>(self, key: K, member: M) -> PreparedCommand<'a, Self, Option<usize>>
694    where
695        Self: Sized,
696        K: SingleArg,
697        M: SingleArg,
698    {
699        prepare_command(self, cmd("ZREVRANK").arg(key).arg(member))
700    }
701
702    /// Iterates elements of Sorted Set types and their associated scores.
703    ///
704    /// # Returns
705    /// A tuple where
706    /// * The first value is the cursor as an unsigned 64 bit number
707    /// * The second value is a list of members and their scores in a Vec of Tuples
708    ///
709    /// # See Also
710    /// [<https://redis.io/commands/zscan/>](https://redis.io/commands/zscan/)
711    #[must_use]
712    fn zscan<K, M>(
713        self,
714        key: K,
715        cursor: usize,
716        options: ZScanOptions,
717    ) -> PreparedCommand<'a, Self, ZScanResult<M>>
718    where
719        Self: Sized,
720        K: SingleArg,
721        M: PrimitiveResponse + DeserializeOwned,
722    {
723        prepare_command(self, cmd("ZSCAN").arg(key).arg(cursor).arg(options))
724    }
725
726    /// Returns the score of member in the sorted set at key.
727    ///
728    /// # Return
729    /// The score of `member` or nil if `key`does not exist
730    ///
731    /// # See Also
732    /// [<https://redis.io/commands/zscore/>](https://redis.io/commands/zscore/)
733    #[must_use]
734    fn zscore<K, M>(self, key: K, member: M) -> PreparedCommand<'a, Self, Option<f64>>
735    where
736        Self: Sized,
737        K: SingleArg,
738        M: SingleArg,
739    {
740        prepare_command(self, cmd("ZSCORE").arg(key).arg(member))
741    }
742
743    /// This command is similar to [zunionstore](SortedSetCommands::zunionstore),
744    /// but instead of storing the resulting sorted set, it is returned to the client.
745    ///
746    /// # Return
747    /// The result of the unionsection as an array of members
748    ///
749    /// # See Also
750    /// [<https://redis.io/commands/zunion/>](https://redis.io/commands/zunion/)
751    #[must_use]
752    fn zunion<K, C, W, E>(
753        self,
754        keys: C,
755        weights: Option<W>,
756        aggregate: ZAggregate,
757    ) -> PreparedCommand<'a, Self, Vec<E>>
758    where
759        Self: Sized,
760        K: SingleArg,
761        C: SingleArgCollection<K>,
762        W: SingleArgCollection<f64>,
763        E: PrimitiveResponse + DeserializeOwned,
764    {
765        prepare_command(
766            self,
767            cmd("ZUNION")
768                .arg(keys.num_args())
769                .arg(keys)
770                .arg(weights.map(|w| ("WEIGHTS", w)))
771                .arg(aggregate),
772        )
773    }
774
775    /// This command is similar to [zunionstore](SortedSetCommands::zunionstore),
776    /// but instead of storing the resulting sorted set, it is returned to the client.
777    ///
778    /// # Return
779    /// The result of the unionsection as an array of members with their scores
780    ///
781    /// # See Also
782    /// [<https://redis.io/commands/zunion/>](https://redis.io/commands/zunion/)
783    #[must_use]
784    fn zunion_with_scores<K, C, W, E>(
785        self,
786        keys: C,
787        weights: Option<W>,
788        aggregate: ZAggregate,
789    ) -> PreparedCommand<'a, Self, Vec<(E, f64)>>
790    where
791        Self: Sized,
792        K: SingleArg,
793        C: SingleArgCollection<K>,
794        W: SingleArgCollection<f64>,
795        E: PrimitiveResponse + DeserializeOwned,
796    {
797        prepare_command(
798            self,
799            cmd("ZUNION")
800                .arg(keys.num_args())
801                .arg(keys)
802                .arg(weights.map(|w| ("WEIGHTS", w)))
803                .arg(aggregate)
804                .arg("WITHSCORES"),
805        )
806    }
807
808    /// Computes the unionsection of numkeys sorted sets given by the specified keys,
809    /// and stores the result in destination.
810    ///
811    /// # Return
812    /// The number of elements in the resulting sorted set at destination.
813    ///
814    /// # See Also
815    /// [<https://redis.io/commands/zunionstore/>](https://redis.io/commands/zunionstore/)
816    #[must_use]
817    fn zunionstore<D, K, C, W>(
818        self,
819        destination: D,
820        keys: C,
821        weights: Option<W>,
822        aggregate: ZAggregate,
823    ) -> PreparedCommand<'a, Self, usize>
824    where
825        Self: Sized,
826        D: SingleArg,
827        K: SingleArg,
828        C: SingleArgCollection<K>,
829        W: SingleArgCollection<f64>,
830    {
831        prepare_command(
832            self,
833            cmd("ZUNIONSTORE")
834                .arg(destination)
835                .arg(keys.num_args())
836                .arg(keys)
837                .arg(weights.map(|w| ("WEIGHTS", w)))
838                .arg(aggregate),
839        )
840    }
841}
842
843/// Condition option for the [`zadd`](SortedSetCommands::zadd) command
844#[derive(Default)]
845pub enum ZAddCondition {
846    /// No condition
847    #[default]
848    None,
849    /// Only update elements that already exist. Don't add new elements.
850    NX,
851    /// Only add new elements. Don't update already existing elements.
852    XX,
853}
854
855impl ToArgs for ZAddCondition {
856    fn write_args(&self, args: &mut CommandArgs) {
857        match self {
858            ZAddCondition::None => {}
859            ZAddCondition::NX => {
860                args.arg("NX");
861            }
862            ZAddCondition::XX => {
863                args.arg("XX");
864            }
865        }
866    }
867}
868
869/// Comparison option for the [`zadd`](SortedSetCommands::zadd) command
870#[derive(Default)]
871pub enum ZAddComparison {
872    /// No comparison
873    #[default]
874    None,
875    /// Only update existing elements if the new score is greater than the current score.
876    ///
877    /// This flag doesn't prevent adding new elements.
878    GT,
879    /// Only update existing elements if the new score is less than the current score.
880    ///
881    /// This flag doesn't prevent adding new elements.
882    LT,
883}
884
885impl ToArgs for ZAddComparison {
886    fn write_args(&self, args: &mut CommandArgs) {
887        match self {
888            ZAddComparison::None => {}
889            ZAddComparison::GT => {
890                args.arg("GT");
891            }
892            ZAddComparison::LT => {
893                args.arg("LT");
894            }
895        }
896    }
897}
898
899/// sort by option of the [`zrange`](SortedSetCommands::zrange) command
900#[derive(Default)]
901pub enum ZRangeSortBy {
902    /// No sort by
903    #[default]
904    None,
905    /// When the `ByScore` option is provided, the command behaves like `ZRANGEBYSCORE` and returns
906    /// the range of elements from the sorted set having scores equal or between `start` and `stop`.
907    ByScore,
908    /// When the `ByLex` option is used, the command behaves like `ZRANGEBYLEX` and returns the range
909    /// of elements from the sorted set between the `start` and `stop` lexicographical closed range intervals.
910    ByLex,
911}
912
913impl ToArgs for ZRangeSortBy {
914    fn write_args(&self, args: &mut CommandArgs) {
915        match self {
916            ZRangeSortBy::None => {}
917            ZRangeSortBy::ByScore => {
918                args.arg("BYSCORE");
919            }
920            ZRangeSortBy::ByLex => {
921                args.arg("BYLEX");
922            }
923        }
924    }
925}
926
927/// Option that specify how results of an union or intersection are aggregated
928///
929/// # See Also
930/// [zinter](SortedSetCommands::zinter)
931/// [zinterstore](SortedSetCommands::zinterstore)
932/// [zunion](SortedSetCommands::zunion)
933/// [zunionstore](SortedSetCommands::zunionstore)
934#[derive(Default)]
935pub enum ZAggregate {
936    /// No aggregation
937    #[default]
938    None,
939    /// The score of an element is summed across the inputs where it exists.
940    Sum,
941    /// The minimum score of an element across the inputs where it exists.
942    Min,
943    /// The maximum score of an element across the inputs where it exists.
944    Max,
945}
946
947impl ToArgs for ZAggregate {
948    fn write_args(&self, args: &mut CommandArgs) {
949        match self {
950            ZAggregate::None => {}
951            ZAggregate::Sum => {
952                args.arg("SUM");
953            }
954            ZAggregate::Min => {
955                args.arg("MIN");
956            }
957            ZAggregate::Max => {
958                args.arg("MAX");
959            }
960        }
961    }
962}
963
964/// Where option of the [`zmpop`](SortedSetCommands::zmpop) command
965pub enum ZWhere {
966    /// When the MIN modifier is used, the elements popped are those
967    /// with the lowest scores from the first non-empty sorted set.
968    Min,
969    /// The MAX modifier causes elements with the highest scores to be popped.
970    Max,
971}
972
973impl ToArgs for ZWhere {
974    fn write_args(&self, args: &mut CommandArgs) {
975        match self {
976            ZWhere::Min => args.arg("MIN"),
977            ZWhere::Max => args.arg("MAX"),
978        };
979    }
980}
981
982/// Options for the [`zadd`](SortedSetCommands::zadd) command.
983#[derive(Default)]
984pub struct ZAddOptions {
985    command_args: CommandArgs,
986}
987
988impl ZAddOptions {
989    #[must_use]
990    pub fn condition(mut self, condition: ZAddCondition) -> Self {
991        Self {
992            command_args: self.command_args.arg(condition).build(),
993        }
994    }
995
996    #[must_use]
997    pub fn comparison(mut self, comparison: ZAddComparison) -> Self {
998        Self {
999            command_args: self.command_args.arg(comparison).build(),
1000        }
1001    }
1002
1003    #[must_use]
1004    pub fn change(mut self) -> Self {
1005        Self {
1006            command_args: self.command_args.arg("CH").build(),
1007        }
1008    }
1009}
1010
1011impl ToArgs for ZAddOptions {
1012    fn write_args(&self, args: &mut CommandArgs) {
1013        self.command_args.write_args(args);
1014    }
1015}
1016
1017/// Result for [`zmpop`](SortedSetCommands::zmpop) the command.
1018pub type ZMPopResult<E> = (String, Vec<(E, f64)>);
1019
1020/// Options for the [`zrange`](SortedSetCommands::zrange)
1021/// and [`zrangestore`](SortedSetCommands::zrangestore) commands
1022#[derive(Default)]
1023pub struct ZRangeOptions {
1024    command_args: CommandArgs,
1025}
1026
1027impl ZRangeOptions {
1028    #[must_use]
1029    pub fn sort_by(mut self, sort_by: ZRangeSortBy) -> Self {
1030        Self {
1031            command_args: self.command_args.arg(sort_by).build(),
1032        }
1033    }
1034
1035    #[must_use]
1036    pub fn reverse(mut self) -> Self {
1037        Self {
1038            command_args: self.command_args.arg("REV").build(),
1039        }
1040    }
1041
1042    #[must_use]
1043    pub fn limit(mut self, offset: usize, count: isize) -> Self {
1044        Self {
1045            command_args: self
1046                .command_args
1047                .arg("LIMIT")
1048                .arg(offset)
1049                .arg(count)
1050                .build(),
1051        }
1052    }
1053}
1054
1055impl ToArgs for ZRangeOptions {
1056    fn write_args(&self, args: &mut CommandArgs) {
1057        args.arg(&self.command_args);
1058    }
1059}
1060
1061/// Options for the [`zscan`](SortedSetCommands::zscan) command
1062#[derive(Default)]
1063pub struct ZScanOptions {
1064    command_args: CommandArgs,
1065}
1066
1067impl ZScanOptions {
1068    #[must_use]
1069    pub fn match_pattern<P: SingleArg>(mut self, match_pattern: P) -> Self {
1070        Self {
1071            command_args: self.command_args.arg("MATCH").arg(match_pattern).build(),
1072        }
1073    }
1074
1075    #[must_use]
1076    pub fn count(mut self, count: usize) -> Self {
1077        Self {
1078            command_args: self.command_args.arg("COUNT").arg(count).build(),
1079        }
1080    }
1081}
1082
1083impl ToArgs for ZScanOptions {
1084    fn write_args(&self, args: &mut CommandArgs) {
1085        args.arg(&self.command_args);
1086    }
1087}
1088
1089/// Result for the [`zscan`](SortedSetCommands::zscan) command.
1090#[derive(Debug, Deserialize)]
1091pub struct ZScanResult<M>
1092where
1093    M: PrimitiveResponse + DeserializeOwned,
1094{
1095    pub cursor: u64,
1096    #[serde(deserialize_with = "deserialize_vec_of_pairs")]
1097    pub elements: Vec<(M, f64)>,
1098}