Skip to content

Commit

Permalink
Go: ZDiff command added
Browse files Browse the repository at this point in the history
Signed-off-by: Prateek Kumar <prateek.kumar@improving.com>
  • Loading branch information
prateek-kumar-improving committed Jan 31, 2025
1 parent 41f423e commit 7f04100
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 0 deletions.
68 changes: 68 additions & 0 deletions go/api/base_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7011,3 +7011,71 @@ func (client *baseClient) Time() ([]string, error) {
}
return handleStringArrayResponse(result)
}

// Returns the difference between the first sorted set and all the successive sorted sets.<br>
// To get the elements with their scores, see `ZDiffWithScores`
// When in cluster mode, all `keys` must map to the same hash slot.
// Valkey 6.2 and above.
//
// See [valkey.io] for details.
//
// Parameters:
//
// keys - The keys of the sorted sets.
//
// Return value:
//
// An array of elements representing the difference between the sorted sets.
// If the first `key` does not exist, it is treated as an empty sorted set, and the
// command returns an empty array.
//
// Example:
//
// zAddResult1, err := client.ZAdd(key1, membersScores1)
// zAddResult2, err := client.ZAdd(key2, membersScores2)
// zDiffResult, err := client.ZDiff([]string{key1, key2})
// fmt.Println(zDiffResult) // Output: {"one", "three"}
//
// [valkey.io]: https://valkey.io/commands/zdiff/
func (client *baseClient) ZDiff(keys []string) ([]string, error) {
args := append([]string{}, strconv.Itoa(len(keys)))
result, err := client.executeCommand(C.ZDiff, append(args, keys...))
if err != nil {
return nil, err
}
return handleStringArrayResponse(result)
}

// Returns the difference between the first sorted set and all the successive sorted sets.
// When in cluster mode, all `keys` must map to the same hash slot.
// Valkey 6.2 and above.
//
// See [valkey.io] for details.
//
// Parameters:
//
// keys - The keys of the sorted sets.
//
// Return value:
//
// A `Map` of elements and their scores representing the difference between the sorted sets.
// If the first `key` does not exist, it is treated as an empty sorted set, and the
// command returns an empty `Map`.
//
// Example:
//
// zAddResult1, err := client.ZAdd(key1, membersScores1)
// zAddResult2, err := client.ZAdd(key2, membersScores2)
// zDiffResultWithScores, err := client.ZDiffWithScores([]string{key1, key2})
// fmt.Println(zDiffResultWithScores) // Output: {"one": 1.0, "three": 3.0}
//
// [valkey.io]: https://valkey.io/commands/zdiff/
func (client *baseClient) ZDiffWithScores(keys []string) (map[string]float64, error) {
args := append([]string{}, strconv.Itoa(len(keys)))
args = append(args, keys...)
result, err := client.executeCommand(C.ZDiff, append(args, options.WithScores))
if err != nil {
return nil, err
}
return handleStringDoubleMapResponse(result)
}
1 change: 1 addition & 0 deletions go/api/options/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const (
WithScore string = "WITHSCORE" // Valkey API keyword for the with score option for zrank and zrevrank commands.
NoScores string = "NOSCORES" // Valkey API keyword for the no scores option for zscan command.
WithValues string = "WITHVALUES" // Valkey API keyword to query hash values along their names in `HRANDFIELD`.
WithScores string = "WITHSCORES" // Valkey API keyword for the with scores option for zdiff command.
)

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

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

ZDiff(keys []string) ([]string, error)

ZDiffWithScores(keys []string) (map[string]float64, error)
}
70 changes: 70 additions & 0 deletions go/integTest/shared_commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7694,3 +7694,73 @@ func (suite *GlideTestSuite) TestBitFieldRO_MultipleGets() {
assert.Equal(suite.T(), []int64{value1, value2}, []int64{getRO[0].Value(), getRO[1].Value()})
})
}

func (suite *GlideTestSuite) TestZDiff() {
suite.runWithDefaultClients(func(client api.BaseClient) {
suite.SkipIfServerVersionLowerThanBy("6.2.0")
t := suite.T()
key1 := "{testKey}:1-" + uuid.NewString()
key2 := "{testKey}:2-" + uuid.NewString()
key3 := "{testKey}:3-" + uuid.NewString()
nonExistentKey := "{testKey}:4-" + uuid.NewString()

membersScores1 := map[string]float64{
"one": 1.0,
"two": 2.0,
"three": 3.0,
}

membersScores2 := map[string]float64{
"two": 2.0,
}

membersScores3 := map[string]float64{
"one": 1.0,
"two": 2.0,
"three": 3.0,
"four": 4.0,
}

zAddResult1, err := client.ZAdd(key1, membersScores1)
assert.NoError(t, err)
assert.Equal(t, int64(3), zAddResult1)
zAddResult2, err := client.ZAdd(key2, membersScores2)
assert.NoError(t, err)
assert.Equal(t, int64(1), zAddResult2)
zAddResult3, err := client.ZAdd(key3, membersScores3)
assert.NoError(t, err)
assert.Equal(t, int64(4), zAddResult3)

zDiffResult, err := client.ZDiff([]string{key1, key2})
assert.NoError(t, err)
assert.Equal(t, []string{"one", "three"}, zDiffResult)
zDiffResult, err = client.ZDiff([]string{key1, key3})
assert.NoError(t, err)
assert.Equal(t, []string{}, zDiffResult)
zDiffResult, err = client.ZDiff([]string{nonExistentKey, key3})
assert.NoError(t, err)
assert.Equal(t, []string{}, zDiffResult)

zDiffResultWithScores, err := client.ZDiffWithScores([]string{key1, key2})
assert.NoError(t, err)
assert.Equal(t, map[string]float64{"one": 1.0, "three": 3.0}, zDiffResultWithScores)
zDiffResultWithScores, err = client.ZDiffWithScores([]string{key1, key3})
assert.NoError(t, err)
assert.Equal(t, map[string]float64{}, zDiffResultWithScores)
zDiffResultWithScores, err = client.ZDiffWithScores([]string{nonExistentKey, key3})
assert.NoError(t, err)
assert.Equal(t, map[string]float64{}, zDiffResultWithScores)

// Key exists, but it is not a set
setResult, err := client.Set(nonExistentKey, "bar")
assert.Equal(t, setResult, "OK")

zDiffResult, err = client.ZDiff([]string{nonExistentKey, key2})
assert.NotNil(t, err)
assert.IsType(t, &errors.RequestError{}, err)

zDiffResultWithScores, err = client.ZDiffWithScores([]string{nonExistentKey, key2})
assert.NotNil(t, err)
assert.IsType(t, &errors.RequestError{}, err)
})
}

0 comments on commit 7f04100

Please sign in to comment.