title: GEOSEARCH

summary: Queries a geospatial index for members inside an area of a box or a circle.

title: Overview

text:
Return the members of a sorted set populated with geospatial information using [`GEOADD`](), which are within the borders of the area specified by a given shape. This command extends the [`GEORADIUS`]() command, so in addition to searching within circular areas, it supports searching within rectangular areas.

This command should be used in place of the deprecated [`GEORADIUS`]() and [`GEORADIUSBYMEMBER`]() commands.

The query's center point is provided by one of these mandatory options:

* `FROMMEMBER`: Use the position of the given existing `<member>` in the sorted set.
* `FROMLONLAT`: Use the given `<longitude>` and `<latitude>` position.

The query's shape is provided by one of these mandatory options:

* `BYRADIUS`: Similar to [`GEORADIUS`](), search inside circular area according to given `<radius>`.
* `BYBOX`: Search inside an axis-aligned rectangle, determined by `<height>` and `<width>`.

The command optionally returns additional information using the following options:

* `WITHDIST`: Also return the distance of the returned items from the specified center point. The distance is returned in the same unit as specified for the radius or height and width arguments.
* `WITHCOORD`: Also return the longitude and latitude of the matching items.
* `WITHHASH`: Also return the raw geohash-encoded sorted set score of the item, in the form of a 52 bit unsigned integer. This is only useful for low level hacks or debugging and is otherwise of little interest for the general user.

Matching items are returned unsorted by default. To sort them, use one of the following two options:

* `ASC`: Sort returned items from the nearest to the farthest, relative to the center point.
* `DESC`: Sort returned items from the farthest to the nearest, relative to the center point.

All matching items are returned by default. To limit the results to the first N matching items, use the **COUNT `<count>`** option.
When the `ANY` option is used, the command returns as soon as enough matches are found.  This means that the results returned may not be the ones closest to the specified point, but the effort invested by the server to generate them is significantly less.
When `ANY` is not provided, the command will perform an effort that is proportional to the number of items matching the specified area and sort them,
so to query very large areas with a very small `COUNT` option may be slow even if just a few results are returned.

title: Examples

text:
GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
GEOADD Sicily 12.758489 38.788135 "edge1"   17.241510 38.788135 "edge2"
GEOSEARCH Sicily FROMLONLAT 15 37 BYRADIUS 200 km ASC
GEOSEARCH Sicily FROMLONLAT 15 37 BYBOX 400 400 km ASC WITHCOORD WITHDIST

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

title: Return information


title: GEOSEARCHSTORE

summary: Queries a geospatial index for members inside an area of a box or a circle, optionally stores the result.

page_type: content

title: Overview

role: overview

text:
This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

This command is like [`GEOSEARCH`](), but stores the result in destination key.

This command replaces the now deprecated [`GEORADIUS`]() and [`GEORADIUSBYMEMBER`]().

By default, it stores the results in the `destination` sorted set with their geospatial information.

When using the `STOREDIST` option, the command stores the items in a sorted set populated with their distance from the center of the circle or box, as a floating-point number, in the same unit specified for that shape.

title: Examples

role: example

text:
GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
GEOADD Sicily 12.758489 38.788135 "edge1"   17.241510 38.788135 "edge2"
GEOSEARCHSTORE key1 Sicily FROMLONLAT 15 37 BYBOX 400 400 km ASC COUNT 3
GEOSEARCH key1 FROMLONLAT 15 37 BYBOX 400 400 km ASC WITHCOORD WITHDIST WITHHASH
GEOSEARCHSTORE key2 Sicily FROMLONLAT 15 37 BYBOX 400 400 km ASC COUNT 3 STOREDIST
ZRANGE key2 0 -1 WITHSCORES

title: Redis Software and Redis Cloud compatibility

role: content

title: Return information

role: returns

text:
**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of elements in the resulting set

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of elements in the resulting set


title: GET

summary: Returns the string value of a key.

title: Examples

text:
GET nonexisting
SET mykey "Hello"
GET mykey

title: Code examples

text:
#### Code Examples

Foundational: Retrieve the string value of a key using GET (returns nil if key doesn't exist)

**Difficulty:** Beginner

**Available in:** Python, JavaScript (Node.js), Java (Synchronous - Jedis), Go, C# (Synchronous)

**Python:**

[code example]

**JavaScript (Node.js):**

[code example]

**Java (Synchronous - Jedis):**

[code example]

**Go:**

[code example]

**C# (Synchronous):**

[code example]

title: Return information

text:
**RESP2:**

One of the following:
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the value of the key.
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if the key does not exist.

**RESP3:**

One of the following:
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the value of the key.
* [Null reply](../../develop/reference/protocol-spec#nulls): key does not exist.

code:
"""
Code samples for data structure store quickstart pages:
    https://redis.io/docs/latest/develop/get-started/data-store/
"""

import redis

r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)

res = r.set("bike:1", "Process 134")
print(res)
# >>> True

res = r.get("bike:1")
print(res)
# >>> "Process 134"

section_id: code-examples

code:
import { createClient } from 'redis';

const client = createClient();

client.on('error', err => console.log('Redis Client Error', err));

await client.connect().catch(console.error);

await client.set('bike:1', 'Process 134');
const value = await client.get('bike:1');
console.log(value);
// returns 'Process 134'

await client.close();

code:
package io.redis.examples;

import redis.clients.jedis.RedisClient;

public class SetGetExample {

  public void run() {

    RedisClient jedis = RedisClient.create("redis://localhost:6379");

    String status = jedis.set("bike:1", "Process 134");

    if ("OK".equals(status)) System.out.println("Successfully added a bike.");

    String value = jedis.get("bike:1");

    if (value != null) System.out.println("The name of the bike is: " + value + ".");

    jedis.close();
  }
}

code:
package example_commands_test

import (
	"context"
	"fmt"

	"github.com/redis/go-redis/v9"
)

func ExampleClient_Set_and_get() {
	ctx := context.Background()

	rdb := redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "", // no password docs
		DB:       0,  // use default DB
	})

	err := rdb.Set(ctx, "bike:1", "Process 134", 0).Err()
	if err != nil {
		panic(err)
	}

	fmt.Println("OK")

	value, err := rdb.Get(ctx, "bike:1").Result()
	if err != nil {
		panic(err)
	}
	fmt.Printf("The name of the bike is %s", value)

}

code:
using NRedisStack.Tests;
using StackExchange.Redis;

public class SetGetExample
{
    public void Run()
    {
        var muxer = ConnectionMultiplexer.Connect("localhost:6379");
        var db = muxer.GetDatabase();

        bool status = db.StringSet("bike:1", "Process 134");

        if (status)
            Console.WriteLine("Successfully added a bike.");

        var value = db.StringGet("bike:1");

        if (value.HasValue)
            Console.WriteLine("The name of the bike is: " + value + ".");

    }
}


title: GETBIT

summary: Returns a bit value by offset.

title: Overview

text:
Returns the bit value at _offset_ in the string value stored at _key_.

When _offset_ is beyond the string length, the string is assumed to be a
contiguous space with 0 bits.
When _key_ does not exist it is assumed to be an empty string, so _offset_ is
always out of range and the value is also assumed to be a contiguous space with
0 bits.

title: Examples

text:
SETBIT mykey 7 1
GETBIT mykey 0
GETBIT mykey 7
GETBIT mykey 100

title: Return information

text:
**RESP2:**

