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