Skip to content

Commit

Permalink
Go: ZMSCORE.
Browse files Browse the repository at this point in the history
Signed-off-by: Yury-Fridlyand <[email protected]>
  • Loading branch information
Yury-Fridlyand committed Jan 25, 2025
1 parent 8ba7ccd commit a852c44
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 0 deletions.
30 changes: 30 additions & 0 deletions go/api/base_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5811,6 +5811,36 @@ func (client *baseClient) ZRemRangeByScore(key string, rangeQuery options.RangeB
return handleIntResponse(result)
}

// Returns the scores associated with the specified `members` in the sorted set stored at `key`.
//
// Since:
//
// Valkey 6.2.0 and above.
//
// Parameters:
//
// key - The key of the sorted set.
// members - A list of members in the sorted set.
//
// Return value:
//
// An array of scores corresponding to `members`.
// If a member does not exist in the sorted set, the corresponding value in the list will be `nil`.
//
// Example:
//
// result, err := client.ZMScore(key, []string{"member1", "non_existent_member", "member2"})
// result: [{1.0 false} {0 true} {2.0 false}]
//
// [valkey.io]: https://valkey.io/commands/zmscore/
func (client *baseClient) ZMScore(key string, members []string) ([]Result[float64], error) {
response, err := client.executeCommand(C.ZMScore, append([]string{key}, members...))
if err != nil {
return nil, err
}
return handleFloatOrNilArrayResponse(response)
}

// Returns the logarithmic access frequency counter of a Valkey object stored at key.
//
// Parameters:
Expand Down
27 changes: 27 additions & 0 deletions go/api/response_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,33 @@ func handleFloatOrNilResponse(response *C.struct_CommandResponse) (Result[float6
return CreateFloat64Result(float64(response.float_value)), nil
}

// elements in the array could be `null`, but array isn't
func handleFloatOrNilArrayResponse(response *C.struct_CommandResponse) ([]Result[float64], error) {
defer C.free_command_response(response)

typeErr := checkResponseType(response, C.Array, true)
if typeErr != nil {
return nil, typeErr
}

slice := make([]Result[float64], 0, response.array_value_len)
for _, v := range unsafe.Slice(response.array_value, response.array_value_len) {
if v.response_type == C.Null {
slice = append(slice, CreateNilFloat64Result())
continue
}

err := checkResponseType(&v, C.Float, false)
if err != nil {
return nil, err
}

slice = append(slice, CreateFloat64Result(float64(v.float_value)))
}

return slice, nil
}

func handleLongAndDoubleOrNullResponse(response *C.struct_CommandResponse) (Result[int64], Result[float64], error) {
defer C.free_command_response(response)

Expand Down
2 changes: 2 additions & 0 deletions go/api/sorted_set_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,6 @@ type SortedSetCommands interface {
ZRemRangeByRank(key string, start int64, stop int64) (int64, error)

ZRemRangeByScore(key string, rangeQuery options.RangeByScore) (int64, error)

ZMScore(key string, members []string) ([]Result[float64], error)
}
50 changes: 50 additions & 0 deletions go/integTest/shared_commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6393,6 +6393,56 @@ func (suite *GlideTestSuite) TestZRemRangeByScore() {
})
}

func (suite *GlideTestSuite) TestZMScore() {
suite.SkipIfServerVersionLowerThanBy("6.2.0")
suite.runWithDefaultClients(func(client api.BaseClient) {
key := uuid.NewString()

zAddResult, err := client.ZAdd(key, map[string]float64{"one": 1.0, "two": 2.0, "three": 3.0})
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), int64(3), zAddResult)

res, err := client.ZMScore(key, []string{"one", "three", "two"})
expected := []api.Result[float64]{
api.CreateFloat64Result(1),
api.CreateFloat64Result(3),
api.CreateFloat64Result(2),
}
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), expected, res)

// not existing members
res, err = client.ZMScore(key, []string{"nonExistingMember", "two", "nonExistingMember"})
expected = []api.Result[float64]{
api.CreateNilFloat64Result(),
api.CreateFloat64Result(2),
api.CreateNilFloat64Result(),
}
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), expected, res)

// not existing key
res, err = client.ZMScore(uuid.NewString(), []string{"one", "three", "two"})
expected = []api.Result[float64]{
api.CreateNilFloat64Result(),
api.CreateNilFloat64Result(),
api.CreateNilFloat64Result(),
}
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), expected, res)

// invalid arg - member list must not be empty
_, err = client.ZMScore(key, []string{})
assert.IsType(suite.T(), &errors.RequestError{}, err)

// key exists, but it is not a sorted set
key2 := uuid.NewString()
suite.verifyOK(client.Set(key2, "ZMScore"))
_, err = client.ZMScore(key2, []string{"one"})
assert.IsType(suite.T(), &errors.RequestError{}, err)
})
}

func (suite *GlideTestSuite) TestObjectIdleTime() {
suite.runWithDefaultClients(func(client api.BaseClient) {
defaultClient := suite.defaultClient()
Expand Down

0 comments on commit a852c44

Please sign in to comment.