The bit value stored at _offset_, one of the following:
* [Integer reply](../../develop/reference/protocol-spec#integers): `0`.
* [Integer reply](../../develop/reference/protocol-spec#integers): `1`.

**RESP3:**

The bit value stored at _offset_, one of the following:
* [Integer reply](../../develop/reference/protocol-spec#integers): `0`.
* [Integer reply](../../develop/reference/protocol-spec#integers): `1`.


title: GETDEL

summary: Returns the string value of a key after deleting the key.

title: Overview

text:
Get the value of `key` and delete the key.
This command is similar to [`GET`](), except for the fact that it also deletes the key on success (if and only if the key's value type is a string).

title: Examples

text:
SET mykey "Hello"
GETDEL mykey
GET mykey

title: Return information

text:
**RESP2:**

One of the following:
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the value of the key.
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if the key does not exist or if the key's value type is not a string.

**RESP3:**

One of the following:
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the value of the key.
* [Null reply](../../develop/reference/protocol-spec#nulls): if the key does not exist or if the key's value type is not a string.


title: GETEX

summary: Returns the string value of a key after setting its expiration time.

title: Overview

text:
Get the value of `key` and optionally set its expiration.
`GETEX` is similar to [`GET`](), but is a write command with additional options.

title: Options

role: parameters

text:
The `GETEX` command supports a set of options that modify its behavior:

* `EX` *seconds* -- Set the specified expire time, in seconds.
* `PX` *milliseconds* -- Set the specified expire time, in milliseconds.
* `EXAT` *timestamp-seconds* -- Set the specified Unix time at which the key will expire, in seconds.
* `PXAT` *timestamp-milliseconds* -- Set the specified Unix time at which the key will expire, in milliseconds.
* [`PERSIST`]() -- Remove the time to live associated with the key.

title: Examples

text:
SET mykey "Hello"
GETEX mykey
TTL mykey
GETEX mykey EX 60
TTL mykey

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active\*</nobr> | ✅ Standard
<nobr>✅ Active-Active\*</nobr> | \*Not supported for HyperLogLog. |

title: Return information

text:
**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the value of `key`
[Nil reply](../../develop/reference/protocol-spec#bulk-strings): if `key` does not exist.

**RESP3:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the value of `key`
[Null reply](../../develop/reference/protocol-spec#nulls): if `key` does not exist.


title: GETRANGE

summary: Returns a substring of the string stored at a key.

title: Overview

text:
Returns the substring of the string value stored at `key`, determined by the
offsets `start` and `end` (both are inclusive).
Negative offsets can be used in order to provide an offset starting from the end
of the string.
So -1 means the last character, -2 the penultimate and so forth.

The function handles out of range requests by limiting the resulting range to
the actual length of the string.

title: Examples

text:
SET mykey "This is a string"
GETRANGE mykey 0 3
GETRANGE mykey -3 -1
GETRANGE mykey 0 -1
GETRANGE mykey 10 100

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

title: Return information

text:
**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): The substring of the string value stored at key, determined by the offsets start and end (both are inclusive).

**RESP3:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): The substring of the string value stored at key, determined by the offsets start and end (both are inclusive).


title: GETSET

summary: Returns the previous string value of a key after setting it to a new value.

title: Overview

text:
Atomically sets `key` to `value` and returns the old value stored at `key`.
Returns an error when `key` exists but does not hold a string value.  Any
previous time to live associated with the key is discarded on successful
[`SET`]() operation.

title: Design pattern

text:
`GETSET` can be used together with [`INCR`]() for counting with atomic reset.
For example: a process may call [`INCR`]() against the key `mycounter` every time
some event occurs, but from time to time we need to get the value of the counter
and reset it to zero atomically.
This can be done using `GETSET mycounter "0"`:

INCR mycounter
GETSET mycounter "0"
GET mycounter

title: Examples

text:
SET mykey "Hello"
GETSET mykey "World"
GET mykey

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> | Deprecated as of Redis v6.2.0. |

title: Return information

text:
**RESP2:**

One of the following:
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the old value stored at the key.
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if the key does not exist.

**RESP3:**

One of the following:
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the old value stored at the key.
* [Null reply](../../develop/reference/protocol-spec#nulls): if the key does not exist.


title: HDEL

summary: Deletes one or more fields and their values from a hash. Deletes the hash if no fields remain.

title: Examples

text:
#### Code Examples

Foundational: Delete one or more fields from a hash using HDEL (returns count of deleted fields, ignores non-existent fields)

**Difficulty:** Beginner

**Redis CLI:**

[code example]

**Available in:** Redis CLI, C, C# (Synchronous), Go, Java (Asynchronous - Lettuce), Java (Reactive - Lettuce), Java (Synchronous - Jedis), JavaScript (Node.js), JavaScript (Node.js), PHP, Python, Rust (Asynchronous), Rust (Synchronous)

**C:**

[code example]

**C# (Synchronous):**

[code example]

**Go:**

[code example]

**Java (Asynchronous - Lettuce):**

[code example]

**Java (Reactive - Lettuce):**

[code example]

**Java (Synchronous - Jedis):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**PHP:**

[code example]

**Python:**

[code example]

**Rust (Asynchronous):**

[code example]

**Rust (Synchronous):**

[code example]

Give these commands a try in the interactive console:

HSET myhash field1 "foo"
HDEL myhash field1
HDEL myhash field2

title: Return information

text:
**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of fields that were removed from the hash, excluding any specified but non-existing fields.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): The number of fields that were removed from the hash, excluding any specified but non-existing fields.

code:
HSET myhash field1 "foo"
(integer) 1
HDEL myhash field1
(integer) 1
HDEL myhash field2
(integer) 0

section_id: examples

code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hiredis/hiredis.h>

int main(int argc, char **argv) {
    redisContext *c = redisConnect("127.0.0.1", 6379);

    if (c == NULL || c->err) {
        if (c) {
            printf("Connection error: %s\n", c->errstr);
            redisFree(c);
        } else {
            printf("Connection error: can't allocate redis context\n");
        }
        return 1;
    }

    redisReply *reply;

    // Set up hash with fields
    reply = redisCommand(c, "HSET %s %s %s %s %s",
        "myhash", "field1", "Hello", "field2", "World");
    freeReplyObject(reply);

    // Get multiple fields at once
    reply = redisCommand(c, "HMGET %s %s %s %s",
        "myhash", "field1", "field2", "nofield");

    printf("HMGET myhash field1 field2 nofield:\n");
    for (size_t i = 0; i < reply->elements; i++) {
        if (reply->element[i]->type == REDIS_REPLY_NIL) {
            printf("  [%zu]: null\n", i);
        } else {
            printf("  [%zu]: %s\n", i, reply->element[i]->str);
        }
    }
    // >>> [0]: Hello
    // >>> [1]: World
    // >>> [2]: null

    freeReplyObject(reply);

    redisFree(c);

    return 0;
}

code:
bool hdelRes1 = db.HashSet("myhash", "field1", "foo");

        RedisValue hdelRes2 = db.HashDelete("myhash", "field1");
        Console.WriteLine(hdelRes2);    // >>> 1

        RedisValue hdelRes3 = db.HashDelete("myhash", "field1");
        Console.WriteLine(hdelRes3);    // >>> 0

code:
hdel1, err := rdb.HSet(ctx, "myhash", "field1", "foo").Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(hdel1) // >>> 1

	hdel2, err := rdb.HDel(ctx, "myhash", "field1").Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(hdel2) // >>> 1

	hdel3, err := rdb.HDel(ctx, "myhash", "field2").Result()

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(hdel3) // >>> 0

code:
Map<String, String> hDelExampleParams = new HashMap<>();
            hDelExampleParams.put("field1", "foo");

            CompletableFuture<Void> hDelExample = asyncCommands.hset("myhash", hDelExampleParams).thenCompose(res1 -> {
                System.out.println(res1); // >>> 1
                return asyncCommands.hdel("myhash", "field1");
            }).thenCompose(res2 -> {
                System.out.println(res2); // >>> 1
                return asyncCommands.hdel("myhash", "field2");
            }).thenAccept(res3 -> {
                System.out.println(res3); // >>> 0
            }).toCompletableFuture();

code:
Map<String, String> hDelExampleParams = new HashMap<>();
            hDelExampleParams.put("field1", "foo");

            Mono<Long> hDelExample1 = reactiveCommands.hset("myhash", hDelExampleParams).doOnNext(result -> {
                System.out.println(result); // >>> 1
            });

            hDelExample1.block();

            Mono<Long> hDelExample2 = reactiveCommands.hdel("myhash", "field1").doOnNext(result -> {
                System.out.println(result); // >>> 1
            });

            hDelExample2.block();

            Mono<Long> hDelExample3 = reactiveCommands.hdel("myhash", "field2").doOnNext(result -> {
                System.out.println(result); // >>> 0
            });

code:
Map<String, String> hDelExampleParams = new HashMap<>();
        hDelExampleParams.put("field1", "foo");

        long hDelResult1 = jedis.hset("myhash", hDelExampleParams);
        System.out.println(hDelResult1);    // >>> 1

        long hDelResult2 = jedis.hdel("myhash", "field1");
        System.out.println(hDelResult2);    // >>> 1

        long hDelResult3 = jedis.hdel("myhash", "field2");
        System.out.println(hDelResult3);    // >>> 0

code:
const hDel1 = await client.hSet('myhash', 'field1', 'Hello')
console.log(hDel1) // 1

const hDel2 = await client.hDel('myhash', 'field1')
console.log(hDel2) // 1

const hDel3 = await client.hDel('myhash', 'field2')
console.log(hDel3) // 0

code:
import assert from 'node:assert';
import { Redis } from 'ioredis';

const redis = new Redis();

await redis.hset('myhash', { field1: 'Hello', field2: 'World' });

const hmgetResult = await redis.hmget('myhash', 'field1', 'field2', 'nofield');
console.log(hmgetResult); // >>> ['Hello', 'World', null]

redis.disconnect();

code:
$hDelResult1 = $this->redis->hset('myhash', 'field1', 'foo');
        echo "HSET myhash field1 foo: " . $hDelResult1 . "\n"; // >>> 1

        $hDelResult2 = $this->redis->hdel('myhash', 'field1');
        echo "HDEL myhash field1: " . $hDelResult2 . "\n"; // >>> 1

        $hDelResult3 = $this->redis->hdel('myhash', 'field2');
        echo "HDEL myhash field2: " . $hDelResult3 . "\n"; // >>> 0

code:
hdel1 = r.hset("myhash", "field1", "foo")
print(hdel1)
# >>> 1

hdel2 = r.hdel("myhash", "field1")
print(hdel2)
# >>> 1

hdel3 = r.hdel("myhash", "field2")
print(hdel3)
# >>> 0

code:
match r.hset("myhash", "field1", "foo").await {
            Ok(hdel1) => {
                let hdel1: i32 = hdel1;
                println!("{hdel1}");    // >>> 1
            },
            Err(e) => {
                println!("Error setting hash field: {e}");
                return;
            }
        }

        match r.hdel("myhash", "field1").await {
            Ok(hdel2) => {
                let hdel2: Option<i32> = hdel2;
                match hdel2 {
                    Some(value) => {
                        println!("{value}");    // >>> 1
                    },
                    None => {
                        println!("None");
                    }
                }
            },
            Err(e) => {
                println!("Error getting hash field: {e}");
                return;
            }
        }

        match r.hdel("myhash", "field2").await {
            Ok(hdel3) => {
                let hdel3: Option<i32> = hdel3;
                match hdel3 {
                    Some(value) => {
                        println!("{value}");    // >>> 0
                    },
                    None => {
                        println!("None");
                    }
                }
            },
            Err(e) => {
                println!("Error getting hash field: {e}");
                return;
            }
        }

code:
match r.hset("myhash", "field1", "foo") {
            Ok(hdel1) => {
                let hdel1: i32 = hdel1;
                println!("{hdel1}");    // >>> 1
            },
            Err(e) => {
                println!("Error setting hash field: {e}");
                return;
            }
        }

        match r.hdel("myhash", "field1") {
            Ok(hdel2) => {
                let hdel2: Option<i32> = hdel2;
                match hdel2 {
                    Some(value) => {
                        println!("{value}");    // >>> 1
                    },
                    None => {
                        println!("None");
                    }
                }
            },
            Err(e) => {
                println!("Error getting hash field: {e}");
                return;
            }
        }

        match r.hdel("myhash", "field2") {
            Ok(hdel3) => {
                let hdel3: Option<i32> = hdel3;
                match hdel3 {
                    Some(value) => {
                        println!("{value}");    // >>> 0
                    },
                    None => {
                        println!("None");
                    }
                }
            },
            Err(e) => {
                println!("Error getting hash field: {e}");
                return;
            }
        }


title: HELLO

summary: Handshakes with the Redis server.

title: Overview

text:
Switch to a different protocol, optionally authenticating and setting the
connection's name, or provide a contextual client report.

Redis version 6 and above supports two protocols: the old protocol, RESP2, and
a new one introduced with Redis 6, RESP3. RESP3 has certain advantages since
when the connection is in this mode, Redis is able to reply with more semantical
replies: for instance, [`HGETALL`]() will return a *map type*, so a client library
implementation no longer requires to know in advance to translate the array into
a hash before returning it to the caller. For a full coverage of RESP3, please
check the [RESP3 specification](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md).

In Redis 6 connections start in RESP2 mode, so clients implementing RESP2 do
not need to updated or changed. There are no short term plans to drop support for
RESP2, although future version may default to RESP3.

`HELLO` always replies with a list of current server and connection properties,
such as: versions, modules loaded, client ID, replication role and so forth.
When called without any arguments in Redis 6.2 and its default use of RESP2
protocol, the reply looks like this:

    > HELLO
     1) "server"
     2) "redis"
     3) "version"
     4) "255.255.255"
     5) "proto"
     6) (integer) 2
     7) "id"
     8) (integer) 5
     9) "mode"
    10) "standalone"
    11) "role"
    12) "master"
    13) "modules"
    14) (empty array)

