...

Source file src/github.com/redis/go-redis/v9/hash_commands.go

Documentation: github.com/redis/go-redis/v9

     1  package redis
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"github.com/redis/go-redis/v9/internal/hashtag"
     8  )
     9  
    10  type HashCmdable interface {
    11  	HDel(ctx context.Context, key string, fields ...string) *IntCmd
    12  	HExists(ctx context.Context, key, field string) *BoolCmd
    13  	HGet(ctx context.Context, key, field string) *StringCmd
    14  	HGetAll(ctx context.Context, key string) *MapStringStringCmd
    15  	HGetDel(ctx context.Context, key string, fields ...string) *StringSliceCmd
    16  	HGetEX(ctx context.Context, key string, fields ...string) *StringSliceCmd
    17  	HGetEXWithArgs(ctx context.Context, key string, options *HGetEXOptions, fields ...string) *StringSliceCmd
    18  	HIncrBy(ctx context.Context, key, field string, incr int64) *IntCmd
    19  	HIncrByFloat(ctx context.Context, key, field string, incr float64) *FloatCmd
    20  	HKeys(ctx context.Context, key string) *StringSliceCmd
    21  	HLen(ctx context.Context, key string) *IntCmd
    22  	HMGet(ctx context.Context, key string, fields ...string) *SliceCmd
    23  	HSet(ctx context.Context, key string, values ...interface{}) *IntCmd
    24  	HMSet(ctx context.Context, key string, values ...interface{}) *BoolCmd
    25  	HSetEX(ctx context.Context, key string, fieldsAndValues ...string) *IntCmd
    26  	HSetEXWithArgs(ctx context.Context, key string, options *HSetEXOptions, fieldsAndValues ...string) *IntCmd
    27  	HSetNX(ctx context.Context, key, field string, value interface{}) *BoolCmd
    28  	HScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
    29  	HScanNoValues(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
    30  	HVals(ctx context.Context, key string) *StringSliceCmd
    31  	HRandField(ctx context.Context, key string, count int) *StringSliceCmd
    32  	HRandFieldWithValues(ctx context.Context, key string, count int) *KeyValueSliceCmd
    33  	HStrLen(ctx context.Context, key, field string) *IntCmd
    34  	HExpire(ctx context.Context, key string, expiration time.Duration, fields ...string) *IntSliceCmd
    35  	HExpireWithArgs(ctx context.Context, key string, expiration time.Duration, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd
    36  	HPExpire(ctx context.Context, key string, expiration time.Duration, fields ...string) *IntSliceCmd
    37  	HPExpireWithArgs(ctx context.Context, key string, expiration time.Duration, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd
    38  	HExpireAt(ctx context.Context, key string, tm time.Time, fields ...string) *IntSliceCmd
    39  	HExpireAtWithArgs(ctx context.Context, key string, tm time.Time, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd
    40  	HPExpireAt(ctx context.Context, key string, tm time.Time, fields ...string) *IntSliceCmd
    41  	HPExpireAtWithArgs(ctx context.Context, key string, tm time.Time, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd
    42  	HPersist(ctx context.Context, key string, fields ...string) *IntSliceCmd
    43  	HExpireTime(ctx context.Context, key string, fields ...string) *IntSliceCmd
    44  	HPExpireTime(ctx context.Context, key string, fields ...string) *IntSliceCmd
    45  	HTTL(ctx context.Context, key string, fields ...string) *IntSliceCmd
    46  	HPTTL(ctx context.Context, key string, fields ...string) *IntSliceCmd
    47  }
    48  
    49  func (c cmdable) HDel(ctx context.Context, key string, fields ...string) *IntCmd {
    50  	args := make([]interface{}, 2+len(fields))
    51  	args[0] = "hdel"
    52  	args[1] = key
    53  	for i, field := range fields {
    54  		args[2+i] = field
    55  	}
    56  	cmd := NewIntCmd(ctx, args...)
    57  	_ = c(ctx, cmd)
    58  	return cmd
    59  }
    60  
    61  func (c cmdable) HExists(ctx context.Context, key, field string) *BoolCmd {
    62  	cmd := NewBoolCmd(ctx, "hexists", key, field)
    63  	_ = c(ctx, cmd)
    64  	return cmd
    65  }
    66  
    67  func (c cmdable) HGet(ctx context.Context, key, field string) *StringCmd {
    68  	cmd := NewStringCmd(ctx, "hget", key, field)
    69  	_ = c(ctx, cmd)
    70  	return cmd
    71  }
    72  
    73  func (c cmdable) HGetAll(ctx context.Context, key string) *MapStringStringCmd {
    74  	cmd := NewMapStringStringCmd(ctx, "hgetall", key)
    75  	_ = c(ctx, cmd)
    76  	return cmd
    77  }
    78  
    79  func (c cmdable) HIncrBy(ctx context.Context, key, field string, incr int64) *IntCmd {
    80  	cmd := NewIntCmd(ctx, "hincrby", key, field, incr)
    81  	_ = c(ctx, cmd)
    82  	return cmd
    83  }
    84  
    85  func (c cmdable) HIncrByFloat(ctx context.Context, key, field string, incr float64) *FloatCmd {
    86  	cmd := NewFloatCmd(ctx, "hincrbyfloat", key, field, incr)
    87  	_ = c(ctx, cmd)
    88  	return cmd
    89  }
    90  
    91  func (c cmdable) HKeys(ctx context.Context, key string) *StringSliceCmd {
    92  	cmd := NewStringSliceCmd(ctx, "hkeys", key)
    93  	_ = c(ctx, cmd)
    94  	return cmd
    95  }
    96  
    97  func (c cmdable) HLen(ctx context.Context, key string) *IntCmd {
    98  	cmd := NewIntCmd(ctx, "hlen", key)
    99  	_ = c(ctx, cmd)
   100  	return cmd
   101  }
   102  
   103  // HMGet returns the values for the specified fields in the hash stored at key.
   104  // It returns an interface{} to distinguish between empty string and nil value.
   105  func (c cmdable) HMGet(ctx context.Context, key string, fields ...string) *SliceCmd {
   106  	args := make([]interface{}, 2+len(fields))
   107  	args[0] = "hmget"
   108  	args[1] = key
   109  	for i, field := range fields {
   110  		args[2+i] = field
   111  	}
   112  	cmd := NewSliceCmd(ctx, args...)
   113  	_ = c(ctx, cmd)
   114  	return cmd
   115  }
   116  
   117  // HSet accepts values in following formats:
   118  //
   119  //   - HSet("myhash", "key1", "value1", "key2", "value2")
   120  //
   121  //   - HSet("myhash", []string{"key1", "value1", "key2", "value2"})
   122  //
   123  //   - HSet("myhash", map[string]interface{}{"key1": "value1", "key2": "value2"})
   124  //
   125  //     Playing struct With "redis" tag.
   126  //     type MyHash struct { Key1 string `redis:"key1"`; Key2 int `redis:"key2"` }
   127  //
   128  //   - HSet("myhash", MyHash{"value1", "value2"}) Warn: redis-server >= 4.0
   129  //
   130  //     For struct, can be a structure pointer type, we only parse the field whose tag is redis.
   131  //     if you don't want the field to be read, you can use the `redis:"-"` flag to ignore it,
   132  //     or you don't need to set the redis tag.
   133  //     For the type of structure field, we only support simple data types:
   134  //     string, int/uint(8,16,32,64), float(32,64), time.Time(to RFC3339Nano), time.Duration(to Nanoseconds ),
   135  //     if you are other more complex or custom data types, please implement the encoding.BinaryMarshaler interface.
   136  //
   137  // Note that in older versions of Redis server(redis-server < 4.0), HSet only supports a single key-value pair.
   138  // redis-docs: https://redis.io/commands/hset (Starting with Redis version 4.0.0: Accepts multiple field and value arguments.)
   139  // If you are using a Struct type and the number of fields is greater than one,
   140  // you will receive an error similar to "ERR wrong number of arguments", you can use HMSet as a substitute.
   141  func (c cmdable) HSet(ctx context.Context, key string, values ...interface{}) *IntCmd {
   142  	args := make([]interface{}, 2, 2+len(values))
   143  	args[0] = "hset"
   144  	args[1] = key
   145  	args = appendArgs(args, values)
   146  	cmd := NewIntCmd(ctx, args...)
   147  	_ = c(ctx, cmd)
   148  	return cmd
   149  }
   150  
   151  // HMSet is a deprecated version of HSet left for compatibility with Redis 3.
   152  func (c cmdable) HMSet(ctx context.Context, key string, values ...interface{}) *BoolCmd {
   153  	args := make([]interface{}, 2, 2+len(values))
   154  	args[0] = "hmset"
   155  	args[1] = key
   156  	args = appendArgs(args, values)
   157  	cmd := NewBoolCmd(ctx, args...)
   158  	_ = c(ctx, cmd)
   159  	return cmd
   160  }
   161  
   162  func (c cmdable) HSetNX(ctx context.Context, key, field string, value interface{}) *BoolCmd {
   163  	cmd := NewBoolCmd(ctx, "hsetnx", key, field, value)
   164  	_ = c(ctx, cmd)
   165  	return cmd
   166  }
   167  
   168  func (c cmdable) HVals(ctx context.Context, key string) *StringSliceCmd {
   169  	cmd := NewStringSliceCmd(ctx, "hvals", key)
   170  	_ = c(ctx, cmd)
   171  	return cmd
   172  }
   173  
   174  // HRandField redis-server version >= 6.2.0.
   175  func (c cmdable) HRandField(ctx context.Context, key string, count int) *StringSliceCmd {
   176  	cmd := NewStringSliceCmd(ctx, "hrandfield", key, count)
   177  	_ = c(ctx, cmd)
   178  	return cmd
   179  }
   180  
   181  // HRandFieldWithValues redis-server version >= 6.2.0.
   182  func (c cmdable) HRandFieldWithValues(ctx context.Context, key string, count int) *KeyValueSliceCmd {
   183  	cmd := NewKeyValueSliceCmd(ctx, "hrandfield", key, count, "withvalues")
   184  	_ = c(ctx, cmd)
   185  	return cmd
   186  }
   187  
   188  func (c cmdable) HScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd {
   189  	args := []interface{}{"hscan", key, cursor}
   190  	if match != "" {
   191  		args = append(args, "match", match)
   192  	}
   193  	if count > 0 {
   194  		args = append(args, "count", count)
   195  	}
   196  	cmd := NewScanCmd(ctx, c, args...)
   197  	if hashtag.Present(match) {
   198  		cmd.SetFirstKeyPos(4)
   199  	}
   200  	_ = c(ctx, cmd)
   201  	return cmd
   202  }
   203  
   204  func (c cmdable) HStrLen(ctx context.Context, key, field string) *IntCmd {
   205  	cmd := NewIntCmd(ctx, "hstrlen", key, field)
   206  	_ = c(ctx, cmd)
   207  	return cmd
   208  }
   209  func (c cmdable) HScanNoValues(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd {
   210  	args := []interface{}{"hscan", key, cursor}
   211  	if match != "" {
   212  		args = append(args, "match", match)
   213  	}
   214  	if count > 0 {
   215  		args = append(args, "count", count)
   216  	}
   217  	args = append(args, "novalues")
   218  	cmd := NewScanCmd(ctx, c, args...)
   219  	if hashtag.Present(match) {
   220  		cmd.SetFirstKeyPos(4)
   221  	}
   222  	_ = c(ctx, cmd)
   223  	return cmd
   224  }
   225  
   226  type HExpireArgs struct {
   227  	NX bool
   228  	XX bool
   229  	GT bool
   230  	LT bool
   231  }
   232  
   233  // HExpire - Sets the expiration time for specified fields in a hash in seconds.
   234  // The command constructs an argument list starting with "HEXPIRE", followed by the key, duration, any conditional flags, and the specified fields.
   235  // Available since Redis 7.4 CE.
   236  // For more information refer to [HEXPIRE Documentation].
   237  //
   238  // [HEXPIRE Documentation]: https://redis.io/commands/hexpire/
   239  func (c cmdable) HExpire(ctx context.Context, key string, expiration time.Duration, fields ...string) *IntSliceCmd {
   240  	args := []interface{}{"HEXPIRE", key, formatSec(ctx, expiration), "FIELDS", len(fields)}
   241  
   242  	for _, field := range fields {
   243  		args = append(args, field)
   244  	}
   245  	cmd := NewIntSliceCmd(ctx, args...)
   246  	_ = c(ctx, cmd)
   247  	return cmd
   248  }
   249  
   250  // HExpireWithArgs - Sets the expiration time for specified fields in a hash in seconds.
   251  // It requires a key, an expiration duration, a struct with boolean flags for conditional expiration settings (NX, XX, GT, LT), and a list of fields.
   252  // The command constructs an argument list starting with "HEXPIRE", followed by the key, duration, any conditional flags, and the specified fields.
   253  // Available since Redis 7.4 CE.
   254  // For more information refer to [HEXPIRE Documentation].
   255  //
   256  // [HEXPIRE Documentation]: https://redis.io/commands/hexpire/
   257  func (c cmdable) HExpireWithArgs(ctx context.Context, key string, expiration time.Duration, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd {
   258  	args := []interface{}{"HEXPIRE", key, formatSec(ctx, expiration)}
   259  
   260  	// only if one argument is true, we can add it to the args
   261  	// if more than one argument is true, it will cause an error
   262  	if expirationArgs.NX {
   263  		args = append(args, "NX")
   264  	} else if expirationArgs.XX {
   265  		args = append(args, "XX")
   266  	} else if expirationArgs.GT {
   267  		args = append(args, "GT")
   268  	} else if expirationArgs.LT {
   269  		args = append(args, "LT")
   270  	}
   271  
   272  	args = append(args, "FIELDS", len(fields))
   273  
   274  	for _, field := range fields {
   275  		args = append(args, field)
   276  	}
   277  	cmd := NewIntSliceCmd(ctx, args...)
   278  	_ = c(ctx, cmd)
   279  	return cmd
   280  }
   281  
   282  // HPExpire - Sets the expiration time for specified fields in a hash in milliseconds.
   283  // Similar to HExpire, it accepts a key, an expiration duration in milliseconds, a struct with expiration condition flags, and a list of fields.
   284  // The command modifies the standard time.Duration to milliseconds for the Redis command.
   285  // Available since Redis 7.4 CE.
   286  // For more information refer to [HPEXPIRE Documentation].
   287  //
   288  // [HPEXPIRE Documentation]: https://redis.io/commands/hpexpire/
   289  func (c cmdable) HPExpire(ctx context.Context, key string, expiration time.Duration, fields ...string) *IntSliceCmd {
   290  	args := []interface{}{"HPEXPIRE", key, formatMs(ctx, expiration), "FIELDS", len(fields)}
   291  
   292  	for _, field := range fields {
   293  		args = append(args, field)
   294  	}
   295  	cmd := NewIntSliceCmd(ctx, args...)
   296  	_ = c(ctx, cmd)
   297  	return cmd
   298  }
   299  
   300  // HPExpireWithArgs - Sets the expiration time for specified fields in a hash in milliseconds.
   301  // It requires a key, an expiration duration, a struct with boolean flags for conditional expiration settings (NX, XX, GT, LT), and a list of fields.
   302  // The command constructs an argument list starting with "HPEXPIRE", followed by the key, duration, any conditional flags, and the specified fields.
   303  // Available since Redis 7.4 CE.
   304  // For more information refer to [HPEXPIRE Documentation].
   305  //
   306  // [HPEXPIRE Documentation]: https://redis.io/commands/hpexpire/
   307  func (c cmdable) HPExpireWithArgs(ctx context.Context, key string, expiration time.Duration, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd {
   308  	args := []interface{}{"HPEXPIRE", key, formatMs(ctx, expiration)}
   309  
   310  	// only if one argument is true, we can add it to the args
   311  	// if more than one argument is true, it will cause an error
   312  	if expirationArgs.NX {
   313  		args = append(args, "NX")
   314  	} else if expirationArgs.XX {
   315  		args = append(args, "XX")
   316  	} else if expirationArgs.GT {
   317  		args = append(args, "GT")
   318  	} else if expirationArgs.LT {
   319  		args = append(args, "LT")
   320  	}
   321  
   322  	args = append(args, "FIELDS", len(fields))
   323  
   324  	for _, field := range fields {
   325  		args = append(args, field)
   326  	}
   327  	cmd := NewIntSliceCmd(ctx, args...)
   328  	_ = c(ctx, cmd)
   329  	return cmd
   330  }
   331  
   332  // HExpireAt - Sets the expiration time for specified fields in a hash to a UNIX timestamp in seconds.
   333  // Takes a key, a UNIX timestamp, a struct of conditional flags, and a list of fields.
   334  // The command sets absolute expiration times based on the UNIX timestamp provided.
   335  // Available since Redis 7.4 CE.
   336  // For more information refer to [HExpireAt Documentation].
   337  //
   338  // [HExpireAt Documentation]: https://redis.io/commands/hexpireat/
   339  func (c cmdable) HExpireAt(ctx context.Context, key string, tm time.Time, fields ...string) *IntSliceCmd {
   340  
   341  	args := []interface{}{"HEXPIREAT", key, tm.Unix(), "FIELDS", len(fields)}
   342  
   343  	for _, field := range fields {
   344  		args = append(args, field)
   345  	}
   346  	cmd := NewIntSliceCmd(ctx, args...)
   347  	_ = c(ctx, cmd)
   348  	return cmd
   349  }
   350  
   351  func (c cmdable) HExpireAtWithArgs(ctx context.Context, key string, tm time.Time, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd {
   352  	args := []interface{}{"HEXPIREAT", key, tm.Unix()}
   353  
   354  	// only if one argument is true, we can add it to the args
   355  	// if more than one argument is true, it will cause an error
   356  	if expirationArgs.NX {
   357  		args = append(args, "NX")
   358  	} else if expirationArgs.XX {
   359  		args = append(args, "XX")
   360  	} else if expirationArgs.GT {
   361  		args = append(args, "GT")
   362  	} else if expirationArgs.LT {
   363  		args = append(args, "LT")
   364  	}
   365  
   366  	args = append(args, "FIELDS", len(fields))
   367  
   368  	for _, field := range fields {
   369  		args = append(args, field)
   370  	}
   371  	cmd := NewIntSliceCmd(ctx, args...)
   372  	_ = c(ctx, cmd)
   373  	return cmd
   374  }
   375  
   376  // HPExpireAt - Sets the expiration time for specified fields in a hash to a UNIX timestamp in milliseconds.
   377  // Similar to HExpireAt but for timestamps in milliseconds. It accepts the same parameters and adjusts the UNIX time to milliseconds.
   378  // Available since Redis 7.4 CE.
   379  // For more information refer to [HExpireAt Documentation].
   380  //
   381  // [HExpireAt Documentation]: https://redis.io/commands/hexpireat/
   382  func (c cmdable) HPExpireAt(ctx context.Context, key string, tm time.Time, fields ...string) *IntSliceCmd {
   383  	args := []interface{}{"HPEXPIREAT", key, tm.UnixNano() / int64(time.Millisecond), "FIELDS", len(fields)}
   384  
   385  	for _, field := range fields {
   386  		args = append(args, field)
   387  	}
   388  	cmd := NewIntSliceCmd(ctx, args...)
   389  	_ = c(ctx, cmd)
   390  	return cmd
   391  }
   392  
   393  func (c cmdable) HPExpireAtWithArgs(ctx context.Context, key string, tm time.Time, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd {
   394  	args := []interface{}{"HPEXPIREAT", key, tm.UnixNano() / int64(time.Millisecond)}
   395  
   396  	// only if one argument is true, we can add it to the args
   397  	// if more than one argument is true, it will cause an error
   398  	if expirationArgs.NX {
   399  		args = append(args, "NX")
   400  	} else if expirationArgs.XX {
   401  		args = append(args, "XX")
   402  	} else if expirationArgs.GT {
   403  		args = append(args, "GT")
   404  	} else if expirationArgs.LT {
   405  		args = append(args, "LT")
   406  	}
   407  
   408  	args = append(args, "FIELDS", len(fields))
   409  
   410  	for _, field := range fields {
   411  		args = append(args, field)
   412  	}
   413  	cmd := NewIntSliceCmd(ctx, args...)
   414  	_ = c(ctx, cmd)
   415  	return cmd
   416  }
   417  
   418  // HPersist - Removes the expiration time from specified fields in a hash.
   419  // Accepts a key and the fields themselves.
   420  // This command ensures that each field specified will have its expiration removed if present.
   421  // Available since Redis 7.4 CE.
   422  // For more information refer to [HPersist Documentation].
   423  //
   424  // [HPersist Documentation]: https://redis.io/commands/hpersist/
   425  func (c cmdable) HPersist(ctx context.Context, key string, fields ...string) *IntSliceCmd {
   426  	args := []interface{}{"HPERSIST", key, "FIELDS", len(fields)}
   427  
   428  	for _, field := range fields {
   429  		args = append(args, field)
   430  	}
   431  	cmd := NewIntSliceCmd(ctx, args...)
   432  	_ = c(ctx, cmd)
   433  	return cmd
   434  }
   435  
   436  // HExpireTime - Retrieves the expiration time for specified fields in a hash as a UNIX timestamp in seconds.
   437  // Requires a key and the fields themselves to fetch their expiration timestamps.
   438  // This command returns the expiration times for each field or error/status codes for each field as specified.
   439  // Available since Redis 7.4 CE.
   440  // For more information refer to [HExpireTime Documentation].
   441  //
   442  // [HExpireTime Documentation]: https://redis.io/commands/hexpiretime/
   443  // For more information - https://redis.io/commands/hexpiretime/
   444  func (c cmdable) HExpireTime(ctx context.Context, key string, fields ...string) *IntSliceCmd {
   445  	args := []interface{}{"HEXPIRETIME", key, "FIELDS", len(fields)}
   446  
   447  	for _, field := range fields {
   448  		args = append(args, field)
   449  	}
   450  	cmd := NewIntSliceCmd(ctx, args...)
   451  	_ = c(ctx, cmd)
   452  	return cmd
   453  }
   454  
   455  // HPExpireTime - Retrieves the expiration time for specified fields in a hash as a UNIX timestamp in milliseconds.
   456  // Similar to HExpireTime, adjusted for timestamps in milliseconds. It requires the same parameters.
   457  // Provides the expiration timestamp for each field in milliseconds.
   458  // Available since Redis 7.4 CE.
   459  // For more information refer to [HExpireTime Documentation].
   460  //
   461  // [HExpireTime Documentation]: https://redis.io/commands/hexpiretime/
   462  // For more information - https://redis.io/commands/hexpiretime/
   463  func (c cmdable) HPExpireTime(ctx context.Context, key string, fields ...string) *IntSliceCmd {
   464  	args := []interface{}{"HPEXPIRETIME", key, "FIELDS", len(fields)}
   465  
   466  	for _, field := range fields {
   467  		args = append(args, field)
   468  	}
   469  	cmd := NewIntSliceCmd(ctx, args...)
   470  	_ = c(ctx, cmd)
   471  	return cmd
   472  }
   473  
   474  // HTTL - Retrieves the remaining time to live for specified fields in a hash in seconds.
   475  // Requires a key and the fields themselves. It returns the TTL for each specified field.
   476  // This command fetches the TTL in seconds for each field or returns error/status codes as appropriate.
   477  // Available since Redis 7.4 CE.
   478  // For more information refer to [HTTL Documentation].
   479  //
   480  // [HTTL Documentation]: https://redis.io/commands/httl/
   481  func (c cmdable) HTTL(ctx context.Context, key string, fields ...string) *IntSliceCmd {
   482  	args := []interface{}{"HTTL", key, "FIELDS", len(fields)}
   483  
   484  	for _, field := range fields {
   485  		args = append(args, field)
   486  	}
   487  	cmd := NewIntSliceCmd(ctx, args...)
   488  	_ = c(ctx, cmd)
   489  	return cmd
   490  }
   491  
   492  // HPTTL - Retrieves the remaining time to live for specified fields in a hash in milliseconds.
   493  // Similar to HTTL, but returns the TTL in milliseconds. It requires a key and the specified fields.
   494  // This command provides the TTL in milliseconds for each field or returns error/status codes as needed.
   495  // Available since Redis 7.4 CE.
   496  // For more information refer to [HPTTL Documentation].
   497  //
   498  // [HPTTL Documentation]: https://redis.io/commands/hpttl/
   499  // For more information - https://redis.io/commands/hpttl/
   500  func (c cmdable) HPTTL(ctx context.Context, key string, fields ...string) *IntSliceCmd {
   501  	args := []interface{}{"HPTTL", key, "FIELDS", len(fields)}
   502  
   503  	for _, field := range fields {
   504  		args = append(args, field)
   505  	}
   506  	cmd := NewIntSliceCmd(ctx, args...)
   507  	_ = c(ctx, cmd)
   508  	return cmd
   509  }
   510  
   511  func (c cmdable) HGetDel(ctx context.Context, key string, fields ...string) *StringSliceCmd {
   512  	args := []interface{}{"HGETDEL", key, "FIELDS", len(fields)}
   513  	for _, field := range fields {
   514  		args = append(args, field)
   515  	}
   516  	cmd := NewStringSliceCmd(ctx, args...)
   517  	_ = c(ctx, cmd)
   518  	return cmd
   519  }
   520  
   521  func (c cmdable) HGetEX(ctx context.Context, key string, fields ...string) *StringSliceCmd {
   522  	args := []interface{}{"HGETEX", key, "FIELDS", len(fields)}
   523  	for _, field := range fields {
   524  		args = append(args, field)
   525  	}
   526  	cmd := NewStringSliceCmd(ctx, args...)
   527  	_ = c(ctx, cmd)
   528  	return cmd
   529  }
   530  
   531  // HGetEXExpirationType represents an expiration option for the HGETEX command.
   532  type HGetEXExpirationType string
   533  
   534  const (
   535  	HGetEXExpirationEX      HGetEXExpirationType = "EX"
   536  	HGetEXExpirationPX      HGetEXExpirationType = "PX"
   537  	HGetEXExpirationEXAT    HGetEXExpirationType = "EXAT"
   538  	HGetEXExpirationPXAT    HGetEXExpirationType = "PXAT"
   539  	HGetEXExpirationPERSIST HGetEXExpirationType = "PERSIST"
   540  )
   541  
   542  type HGetEXOptions struct {
   543  	ExpirationType HGetEXExpirationType
   544  	ExpirationVal  int64
   545  }
   546  
   547  func (c cmdable) HGetEXWithArgs(ctx context.Context, key string, options *HGetEXOptions, fields ...string) *StringSliceCmd {
   548  	args := []interface{}{"HGETEX", key}
   549  	if options.ExpirationType != "" {
   550  		args = append(args, string(options.ExpirationType))
   551  		if options.ExpirationType != HGetEXExpirationPERSIST {
   552  			args = append(args, options.ExpirationVal)
   553  		}
   554  	}
   555  
   556  	args = append(args, "FIELDS", len(fields))
   557  	for _, field := range fields {
   558  		args = append(args, field)
   559  	}
   560  
   561  	cmd := NewStringSliceCmd(ctx, args...)
   562  	_ = c(ctx, cmd)
   563  	return cmd
   564  }
   565  
   566  type HSetEXCondition string
   567  
   568  const (
   569  	HSetEXFNX HSetEXCondition = "FNX" // Only set the fields if none of them already exist.
   570  	HSetEXFXX HSetEXCondition = "FXX" // Only set the fields if all already exist.
   571  )
   572  
   573  type HSetEXExpirationType string
   574  
   575  const (
   576  	HSetEXExpirationEX      HSetEXExpirationType = "EX"
   577  	HSetEXExpirationPX      HSetEXExpirationType = "PX"
   578  	HSetEXExpirationEXAT    HSetEXExpirationType = "EXAT"
   579  	HSetEXExpirationPXAT    HSetEXExpirationType = "PXAT"
   580  	HSetEXExpirationKEEPTTL HSetEXExpirationType = "KEEPTTL"
   581  )
   582  
   583  type HSetEXOptions struct {
   584  	Condition      HSetEXCondition
   585  	ExpirationType HSetEXExpirationType
   586  	ExpirationVal  int64
   587  }
   588  
   589  func (c cmdable) HSetEX(ctx context.Context, key string, fieldsAndValues ...string) *IntCmd {
   590  	args := []interface{}{"HSETEX", key, "FIELDS", len(fieldsAndValues) / 2}
   591  	for _, field := range fieldsAndValues {
   592  		args = append(args, field)
   593  	}
   594  
   595  	cmd := NewIntCmd(ctx, args...)
   596  	_ = c(ctx, cmd)
   597  	return cmd
   598  }
   599  
   600  func (c cmdable) HSetEXWithArgs(ctx context.Context, key string, options *HSetEXOptions, fieldsAndValues ...string) *IntCmd {
   601  	args := []interface{}{"HSETEX", key}
   602  	if options.Condition != "" {
   603  		args = append(args, string(options.Condition))
   604  	}
   605  	if options.ExpirationType != "" {
   606  		args = append(args, string(options.ExpirationType))
   607  		if options.ExpirationType != HSetEXExpirationKEEPTTL {
   608  			args = append(args, options.ExpirationVal)
   609  		}
   610  	}
   611  	args = append(args, "FIELDS", len(fieldsAndValues)/2)
   612  	for _, field := range fieldsAndValues {
   613  		args = append(args, field)
   614  	}
   615  
   616  	cmd := NewIntCmd(ctx, args...)
   617  	_ = c(ctx, cmd)
   618  	return cmd
   619  }
   620  

View as plain text