redis_ac/commands.rs
1// Copyright (c) 2019 by Yushi Omote.
2//
3// Some rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11//
12// * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following
14// disclaimer in the documentation and/or other materials provided
15// with the distribution.
16//
17// * The names of the contributors may not be used to endorse or
18// promote products derived from this software without specific
19// prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33use redis::aio::ConnectionLike;
34use redis::{cmd, FromRedisValue, NumericBehavior, RedisFuture, ToRedisArgs};
35
36#[cfg(feature = "geospatial")]
37use redis::geo;
38
39use crate::stream::stream;
40pub use crate::stream::{RedisScanAll, RedisScanStream};
41
42impl<T> Commands for T where T: ConnectionLike + Send + Sized + 'static {}
43
44macro_rules! implement_commands {
45 (
46 $(
47 $(#[$attr:meta])+
48 fn $name:ident<$($tyargs:ident : $ty:ident),*>(
49 $($argname:ident: $argty:ty),*) $body:block
50 )*
51 ) =>
52 (
53
54 /// Asynchronous version of [`redis::Commands`][].
55 ///
56 /// # Constraints
57 ///
58 /// The arguments of scan commands are required to implement `Clone` because
59 /// they need to create multiple [`redis::Cmd`][] objects internally.
60 pub trait Commands : ConnectionLike+Send+Sized+'static {
61 $(
62 $(#[$attr])*
63 #[inline]
64 fn $name<$($tyargs: $ty,)* RV: FromRedisValue+Send+'static>(self $(, $argname: $argty)*) -> RedisFuture<(Self, RV)>
65 { ($body).query_async(self) }
66 )*
67
68 /// Incrementally iterate the keys space.
69 #[inline]
70 fn scan<RV: FromRedisValue+Send+'static>(self) -> RedisScanStream<Self, RV> {
71 stream(self, |cur| {
72 let mut c = cmd("SCAN");
73 c.arg(cur);
74 c
75 })
76 }
77
78 /// Incrementally iterate the keys space for keys matching a pattern.
79 #[inline]
80 fn scan_match<P: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>(self, pattern: P) -> RedisScanStream<Self, RV> {
81 stream(self, move |cur| {
82 let mut c = cmd("SCAN");
83 c.arg(cur)
84 .arg("MATCH")
85 .arg(pattern.clone());
86 c
87 })
88 }
89
90 /// Incrementally iterate hash fields and associated values.
91 #[inline]
92 fn hscan<K: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>(self, key: K) -> RedisScanStream<Self, RV> {
93 stream(self, move |cur| {
94 let mut c = cmd("HSCAN");
95 c.arg(key.clone()).arg(cur);
96 c
97 })
98 }
99
100 /// Incrementally iterate hash fields and associated values for
101 /// field names matching a pattern.
102 #[inline]
103 fn hscan_match<K: ToRedisArgs+Clone+Send+'static, P: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>
104 (self, key: K, pattern: P) -> RedisScanStream<Self, RV> {
105 stream(self, move |cur| {
106 let mut c = cmd("HSCAN");
107 c.arg(key.clone()).arg(cur).arg("MATCH").arg(pattern.clone());
108 c
109 })
110 }
111
112 /// Incrementally iterate set elements.
113 #[inline]
114 fn sscan<K: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>(self, key: K) -> RedisScanStream<Self, RV> {
115 stream(self, move |cur| {
116 let mut c = cmd("SSCAN");
117 c.arg(key.clone()).cursor_arg(cur);
118 c
119 })
120 }
121
122 /// Incrementally iterate set elements for elements matching a pattern.
123 #[inline]
124 fn sscan_match<K: ToRedisArgs+Clone+Send+'static, P: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>
125 (self, key: K, pattern: P) -> RedisScanStream<Self, RV> {
126 stream(self, move |cur| {
127 let mut c = cmd("SSCAN");
128 c.arg(key.clone()).arg(cur).arg("MATCH").arg(pattern.clone());
129 c
130 })
131 }
132
133 /// Incrementally iterate sorted set elements.
134 #[inline]
135 fn zscan<K: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>(self, key: K) -> RedisScanStream<Self, RV> {
136 stream(self, move |cur| {
137 let mut c = cmd("ZSCAN");
138 c.arg(key.clone()).arg(cur);
139 c
140 })
141 }
142
143 /// Incrementally iterate sorted set elements for elements matching a pattern.
144 #[inline]
145 fn zscan_match<K: ToRedisArgs+Clone+Send+'static, P: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>
146 (self, key: K, pattern: P) -> RedisScanStream<Self, RV> {
147 stream(self, move |cur| {
148 let mut c = cmd("ZSCAN");
149 c.arg(key.clone()).arg(cur).arg("MATCH").arg(pattern.clone());
150 c
151 })
152 }
153 }
154 )
155}
156
157// Copyright (c) 2013 by Armin Ronacher.
158//
159// Some rights reserved.
160//
161// Redistribution and use in source and binary forms, with or without
162// modification, are permitted provided that the following conditions are
163// met:
164//
165// * Redistributions of source code must retain the above copyright
166// notice, this list of conditions and the following disclaimer.
167//
168// * Redistributions in binary form must reproduce the above
169// copyright notice, this list of conditions and the following
170// disclaimer in the documentation and/or other materials provided
171// with the distribution.
172//
173// * The names of the contributors may not be used to endorse or
174// promote products derived from this software without specific
175// prior written permission.
176//
177// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
178// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
179// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
180// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
181// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
182// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
183// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
184// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
185// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
186// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
187// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
188//
189// https://docs.rs/redis/0.13.0/src/redis/commands.rs.html
190//
191
192implement_commands! {
193 // most common operations
194
195 /// Get the value of a key. If key is a vec this becomes an `MGET`.
196 fn get<K: ToRedisArgs>(key: K) {
197 cmd(if key.is_single_arg() { "GET" } else { "MGET" }).arg(key)
198 }
199
200 /// Gets all keys matching pattern
201 fn keys<K: ToRedisArgs>(key: K) {
202 cmd("KEYS").arg(key)
203 }
204
205 /// Set the string value of a key.
206 fn set<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
207 cmd("SET").arg(key).arg(value)
208 }
209
210 /// Sets multiple keys to their values.
211 fn set_multiple<K: ToRedisArgs, V: ToRedisArgs>(items: &[(K, V)]) {
212 cmd("MSET").arg(items)
213 }
214
215 /// Set the value and expiration of a key.
216 fn set_ex<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V, seconds: usize) {
217 cmd("SETEX").arg(key).arg(seconds).arg(value)
218 }
219
220 /// Set the value of a key, only if the key does not exist
221 fn set_nx<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
222 cmd("SETNX").arg(key).arg(value)
223 }
224
225 /// Sets multiple keys to their values failing if at least one already exists.
226 fn mset_nx<K: ToRedisArgs, V: ToRedisArgs>(items: &[(K, V)]) {
227 cmd("MSETNX").arg(items)
228 }
229
230 /// Set the string value of a key and return its old value.
231 fn getset<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
232 cmd("GETSET").arg(key).arg(value)
233 }
234
235 /// Get a range of bytes/substring from the value of a key. Negative values provide an offset from the end of the value.
236 fn getrange<K: ToRedisArgs>(key: K, from: isize, to: isize) {
237 cmd("GETRANGE").arg(key).arg(from).arg(to)
238 }
239
240 /// Overwrite the part of the value stored in key at the specified offset.
241 fn setrange<K: ToRedisArgs, V: ToRedisArgs>(key: K, offset: isize, value: V) {
242 cmd("SETRANGE").arg(key).arg(offset).arg(value)
243 }
244
245 /// Delete one or more keys.
246 fn del<K: ToRedisArgs>(key: K) {
247 cmd("DEL").arg(key)
248 }
249
250 /// Determine if a key exists.
251 fn exists<K: ToRedisArgs>(key: K) {
252 cmd("EXISTS").arg(key)
253 }
254
255 /// Set a key's time to live in seconds.
256 fn expire<K: ToRedisArgs>(key: K, seconds: usize) {
257 cmd("EXPIRE").arg(key).arg(seconds)
258 }
259
260 /// Set the expiration for a key as a UNIX timestamp.
261 fn expire_at<K: ToRedisArgs>(key: K, ts: usize) {
262 cmd("EXPIREAT").arg(key).arg(ts)
263 }
264
265 /// Set a key's time to live in milliseconds.
266 fn pexpire<K: ToRedisArgs>(key: K, ms: usize) {
267 cmd("PEXPIRE").arg(key).arg(ms)
268 }
269
270 /// Set the expiration for a key as a UNIX timestamp in milliseconds.
271 fn pexpire_at<K: ToRedisArgs>(key: K, ts: usize) {
272 cmd("PEXPIREAT").arg(key).arg(ts)
273 }
274
275 /// Remove the expiration from a key.
276 fn persist<K: ToRedisArgs>(key: K) {
277 cmd("PERSIST").arg(key)
278 }
279
280 /// Check the expiration time of a key.
281 fn ttl<K: ToRedisArgs>(key: K) {
282 cmd("TTL").arg(key)
283 }
284
285 /// Rename a key.
286 fn rename<K: ToRedisArgs>(key: K, new_key: K) {
287 cmd("RENAME").arg(key).arg(new_key)
288 }
289
290 /// Rename a key, only if the new key does not exist.
291 fn rename_nx<K: ToRedisArgs>(key: K, new_key: K) {
292 cmd("RENAMENX").arg(key).arg(new_key)
293 }
294
295 // common string operations
296
297 /// Append a value to a key.
298 fn append<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
299 cmd("APPEND").arg(key).arg(value)
300 }
301
302 /// Increment the numeric value of a key by the given amount. This
303 /// issues a `INCRBY` or `INCRBYFLOAT` depending on the type.
304 fn incr<K: ToRedisArgs, V: ToRedisArgs>(key: K, delta: V) {
305 cmd(if delta.describe_numeric_behavior() == NumericBehavior::NumberIsFloat {
306 "INCRBYFLOAT"
307 } else {
308 "INCRBY"
309 }).arg(key).arg(delta)
310 }
311
312 /// Sets or clears the bit at offset in the string value stored at key.
313 fn setbit<K: ToRedisArgs>(key: K, offset: usize, value: bool) {
314 cmd("SETBIT").arg(key).arg(offset).arg(if value {1} else {0})
315 }
316
317 /// Returns the bit value at offset in the string value stored at key.
318 fn getbit<K: ToRedisArgs>(key: K, offset: usize) {
319 cmd("GETBIT").arg(key).arg(offset)
320 }
321
322 /// Count set bits in a string.
323 fn bitcount<K: ToRedisArgs>(key: K) {
324 cmd("BITCOUNT").arg(key)
325 }
326
327 /// Count set bits in a string in a range.
328 fn bitcount_range<K: ToRedisArgs>(key: K, start: usize, end: usize) {
329 cmd("BITCOUNT").arg(key).arg(start).arg(end)
330 }
331
332 /// Perform a bitwise AND between multiple keys (containing string values)
333 /// and store the result in the destination key.
334 fn bit_and<K: ToRedisArgs>(dstkey: K, srckeys: K) {
335 cmd("BITOP").arg("AND").arg(dstkey).arg(srckeys)
336 }
337
338 /// Perform a bitwise OR between multiple keys (containing string values)
339 /// and store the result in the destination key.
340 fn bit_or<K: ToRedisArgs>(dstkey: K, srckeys: K) {
341 cmd("BITOP").arg("OR").arg(dstkey).arg(srckeys)
342 }
343
344 /// Perform a bitwise XOR between multiple keys (containing string values)
345 /// and store the result in the destination key.
346 fn bit_xor<K: ToRedisArgs>(dstkey: K, srckeys: K) {
347 cmd("BITOP").arg("XOR").arg(dstkey).arg(srckeys)
348 }
349
350 /// Perform a bitwise NOT of the key (containing string values)
351 /// and store the result in the destination key.
352 fn bit_not<K: ToRedisArgs>(dstkey: K, srckey: K) {
353 cmd("BITOP").arg("NOT").arg(dstkey).arg(srckey)
354 }
355
356 /// Get the length of the value stored in a key.
357 fn strlen<K: ToRedisArgs>(key: K) {
358 cmd("STRLEN").arg(key)
359 }
360
361 // hash operations
362
363 /// Gets a single (or multiple) fields from a hash.
364 fn hget<K: ToRedisArgs, F: ToRedisArgs>(key: K, field: F) {
365 cmd(if field.is_single_arg() { "HGET" } else { "HMGET" }).arg(key).arg(field)
366 }
367
368 /// Deletes a single (or multiple) fields from a hash.
369 fn hdel<K: ToRedisArgs, F: ToRedisArgs>(key: K, field: F) {
370 cmd("HDEL").arg(key).arg(field)
371 }
372
373 /// Sets a single field in a hash.
374 fn hset<K: ToRedisArgs, F: ToRedisArgs, V: ToRedisArgs>(key: K, field: F, value: V) {
375 cmd("HSET").arg(key).arg(field).arg(value)
376 }
377
378 /// Sets a single field in a hash if it does not exist.
379 fn hset_nx<K: ToRedisArgs, F: ToRedisArgs, V: ToRedisArgs>(key: K, field: F, value: V) {
380 cmd("HSETNX").arg(key).arg(field).arg(value)
381 }
382
383 /// Sets a multiple fields in a hash.
384 fn hset_multiple<K: ToRedisArgs, F: ToRedisArgs, V: ToRedisArgs>(key: K, items: &[(F, V)]) {
385 cmd("HMSET").arg(key).arg(items)
386 }
387
388 /// Increments a value.
389 fn hincr<K: ToRedisArgs, F: ToRedisArgs, D: ToRedisArgs>(key: K, field: F, delta: D) {
390 cmd(if delta.describe_numeric_behavior() == NumericBehavior::NumberIsFloat {
391 "HINCRBYFLOAT"
392 } else {
393 "HINCRBY"
394 }).arg(key).arg(field).arg(delta)
395 }
396
397 /// Checks if a field in a hash exists.
398 fn hexists<K: ToRedisArgs, F: ToRedisArgs>(key: K, field: F) {
399 cmd("HEXISTS").arg(key).arg(field)
400 }
401
402 /// Gets all the keys in a hash.
403 fn hkeys<K: ToRedisArgs>(key: K) {
404 cmd("HKEYS").arg(key)
405 }
406
407 /// Gets all the values in a hash.
408 fn hvals<K: ToRedisArgs>(key: K) {
409 cmd("HVALS").arg(key)
410 }
411
412 /// Gets all the fields and values in a hash.
413 fn hgetall<K: ToRedisArgs>(key: K) {
414 cmd("HGETALL").arg(key)
415 }
416
417 /// Gets the length of a hash.
418 fn hlen<K: ToRedisArgs>(key: K) {
419 cmd("HLEN").arg(key)
420 }
421
422 // list operations
423
424 /// Remove and get the first element in a list, or block until one is available.
425 fn blpop<K: ToRedisArgs>(key: K, timeout: usize) {
426 cmd("BLPOP").arg(key).arg(timeout)
427 }
428
429 /// Remove and get the last element in a list, or block until one is available.
430 fn brpop<K: ToRedisArgs>(key: K, timeout: usize) {
431 cmd("BRPOP").arg(key).arg(timeout)
432 }
433
434 /// Pop a value from a list, push it to another list and return it;
435 /// or block until one is available.
436 fn brpoplpush<K: ToRedisArgs>(srckey: K, dstkey: K, timeout: usize) {
437 cmd("BRPOPLPUSH").arg(srckey).arg(dstkey).arg(timeout)
438 }
439
440 /// Get an element from a list by its index.
441 fn lindex<K: ToRedisArgs>(key: K, index: isize) {
442 cmd("LINDEX").arg(key).arg(index)
443 }
444
445 /// Insert an element before another element in a list.
446 fn linsert_before<K: ToRedisArgs, P: ToRedisArgs, V: ToRedisArgs>(
447 key: K, pivot: P, value: V) {
448 cmd("LINSERT").arg(key).arg("BEFORE").arg(pivot).arg(value)
449 }
450
451 /// Insert an element after another element in a list.
452 fn linsert_after<K: ToRedisArgs, P: ToRedisArgs, V: ToRedisArgs>(
453 key: K, pivot: P, value: V) {
454 cmd("LINSERT").arg(key).arg("AFTER").arg(pivot).arg(value)
455 }
456
457 /// Returns the length of the list stored at key.
458 fn llen<K: ToRedisArgs>(key: K) {
459 cmd("LLEN").arg(key)
460 }
461
462 /// Removes and returns the first element of the list stored at key.
463 fn lpop<K: ToRedisArgs>(key: K) {
464 cmd("LPOP").arg(key)
465 }
466
467 /// Insert all the specified values at the head of the list stored at key.
468 fn lpush<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
469 cmd("LPUSH").arg(key).arg(value)
470 }
471
472 /// Inserts a value at the head of the list stored at key, only if key
473 /// already exists and holds a list.
474 fn lpush_exists<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
475 cmd("LPUSHX").arg(key).arg(value)
476 }
477
478 /// Returns the specified elements of the list stored at key.
479 fn lrange<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
480 cmd("LRANGE").arg(key).arg(start).arg(stop)
481 }
482
483 /// Removes the first count occurrences of elements equal to value
484 /// from the list stored at key.
485 fn lrem<K: ToRedisArgs, V: ToRedisArgs>(key: K, count: isize, value: V) {
486 cmd("LREM").arg(key).arg(count).arg(value)
487 }
488
489 /// Trim an existing list so that it will contain only the specified
490 /// range of elements specified.
491 fn ltrim<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
492 cmd("LTRIM").arg(key).arg(start).arg(stop)
493 }
494
495 /// Sets the list element at index to value
496 fn lset<K: ToRedisArgs, V: ToRedisArgs>(key: K, index: isize, value: V) {
497 cmd("LSET").arg(key).arg(index).arg(value)
498 }
499
500 /// Removes and returns the last element of the list stored at key.
501 fn rpop<K: ToRedisArgs>(key: K) {
502 cmd("RPOP").arg(key)
503 }
504
505 /// Pop a value from a list, push it to another list and return it.
506 fn rpoplpush<K: ToRedisArgs>(key: K, dstkey: K) {
507 cmd("RPOPLPUSH").arg(key).arg(dstkey)
508 }
509
510 /// Insert all the specified values at the tail of the list stored at key.
511 fn rpush<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
512 cmd("RPUSH").arg(key).arg(value)
513 }
514
515 /// Inserts value at the tail of the list stored at key, only if key
516 /// already exists and holds a list.
517 fn rpush_exists<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
518 cmd("RPUSHX").arg(key).arg(value)
519 }
520
521 // set commands
522
523 /// Add one or more members to a set.
524 fn sadd<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
525 cmd("SADD").arg(key).arg(member)
526 }
527
528 /// Get the number of members in a set.
529 fn scard<K: ToRedisArgs>(key: K) {
530 cmd("SCARD").arg(key)
531 }
532
533 /// Subtract multiple sets.
534 fn sdiff<K: ToRedisArgs>(keys: K) {
535 cmd("SDIFF").arg(keys)
536 }
537
538 /// Subtract multiple sets and store the resulting set in a key.
539 fn sdiffstore<K: ToRedisArgs>(dstkey: K, keys: K) {
540 cmd("SDIFFSTORE").arg(dstkey).arg(keys)
541 }
542
543 /// Intersect multiple sets.
544 fn sinter<K: ToRedisArgs>(keys: K) {
545 cmd("SINTER").arg(keys)
546 }
547
548 /// Intersect multiple sets and store the resulting set in a key.
549 fn sinterstore<K: ToRedisArgs>(dstkey: K, keys: K) {
550 cmd("SINTERSTORE").arg(dstkey).arg(keys)
551 }
552
553 /// Determine if a given value is a member of a set.
554 fn sismember<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
555 cmd("SISMEMBER").arg(key).arg(member)
556 }
557
558 /// Get all the members in a set.
559 fn smembers<K: ToRedisArgs>(key: K) {
560 cmd("SMEMBERS").arg(key)
561 }
562
563 /// Move a member from one set to another.
564 fn smove<K: ToRedisArgs, M: ToRedisArgs>(srckey: K, dstkey: K, member: M) {
565 cmd("SMOVE").arg(srckey).arg(dstkey).arg(member)
566 }
567
568 /// Remove and return a random member from a set.
569 fn spop<K: ToRedisArgs>(key: K) {
570 cmd("SPOP").arg(key)
571 }
572
573 /// Get one random member from a set.
574 fn srandmember<K: ToRedisArgs>(key: K) {
575 cmd("SRANDMEMBER").arg(key)
576 }
577
578 /// Get multiple random members from a set.
579 fn srandmember_multiple<K: ToRedisArgs>(key: K, count: usize) {
580 cmd("SRANDMEMBER").arg(key).arg(count)
581 }
582
583 /// Remove one or more members from a set.
584 fn srem<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
585 cmd("SREM").arg(key).arg(member)
586 }
587
588 /// Add multiple sets.
589 fn sunion<K: ToRedisArgs>(keys: K) {
590 cmd("SUNION").arg(keys)
591 }
592
593 /// Add multiple sets and store the resulting set in a key.
594 fn sunionstore<K: ToRedisArgs>(dstkey: K, keys: K) {
595 cmd("SUNIONSTORE").arg(dstkey).arg(keys)
596 }
597
598 // sorted set commands
599
600 /// Add one member to a sorted set, or update its score if it already exists.
601 fn zadd<K: ToRedisArgs, S: ToRedisArgs, M: ToRedisArgs>(key: K, member: M, score: S) {
602 cmd("ZADD").arg(key).arg(score).arg(member)
603 }
604
605 /// Add multiple members to a sorted set, or update its score if it already exists.
606 fn zadd_multiple<K: ToRedisArgs, S: ToRedisArgs, M: ToRedisArgs>(key: K, items: &[(S, M)]) {
607 cmd("ZADD").arg(key).arg(items)
608 }
609
610 /// Get the number of members in a sorted set.
611 fn zcard<K: ToRedisArgs>(key: K) {
612 cmd("ZCARD").arg(key)
613 }
614
615 /// Count the members in a sorted set with scores within the given values.
616 fn zcount<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
617 cmd("ZCOUNT").arg(key).arg(min).arg(max)
618 }
619
620 /// Increments the member in a sorted set at key by delta.
621 /// If the member does not exist, it is added with delta as its score.
622 fn zincr<K: ToRedisArgs, M: ToRedisArgs, D: ToRedisArgs>(key: K, member: M, delta: D) {
623 cmd("ZINCRBY").arg(key).arg(delta).arg(member)
624 }
625
626 /// Intersect multiple sorted sets and store the resulting sorted set in
627 /// a new key using SUM as aggregation function.
628 fn zinterstore<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
629 cmd("ZINTERSTORE").arg(dstkey).arg(keys.len()).arg(keys)
630 }
631
632 /// Intersect multiple sorted sets and store the resulting sorted set in
633 /// a new key using MIN as aggregation function.
634 fn zinterstore_min<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
635 cmd("ZINTERSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MIN")
636 }
637
638 /// Intersect multiple sorted sets and store the resulting sorted set in
639 /// a new key using MAX as aggregation function.
640 fn zinterstore_max<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
641 cmd("ZINTERSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MAX")
642 }
643
644 /// Count the number of members in a sorted set between a given lexicographical range.
645 fn zlexcount<K: ToRedisArgs, L: ToRedisArgs>(key: K, min: L, max: L) {
646 cmd("ZLEXCOUNT").arg(key).arg(min).arg(max)
647 }
648
649 /// Return a range of members in a sorted set, by index
650 fn zrange<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
651 cmd("ZRANGE").arg(key).arg(start).arg(stop)
652 }
653
654 /// Return a range of members in a sorted set, by index with scores.
655 fn zrange_withscores<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
656 cmd("ZRANGE").arg(key).arg(start).arg(stop).arg("WITHSCORES")
657 }
658
659 /// Return a range of members in a sorted set, by lexicographical range.
660 fn zrangebylex<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
661 cmd("ZRANGEBYLEX").arg(key).arg(min).arg(max)
662 }
663
664 /// Return a range of members in a sorted set, by lexicographical
665 /// range with offset and limit.
666 fn zrangebylex_limit<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(
667 key: K, min: M, max: MM, offset: isize, count: isize) {
668 cmd("ZRANGEBYLEX").arg(key).arg(min).arg(max).arg("LIMIT").arg(offset).arg(count)
669 }
670
671 /// Return a range of members in a sorted set, by lexicographical range.
672 fn zrevrangebylex<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>(key: K, max: MM, min: M) {
673 cmd("ZREVRANGEBYLEX").arg(key).arg(max).arg(min)
674 }
675
676 /// Return a range of members in a sorted set, by lexicographical
677 /// range with offset and limit.
678 fn zrevrangebylex_limit<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>(
679 key: K, max: MM, min: M, offset: isize, count: isize) {
680 cmd("ZREVRANGEBYLEX").arg(key).arg(max).arg(min).arg("LIMIT").arg(offset).arg(count)
681 }
682
683 /// Return a range of members in a sorted set, by score.
684 fn zrangebyscore<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
685 cmd("ZRANGEBYSCORE").arg(key).arg(min).arg(max)
686 }
687
688 /// Return a range of members in a sorted set, by score with scores.
689 fn zrangebyscore_withscores<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
690 cmd("ZRANGEBYSCORE").arg(key).arg(min).arg(max).arg("WITHSCORES")
691 }
692
693 /// Return a range of members in a sorted set, by score with limit.
694 fn zrangebyscore_limit<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>
695 (key: K, min: M, max: MM, offset: isize, count: isize) {
696 cmd("ZRANGEBYSCORE").arg(key).arg(min).arg(max).arg("LIMIT").arg(offset).arg(count)
697 }
698
699 /// Return a range of members in a sorted set, by score with limit with scores.
700 fn zrangebyscore_limit_withscores<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>
701 (key: K, min: M, max: MM, offset: isize, count: isize) {
702 cmd("ZRANGEBYSCORE").arg(key).arg(min).arg(max).arg("WITHSCORES")
703 .arg("LIMIT").arg(offset).arg(count)
704 }
705
706 /// Determine the index of a member in a sorted set.
707 fn zrank<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
708 cmd("ZRANK").arg(key).arg(member)
709 }
710
711 /// Remove one or more members from a sorted set.
712 fn zrem<K: ToRedisArgs, M: ToRedisArgs>(key: K, members: M) {
713 cmd("ZREM").arg(key).arg(members)
714 }
715
716 /// Remove all members in a sorted set between the given lexicographical range.
717 fn zrembylex<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
718 cmd("ZREMBYLEX").arg(key).arg(min).arg(max)
719 }
720
721 /// Remove all members in a sorted set within the given indexes.
722 fn zrembyrank<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
723 cmd("ZREMBYRANK").arg(key).arg(start).arg(stop)
724 }
725
726 /// Remove all members in a sorted set within the given scores.
727 fn zrembyscore<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
728 cmd("ZREMRANGEBYSCORE").arg(key).arg(min).arg(max)
729 }
730
731 /// Return a range of members in a sorted set, by index, with scores
732 /// ordered from high to low.
733 fn zrevrange<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
734 cmd("ZREVRANGE").arg(key).arg(start).arg(stop)
735 }
736
737 /// Return a range of members in a sorted set, by index, with scores
738 /// ordered from high to low.
739 fn zrevrange_withscores<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
740 cmd("ZREVRANGE").arg(key).arg(start).arg(stop).arg("WITHSCORES")
741 }
742
743 /// Return a range of members in a sorted set, by score.
744 fn zrevrangebyscore<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>(key: K, max: MM, min: M) {
745 cmd("ZREVRANGEBYSCORE").arg(key).arg(max).arg(min)
746 }
747
748 /// Return a range of members in a sorted set, by score with scores.
749 fn zrevrangebyscore_withscores<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>(key: K, max: MM, min: M) {
750 cmd("ZREVRANGEBYSCORE").arg(key).arg(max).arg(min).arg("WITHSCORES")
751 }
752
753 /// Return a range of members in a sorted set, by score with limit.
754 fn zrevrangebyscore_limit<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>
755 (key: K, max: MM, min: M, offset: isize, count: isize) {
756 cmd("ZREVRANGEBYSCORE").arg(key).arg(max).arg(min).arg("LIMIT").arg(offset).arg(count)
757 }
758
759 /// Return a range of members in a sorted set, by score with limit with scores.
760 fn zrevrangebyscore_limit_withscores<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>
761 (key: K, max: MM, min: M, offset: isize, count: isize) {
762 cmd("ZREVRANGEBYSCORE").arg(key).arg(max).arg(min).arg("WITHSCORES")
763 .arg("LIMIT").arg(offset).arg(count)
764 }
765
766 /// Determine the index of a member in a sorted set, with scores ordered from high to low.
767 fn zrevrank<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
768 cmd("ZREVRANK").arg(key).arg(member)
769 }
770
771 /// Get the score associated with the given member in a sorted set.
772 fn zscore<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
773 cmd("ZSCORE").arg(key).arg(member)
774 }
775
776 /// Unions multiple sorted sets and store the resulting sorted set in
777 /// a new key using SUM as aggregation function.
778 fn zunionstore<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
779 cmd("ZUNIONSTORE").arg(dstkey).arg(keys.len()).arg(keys)
780 }
781
782 /// Unions multiple sorted sets and store the resulting sorted set in
783 /// a new key using MIN as aggregation function.
784 fn zunionstore_min<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
785 cmd("ZUNIONSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MIN")
786 }
787
788 /// Unions multiple sorted sets and store the resulting sorted set in
789 /// a new key using MAX as aggregation function.
790 fn zunionstore_max<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
791 cmd("ZUNIONSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MAX")
792 }
793
794 // hyperloglog commands
795
796 /// Adds the specified elements to the specified HyperLogLog.
797 fn pfadd<K: ToRedisArgs, E: ToRedisArgs>(key: K, element: E) {
798 cmd("PFADD").arg(key).arg(element)
799 }
800
801 /// Return the approximated cardinality of the set(s) observed by the
802 /// HyperLogLog at key(s).
803 fn pfcount<K: ToRedisArgs>(key: K) {
804 cmd("PFCOUNT").arg(key)
805 }
806
807 /// Merge N different HyperLogLogs into a single one.
808 fn pfmerge<K: ToRedisArgs>(dstkey: K, srckeys: K) {
809 cmd("PFMERGE").arg(dstkey).arg(srckeys)
810 }
811
812 /// Posts a message to the given channel.
813 fn publish<K: ToRedisArgs, E: ToRedisArgs>(channel: K, message: E) {
814 cmd("PUBLISH").arg(channel).arg(message)
815 }
816
817 // geospatial commands
818
819 /// Adds the specified geospatial items to the specified key.
820 ///
821 /// Every member has to be written as a tuple of `(longitude, latitude,
822 /// member_name)`. It can be a single tuple, or a vector of tuples.
823 ///
824 /// `longitude, latitude` can be set using [`redis::geo::Coord`][1].
825 ///
826 /// [1]: ./geo/struct.Coord.html
827 ///
828 /// Returns the number of elements added to the sorted set, not including
829 /// elements already existing for which the score was updated.
830 ///
831 /// # Example
832 ///
833 /// ```rust,no_run
834 /// use redis::{Commands, Connection, RedisFuture};
835 /// use redis::geo::Coord;
836 ///
837 /// fn add_point(con: &mut Connection) -> RedisFuture<isize> {
838 /// con.geo_add("my_gis", (Coord::lon_lat(13.361389, 38.115556), "Palermo"))
839 /// }
840 ///
841 /// fn add_point_with_tuples(con: &mut Connection) -> RedisFuture<isize> {
842 /// con.geo_add("my_gis", ("13.361389", "38.115556", "Palermo"))
843 /// }
844 ///
845 /// fn add_many_points(con: &mut Connection) -> RedisFuture<isize> {
846 /// con.geo_add("my_gis", &[
847 /// ("13.361389", "38.115556", "Palermo"),
848 /// ("15.087269", "37.502669", "Catania")
849 /// ])
850 /// }
851 /// ```
852 #[cfg(feature = "geospatial")]
853 fn geo_add<K: ToRedisArgs, M: ToRedisArgs>(key: K, members: M) {
854 cmd("GEOADD").arg(key).arg(members)
855 }
856
857 /// Return the distance between two members in the geospatial index
858 /// represented by the sorted set.
859 ///
860 /// If one or both the members are missing, the command returns NULL, so
861 /// it may be convenient to parse its response as either `Option<f64>` or
862 /// `Option<String>`.
863 ///
864 /// # Example
865 ///
866 /// ```rust,no_run
867 /// use redis::{Commands, RedisFuture};
868 /// use redis::geo::Unit;
869 ///
870 /// fn get_dists(con: &mut redis::Connection) {
871 /// let x: RedisFuture<f64> = con.geo_dist(
872 /// "my_gis",
873 /// "Palermo",
874 /// "Catania",
875 /// Unit::Kilometers
876 /// );
877 /// // x is Ok(166.2742)
878 ///
879 /// let x: RedisFuture<Option<f64>> = con.geo_dist(
880 /// "my_gis",
881 /// "Palermo",
882 /// "Atlantis",
883 /// Unit::Meters
884 /// );
885 /// // x is Ok(None)
886 /// }
887 /// ```
888 #[cfg(feature = "geospatial")]
889 fn geo_dist<K: ToRedisArgs, M1: ToRedisArgs, M2: ToRedisArgs>(
890 key: K,
891 member1: M1,
892 member2: M2,
893 unit: geo::Unit
894 ) {
895 cmd("GEODIST")
896 .arg(key)
897 .arg(member1)
898 .arg(member2)
899 .arg(unit)
900 }
901
902 /// Return valid [Geohash][1] strings representing the position of one or
903 /// more members of the geospatial index represented by the sorted set at
904 /// key.
905 ///
906 /// [1]: https://en.wikipedia.org/wiki/Geohash
907 ///
908 /// # Example
909 ///
910 /// ```rust,no_run
911 /// use redis::{Commands, RedisFuture};
912 ///
913 /// fn get_hash(con: &mut redis::Connection) {
914 /// let x: RedisFuture<Vec<String>> = con.geo_hash("my_gis", "Palermo");
915 /// // x is vec!["sqc8b49rny0"]
916 ///
917 /// let x: RedisFuture<Vec<String>> = con.geo_hash("my_gis", &["Palermo", "Catania"]);
918 /// // x is vec!["sqc8b49rny0", "sqdtr74hyu0"]
919 /// }
920 /// ```
921 #[cfg(feature = "geospatial")]
922 fn geo_hash<K: ToRedisArgs, M: ToRedisArgs>(key: K, members: M) {
923 cmd("GEOHASH").arg(key).arg(members)
924 }
925
926 /// Return the positions of all the specified members of the geospatial
927 /// index represented by the sorted set at key.
928 ///
929 /// Every position is a pair of `(longitude, latitude)`. [`redis::geo::Coord`][1]
930 /// can be used to convert these value in a struct.
931 ///
932 /// [1]: ./geo/struct.Coord.html
933 ///
934 /// # Example
935 ///
936 /// ```rust,no_run
937 /// use redis::{Commands, RedisFuture};
938 /// use redis::geo::Coord;
939 ///
940 /// fn get_position(con: &mut redis::Connection) {
941 /// let x: RedisFuture<Vec<Vec<f64>>> = con.geo_pos("my_gis", &["Palermo", "Catania"]);
942 /// // x is [ [ 13.361389, 38.115556 ], [ 15.087269, 37.502669 ] ];
943 ///
944 /// let x: Vec<Coord<f64>> = con.geo_pos("my_gis", "Palermo").unwrap();
945 /// // x[0].longitude is 13.361389
946 /// // x[0].latitude is 38.115556
947 /// }
948 /// ```
949 #[cfg(feature = "geospatial")]
950 fn geo_pos<K: ToRedisArgs, M: ToRedisArgs>(key: K, members: M) {
951 cmd("GEOPOS").arg(key).arg(members)
952 }
953
954 /// Return the members of a sorted set populated with geospatial information
955 /// using [`geo_add`](#method.geo_add), which are within the borders of the area
956 /// specified with the center location and the maximum distance from the center
957 /// (the radius).
958 ///
959 /// Every item in the result can be read with [`redis::geo::RadiusSearchResult`][1],
960 /// which support the multiple formats returned by `GEORADIUS`.
961 ///
962 /// [1]: ./geo/struct.RadiusSearchResult.html
963 ///
964 /// ```rust,no_run
965 /// use redis::{Commands, RedisFuture};
966 /// use redis::geo::{RadiusOptions, RadiusSearchResult, RadiusOrder, Unit};
967 ///
968 /// fn radius(con: &mut redis::Connection) -> Vec<RadiusSearchResult> {
969 /// let opts = RadiusOptions::default().with_dist().order(RadiusOrder::Asc);
970 /// con.geo_radius("my_gis", 15.90, 37.21, 51.39, Unit::Kilometers, opts).unwrap()
971 /// }
972 /// ```
973 #[cfg(feature = "geospatial")]
974 fn geo_radius<K: ToRedisArgs>(
975 key: K,
976 longitude: f64,
977 latitude: f64,
978 radius: f64,
979 unit: geo::Unit,
980 options: geo::RadiusOptions
981 ) {
982 cmd("GEORADIUS")
983 .arg(key)
984 .arg(longitude)
985 .arg(latitude)
986 .arg(radius)
987 .arg(unit)
988 .arg(options)
989 }
990
991 /// Retrieve members selected by distance with the center of `member`. The
992 /// member itself is always contained in the results.
993 #[cfg(feature = "geospatial")]
994 fn geo_radius_by_member<K: ToRedisArgs, M: ToRedisArgs>(
995 key: K,
996 member: M,
997 radius: f64,
998 unit: geo::Unit,
999 options: geo::RadiusOptions
1000 ) {
1001 cmd("GEORADIUSBYMEMBER")
1002 .arg(key)
1003 .arg(member)
1004 .arg(radius)
1005 .arg(unit)
1006 .arg(options)
1007 }
1008
1009}