Clients that want to handshake using the RESP3 mode need to call the `HELLO`
command and specify the value "3" as the `protover` argument, like so:

    > HELLO 3
    1# "server" => "redis"
    2# "version" => "6.0.0"
    3# "proto" => (integer) 3
    4# "id" => (integer) 10
    5# "mode" => "standalone"
    6# "role" => "master"
    7# "modules" => (empty array)

Because `HELLO` replies with useful information, and given that `protover` is
optional or can be set to "2", client library authors may consider using this
command instead of the canonical [`PING`]() when setting up the connection.

When called with the optional `protover` argument, this command switches the
protocol to the specified version and also accepts the following options:

* `AUTH <username> <password>`: directly authenticate the connection in addition to switching to the specified protocol version. This makes calling [`AUTH`]() before `HELLO` unnecessary when setting up a new connection. Note that the `username` can be set to "default" to authenticate against a server that does not use ACLs, but rather the simpler `requirepass` mechanism of Redis prior to version 6.
* `SETNAME <clientname>`: this is the equivalent of calling [`CLIENT SETNAME`]().

title: Return information

text:
**RESP2:**

[Map reply](../../develop/reference/protocol-spec#maps): a list of server properties.
[Simple error reply](../../develop/reference/protocol-spec#simple-errors): if the `protover` requested does not exist.

**RESP3:**

[Map reply](../../develop/reference/protocol-spec#maps): a list of server properties.
[Simple error reply](../../develop/reference/protocol-spec#simple-errors): if the `protover` requested does not exist.


title: HEXISTS

summary: Determines whether a field exists in a hash.

title: Overview

text: Returns if `field` is an existing field in the hash stored at `key`.

title: Examples

text:
HSET myhash field1 "foo"
HEXISTS myhash field1
HEXISTS myhash field2

title: Return information

text:
**RESP2:**

One of the following:
* [Integer reply](../../develop/reference/protocol-spec#integers): `0` if the hash does not contain the field, or the key does not exist.
* [Integer reply](../../develop/reference/protocol-spec#integers): `1` if the hash contains the field.

**RESP3:**

One of the following:
* [Integer reply](../../develop/reference/protocol-spec#integers): `0` if the hash does not contain the field, or the key does not exist.
* [Integer reply](../../develop/reference/protocol-spec#integers): `1` if the hash contains the field.


title: HEXPIRE

summary: Set expiration for hash fields using relative time to expire (seconds)

title: Options

text:
The `HEXPIRE` command supports a set of options:

* `NX` -- For each specified field, set expiration only when the field has no expiration.
* `XX` -- For each specified field, set expiration only when the field has an existing expiration.
* `GT` -- For each specified field, set expiration only when the new expiration is greater than current one.
* `LT` -- For each specified field, set expiration only when the new expiration is less than current one.

A non-volatile field is treated as an infinite TTL for the purpose of `GT` and `LT`.
The `NX`, `XX`, `GT`, and `LT` options are mutually exclusive.

title: Refreshing expires

text:
You can call `HEXPIRE` using as argument a field that already has an
existing TTL set.
In this case, the time to live is _updated_ to the new value.

title: Redis Search and field expiration

text: Starting with Redis 8, Redis Search has enhanced behavior when handling expiring hash fields. For detailed information about how [`FT.SEARCH`]() and [`FT.AGGREGATE`]() commands interact with expiring hash fields, see [Key and field expiration behavior]().

title: Examples

text:
#### Code Examples

Field expiration: Set TTL on individual hash fields using HEXPIRE with conditional options (NX, XX, GT, LT) when you need fine-grained control over field lifecycle

**Difficulty:** Intermediate

**Redis CLI:**

[code example]

**Available in:** Redis CLI, C, C# (Synchronous), Go, Java (Asynchronous - Lettuce), Java (Reactive - Lettuce), Java (Synchronous - Jedis), JavaScript (Node.js), JavaScript (Node.js), PHP, Python, Rust (Asynchronous), Rust (Synchronous)

**C:**

[code example]

**C# (Synchronous):**

[code example]

**Go:**

[code example]

**Java (Asynchronous - Lettuce):**

[code example]

**Java (Reactive - Lettuce):**

[code example]

**Java (Synchronous - Jedis):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**PHP:**

[code example]

**Python:**

[code example]

**Rust (Asynchronous):**

[code example]

**Rust (Synchronous):**

[code example]

Give these commands a try in the interactive console:

HEXPIRE no-key 20 NX FIELDS 2 field1 field2
HSET mykey field1 "hello" field2 "world"
HEXPIRE mykey 10 FIELDS 3 field1 field2 field3
HGETALL mykey

title: Return information

text:
**RESP2:**

One of the following:
* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `0` if the specified NX | XX | GT | LT condition has not been met.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `1` if the expiration time was set/updated.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `2` when `HEXPIRE`/`HPEXPIRE` is called with 0 seconds/milliseconds or when `HEXPIREAT`/`HPEXPIREAT` is called with a past Unix time in seconds/milliseconds.
* [Simple error reply](../../develop/reference/protocol-spec#simple-errors):
    - if parsing failed, mandatory arguments are missing, unknown arguments are specified, or argument values are of the wrong type or out of range.
    - if the provided key exists but is not a hash.

**RESP3:**

One of the following:
* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `0` if the specified NX | XX | GT | LT condition has not been met.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `1` if the expiration time was set/updated.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `2` when `HEXPIRE`/`HPEXPIRE` is called with 0 seconds/milliseconds or when `HEXPIREAT`/`HPEXPIREAT` is called with a past Unix time in seconds/milliseconds.
* [Simple error reply](../../develop/reference/protocol-spec#simple-errors):
    - if parsing failed, mandatory arguments are missing, unknown arguments are specified, or argument values are of the wrong type or out of range.
    - if the provided key exists but is not a hash.

code:
HEXPIRE no-key 20 NX FIELDS 2 field1 field2
(nil)
HSET mykey field1 "hello" field2 "world"
(integer) 2
HEXPIRE mykey 10 FIELDS 3 field1 field2 field3
1) (integer) 1
2) (integer) 1
3) (integer) -2
HGETALL mykey

code:
// Set up hash with fields
        db.HashSet("myhash",
            [
                new("field1", "Hello"),
                new("field2", "World")
            ]
        );

        ExpireResult[] hexpireRes1 = db.HashFieldExpire(
            "myhash",
            new RedisValue[] { "field1", "field2" },
            TimeSpan.FromSeconds(10)
        );
        Console.WriteLine(string.Join(", ", hexpireRes1));
        // >>> Success, Success

        long[] hexpireRes2 = db.HashFieldGetTimeToLive(
            "myhash",
            new RedisValue[] { "field1", "field2" }
        );
        Console.WriteLine(string.Join(", ", hexpireRes2));
        // >>> 10, 10 (approximately)

        // Try to set expiration on non-existent field
        ExpireResult[] hexpireRes3 = db.HashFieldExpire(
            "myhash",
            new RedisValue[] { "nonexistent" },
            TimeSpan.FromSeconds(10)
        );
        Console.WriteLine(string.Join(", ", hexpireRes3));
        // >>> NoSuchField

code:
// Set up hash with fields
	rdb.HSet(ctx, "myhash", "field1", "Hello", "field2", "World")

	// Set expiration on hash fields
	res1, err := rdb.HExpire(ctx, "myhash", 10*time.Second, "field1", "field2").Result()

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(res1) // >>> [1 1]

	// Check TTL of the fields
	res2, err := rdb.HTTL(ctx, "myhash", "field1", "field2").Result()

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(len(res2)) // >>> 2

	// Try to set expiration on non-existent field
	res3, err := rdb.HExpire(ctx, "myhash", 10*time.Second, "nonexistent").Result()

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(res3) // >>> [-2]

	// Clean up
	rdb.Del(ctx, "myhash")

code:
// Set up hash with fields
            Map<String, String> hExpireExampleParams = new HashMap<>();
            hExpireExampleParams.put("field1", "Hello");
            hExpireExampleParams.put("field2", "World");

            CompletableFuture<Void> hExpireExample = asyncCommands.hset("myhash", hExpireExampleParams).thenCompose(res1 -> {
                // Set expiration on hash fields
                return asyncCommands.hexpire("myhash", 10, "field1", "field2");
            }).thenCompose(res2 -> {
                System.out.println(res2);
                // >>> [1, 1]
                // Check TTL of the fields
                return asyncCommands.httl("myhash", "field1", "field2");
            }).thenCompose(res3 -> {
                System.out.println(res3.size());
                // >>> 2
                // Try to set expiration on non-existent field
                return asyncCommands.hexpire("myhash", 10, "nonexistent");
            })
                    .thenAccept(System.out::println)
                    // >>> -2
                    .toCompletableFuture();

code:
// Set up hash with fields
            Map<String, String> hExpireExampleParams = new HashMap<>();
            hExpireExampleParams.put("field1", "Hello");
            hExpireExampleParams.put("field2", "World");

            Mono<Long> hExpireExample1 = reactiveCommands.hset("myhash", hExpireExampleParams).doOnNext(result -> {
            });

            hExpireExample1.block();

            // Set expiration on hash fields
            Mono<List<Long>> hExpireExample2 = reactiveCommands.hexpire("myhash", 10, "field1", "field2").collectList().doOnNext(result -> {
                System.out.println(result);
                // >>> [1, 1]
            });

            hExpireExample2.block();

            // Check TTL of the fields
            Mono<List<Long>> hExpireExample3 = reactiveCommands.httl("myhash", "field1", "field2").collectList().doOnNext(result -> {
                System.out.println(result.size());
                // >>> 2
            });

            hExpireExample3.block();

            // Try to set expiration on non-existent field
            Mono<List<Long>> hExpireExample4 = reactiveCommands.hexpire("myhash", 10, "nonexistent").collectList().doOnNext(result -> {
                System.out.println(result);
                // >>> [-2]
            });

code:
// Set up hash with fields
        Map<String, String> hExpireExampleParams = new HashMap<>();
        hExpireExampleParams.put("field1", "Hello");
        hExpireExampleParams.put("field2", "World");
        jedis.hset("myhash", hExpireExampleParams);

        // Set expiration on hash fields
        List<Long> hExpireResult1 = jedis.hexpire("myhash", 10, "field1", "field2");
        System.out.println(hExpireResult1); // >>> [1, 1]

        // Check TTL of the fields
        List<Long> hExpireResult2 = jedis.httl("myhash", "field1", "field2");
        System.out.println(hExpireResult2.size()); // >>> 2

        // Try to set expiration on non-existent field
        List<Long> hExpireResult3 = jedis.hexpire("myhash", 10, "nonexistent");
        System.out.println(hExpireResult3); // >>> [-2]

code:
// Set up hash with fields
await client.hSet('myhash', {
  'field1': 'Hello',
  'field2': 'World'
})

// Set expiration on hash fields
const res14 = await client.hExpire('myhash', ['field1', 'field2'], 10)
console.log(res14) // [1, 1]

// Check TTL of the fields
const res15 = await client.hTTL('myhash', ['field1', 'field2'])
console.log(res15) // [10, 10] (or close to 10)

// Try to set expiration on non-existent field
const res16 = await client.hExpire('myhash', ['nonexistent'], 10)
console.log(res16) // [-2]

code:
// Set up hash with fields
        $hExpireResult1 = $this->redis->hmset('myhash', ['field1' => 'Hello', 'field2' => 'World']);
        echo "HMSET myhash field1 Hello field2 World: " . ($hExpireResult1 ? 'OK' : 'FAIL') . "\n"; // >>> OK

        // Set expiration on hash fields
        $hExpireResult2 = $this->redis->hexpire('myhash', 10, ['field1', 'field2']);
        echo "HEXPIRE myhash 10 FIELDS field1 field2: " . json_encode($hExpireResult2) . "\n"; // >>> [1,1]

        // Check TTL of the fields
        $hExpireResult3 = $this->redis->httl('myhash', ['field1', 'field2']);
        echo "HTTL myhash FIELDS field1 field2 count: " . count($hExpireResult3) . "\n"; // >>> 2

        // Try to set expiration on non-existent field
        $hExpireResult4 = $this->redis->hexpire('myhash', 10, ['nonexistent']);
        echo "HEXPIRE myhash 10 FIELDS nonexistent: " . json_encode($hExpireResult4) . "\n"; // >>> [-2]

code:
# Set up hash with fields
r.hset("myhash", mapping={"field1": "Hello", "field2": "World"})

# Set expiration on hash fields
res12 = r.hexpire("myhash", 10, "field1", "field2")
print(res12)  # >>> [1, 1]

# Check TTL of the fields
res13 = r.httl("myhash", "field1", "field2")
print(res13)  # >>> [10, 10] (or close to 10)

# Try to set expiration on non-existent field
res14 = r.hexpire("myhash", 10, "nonexistent")
print(res14)  # >>> [-2]

code:
// Set up hash with fields
        let hash_fields = vec![("field1", "Hello"), ("field2", "World")];
        if let Ok(res) = r.hset_multiple("myhash", &hash_fields).await {
            let res: String = res;
            println!("{res}");    // >>> OK
        }

        // Set expiration on hash fields
        match r.hexpire("myhash", 10, redis::ExpireOption::NONE, &["field1", "field2"]).await {
            Ok(res1) => {
                let res1: Vec<i32> = res1;
                println!("{:?}", res1);    // >>> [1, 1]
            },
            Err(e) => {
                println!("Error setting expiration: {e}");
                return;
            }
        }

        // Check TTL of the fields
        match r.httl("myhash", &["field1", "field2"]).await {
            Ok(res2) => {
                let res2: Vec<i32> = res2;
                println!("{}", res2.len());    // >>> 2
            },
            Err(e) => {
                println!("Error getting TTL: {e}");
                return;
            }
        }

        // Try to set expiration on non-existent field
        match r.hexpire("myhash", 10, redis::ExpireOption::NONE, &["nonexistent"]).await {
            Ok(res3) => {
                let res3: Vec<i32> = res3;
                println!("{:?}", res3);    // >>> [-2]
            },
            Err(e) => {
                println!("Error setting expiration on non-existent field: {e}");
                return;
            }
        }

code:
// Set up hash with fields
        let hash_fields = vec![("field1", "Hello"), ("field2", "World")];
        if let Ok(res) = r.hset_multiple("myhash", &hash_fields) {
            let res: String = res;
            println!("{res}");    // >>> OK
        }

        // Set expiration on hash fields
        match r.hexpire("myhash", 10, redis::ExpireOption::NONE, &["field1", "field2"]) {
            Ok(res1) => {
                let res1: Vec<i32> = res1;
                println!("{:?}", res1);    // >>> [1, 1]
            },
            Err(e) => {
                println!("Error setting expiration: {e}");
                return;
            }
        }

        // Check TTL of the fields
        match r.httl("myhash", &["field1", "field2"]) {
            Ok(res2) => {
                let res2: Vec<i32> = res2;
                println!("{}", res2.len());    // >>> 2
            },
            Err(e) => {
                println!("Error getting TTL: {e}");
                return;
            }
        }

        // Try to set expiration on non-existent field
        match r.hexpire("myhash", 10, redis::ExpireOption::NONE, &["nonexistent"]) {
            Ok(res3) => {
                let res3: Vec<i32> = res3;
                println!("{:?}", res3);    // >>> [-2]
            },
            Err(e) => {
                println!("Error setting expiration on non-existent field: {e}");
                return;
            }
        }


title: HEXPIREAT

summary: Set expiration for hash fields using an absolute Unix timestamp (seconds)

title: Overview

text:
`HEXPIREAT` has the same effect and semantics as [`HEXPIRE`](), but instead of
specifying the number of seconds for the TTL (time to live), it takes
an absolute [Unix timestamp](http://en.wikipedia.org/wiki/Unix_time) in seconds since Unix epoch. A
timestamp in the past will delete the field immediately.

For the specific semantics of the command, see [`HEXPIRE`]().

title: Options

text:
The `HEXPIREAT` command supports a set of options:

* `NX` -- For each specified field, set expiration only when the field has no expiration.
* `XX` -- For each specified field, set expiration only when the field has an existing expiration.
* `GT` -- For each specified field, set expiration only when the new expiration is greater than current one.
* `LT` -- For each specified field, set expiration only when the new expiration is less than current one.

A non-volatile key is treated as an infinite TTL for the purposes of `GT` and `LT`.
The `NS`, `XX`, `GT`, and `LT` options are mutually exclusive.

title: Example

text: [code example]

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

title: Return information

text:
**RESP2:**

One of the following:
* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `0` if the specified NX, XX, GT, or LT condition has not been met.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `1` if the expiration time was set/updated.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `2` when `HEXPIRE` or `HPEXPIRE` is called with 0 seconds or milliseconds, or when `HEXPIREAT` or `HPEXPIREAT` is called with a past Unix time in seconds or milliseconds.
* [Simple error reply](../../develop/reference/protocol-spec#simple-errors):
    - if parsing failed, mandatory arguments are missing, unknown arguments are specified, or argument values are of the wrong type or out of range.
    - if the provided key exists but is not a hash.

**RESP3:**

One of the following:
* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `0` if the specified NX, XX, GT, or LT condition has not been met.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `1` if the expiration time was set/updated.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `2` when `HEXPIRE` or `HPEXPIRE` is called with 0 seconds or milliseconds, or when `HEXPIREAT` or `HPEXPIREAT` is called with a past Unix time in seconds or milliseconds.
* [Simple error reply](../../develop/reference/protocol-spec#simple-errors):
    - if parsing failed, mandatory arguments are missing, unknown arguments are specified, or argument values are of the wrong type or out of range.
    - if the provided key exists but is not a hash.

code:
redis> HSET mykey field1 "hello" field2 "world"
(integer) 2
redis> HEXPIREAT mykey 1715704971 FIELDS 2 field1 field2
1) (integer) 1
2) (integer) 1
redis> HTTL mykey FIELDS 2 field1 field2
1) (integer) 567
2) (integer) 567

section_id: example


title: HEXPIRETIME

summary: Returns the expiration time of a hash field as a Unix timestamp, in seconds.

title: Overview

text:
Returns the absolute Unix timestamp in seconds since Unix epoch at which the given key's field(s) will expire.

See also the [`HPEXPIRETIME`]() command, which returns the same information with millisecond resolution.

title: Examples

text: [code example]

title: Return information

text:
**RESP2:**

* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-1` if the field exists but has no associated expiration set.
    - [Integer reply](../../develop/reference/protocol-spec#integers): the expiration (Unix timestamp) in seconds.

**RESP3:**

* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-1` if the field exists but has no associated expiration set.
    - [Integer reply](../../develop/reference/protocol-spec#integers): the expiration (Unix timestamp) in seconds.

code:
redis> HSET mykey field1 "hello" field2 "world"
(integer) 2
redis> HEXPIRE mykey 300  FIELDS 2 field1 field2
1) (integer) 1
2) (integer) 1
redis> HEXPIRETIME mykey FIELDS 2 field1 field2
1) (integer) 1715705914
2) (integer) 1715705914


title: HGET

summary: Returns the value of a field in a hash.

title: Examples

text:
#### Code Examples

Foundational: Retrieve a single field value from a hash using HGET (returns nil if field or key doesn't exist)

**Difficulty:** Beginner

**Commands:** HSET, HGET

**Complexity:**
- HSET: O(1)
- HGET: O(1)

**Redis CLI:**

[code example]

**Available in:** Redis CLI, C, C# (Synchronous), Go, Java (Asynchronous - Lettuce), Java (Reactive - Lettuce), Java (Synchronous - Jedis), JavaScript (Node.js), JavaScript (Node.js), PHP, Python, Rust (Asynchronous), Rust (Synchronous)

**C:**

[code example]

**C# (Synchronous):**

[code example]

**Go:**

[code example]

**Java (Asynchronous - Lettuce):**

[code example]

**Java (Reactive - Lettuce):**

[code example]

**Java (Synchronous - Jedis):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**PHP:**

[code example]

**Python:**

[code example]

**Rust (Asynchronous):**

[code example]

**Rust (Synchronous):**

[code example]

Give these commands a try in the interactive console:

HSET myhash field1 "foo"
HGET myhash field1
HGET myhash field2

title: Return information

text:
**RESP2:**

One of the following:
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): The value associated with the field.
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): If the field is not present in the hash or key does not exist.

**RESP3:**

One of the following:
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): The value associated with the field.
* [Null reply](../../develop/reference/protocol-spec#nulls): If the field is not present in the hash or key does not exist.

code:
> HSET myhash field1 "foo"
(integer) 1
> HGET myhash field1
"foo"
> HGET myhash field2
(nil)

code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hiredis/hiredis.h>

int main(int argc, char **argv) {
    redisContext *c = redisConnect("127.0.0.1", 6379);

    if (c == NULL || c->err) {
        if (c) {
            printf("Connection error: %s\n", c->errstr);
            redisFree(c);
        } else {
            printf("Connection error: can't allocate redis context\n");
        }
        return 1;
    }

    redisReply *reply;

    // Set up hash with fields
    reply = redisCommand(c, "HSET %s %s %s %s %s",
        "myhash", "field1", "Hello", "field2", "World");
    freeReplyObject(reply);

    // Get multiple fields at once
    reply = redisCommand(c, "HMGET %s %s %s %s",
        "myhash", "field1", "field2", "nofield");

    printf("HMGET myhash field1 field2 nofield:\n");
    for (size_t i = 0; i < reply->elements; i++) {
        if (reply->element[i]->type == REDIS_REPLY_NIL) {
            printf("  [%zu]: null\n", i);
        } else {
            printf("  [%zu]: %s\n", i, reply->element[i]->str);
        }
    }
    // >>> [0]: Hello
    // >>> [1]: World
    // >>> [2]: null

    freeReplyObject(reply);

    redisFree(c);

    return 0;
}

code:
bool hgetRes1 = db.HashSet("myhash", "field1", "foo");

        RedisValue hgetRes2 = db.HashGet("myhash", "field1");
        Console.WriteLine(hgetRes2);    // >>> foo

        RedisValue hgetRes3 = db.HashGet("myhash", "field2");
        Console.WriteLine(hgetRes3);    // >>> Null

code:
res7, err := rdb.HSet(ctx, "myhash", "field1", "foo").Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(res7) // >>> 1

	res8, err := rdb.HGet(ctx, "myhash", "field1").Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(res8) // >>> foo

	res9, err := rdb.HGet(ctx, "myhash", "field2").Result()

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(res9) // >>> <empty string>

code:
Map<String, String> hGetExampleParams = new HashMap<>();
            hGetExampleParams.put("field1", "foo");

            CompletableFuture<Void> hGetExample = asyncCommands.hset("myhash", hGetExampleParams).thenCompose(res1 -> {
                System.out.println(res1); // >>> 1
                return asyncCommands.hget("myhash", "field1");
            }).thenCompose(res2 -> {
                System.out.println(res2); // >>> foo
                return asyncCommands.hget("myhash", "field2");
            }).thenAccept(res3 -> {
                System.out.println(res3); // >>> null
            }).toCompletableFuture();

code:
Map<String, String> hGetExampleParams = new HashMap<>();
            hGetExampleParams.put("field1", "foo");

            Mono<Long> hGetExample1 = reactiveCommands.hset("myhash", hGetExampleParams).doOnNext(result -> {
                System.out.println(result); // >>> 1
            });

            hGetExample1.block();

            Mono<String> hGetExample2 = reactiveCommands.hget("myhash", "field1").doOnNext(result -> {
                System.out.println(result); // >>> foo
            });

            hGetExample2.block();

            Mono<String> hGetExample3 = reactiveCommands.hget("myhash", "field2").doOnNext(result -> {
                System.out.println(result); // >>> null
            });

code:
Map<String, String> hGetExampleParams = new HashMap<>();
        hGetExampleParams.put("field1", "foo");

        long hGetResult1 = jedis.hset("myhash", hGetExampleParams);
        System.out.println(hGetResult1);    // >>> 1

        String hGetResult2 = jedis.hget("myhash", "field1");
        System.out.println(hGetResult2);    // >>> foo

        String hGetResult3 = jedis.hget("myhash", "field2");
        System.out.println(hGetResult3);    // >>> null

code:
const res7 = await client.hSet('myhash', 'field1', 'foo')
console.log(res7) // 1

const res8 = await client.hGet('myhash', 'field1')
console.log(res8) // foo

const res9 = await client.hGet('myhash', 'field2')
console.log(res9) // null

code:
import assert from 'node:assert';
import { Redis } from 'ioredis';

const redis = new Redis();

await redis.hset('myhash', { field1: 'Hello', field2: 'World' });

const hmgetResult = await redis.hmget('myhash', 'field1', 'field2', 'nofield');
console.log(hmgetResult); // >>> ['Hello', 'World', null]

redis.disconnect();

code:
$hGetResult1 = $this->redis->hset('myhash', 'field1', 'foo');
        echo "HSET myhash field1 foo: " . $hGetResult1 . "\n"; // >>> 1

        $hGetResult2 = $this->redis->hget('myhash', 'field1');
        echo "HGET myhash field1: " . ($hGetResult2 ?? 'null') . "\n"; // >>> foo

        $hGetResult3 = $this->redis->hget('myhash', 'field2');
        echo "HGET myhash field2: " . ($hGetResult3 ?? 'null') . "\n"; // >>> null

code:
res7 = r.hset("myhash", "field1", "foo")
print(res7)
# >>> 1

res8 = r.hget("myhash", "field1")
print(res8)
# >>> foo

res9 = r.hget("myhash", "field2")
print(res9)
# >>> None

code:
match r.hset("myhash", "field1", "foo").await {
            Ok(res7) => {
                let res7: i32 = res7;
                println!("{res7}");    // >>> 1
            },
            Err(e) => {
                println!("Error setting hash field: {e}");
                return;
            }
        }

        match r.hget("myhash", "field1").await {
            Ok(res8) => {
                let res8: Option<String> = res8;
                match res8 {
                    Some(value) => {
                        println!("{value}");    // >>> foo
                    },
                    None => {
                        println!("None");
                    }
                }
            },
            Err(e) => {
                println!("Error getting hash field: {e}");
                return;
            }
        }

        match r.hget("myhash", "field2").await {
            Ok(res9) => {
                let res9: Option<String> = res9;
                match res9 {
                    Some(_) => {
                        println!("Some value");
                    },
                    None => {
                        println!("None");    // >>> None
                    }
                }
            },
            Err(e) => {
                println!("Error getting hash field: {e}");
                return;
            }
        }

code:
match r.hset("myhash", "field1", "foo") {
            Ok(res7) => {
                let res7: i32 = res7;
                println!("{res7}");    // >>> 1
            },
            Err(e) => {
                println!("Error setting hash field: {e}");
                return;
            }
        }

        match r.hget("myhash", "field1") {
            Ok(res8) => {
                let res8: Option<String> = res8;
                match res8 {
                    Some(value) => {
                        println!("{value}");    // >>> foo
                    },
                    None => {
                        println!("None");
                    }
                }
            },
            Err(e) => {
                println!("Error getting hash field: {e}");
                return;
            }
        }

        match r.hget("myhash", "field2") {
            Ok(res9) => {
                let res9: Option<String> = res9;
                match res9 {
                    Some(_) => {
                        println!("Some value");
                    },
                    None => {
                        println!("None");    // >>> None
                    }
                }
            },
            Err(e) => {
                println!("Error getting hash field: {e}");
                return;
            }
        }


title: HGETALL

summary: Returns all fields and values in a hash.

title: Examples

text:
#### Code Examples

Foundational: Retrieve all fields and values from a hash using HGETALL (returns alternating field-value pairs, useful for loading entire hash data)

**Difficulty:** Beginner

**Commands:** HSET, HGETALL

**Complexity:**
- HSET: O(1)
- HGETALL: O(N)

**Redis CLI:**

[code example]

**Available in:** Redis CLI, C, C# (Synchronous), Go, Java (Asynchronous - Lettuce), Java (Reactive - Lettuce), Java (Synchronous - Jedis), JavaScript (Node.js), JavaScript (Node.js), PHP, Python, Rust (Asynchronous), Rust (Synchronous)

**C:**

[code example]

**C# (Synchronous):**

[code example]

**Go:**

[code example]

**Java (Asynchronous - Lettuce):**

[code example]

**Java (Reactive - Lettuce):**

[code example]

**Java (Synchronous - Jedis):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**JavaScript (Node.js):**

[code example]

**PHP:**

[code example]

**Python:**

[code example]

**Rust (Asynchronous):**

[code example]

**Rust (Synchronous):**

[code example]

Give these commands a try in the interactive console:

HSET myhash field1 "Hello"
HSET myhash field2 "World"
HGETALL myhash

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of fields and their values, or an empty list when key does not exist.

**RESP3:**

[Map reply](../../develop/reference/protocol-spec#maps): a map of fields and their values, or an empty list when key does not exist.

code:
redis> HSET myhash field1 "Hello"
(integer) 1
redis> HSET myhash field2 "World"
(integer) 1
redis> HGETALL myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"

code:
db.HashSet("myhash",
            [
                new("field1", "Hello"),
                new("field2", "World")
            ]
        );

        HashEntry[] hGetAllResult = db.HashGetAll("myhash");
        Array.Sort(hGetAllResult, (a1, a2) => a1.Name.CompareTo(a2.Name));
        Console.WriteLine(
            string.Join(", ", hGetAllResult.Select(e => $"{e.Name}: {e.Value}"))
        );
        // >>> field1: Hello, field2: World

code:
hGetAllResult1, err := rdb.HSet(ctx, "myhash",
		"field1", "Hello",
		"field2", "World",
	).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(hGetAllResult1) // >>> 2

	hGetAllResult2, err := rdb.HGetAll(ctx, "myhash").Result()

	if err != nil {
		panic(err)
	}

	keys := make([]string, 0, len(hGetAllResult2))

	for key, _ := range hGetAllResult2 {
		keys = append(keys, key)
	}

	sort.Strings(keys)

	for _, key := range keys {
		fmt.Printf("Key: %v, value: %v\n", key, hGetAllResult2[key])
	}
	// >>> Key: field1, value: Hello
	// >>> Key: field2, value: World

code:
Map<String, String> hGetAllExampleParams = new HashMap<>();
            hGetAllExampleParams.put("field1", "Hello");
            hGetAllExampleParams.put("field2", "World");

            CompletableFuture<Void> hGetAllExample = asyncCommands.hset("myhash", hGetAllExampleParams).thenCompose(res1 -> {
                return asyncCommands.hgetall("myhash");
            }).thenAccept(res2 -> {
                System.out.println(res2);
                // >>> {field1=Hello, field2=World}
            }).toCompletableFuture();

code:
Map<String, String> hGetAllExampleParams = new HashMap<>();
            hGetAllExampleParams.put("field1", "Hello");
            hGetAllExampleParams.put("field2", "World");

            Mono<Long> hGetAllExample1 = reactiveCommands.hset("myhash", hGetAllExampleParams).doOnNext(result -> {
            });

            hGetAllExample1.block();

            Mono<Map<String, String>> hGetAllExample2 = reactiveCommands.hgetall("myhash").collectMap(
                    KeyValue::getKey, KeyValue::getValue
            ).doOnNext(result -> {
                System.out.println(result);
                // >>> {field1=Hello, field2=World}
            });

code:
Map<String, String> hGetAllExampleParams = new HashMap<>();
        hGetAllExampleParams.put("field1", "Hello");
        hGetAllExampleParams.put("field2", "World");

        long hGetAllResult1 = jedis.hset("myhash", hGetAllExampleParams);
        System.out.println(hGetAllResult1); // >>> 2

        Map<String, String> hGetAllResult2 = jedis.hgetAll("myhash");
        System.out.println(
            hGetAllResult2.entrySet().stream()
                    .sorted((s1, s2)-> s1.getKey().compareTo(s2.getKey()))
                    .collect(toList())
                    .toString()
        );
        // >>> [field1=Hello, field2=World]

code:
const res10 = await client.hSet(
  'myhash',
  {
    'field1': 'Hello',
    'field2': 'World'
  }
)

const res11 = await client.hGetAll('myhash')
console.log(res11) // [Object: null prototype] { field1: 'Hello', field2: 'World' }

code:
$hGetAllResult1 = $this->redis->hmset('myhash', ['field1' => 'Hello', 'field2' => 'World']);
        echo "HMSET myhash field1 Hello field2 World: " . ($hGetAllResult1 ? 'OK' : 'FAIL') . "\n"; // >>> OK

        $hGetAllResult2 = $this->redis->hgetall('myhash');
        echo "HGETALL myhash: " . json_encode($hGetAllResult2) . "\n"; // >>> {"field1":"Hello","field2":"World"}

code:
res10 = r.hset("myhash", mapping={"field1": "Hello", "field2": "World"})

res11 = r.hgetall("myhash")
print(res11) # >>> { "field1": "Hello", "field2": "World" }

code:
let hash_fields = [
            ("field1", "Hello"),
            ("field2", "World"),
        ];

        if let Ok(_) = r.hset_multiple::<&str, &str, &str, String>("myhash", &hash_fields).await {
            // Fields set successfully
        }

        match r.hgetall("myhash").await {
            Ok(res11) => {
                let res11: HashMap<String, String> = res11;
                println!("{res11:?}");    // >>> {"field1": "Hello", "field2": "World"}
            },
            Err(e) => {
                println!("Error getting all hash fields: {e}");
                return;
            }
        }

code:
let hash_fields = [
            ("field1", "Hello"),
            ("field2", "World"),
        ];

        if let Ok(_) = r.hset_multiple::<&str, &str, &str, String>("myhash", &hash_fields) {
            // Fields set successfully
        }

        match r.hgetall("myhash") {
            Ok(res11) => {
                let res11: HashMap<String, String> = res11;
                println!("{res11:?}");    // >>> {"field1": "Hello", "field2": "World"}
            },
            Err(e) => {
                println!("Error getting all hash fields: {e}");
                return;
            }
        }


title: HGETDEL

summary: Returns the value of a field and deletes it from the hash.

title: Overview

text: Get and delete the value of one or more fields of a given hash key. When the last field is deleted, the key will also be deleted.

title: Example

text: [code example]

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of deleted fields and their values or `nil` for fields that do not exist.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of deleted fields and their values or `nil` for fields that do not exist.

code:
redis> HSET mykey field1 "Hello" field2 "World" field3 "!"
(integer) 3
redis> HGETALL mykey
1) "field1"
2) "Hello"
3) "field2"
4) "World"
5) "field3"
6) "!"
redis> HGETDEL mykey FIELDS 2 field3 field4
1) "!"
2) (nil)
redis> HGETALL mykey
1) "field1"
2) "Hello"
3) "field2"
4) "World"
redis> HGETDEL mykey FIELDS 2 field1 field2
1) "Hello"
2) "World"
redis> KEYS *
(empty array)


