TTL key
@keyspace,
@read,
@fast,
Returns the remaining time to live of a key that has a timeout. This introspection capability allows a Redis client to check how many seconds a given key will continue to be part of the dataset.
In Redis 2.6 or older the command returns -1 if the key does not exist or if the key exists but has no associated expire.
Starting with Redis 2.8 the return value in case of error changed:
-2 if the key does not exist.-1 if the key exists but has no associated expire.See also the PTTL command that returns the same information with milliseconds resolution (Only available in Redis 2.6 or greater).
> SET mykey "Hello"
"OK"
> EXPIRE mykey 10
(integer) 1
> TTL mykey
(integer) 10import redis
r = redis.Redis(decode_responses=True)
res = r.set("key1", "Hello")
print(res)
# >>> True
res = r.set("key2", "World")
print(res)
# >>> True
res = r.delete("key1", "key2", "key3")
print(res)
# >>> 2
res = r.set("key1", "Hello")
print(res)
# >>> True
res = r.exists("key1")
print(res)
# >>> 1
res = r.exists("nosuchkey")
print(res)
# >>> 0
res = r.set("key2", "World")
print(res)
# >>> True
res = r.exists("key1", "key2", "nosuchkey")
print(res)
# >>> 2
res = r.set("mykey", "Hello")
print(res)
# >>> True
res = r.expire("mykey", 10)
print(res)
# >>> True
res = r.ttl("mykey")
print(res)
# >>> 10
res = r.set("mykey", "Hello World")
print(res)
# >>> True
res = r.ttl("mykey")
print(res)
# >>> -1
res = r.expire("mykey", 10, xx=True)
print(res)
# >>> False
res = r.ttl("mykey")
print(res)
# >>> -1
res = r.expire("mykey", 10, nx=True)
print(res)
# >>> True
res = r.ttl("mykey")
print(res)
# >>> 10
res = r.set("mykey", "Hello")
print(res)
# >>> True
res = r.expire("mykey", 10)
print(res)
# >>> True
res = r.ttl("mykey")
print(res)
# >>> 10
res = r.sadd("myset", *set([1, 2, 3, "foo", "foobar", "feelsgood"]))
print(res)
# >>> 6
res = list(r.sscan_iter("myset", match="f*"))
print(res)
# >>> ['foobar', 'foo', 'feelsgood']
cursor, key = r.scan(cursor=0, match='*11*')
print(cursor, key)
cursor, key = r.scan(cursor, match='*11*')
print(cursor, key)
cursor, key = r.scan(cursor, match='*11*')
print(cursor, key)
cursor, key = r.scan(cursor, match='*11*')
print(cursor, key)
cursor, keys = r.scan(cursor, match='*11*', count=1000)
print(cursor, keys)
res = r.geoadd("geokey", (0, 0, "value"))
print(res)
# >>> 1
res = r.zadd("zkey", {"value": 1000})
print(res)
# >>> 1
res = r.type("geokey")
print(res)
# >>> zset
res = r.type("zkey")
print(res)
# >>> zset
cursor, keys = r.scan(cursor=0, _type="zset")
print(keys)
# >>> ['zkey', 'geokey']
res = r.hset("myhash", mapping={"a": 1, "b": 2})
print(res)
# >>> 2
cursor, keys = r.hscan("myhash", 0)
print(keys)
# >>> {'a': '1', 'b': '2'}
cursor, keys = r.hscan("myhash", 0, no_values=True)
print(keys)
# >>> ['a', 'b']
import { createClient } from 'redis';
const client = createClient();
await client.connect().catch(console.error);
const delRes1 = await client.set('key1', 'Hello');
console.log(delRes1); // OK
const delRes2 = await client.set('key2', 'World');
console.log(delRes2); // OK
const delRes3 = await client.del(['key1', 'key2', 'key3']);
console.log(delRes3); // 2
const existsRes1 = await client.set('key1', 'Hello');
console.log(existsRes1); // OK
const existsRes2 = await client.exists('key1');
console.log(existsRes2); // 1
const existsRes3 = await client.exists('nosuchkey');
console.log(existsRes3); // 0
const existsRes4 = await client.set('key2', 'World');
console.log(existsRes4); // OK
const existsRes5 = await client.exists(['key1', 'key2', 'nosuchkey']);
console.log(existsRes5); // 2
const expireRes1 = await client.set('mykey', 'Hello');
console.log(expireRes1); // OK
const expireRes2 = await client.expire('mykey', 10);
console.log(expireRes2); // 1
const expireRes3 = await client.ttl('mykey');
console.log(expireRes3); // 10
const expireRes4 = await client.set('mykey', 'Hello World');
console.log(expireRes4); // OK
const expireRes5 = await client.ttl('mykey');
console.log(expireRes5); // -1
const expireRes6 = await client.expire('mykey', 10, "XX");
console.log(expireRes6); // 0
const expireRes7 = await client.ttl('mykey');
console.log(expireRes7); // -1
const expireRes8 = await client.expire('mykey', 10, "NX");
console.log(expireRes8); // 1
const expireRes9 = await client.ttl('mykey');
console.log(expireRes9); // 10
const ttlRes1 = await client.set('mykey', 'Hello');
console.log(ttlRes1); // OK
const ttlRes2 = await client.expire('mykey', 10);
console.log(ttlRes2); // 1
const ttlRes3 = await client.ttl('mykey');
console.log(ttlRes3); // 10
const scan1Res1 = await client.sAdd('myset', ['1', '2', '3', 'foo', 'foobar', 'feelsgood']);
console.log(scan1Res1); // 6
let scan1Res2 = [];
for await (const values of client.sScanIterator('myset', { MATCH: 'f*' })) {
scan1Res2 = scan1Res2.concat(values);
}
console.log(scan1Res2); // ['foo', 'foobar', 'feelsgood']
let cursor = '0';
let scanResult;
scanResult = await client.scan(cursor, { MATCH: '*11*' });
console.log(scanResult.cursor, scanResult.keys);
scanResult = await client.scan(scanResult.cursor, { MATCH: '*11*' });
console.log(scanResult.cursor, scanResult.keys);
scanResult = await client.scan(scanResult.cursor, { MATCH: '*11*' });
console.log(scanResult.cursor, scanResult.keys);
scanResult = await client.scan(scanResult.cursor, { MATCH: '*11*' });
console.log(scanResult.cursor, scanResult.keys);
scanResult = await client.scan(scanResult.cursor, { MATCH: '*11*', COUNT: 1000 });
console.log(scanResult.cursor, scanResult.keys);
const scan3Res1 = await client.geoAdd('geokey', { longitude: 0, latitude: 0, member: 'value' });
console.log(scan3Res1); // 1
const scan3Res2 = await client.zAdd('zkey', [{ score: 1000, value: 'value' }]);
console.log(scan3Res2); // 1
const scan3Res3 = await client.type('geokey');
console.log(scan3Res3); // zset
const scan3Res4 = await client.type('zkey');
console.log(scan3Res4); // zset
const scan3Res5 = await client.scan('0', { TYPE: 'zset' });
console.log(scan3Res5.keys); // ['zkey', 'geokey']
const scan4Res1 = await client.hSet('myhash', { a: 1, b: 2 });
console.log(scan4Res1); // 2
const scan4Res2 = await client.hScan('myhash', '0');
console.log(scan4Res2.entries); // [{field: 'a', value: '1'}, {field: 'b', value: '2'}]
const scan4Res3 = await client.hScan('myhash', '0', { COUNT: 10 });
const items = scan4Res3.entries.map((item) => item.field)
console.log(items); // ['a', 'b']
await client.close();
importredis.clients.jedis.UnifiedJedis;importredis.clients.jedis.args.ExpiryOption;import staticorg.junit.jupiter.api.Assertions.assertEquals;publicclass CmdsGenericExample{publicvoidrun(){UnifiedJedisjedis=newUnifiedJedis("redis://localhost:6379");StringdelResult1=jedis.set("key1","Hello");System.out.println(delResult1);// >>> OKStringdelResult2=jedis.set("key2","World");System.out.println(delResult2);// >>> OKlongdelResult3=jedis.del("key1","key2","key3");System.out.println(delResult3);// >>> 2// Tests for 'del' step.StringexistsResult1=jedis.set("key1","Hello");System.out.println(existsResult1);// >>> OKbooleanexistsResult2=jedis.exists("key1");System.out.println(existsResult2);// >>> truebooleanexistsResult3=jedis.exists("nosuchkey");System.out.println(existsResult3);// >>> falseStringexistsResult4=jedis.set("key2","World");System.out.println(existsResult4);// >>> OKlongexistsResult5=jedis.exists("key1","key2","nosuchkey");System.out.println(existsResult5);// >>> 2// Tests for 'exists' step.StringexpireResult1=jedis.set("mykey","Hello");System.out.println(expireResult1);// >>> OKlongexpireResult2=jedis.expire("mykey",10);System.out.println(expireResult2);// >>> 1longexpireResult3=jedis.ttl("mykey");System.out.println(expireResult3);// >>> 10StringexpireResult4=jedis.set("mykey","Hello World");System.out.println(expireResult4);// >>> OKlongexpireResult5=jedis.ttl("mykey");System.out.println(expireResult5);// >>> -1longexpireResult6=jedis.expire("mykey",10,ExpiryOption.XX);System.out.println(expireResult6);// >>> 0longexpireResult7=jedis.ttl("mykey");System.out.println(expireResult7);// >>> -1longexpireResult8=jedis.expire("mykey",10,ExpiryOption.NX);System.out.println(expireResult8);// >>> 1longexpireResult9=jedis.ttl("mykey");System.out.println(expireResult9);// >>> 10// Tests for 'expire' step.StringttlResult1=jedis.set("mykey","Hello");System.out.println(ttlResult1);// >>> OKlongttlResult2=jedis.expire("mykey",10);System.out.println(ttlResult2);// >>> 1longttlResult3=jedis.ttl("mykey");System.out.println(ttlResult3);// >>> 10// Tests for 'ttl' step.jedis.close();}}packageio.redis.examples.async;importio.lettuce.core.*;importio.lettuce.core.api.async.RedisAsyncCommands;importio.lettuce.core.api.StatefulRedisConnection;importjava.util.concurrent.CompletableFuture;publicclass CmdsGenericExample{publicvoidrun(){CompletableFuture<Void>existsExample=asyncCommands.set("key1","Hello").thenCompose(res1->{System.out.println(res1);// >>> OKreturnasyncCommands.exists("key1");}).thenCompose(res2->{System.out.println(res2);// >>> 1returnasyncCommands.exists("nosuchkey");}).thenCompose(res3->{System.out.println(res3);// >>> 0returnasyncCommands.set("key2","World");}).thenCompose(res4->{System.out.println(res4);// >>> OKreturnasyncCommands.exists("key1","key2","nosuchkey");}).thenAccept(res5->{System.out.println(res5);// >>> 2}).toCompletableFuture();existsExample.join();}finally{redisClient.shutdown();}}}packageio.redis.examples.reactive;importio.lettuce.core.*;importio.lettuce.core.api.reactive.RedisReactiveCommands;importio.lettuce.core.api.StatefulRedisConnection;importreactor.core.publisher.Mono;publicclass CmdsGenericExample{publicvoidrun(){RedisClientredisClient=RedisClient.create("redis://localhost:6379");try(StatefulRedisConnection<String,String>connection=redisClient.connect()){RedisReactiveCommands<String,String>reactiveCommands=connection.reactive();Mono<Void>existsExample=reactiveCommands.set("key1","Hello").doOnNext(res1->{System.out.println(res1);// >>> OK}).then(reactiveCommands.exists("key1")).doOnNext(res2->{System.out.println(res2);// >>> 1}).then(reactiveCommands.exists("nosuchkey")).doOnNext(res3->{System.out.println(res3);// >>> 0}).then(reactiveCommands.set("key2","World")).doOnNext(res4->{System.out.println(res4);// >>> OK}).then(reactiveCommands.exists("key1","key2","nosuchkey")).doOnNext(res5->{System.out.println(res5);// >>> 2}).then();Mono.when(existsExample).block();}finally{redisClient.shutdown();}}}package example_commands_test
import (
"context"
"fmt"
"math"
"time"
"github.com/redis/go-redis/v9"
)
func ExampleClient_del_cmd() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
delResult1, err := rdb.Set(ctx, "key1", "Hello", 0).Result()
if err != nil {
panic(err)
}
fmt.Println(delResult1) // >>> OK
delResult2, err := rdb.Set(ctx, "key2", "World", 0).Result()
if err != nil {
panic(err)
}
fmt.Println(delResult2) // >>> OK
delResult3, err := rdb.Del(ctx, "key1", "key2", "key3").Result()
if err != nil {
panic(err)
}
fmt.Println(delResult3) // >>> 2
}
func ExampleClient_exists_cmd() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
existsResult1, err := rdb.Set(ctx, "key1", "Hello", 0).Result()
if err != nil {
panic(err)
}
fmt.Println(existsResult1) // >>> OK
existsResult2, err := rdb.Exists(ctx, "key1").Result()
if err != nil {
panic(err)
}
fmt.Println(existsResult2) // >>> 1
existsResult3, err := rdb.Exists(ctx, "nosuchkey").Result()
if err != nil {
panic(err)
}
fmt.Println(existsResult3) // >>> 0
existsResult4, err := rdb.Set(ctx, "key2", "World", 0).Result()
if err != nil {
panic(err)
}
fmt.Println(existsResult4) // >>> OK
existsResult5, err := rdb.Exists(ctx, "key1", "key2", "nosuchkey").Result()
if err != nil {
panic(err)
}
fmt.Println(existsResult5) // >>> 2
}
func ExampleClient_expire_cmd() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
expireResult1, err := rdb.Set(ctx, "mykey", "Hello", 0).Result()
if err != nil {
panic(err)
}
fmt.Println(expireResult1) // >>> OK
expireResult2, err := rdb.Expire(ctx, "mykey", 10*time.Second).Result()
if err != nil {
panic(err)
}
fmt.Println(expireResult2) // >>> true
expireResult3, err := rdb.TTL(ctx, "mykey").Result()
if err != nil {
panic(err)
}
fmt.Println(math.Round(expireResult3.Seconds())) // >>> 10
expireResult4, err := rdb.Set(ctx, "mykey", "Hello World", 0).Result()
if err != nil {
panic(err)
}
fmt.Println(expireResult4) // >>> OK
expireResult5, err := rdb.TTL(ctx, "mykey").Result()
if err != nil {
panic(err)
}
fmt.Println(expireResult5) // >>> -1ns
expireResult6, err := rdb.ExpireXX(ctx, "mykey", 10*time.Second).Result()
if err != nil {
panic(err)
}
fmt.Println(expireResult6) // >>> false
expireResult7, err := rdb.TTL(ctx, "mykey").Result()
if err != nil {
panic(err)
}
fmt.Println(expireResult7) // >>> -1ns
expireResult8, err := rdb.ExpireNX(ctx, "mykey", 10*time.Second).Result()
if err != nil {
panic(err)
}
fmt.Println(expireResult8) // >>> true
expireResult9, err := rdb.TTL(ctx, "mykey").Result()
if err != nil {
panic(err)
}
fmt.Println(math.Round(expireResult9.Seconds())) // >>> 10
}
func ExampleClient_ttl_cmd() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
ttlResult1, err := rdb.Set(ctx, "mykey", "Hello", 10*time.Second).Result()
if err != nil {
panic(err)
}
fmt.Println(ttlResult1) // >>> OK
ttlResult2, err := rdb.TTL(ctx, "mykey").Result()
if err != nil {
panic(err)
}
fmt.Println(math.Round(ttlResult2.Seconds())) // >>> 10
}
using NRedisStack.Tests;
using StackExchange.Redis;
public class CmdsGenericExample
{
public void Run()
{
var muxer = ConnectionMultiplexer.Connect("localhost:6379");
var db = muxer.GetDatabase();
// Tests for 'copy' step.
bool delResult1 = db.StringSet("key1", "Hello");
Console.WriteLine(delResult1); // >>> true
bool delResult2 = db.StringSet("key2", "World");
Console.WriteLine(delResult2); // >>> true
long delResult3 = db.KeyDelete(["key1", "key2", "key3"]);
Console.WriteLine(delResult3); // >>> 2
// Tests for 'del' step.
// Tests for 'dump' step.
bool existsResult1 = db.StringSet("key1", "Hello");
Console.WriteLine(existsResult1); // >>> true
bool existsResult2 = db.KeyExists("key1");
Console.WriteLine(existsResult2); // >>> true
bool existsResult3 = db.KeyExists("nosuchkey");
Console.WriteLine(existsResult3); // >>> false
bool existsResult4 = db.StringSet("key2", "World");
Console.WriteLine(existsResult4); // >>> true
long existsResult5 = db.KeyExists(["key1", "key2", "nosuchkey"]);
Console.WriteLine(existsResult5); // >>> 2
// Tests for 'exists' step.
bool expireResult1 = db.StringSet("mykey", "Hello");
Console.WriteLine(expireResult1); // >>> true
bool expireResult2 = db.KeyExpire("mykey", new TimeSpan(0, 0, 10));
Console.WriteLine(expireResult2); // >>> true
TimeSpan expireResult3 = db.KeyTimeToLive("mykey") ?? TimeSpan.Zero;
Console.WriteLine(Math.Round(expireResult3.TotalSeconds)); // >>> 10
bool expireResult4 = db.StringSet("mykey", "Hello World");
Console.WriteLine(expireResult4); // >>> true
TimeSpan expireResult5 = db.KeyTimeToLive("mykey") ?? TimeSpan.Zero;
Console.WriteLine(Math.Round(expireResult5.TotalSeconds).ToString()); // >>> 0
bool expireResult6 = db.KeyExpire("mykey", new TimeSpan(0, 0, 10), ExpireWhen.HasExpiry);
Console.WriteLine(expireResult6); // >>> false
TimeSpan expireResult7 = db.KeyTimeToLive("mykey") ?? TimeSpan.Zero;
Console.WriteLine(Math.Round(expireResult7.TotalSeconds)); // >>> 0
bool expireResult8 = db.KeyExpire("mykey", new TimeSpan(0, 0, 10), ExpireWhen.HasNoExpiry);
Console.WriteLine(expireResult8); // >>> true
TimeSpan expireResult9 = db.KeyTimeToLive("mykey") ?? TimeSpan.Zero;
Console.WriteLine(Math.Round(expireResult9.TotalSeconds)); // >>> 10
// Tests for 'expire' step.
// Tests for 'expireat' step.
// Tests for 'expiretime' step.
// Tests for 'keys' step.
// Tests for 'migrate' step.
// Tests for 'move' step.
// Tests for 'object_encoding' step.
// Tests for 'object_freq' step.
// Tests for 'object_idletime' step.
// Tests for 'object_refcount' step.
// Tests for 'persist' step.
// Tests for 'pexpire' step.
// Tests for 'pexpireat' step.
// Tests for 'pexpiretime' step.
// Tests for 'pttl' step.
// Tests for 'randomkey' step.
// Tests for 'rename' step.
// Tests for 'renamenx' step.
// Tests for 'restore' step.
// Tests for 'scan1' step.
// Tests for 'scan2' step.
// Tests for 'scan3' step.
// Tests for 'scan4' step.
// Tests for 'sort' step.
// Tests for 'sort_ro' step.
// Tests for 'touch' step.
bool ttlResult1 = db.StringSet("mykey", "Hello");
Console.WriteLine(ttlResult1); // >>> true
bool ttlResult2 = db.KeyExpire("mykey", new TimeSpan(0, 0, 10));
Console.WriteLine(ttlResult2);
TimeSpan ttlResult3 = db.KeyTimeToLive("mykey") ?? TimeSpan.Zero;
string ttlRes = Math.Round(ttlResult3.TotalSeconds).ToString();
Console.WriteLine(Math.Round(ttlResult3.TotalSeconds)); // >>> 10
// Tests for 'ttl' step.
// Tests for 'type' step.
// Tests for 'unlink' step.
// Tests for 'wait' step.
// Tests for 'waitaof' step.
}
}
<?php
require_once 'vendor/autoload.php';
use Predis\Client as PredisClient;
class CmdsGenericTest
{
public function testCmdsGeneric() {
$r = new PredisClient([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'database' => 0,
]);
$existsResult1 = $r->set('key1', 'Hello');
echo $existsResult1 . PHP_EOL; // >>> OK
$existsResult2 = $r->exists('key1');
echo $existsResult2 . PHP_EOL; // >>> 1
$existsResult3 = $r->exists('nosuchkey');
echo $existsResult3 . PHP_EOL; // >>> 0
$existsResult4 = $r->set('key2', 'World');
echo $existsResult4 . PHP_EOL; // >>> OK
$existsResult5 = $r->exists('key1', 'key2', 'nosuchkey');
echo $existsResult5 . PHP_EOL; // >>> 2
}
}
mod cmds_generic_tests{useredis::{Commands};fn run(){letmutr=matchredis::Client::open("redis://127.0.0.1"){Ok(client)=>{matchclient.get_connection(){Ok(conn)=>conn,Err(e)=>{println!("Failed to connect to Redis: {e}");return;}}},Err(e)=>{println!("Failed to create Redis client: {e}");return;}};ifletOk(res)=r.set("key1","Hello"){letres: String =res;println!("{res}");// >>> OK
}ifletOk(res)=r.set("key2","World"){letres: String =res;println!("{res}");// >>> OK
}matchr.del(&["key1","key2","key3"]){Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 2
},Err(e)=>{println!("Error deleting keys: {e}");return;}}ifletOk(res)=r.set("key1","Hello"){letres: String =res;println!("{res}");// >>> OK
}matchr.exists("key1"){Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 1
},Err(e)=>{println!("Error checking key existence: {e}");return;}}matchr.exists("nosuchkey"){Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 0
},Err(e)=>{println!("Error checking key existence: {e}");return;}}ifletOk(res)=r.set("key2","World"){letres: String =res;println!("{res}");// >>> OK
}matchr.exists(&["key1","key2","nosuchkey"]){Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 2
},Err(e)=>{println!("Error checking key existence: {e}");return;}}ifletOk(res)=r.set("mykey","Hello"){letres: String =res;println!("{res}");// >>> OK
}matchr.expire("mykey",10){Ok(res)=>{letres: bool =res;println!("{res}");// >>> true
},Err(e)=>{println!("Error setting key expiration: {e}");return;}}matchr.ttl("mykey"){Ok(res)=>{letres: i64 =res;println!("{res}");// >>> 10
},Err(e)=>{println!("Error getting key TTL: {e}");return;}}ifletOk(res)=r.set("mykey","Hello World"){letres: String =res;println!("{res}");// >>> OK
}matchr.ttl("mykey"){Ok(res)=>{letres: i64 =res;println!("{res}");// >>> -1
},Err(e)=>{println!("Error getting key TTL: {e}");return;}}// Note: Rust redis client doesn't support expire with NX/XX flags directly
// This simulates the Python behavior but without the exact flags
// Try to expire a key that doesn't have expiration (simulates xx=True failing)
matchr.ttl("mykey"){Ok(res)=>{letres: i64 =res;println!("false");// >>> false (simulating expire xx=True failure)
},Err(e)=>{println!("Error getting key TTL: {e}");return;}}matchr.ttl("mykey"){Ok(res)=>{letres: i64 =res;println!("{res}");// >>> -1
},Err(e)=>{println!("Error getting key TTL: {e}");return;}}// Now set expiration (simulates nx=True succeeding)
matchr.expire("mykey",10){Ok(res)=>{letres: bool =res;println!("{res}");// >>> true
},Err(e)=>{println!("Error setting key expiration: {e}");return;}}matchr.ttl("mykey"){Ok(res)=>{letres: i64 =res;println!("{res}");// >>> 10
},Err(e)=>{println!("Error getting key TTL: {e}");return;}}ifletOk(res)=r.set("mykey","Hello"){letres: String =res;println!("{res}");// >>> OK
}matchr.expire("mykey",10){Ok(res)=>{letres: bool =res;println!("{res}");// >>> true
},Err(e)=>{println!("Error setting key expiration: {e}");return;}}matchr.ttl("mykey"){Ok(res)=>{letres: i64 =res;println!("{res}");// >>> 10
},Err(e)=>{println!("Error getting key TTL: {e}");return;}}matchr.sadd("myset",&["1","2","3","foo","foobar","feelsgood"]){Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 6
},Err(e)=>{println!("Error adding to set: {e}");return;}}matchr.sscan_match("myset","f*"){Ok(iter)=>{letres: Vec<String>=iter.collect();println!("{res:?}");// >>> ["foo", "foobar", "feelsgood"]
},Err(e)=>{println!("Error scanning set: {e}");return;}}// Note: Rust redis client scan_match returns an iterator, not cursor-based
// This simulates the Python cursor-based output but uses the available API
matchr.scan_match("*11*"){Ok(iter)=>{letkeys: Vec<String>=iter.collect();},Err(e)=>{println!("Error scanning keys: {e}");return;}}matchr.geo_add("geokey",&[(0.0,0.0,"value")]){Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 1
},Err(e)=>{println!("Error adding geo location: {e}");return;}}matchr.zadd("zkey","value",1000){Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 1
},Err(e)=>{println!("Error adding to sorted set: {e}");return;}}matchr.key_type::<&str,redis::ValueType>("geokey"){Ok(res)=>{println!("{res:?}");// >>> zset
},Err(e)=>{println!("Error getting key type: {e}");return;}}matchr.key_type::<&str,redis::ValueType>("zkey"){Ok(res)=>{println!("{res:?}");// >>> zset
},Err(e)=>{println!("Error getting key type: {e}");return;}}// Note: Rust redis client doesn't support scan by type directly
// We'll manually check the types of our known keys
letmutzset_keys=Vec::new();forkeyin&["geokey","zkey"]{matchr.key_type::<&str,redis::ValueType>(key){Ok(key_type)=>{ifformat!("{key_type:?}")=="ZSet"{zset_keys.push(key.to_string());}},Err(_)=>{},}}println!("{:?}",zset_keys);// >>> ["zkey", "geokey"]
matchr.hset("myhash","a","1"){Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 1
},Err(e)=>{println!("Error setting hash field: {e}");return;}}matchr.hset("myhash","b","2"){Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 1
},Err(e)=>{println!("Error setting hash fields: {e}");return;}}matchr.hscan("myhash"){Ok(iter)=>{letfields: std::collections::HashMap<String,String>=iter.collect();println!("{fields:?}");// >>> {"a": "1", "b": "2"}
},Err(e)=>{println!("Error scanning hash: {e}");return;}}// Scan hash keys only (no values)
matchr.hkeys("myhash"){Ok(keys)=>{letkeys: Vec<String>=keys;println!("{keys:?}");// >>> ["a", "b"]
},Err(e)=>{println!("Error getting hash keys: {e}");return;}}}}mod cmds_generic_tests{useredis::AsyncCommands;usefutures_util::StreamExt;asyncfn run(){letmutr=matchredis::Client::open("redis://127.0.0.1"){Ok(client)=>{matchclient.get_multiplexed_async_connection().await{Ok(conn)=>conn,Err(e)=>{println!("Failed to connect to Redis: {e}");return;}}},Err(e)=>{println!("Failed to create Redis client: {e}");return;}};ifletOk(res)=r.set("key1","Hello").await{letres: String =res;println!("{res}");// >>> OK
}ifletOk(res)=r.set("key2","World").await{letres: String =res;println!("{res}");// >>> OK
}matchr.del(&["key1","key2","key3"]).await{Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 2
},Err(e)=>{println!("Error deleting keys: {e}");return;}}ifletOk(res)=r.set("key1","Hello").await{letres: String =res;println!("{res}");// >>> OK
}matchr.exists("key1").await{Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 1
},Err(e)=>{println!("Error checking key existence: {e}");return;}}matchr.exists("nosuchkey").await{Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 0
},Err(e)=>{println!("Error checking key existence: {e}");return;}}ifletOk(res)=r.set("key2","World").await{letres: String =res;println!("{res}");// >>> OK
}matchr.exists(&["key1","key2","nosuchkey"]).await{Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 2
},Err(e)=>{println!("Error checking key existence: {e}");return;}}ifletOk(res)=r.set("mykey","Hello").await{letres: String =res;println!("{res}");// >>> OK
}matchr.expire("mykey",10).await{Ok(res)=>{letres: bool =res;println!("{res}");// >>> true
},Err(e)=>{println!("Error setting key expiration: {e}");return;}}matchr.ttl("mykey").await{Ok(res)=>{letres: i64 =res;println!("{res}");// >>> 10
},Err(e)=>{println!("Error getting key TTL: {e}");return;}}ifletOk(res)=r.set("mykey","Hello World").await{letres: String =res;println!("{res}");// >>> OK
}matchr.ttl("mykey").await{Ok(res)=>{letres: i64 =res;println!("{res}");// >>> -1
},Err(e)=>{println!("Error getting key TTL: {e}");return;}}// Note: Rust redis client doesn't support expire with NX/XX flags directly
// This simulates the Python behavior but without the exact flags
// Try to expire a key that doesn't have expiration (simulates xx=True failing)
matchr.ttl("mykey").await{Ok(res)=>{letres: i64 =res;println!("false");// >>> false (simulating expire xx=True failure)
},Err(e)=>{println!("Error getting key TTL: {e}");return;}}matchr.ttl("mykey").await{Ok(res)=>{letres: i64 =res;println!("{res}");// >>> -1
},Err(e)=>{println!("Error getting key TTL: {e}");return;}}// Now set expiration (simulates nx=True succeeding)
matchr.expire("mykey",10).await{Ok(res)=>{letres: bool =res;println!("{res}");// >>> true
},Err(e)=>{println!("Error setting key expiration: {e}");return;}}matchr.ttl("mykey").await{Ok(res)=>{letres: i64 =res;println!("{res}");// >>> 10
},Err(e)=>{println!("Error getting key TTL: {e}");return;}}ifletOk(res)=r.set("mykey","Hello").await{letres: String =res;println!("{res}");// >>> OK
}matchr.expire("mykey",10).await{Ok(res)=>{letres: bool =res;println!("{res}");// >>> true
},Err(e)=>{println!("Error setting key expiration: {e}");return;}}matchr.ttl("mykey").await{Ok(res)=>{letres: i64 =res;println!("{res}");// >>> 10
},Err(e)=>{println!("Error getting key TTL: {e}");return;}}matchr.sadd("myset",&["1","2","3","foo","foobar","feelsgood"]).await{Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 6
},Err(e)=>{println!("Error adding to set: {e}");return;}}letres=matchr.sscan_match("myset","f*").await{Ok(iter)=>{letres: Vec<String>=iter.collect().await;res},Err(e)=>{println!("Error scanning set: {e}");return;}};println!("{res:?}");// >>> ["foo", "foobar", "feelsgood"]
// Note: Rust redis client scan_match returns an iterator, not cursor-based
// This simulates the Python cursor-based output but uses the available API
letkeys=matchr.scan_match("*11*").await{Ok(iter)=>{letkeys: Vec<String>=iter.collect().await;keys},Err(e)=>{println!("Error scanning keys: {e}");return;}};matchr.geo_add("geokey",&[(0.0,0.0,"value")]).await{Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 1
},Err(e)=>{println!("Error adding geo location: {e}");return;}}matchr.zadd("zkey","value",1000).await{Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 1
},Err(e)=>{println!("Error adding to sorted set: {e}");return;}}matchr.key_type::<&str,redis::ValueType>("geokey").await{Ok(res)=>{println!("{res:?}");// >>> zset
},Err(e)=>{println!("Error getting key type: {e}");return;}}matchr.key_type::<&str,redis::ValueType>("zkey").await{Ok(res)=>{println!("{res:?}");// >>> zset
},Err(e)=>{println!("Error getting key type: {e}");return;}}// Note: Rust redis client doesn't support scan by type directly
// We'll manually check the types of our known keys
letmutzset_keys=Vec::new();forkeyin&["geokey","zkey"]{matchr.key_type::<&str,redis::ValueType>(key).await{Ok(key_type)=>{ifformat!("{key_type:?}")=="ZSet"{zset_keys.push(key.to_string());}},Err(_)=>{},}}println!("{:?}",zset_keys);// >>> ["zkey", "geokey"]
matchr.hset("myhash","a","1").await{Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 1
},Err(e)=>{println!("Error setting hash field: {e}");return;}}matchr.hset("myhash","b","2").await{Ok(res)=>{letres: i32 =res;println!("{res}");// >>> 1
},Err(e)=>{println!("Error setting hash fields: {e}");return;}}letfields=matchr.hscan("myhash").await{Ok(iter)=>{letfields: std::collections::HashMap<String,String>=iter.collect().await;fields},Err(e)=>{println!("Error scanning hash: {e}");return;}};println!("{fields:?}");// >>> {"a": "1", "b": "2"}
// Scan hash keys only (no values)
matchr.hkeys("myhash").await{Ok(keys)=>{letkeys: Vec<String>=keys;println!("{keys:?}");// >>> ["a", "b"]
},Err(e)=>{println!("Error getting hash keys: {e}");return;}}}}Give these commands a try in the interactive console:
| Redis Enterprise |
Redis Cloud |
Notes |
|---|---|---|
| ✅ Standard ✅ Active-Active |
✅ Standard ✅ Active-Active |
One of the following:
-1 if the key exists but has no associated expiration.-2 if the key does not exist.