# HSETEX

> Set hash fields with expiration support.

The `HSETEX` command sets the specified fields with their values and optionally sets their expiration time or TTL. It supports conditional operations to control when fields should be set.

## Arguments

<ParamField body="key" type="str" required>
  The key of the hash.
</ParamField>

<ParamField body="field" type="str">
  A single field name to set. Use with `value` parameter.
</ParamField>

<ParamField body="value" type="Any">
  A single value to set. Use with `field` parameter.
</ParamField>

<ParamField body="values" type="Dict[str, Any]">
  A dictionary of fields and their values to set. Either use `field`/`value` or `values`, but not both.
</ParamField>

<ParamField body="fnx" type="bool">
  Only set fields if the hash does not exist.
</ParamField>

<ParamField body="fxx" type="bool">
  Only set fields if the hash already exists.
</ParamField>

<ParamField body="ex" type="int">
  Set expiration time in seconds.
</ParamField>

<ParamField body="px" type="int">
  Set expiration time in milliseconds.
</ParamField>

<ParamField body="exat" type="int">
  Set expiration as Unix timestamp in seconds.
</ParamField>

<ParamField body="pxat" type="int">
  Set expiration as Unix timestamp in milliseconds.
</ParamField>

<ParamField body="keepttl" type="bool">
  Retain the existing time to live (TTL) associated with the hash key when setting fields. If the hash has an expiration, it will be preserved.
</ParamField>

## Response

<ResponseField type="int" required>
  0 if no fields were set, 1 if all the fields were set.
</ResponseField>

<RequestExample>
```py Single Field
# Set a single field with expiration
result = redis.hsetex("myhash", "field1", "Hello", ex=60)
assert result == 1
```

```py Multiple Fields
# Set fields with 1 hour expiration
result = redis.hsetex(
    "user:123",
    values={"name": "John", "email": "john@example.com"},
    ex=3600
)
assert result == 2
```

```py With FNX (only if hash doesn't exist)
# Set fields only if the hash doesn't exist
result = redis.hsetex(
    "user:456",
    values={"name": "Jane", "age": "25"},
    fnx=True
)
assert result == 2

# Try again - will return 0 since hash now exists
result = redis.hsetex(
    "user:456",
    values={"email": "jane@example.com"},
    fnx=True
)
assert result == 0
```

```py With FXX (only if hash exists)
# First create the hash
redis.hset("session:abc", "token", "xyz")

# Update only if hash exists
result = redis.hsetex(
    "session:abc",
    values={"user": "john"},
    fxx=True
)
assert result == 1  # Hash exists, field added

# Try on non-existent hash
result = redis.hsetex(
    "session:nonexistent",
    values={"user": "jane"},
    fxx=True
)
assert result == 0  # Hash doesn't exist
```

```py With PX (milliseconds)
import time

# Set fields with 30 second expiration
result = redis.hsetex(
    "cache:data",
    values={"value": "cached data", "timestamp": str(int(time.time()))},
    px=30000
)
assert result == 2
```

```py With EXAT (Unix timestamp in seconds)
import time

# Set expiration to specific timestamp
future_time = int(time.time()) + 7200  # 2 hours from now
result = redis.hsetex(
    "temp:data",
    values={"info": "temporary information"},
    exat=future_time
)
assert result == 1
```

```py With PXAT (Unix timestamp in milliseconds)
import time

# Set expiration to specific timestamp in milliseconds
future_time = int(time.time() * 1000) + 300000  # 5 minutes from now
result = redis.hsetex(
    "session:xyz",
    values={"token": "abc123", "user": "john"},
    pxat=future_time
)
assert result == 2
```

```py Combined: Conditional + Expiration
import time

# Set fields only if hash doesn't exist, with 1 hour expiration
result = redis.hsetex(
    "user:789",
    values={
        "name": "Alice",
        "email": "alice@example.com",
        "created": str(int(time.time()))
    },
    fnx=True,
    ex=3600
)
assert result == 3
```

```py With KEEPTTL
# First set fields with expiration
redis.hsetex("cache:data", values={"value": "cached"}, ex=300)

# Later update fields while retaining the existing TTL
result = redis.hsetex("cache:data", values={"updated": "yes"}, keepttl=True)
assert result == 1

# Verify TTL is still 300 seconds (or less if time passed)
ttl = redis.ttl("cache:data")
assert ttl > 0 and ttl <= 300  # TTL was retained
```

```py Without Options
# Just set fields without expiration or conditions
result = redis.hsetex(
    "data:simple",
    values={"field1": "value1", "field2": "value2"}
)
assert result == 2
```
</RequestExample>

## Use Cases

- **Session Management**: Create sessions with automatic expiration
- **Cache with TTL**: Store cached data that expires automatically
- **Temporary Data**: Create temporary records with built-in cleanup
- **Rate Limiting**: Store rate limit counters with automatic reset
- **Conditional Updates**: Ensure data consistency with FNX/FXX options