title: HGETEX

summary: Get the value of one or more fields of a given hash key, and optionally set their expiration.

title: Overview

text: Get the value of one or more fields of a given hash key and optionally set their expiration time or time-to-live (TTL).

title: Options

text:
The `HGETEX` command supports a set of options:

* `EX seconds` -- Set the specified expiration time, in seconds.
* `PX milliseconds` -- Set the specified expiration time, in milliseconds.
* `EXAT unix-time-seconds` -- Set the specified Unix time at which the fields will expire, in seconds.
* `PXAT unix-time-milliseconds` -- Set the specified Unix time at which the fields will expire, in milliseconds.
* `PERSIST` -- Remove the TTL associated with the fields.

The `EX`, `PX`, `EXAT`, `PXAT`, and `PERSIST` options are mutually exclusive.

title: Example

text: [code example]

title: Return information

text:
**RESP2:**

* [Array reply](../../develop/reference/protocol-spec#arrays): a list of values associated with the given fields, in the same order as they are requested.

**RESP3:**

* [Array reply](../../develop/reference/protocol-spec#arrays): a list of values associated with the given fields, in the same order as they are requested.

code:
redis> HSET mykey field1 "Hello" field2 "World"
(integer) 2
redis> HGETEX mykey EX 120 FIELDS 1 field1
1) "Hello"
redis> HGETEX mykey EX 100 FIELDS 1 field2
1) "World"
redis> HTTL mykey FIELDS 2 field1 field2
1) (integer) 91
2) (integer) 85
redis> HTTL mykey FIELDS 3 field1 field2 field3
1) (integer) 75
2) (integer) 68
3) (integer) -2
...
redis> HTTL mykey FIELDS 3 field1 field2
1) (integer) -2
2) (integer) -2
redis> HGETALL mykey
(empty array)


