mirror of
https://github.com/nalgeon/redka.git
synced 2025-11-02 22:14:03 +08:00
refactor: rstring - return a map from GetMany
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package command
|
||||
|
||||
import "github.com/nalgeon/redka"
|
||||
|
||||
// Atomically returns the string values of one or more keys.
|
||||
// MGET key [key ...]
|
||||
// https://redis.io/commands/mget
|
||||
@@ -21,12 +23,22 @@ func parseMGet(b baseCmd) (*MGet, error) {
|
||||
}
|
||||
|
||||
func (cmd *MGet) Run(w Writer, red Redka) (any, error) {
|
||||
vals, err := red.Str().GetMany(cmd.keys...)
|
||||
// Get the key-value map for requested keys.
|
||||
items, err := red.Str().GetMany(cmd.keys...)
|
||||
if err != nil {
|
||||
w.WriteError(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build the result slice.
|
||||
// It will contain all values in the order of keys.
|
||||
// Missing keys will have nil values.
|
||||
vals := make([]redka.Value, len(cmd.keys))
|
||||
for i, key := range cmd.keys {
|
||||
vals[i] = items[key]
|
||||
}
|
||||
|
||||
// Write the result.
|
||||
w.WriteArray(len(vals))
|
||||
for _, v := range vals {
|
||||
if v.IsEmpty() {
|
||||
|
||||
@@ -28,7 +28,7 @@ func (d *DB) Get(key string) (core.Value, error) {
|
||||
}
|
||||
|
||||
// GetMany returns the values of multiple keys.
|
||||
func (d *DB) GetMany(keys ...string) ([]core.Value, error) {
|
||||
func (d *DB) GetMany(keys ...string) (map[string]core.Value, error) {
|
||||
tx := NewTx(d.SQL)
|
||||
return tx.GetMany(keys...)
|
||||
}
|
||||
|
||||
@@ -43,16 +43,22 @@ func TestStringGetMany(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
keys []string
|
||||
want []redka.Value
|
||||
want map[string]redka.Value
|
||||
}{
|
||||
{"all found", []string{"name", "age"},
|
||||
[]redka.Value{redka.Value("alice"), redka.Value("25")},
|
||||
map[string]redka.Value{
|
||||
"name": redka.Value("alice"), "age": redka.Value("25"),
|
||||
},
|
||||
},
|
||||
{"some found", []string{"name", "key1"},
|
||||
[]redka.Value{redka.Value("alice"), redka.Value(nil)},
|
||||
map[string]redka.Value{
|
||||
"name": redka.Value("alice"), "key1": redka.Value(nil),
|
||||
},
|
||||
},
|
||||
{"none found", []string{"key1", "key2"},
|
||||
[]redka.Value{redka.Value(nil), redka.Value(nil)},
|
||||
map[string]redka.Value{
|
||||
"key1": redka.Value(nil), "key2": redka.Value(nil),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -75,7 +75,14 @@ func (tx *Tx) Get(key string) (core.Value, error) {
|
||||
}
|
||||
|
||||
// GetMany returns the values of multiple keys.
|
||||
func (tx *Tx) GetMany(keys ...string) ([]core.Value, error) {
|
||||
func (tx *Tx) GetMany(keys ...string) (map[string]core.Value, error) {
|
||||
// Build a map of requested keys.
|
||||
items := make(map[string]core.Value, len(keys))
|
||||
for _, key := range keys {
|
||||
items[key] = nil
|
||||
}
|
||||
|
||||
// Get the values of the requested keys.
|
||||
now := time.Now().UnixMilli()
|
||||
query, keyArgs := sqlx.ExpandIn(sqlStringGetMany, ":keys", keys)
|
||||
args := slices.Concat(keyArgs, []any{sql.Named("now", now)})
|
||||
@@ -87,29 +94,20 @@ func (tx *Tx) GetMany(keys ...string) ([]core.Value, error) {
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
// Build a map of known keys.
|
||||
// It will be used to fill in the missing keys.
|
||||
known := make(map[string]core.Value, len(keys))
|
||||
// Fill the map with the values for existing keys
|
||||
// (the rest of the keys will remain nil).
|
||||
for rows.Next() {
|
||||
key, val, err := scanValue(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
known[key] = val
|
||||
items[key] = val
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
return nil, rows.Err()
|
||||
}
|
||||
|
||||
// Build the result slice.
|
||||
// It will contain all values in the order of keys.
|
||||
// Missing keys will have nil values.
|
||||
vals := make([]core.Value, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
vals = append(vals, known[key])
|
||||
}
|
||||
|
||||
return vals, nil
|
||||
return items, nil
|
||||
}
|
||||
|
||||
// Set sets the key value. The key does not expire.
|
||||
|
||||
2
redka.go
2
redka.go
@@ -48,7 +48,7 @@ type Keys interface {
|
||||
// Strings is a string repository.
|
||||
type Strings interface {
|
||||
Get(key string) (Value, error)
|
||||
GetMany(keys ...string) ([]Value, error)
|
||||
GetMany(keys ...string) (map[string]Value, error)
|
||||
Set(key string, value any) error
|
||||
SetExpires(key string, value any, ttl time.Duration) error
|
||||
SetNotExists(key string, value any, ttl time.Duration) (bool, error)
|
||||
|
||||
Reference in New Issue
Block a user