title: HINCRBY

summary: Increments the integer value of a field in a hash by a number. Uses 0 as initial value if the field doesn't exist.

title: Overview

text:
Increments the number stored at `field` in the hash stored at `key` by
`increment`.
If `key` does not exist, a new key holding a hash is created.
If `field` does not exist the value is set to `0` before the operation is
performed.

The range of values supported by `HINCRBY` is limited to 64 bit signed integers.

title: Examples

text:
Since the `increment` argument is signed, both increment and decrement
operations can be performed:

HSET myhash field 5
HINCRBY myhash field 1
HINCRBY myhash field -1
HINCRBY myhash field -10

title: Return information

text:
**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the value of the field after the increment operation.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the value of the field after the increment operation.


title: HINCRBYFLOAT

summary: Increments the floating point value of a field by a number. Uses 0 as initial value if the field doesn't exist.

title: Overview

text:
Increment the specified `field` of a hash stored at `key`, and representing a
floating point number, by the specified `increment`. If the increment value
is negative, the result is to have the hash field value **decremented** instead of incremented.
If the field does not exist, it is set to `0` before performing the operation.
An error is returned if one of the following conditions occur:

* The key contains a value of the wrong type (not a hash).
* The current field content or the specified increment are not parsable as a
  double precision floating point number.

The exact behavior of this command is identical to the one of the [`INCRBYFLOAT`]()
command, please refer to the documentation of [`INCRBYFLOAT`]() for further
information.

title: Examples

text:
HSET mykey field 10.50
HINCRBYFLOAT mykey field 0.1
HINCRBYFLOAT mykey field -5
HSET mykey field 5.0e3
HINCRBYFLOAT mykey field 2.0e2

title: Implementation details

text:
The command is always propagated in the replication link and the Append Only
File as a [`HSET`]() operation, so that differences in the underlying floating point
math implementation will not be sources of inconsistency.

title: Return information

text:
**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the value of the field after the increment operation.

**RESP3:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): The value of the field after the increment operation.


title: HKEYS

summary: Returns all fields in a hash.

title: Overview

text: Returns all field names in the hash stored at `key`.

title: Examples

text:
HSET myhash field1 "Hello"
HSET myhash field2 "World"
HKEYS myhash

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of fields in the hash, or an empty list when the key does not exist

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of fields in the hash, or an empty list when the key does not exist.


title: HLEN

summary: Returns the number of fields in a hash.

title: Overview

text: Returns the number of fields contained in the hash stored at `key`.

title: Examples

text:
HSET myhash field1 "Hello"
HSET myhash field2 "World"
HLEN myhash

title: Return information

text:
**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of fields in the hash, or 0 when the key does not exist.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of the fields in the hash, or 0 when the key does not exist.


title: HMGET

summary: Returns the values of all fields in a hash.

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of values associated with the given fields, in the same order as they are requested.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of values associated with the given fields, in the same order as they are requested.


title: HMSET

summary: Sets the values of multiple fields.

title: Overview

text:
Sets the specified fields to their respective values in the hash stored at
`key`.
This command overwrites any specified fields already existing in the hash.
If `key` does not exist, a new key holding a hash is created.

title: Examples

text:
HMSET myhash field1 "Hello" field2 "World"
HGET myhash field1
HGET myhash field2

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> | Deprecated as of Redis v4.0.0. |

title: Return information

text:
**RESP2:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK`.

**RESP3:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK`.


title: HOTKEYS

summary: A container for hotkeys tracking commands.

title: Overview

text:
This is a container command for hotkeys tracking commands that provides a method for identifying hotkeys inside a Redis server during a specified tracking time period.

Hotkeys in this context are defined by two metrics:
* Percentage of CPU time spent on the key from the total time during the tracking period.
* Percentage of network bytes (input + output) used for the key from the total network bytes used by Redis during the tracking period.

title: Usage

role: syntax

text:
The general workflow is for the user to initiate a hotkeys tracking process which should run for some time. The keys' metrics are recorded inside a probabilistic data structure, after which the user is able to fetch the top K metrics.

Available subcommands:

- [`HOTKEYS START`]() - Starts hotkeys tracking with specified metrics.
- [`HOTKEYS STOP`]() - Stops hotkeys tracking but preserves data.
- [`HOTKEYS GET`]() - Returns tracking results and metadata.
- [`HOTKEYS RESET`]() - Releases resources used for tracking.


title: HOTKEYS GET

summary: Returns lists of top K hotkeys depending on metrics chosen in HOTKEYS START command.

title: Overview

text:
Returns tracking results and metadata from the current or most recent hotkeys tracking session.

This command returns comprehensive information about the hotkeys tracking session, including:

- Tracking metadata (start time, duration, sample ratio, etc.)
- Performance statistics (CPU time, network bytes)
- Lists of top K hot keys sorted by the metrics specified in `HOTKEYS START`

The following metrics are collected for non-clustered as well as clustered Redis environments:

- `tracking-active` (integer): 1 if tracking is active, 0 if stopped
- `sample-ratio` (integer): The sampling ratio used during tracking
- `selected-slots` (array): [Array]() of select slots and slot ranges
- `all-commands-all-slots-us` (integer): CPU time in microseconds for all commands on all slots
- `net-bytes-all-commands-all-slots` (integer): Network bytes for all commands on all slots
- `collection-start-time-unix-ms` (integer): Unix timestamp in milliseconds when tracking started
- `collection-duration-ms` (integer): Duration of tracking in milliseconds
- `total-cpu-time-user-ms` (integer): User CPU time used in milliseconds (only when the `CPU` metric was specified with `HOTKEYS START`)
- `total-cpu-time-sys-ms` (integer): System CPU time used in milliseconds (only when the `CPU` metric was specified with `HOTKEYS START`)
- `total-net-bytes` (integer): Total network bytes processed (only when the `NET` metric was specified with `HOTKEYS START`)
- `by-cpu-time-us` (array): [Array]() of key-time pairs sorted by CPU time in microseconds (only when the `CPU` metric was specified with `HOTKEYS START`)
- `by-net-bytes` (array): [Array]() of key-bytes pairs sorted by network bytes (only when the `NET` metric was specified with `HOTKEYS START`)

The following additional results are collected only on clustered Redis environments, when `SLOTS` was used with `HOTKEYS START`:

- `sampled-commands-selected-slots-us` (integer): CPU time in milliseconds for sampled commands in selected slots (only when `SAMPLE` was used with `HOTKEYS START`)
- `all-commands-selected-slots-us` (integer): CPU time in milliseconds for all commands in selected slots
- `net-bytes-sampled-commands-selected-slots` (integer): Network bytes for sampled commands in selected slots (only when `SAMPLE` was used with `HOTKEYS START`)
- `net-bytes-all-commands-selected-slots` (integer): Network bytes for all commands on selected slots

title: Example (both `NET` and `CPU` metrics specified)

text: [code example]

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ❌ Standard
<nobr>❌ Active-Active</nobr> | ❌ Standard
<nobr>❌ Active-Active</nobr> |  |

title: Return information

text:
**RESP2:**

One of the following:

- [Array reply]() when tracking data is available, containing an array of pairs of field names and values.
- [Null reply]() when no tracking has been started or data has been reset.

**RESP3:**

One of the following:

- [Array reply]() when tracking data is available, containing a [map]() of field names and values.
- [Null reply]() when no tracking has been started or data has been reset.

code:
HOTKEYS GET
1)  1) "tracking-active"
    2) (integer) 0
    3) "sample-ratio"
    4) (integer) 1
    5) "selected-slots"
    6) 1) 1) (integer) 0
          2) (integer) 16383
    7) "all-commands-all-slots-us"
    8) (integer) 103
    9) "net-bytes-all-commands-all-slots"
   10) (integer) 2042
   11) "collection-start-time-unix-ms"
   12) (integer) 1770824933147
   13) "collection-duration-ms"
   14) (integer) 0
   15) "total-cpu-time-user-ms"
   16) (integer) 23
   17) "total-cpu-time-sys-ms"
   18) (integer) 7
   19) "total-net-bytes"
   20) (integer) 2038
   21) "by-cpu-time-us"
   22)  1) "hotkey_001_counter"
        2) (integer) 29
        3) "hotkey_001"
        4) (integer) 25
        5) "hotkey_001_hash"
        6) (integer) 11
        7) "hotkey_001_list"
        8) (integer) 9
        9) "hotkey_001_set"
       10) (integer) 9
   23) "by-net-bytes"
   24)  1) "hotkey_001"
        2) (integer) 446
        3) "hotkey_002"
        4) (integer) 328
        5) "hotkey_001_hash"
        6) (integer) 198
        7) "hotkey_001_set"
        8) (integer) 167
        9) "hotkey_001_counter"
       10) (integer) 116


title: HOTKEYS HELP

summary: Returns helpful text about HOTKEYS commands and parameters.

title: Overview

text: Returns helpful text about `HOTKEYS` commands and parameters.

title: Return information

text:
**RESP2:**

Returns an [array reply]() with the list of `HOTKEYS` subcommands and their descriptions.

**RESP3:**

Returns an [array reply]() with the list of `HOTKEYS` subcommands and their descriptions.


title: HOTKEYS RESET

title: Overview

text:
Release the resources used for hotkey tracking.

This command can only be executed when hotkey tracking is stopped. It will return an error if tracking is currently active. Use [`HOTKEYS STOP`]() first to stop tracking, then use `HOTKEYS RESET` to free the allocated resources.

title: Return information

text:
**RESP2:**

One of the following:

- [Simple string reply](): `OK` when resources are successfully released.
- [Simple error reply](): when tracking is currently active.

**RESP3:**

One of the following:

- [Simple string reply](): `OK` when resources are successfully released.
- [Simple error reply](): when tracking is currently active.


title: HOTKEYS START

summary: Starts hotkeys tracking.

title: Overview

text:
Starts hotkeys tracking with specified metrics.

This command initiates a hotkey tracking session. You must specify which metrics to track using the required `METRICS` parameter.
An error is returned if a tracking session is already in progress.

The tracking session continues until manually stopped with [`HOTKEYS STOP`]() or automatically stopped after the specified duration.

title: Arguments

text:
METRICS count [CPU] [NET]

**Required.** Specifies which metrics to track and how many hotkeys to track.

- `count` - The number of metrics to collect (required).
- `CPU` - Track hotkeys by CPU time percentage (optional).
- `NET` - Track hotkeys by network bytes percentage (optional).

At least one of `CPU` or `NET` must be specified.

title: Optional arguments

text:
COUNT

Specifies the value of K for the top-K hotkeys tracking.

DURATION

The duration in seconds for how long the hotkeys tracking should run. After this time period, tracking will automatically stop. If not specified, tracking continues until manually stopped with `HOTKEYS STOP`.

SAMPLE

Sampling ratio for probabilistic tracking. Each key is sampled with probability `1/ratio`. Higher values reduce performance impact but may miss some hotkeys. Lower values provide more accurate results but with higher performance cost.

SLOTS

Specifies which hash slots to track in a cluster environment. Takes a count followed by that many slot numbers. Only keys that hash to the specified slots will be tracked. Useful for tracking hotkeys on specific shards in a Redis cluster. Using `SLOTS` when not in cluster mode will result in an error.

title: Return information

text:
**RESP2:**

One of the following:

- [Simple string]() reply: `OK` when tracking is successfully started.
- [Error reply](): when invalid parameters are provided.

**RESP3:**

One of the following:

- [Simple string]() reply: `OK` when tracking is successfully started.
- [Error reply](): when invalid parameters are provided.


title: HOTKEYS STOP

summary: Stops hotkeys tracking.

title: Overview

text:
Stops hotkeys tracking but preserves the collected data.

After stopping, the tracking data remains available through [`HOTKEYS GET`]() until [`HOTKEYS RESET`]() is called or a new tracking session is started.

title: Return information

text:
**RESP2:**

One of the following:

- [Simple string reply](): `OK` when tracking is successfully stopped.
- [Simple error reply](): when tracking is not currently active.

**RESP3:**

One of the following:

- [Simple string reply](): `OK` when tracking is successfully stopped.
- [Simple error reply](): when tracking is not currently active.


title: HPERSIST

summary: Removes the expiration time for each specified field

title: Overview

text:
Remove the existing expiration on a hash key's field(s), turning the field(s) from _volatile_ (a field
with expiration set) to _persistent_ (a field that will never expire as no TTL (time to live)
is associated).

title: Examples

text: [code example]

text:
| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

title: Return information

text:
**RESP2:**

* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-1` if the field exists but has no associated expiration set.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `1` the expiration was removed.

**RESP3:**

* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-1` if the field exists but has no associated expiration set.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `1` the expiration was removed.

code:
redis> HSET mykey field1 "hello" field2 "world"
(integer) 2
redis> HEXPIRE mykey 300 FIELDS 2 field1 field2
1) (integer) 1
2) (integer) 1
redis> HTTL mykey FIELDS 2 field1 field2
1) (integer) 283
2) (integer) 283
redis> HPERSIST mykey FIELDS 1 field2
1) (integer) 1
redis> HTTL mykey FIELDS 2 field1 field2
1) (integer) 268
2) (integer) -1


title: HPEXPIRE

summary: Set expiration for hash fields using relative time to expire (milliseconds)

title: Overview

text:
This command works like [`HEXPIRE`](), but the expiration of a field is
specified in milliseconds instead of seconds.

title: Options

text:
The `HPEXPIRE` command supports a set of options:

* `NX` -- For each specified field, set expiration only when the field has no expiration.
* `XX` -- For each specified field, set expiration only when the field has an existing expiration.
* `GT` -- For each specified field, set expiration only when the new expiration is greater than current one.
* `LT` -- For each specified field, set expiration only when the new expiration is less than current one.

A non-volatile key is treated as an infinite TTL for the purposes of `GT` and `LT`.
The `NX`, `XX`, `GT`, and `LT` options are mutually exclusive.

title: Example

text: [code example]

title: Return information

text:
**RESP2:**

One of the following:
* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `0` if the specified NX, XX, GT, or LT condition has not been met.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `1` if the expiration time was set/updated.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `2` when `HEXPIRE` or `HPEXPIRE` is called with 0 seconds or milliseconds, or when `HEXPIREAT` or `HPEXPIREAT` is called with a past Unix time in seconds or milliseconds.
* [Simple error reply](../../develop/reference/protocol-spec#simple-errors):
    - if parsing failed, mandatory arguments are missing, unknown arguments are specified, or argument values are of the wrong type or out of range.
    - if the provided key exists but is not a hash.

**RESP3:**

One of the following:
* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `0` if the specified NX, XX, GT, or LT condition has not been met.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `1` if the expiration time was set/updated.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `2` when `HEXPIRE` or `HPEXPIRE` is called with 0 seconds or milliseconds, or when `HEXPIREAT` or `HPEXPIREAT` is called with a past Unix time in seconds or milliseconds.
* [Simple error reply](../../develop/reference/protocol-spec#simple-errors):
    - if parsing failed, mandatory arguments are missing, unknown arguments are specified, or argument values are of the wrong type or out of range.
    - if the provided key exists but is not a hash.

code:
redis> HSET mykey field1 "hello" field2 "world"
(integer) 2
redis> HPEXPIRE mykey 2000 FIELDS 2 field1 field2
1) (integer) 1
2) (integer) 1
redis> HGETALL mykey
(empty array)


title: HPEXPIREAT

summary: Set expiration for hash fields using an absolute Unix timestamp (milliseconds)

title: Overview

text:
`HPEXPIREAT` has the same effect and semantics as [`HEXPIREAT`](), but the Unix time at
which the field will expire is specified in milliseconds since Unix epoch instead of seconds.

title: Options

text:
The `HPEXPIREAT` command supports a set of options:

* `NX` -- For each specified field, set expiration only when the field has no expiration.
* `XX` -- For each specified field, set expiration only when the field has an existing expiration.
* `GT` -- For each specified field, set expiration only when the new expiration is greater than current one.
* `LT` -- For each specified field, set expiration only when the new expiration is less than current one.

A non-volatile key is treated as an infinite TTL for the purposes of `GT` and `LT`.
The `NX`, `XX`, `GT`, and `LT` options are mutually exclusive.

title: Example

text: [code example]

title: Return information

code:
redis> HSET mykey field1 "hello" field2 "world"
(integer) 2
redis> HPEXPIREAT mykey 1715704971000 FIELDS 2 field1 field2
1) (integer) 1
2) (integer) 1
redis> HPTTL mykey FIELDS 2 field1 field2
1) (integer) 303340
2) (integer) 303340


title: HPEXPIRETIME

summary: Returns the expiration time of a hash field as a Unix timestamp, in msec.

title: Overview

text: `HPEXPIRETIME` has the same semantics as [`HEXPIRETIME`](), but returns the absolute Unix expiration timestamp in milliseconds since Unix epoch instead of seconds.

title: Examples

text: [code example]

title: Return information

text:
**RESP2:**

* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-1` if the field exists but has no associated expiration set.
    - [Integer reply](../../develop/reference/protocol-spec#integers): the expiration (Unix timestamp) in milliseconds.

**RESP3:**

* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-1` if the field exists but has no associated expiration set.
    - [Integer reply](../../develop/reference/protocol-spec#integers): the expiration (Unix timestamp) in milliseconds.

code:
redis> HSET mykey field1 "hello" field2 "world"
(integer) 2
redis> HEXPIRE mykey 300 FIELDS 2 field1 field2
1) (integer) 1
2) (integer) 1
redis> HPEXPIRETIME mykey FIELDS 2 field1 field2
1) (integer) 1715705913659
2) (integer) 1715705913659


title: HPTTL

summary: Returns the TTL in milliseconds of a hash field.

title: Overview

text:
Like [`HTTL`](), this command returns the remaining TTL (time to live) of a field that has an
expiration set, but in milliseconds instead of seconds.

title: Example

text: [code example]

title: Return information

text:
**RESP2:**

* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-1` if the field exists but has no associated expiration set.
    - [Integer reply](../../develop/reference/protocol-spec#integers): the TTL in milliseconds.

**RESP3:**

* [Array reply](../../develop/reference/protocol-spec#arrays). For each field:
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-2` if no such field exists in the provided hash key, or the provided key does not exist.
    - [Integer reply](../../develop/reference/protocol-spec#integers): `-1` if the field exists but has no associated expiration set.
    - [Integer reply](../../develop/reference/protocol-spec#integers): the TTL in milliseconds.

code:
redis> HPTTL no-key FIELDS 3 field1 field2 field3
(nil)
redis> HSET mykey field1 "hello" field2 "world"
(integer) 2
redis> HEXPIRE mykey 300 FIELDS 2 field1 field3
1) (integer) 1
2) (integer) -2
redis> HPTTL mykey FIELDS 3 field1 field2 field3
1) (integer) 292202
2) (integer) -1
3) (integer) -2


title: HRANDFIELD

summary: Returns one or more random fields from a hash.

title: Overview

text:
When called with just the `key` argument, return a random field from the hash value stored at `key`.

If the provided `count` argument is positive, return an array of **distinct fields**.
The array's length is either `count` or the hash's number of fields ([`HLEN`]()), whichever is lower.

If called with a negative `count`, the behavior changes and the command is allowed to return the **same field multiple times**.
In this case, the number of returned fields is the absolute value of the specified `count`.

The optional `WITHVALUES` modifier changes the reply so it includes the respective values of the randomly selected hash fields.

title: Examples

text:
HSET coin heads obverse tails reverse edge null
HRANDFIELD coin
HRANDFIELD coin
HRANDFIELD coin -5 WITHVALUES

title: Specification of the behavior when count is passed

text:
When the `count` argument is a positive value this command behaves as follows:

* No repeated fields are returned.
* If `count` is bigger than the number of fields in the hash, the command will only return the whole hash without additional fields.
* The order of fields in the reply is not truly random, so it is up to the client to shuffle them if needed.

When the `count` is a negative value, the behavior changes as follows:

* Repeating fields are possible.
* Exactly `count` fields, or an empty array if the hash is empty (non-existing key), are always returned.
* The order of fields in the reply is truly random.

title: Return information

text:
**RESP2:**

Any of the following:
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if the key doesn't exist
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): a single, randomly selected field when the `count` option is not used
* [Array reply](../../develop/reference/protocol-spec#arrays): a list containing `count` fields when the `count` option is used, or an empty array if the key does not exists.
* [Array reply](../../develop/reference/protocol-spec#arrays): a list of fields and their values when `count` and `WITHVALUES` were both used.

**RESP3:**

Any of the following:
* [Null reply](../../develop/reference/protocol-spec#nulls): if the key doesn't exist
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): a single, randomly selected field when the `count` option is not used
* [Array reply](../../develop/reference/protocol-spec#arrays): a list containing `count` fields when the `count` option is used, or an empty array if the key does not exists.
* [Array reply](../../develop/reference/protocol-spec#arrays): a list of fields and their values when `count` and `WITHVALUES` were both used.


title: HSCAN

summary: Iterates over fields and values of a hash.

title: Overview

text: See [`SCAN`]() for `HSCAN` documentation.

title: Return information

text:
**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a two-element array.
* The first element is a [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings) that represents an unsigned 64-bit number, the cursor.
* The second element is an [Array reply](../../develop/reference/protocol-spec#arrays) of field/value pairs that were scanned. When the `NOVALUES` flag (since Redis 7.4) is used, only the field names are returned.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a two-element array.
* The first element is a [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings) that represents an unsigned 64-bit number, the cursor.
* The second element is an [Array reply](../../develop/reference/protocol-spec#arrays) of field/value pairs that were scanned. When the `NOVALUES` flag (since Redis 7.4) is used, only the field names are returned.