forked from DiceDB/dice
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DiceDB#1128: Added support for ZPOPMIN (DiceDB#1143)
- Loading branch information
Showing
11 changed files
with
740 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
--- | ||
title: ZPOPMIN | ||
description: The `ZPOPMIN` command in DiceDB is used to remove and return the members with the lowest scores from the sorted set data structure at the specified key. If a count is provided, it returns up to that number of members with the lowest scores, removing them from the set. | ||
--- | ||
|
||
The `ZPOPMIN` command in DiceDB is used to remove and return the members with the lowest scores from the sorted set data structure at the specified key. If a count is provided, it returns up to that number of members with the lowest scores, removing them from the set. | ||
|
||
## Syntax | ||
|
||
``` | ||
ZPOPMIN key [count] | ||
``` | ||
|
||
## Parameters | ||
|
||
| Parameter | Description | Type | Required | | ||
|------------|----------------------------------------------------------------------------------------------|---------|----------| | ||
| `key` | The name of the sorted set data structure. If it does not exist, an empty array is returned. | String | Yes | | ||
| `count` | The count argument specifies the maximum number of members to return with the lowest scores. | Integer | No | | ||
|
||
## Return values | ||
|
||
| Condition | Return Value | | ||
|----------------------------------------------------------|------------------------------------------| | ||
| If the key is of valid type and records are present | List of members including their scores | | ||
| If the key does not exist or if the sorted set is empty | `(empty list or set)` | | ||
|
||
## Behaviour | ||
|
||
- The command first checks if the specified key exists. | ||
- If the key does not exist, an empty array is returned. | ||
- If the key exists but is not a sorted set, an error is returned. | ||
- If the `count` argument is specified, up to that number of members with the lowest scores are returned and removed. | ||
- The returned array contains the members and their corresponding scores in the order of lowest to highest. | ||
|
||
## Errors | ||
1. `Wrong type error`: | ||
- Error Message: `(error) WRONGTYPE Operation against a key holding the wrong kind of value` | ||
- Occurs when trying to use the command on a key that is not a sorted set. | ||
|
||
2. `Syntax error`: | ||
- Error Message: `(error) ERROR wrong number of arguments for 'zpopmin' command` | ||
- Occurs when the command syntax is incorrect or missing required parameters. | ||
|
||
3. `Invalid argument type error`: | ||
- Error Message : `(error) ERR value is not an integer or out of range` | ||
- Occurs when the count argument passed to the command is not an integer. | ||
|
||
## Examples | ||
|
||
### Non-Existing Key (without count argument) | ||
|
||
Attempting to pop the member with the lowest score from a non-existent sorted set: | ||
|
||
```bash | ||
127.0.0.1:7379> ZPOPMIN NON_EXISTENT_KEY | ||
(empty array) | ||
``` | ||
|
||
### Existing Key (without count argument) | ||
|
||
Popping the member with the lowest score from an existing sorted set: | ||
|
||
```bash | ||
127.0.0.1:7379> ZADD myzset 1 member1 2 member2 3 member3 | ||
(integer) 3 | ||
127.0.0.1:7379> ZPOPMIN myzset | ||
1) 1 "member1" | ||
``` | ||
|
||
### With Count Argument | ||
|
||
Popping multiple members with the lowest scores using the count argument: | ||
|
||
```bash | ||
127.0.0.1:7379> ZADD myzset 1 member1 2 member2 3 member3 | ||
(integer) 3 | ||
127.0.0.1:7379> ZPOPMIN myzset 2 | ||
1) 1 "member1" | ||
2) 2 "member2" | ||
``` | ||
|
||
### Count Argument but Multiple Members Have the Same Score | ||
|
||
Popping members when multiple members share the same score: | ||
|
||
```bash | ||
127.0.0.1:7379> ZADD myzset 1 member1 1 member2 1 member3 | ||
(integer) 3 | ||
127.0.0.1:7379> ZPOPMIN myzset 2 | ||
1) 1 "member1" | ||
2) 1 "member2" | ||
``` | ||
|
||
### Negative Count Argument | ||
|
||
Attempting to pop members using a negative count argument: | ||
|
||
```bash | ||
127.0.0.1:7379> ZADD myzset 1 member1 2 member2 3 member3 | ||
(integer) 3 | ||
127.0.0.1:7379> ZPOPMIN myzset -1 | ||
(empty array) | ||
``` | ||
|
||
### Floating-Point Scores | ||
|
||
Popping members with floating-point scores: | ||
|
||
```bash | ||
127.0.0.1:7379> ZADD myzset 1.5 member1 2.7 member2 3.8 member3 | ||
(integer) 3 | ||
127.0.0.1:7379> ZPOPMIN myzset | ||
1) 1.5 "member1" | ||
``` | ||
|
||
### Wrong number of arguments | ||
|
||
Attempting to pop from a key that is not a sorted set: | ||
|
||
```bash | ||
127.0.0.1:7379> SET stringkey "string_value" | ||
OK | ||
127.0.0.1:7379> ZPOPMIN stringkey | ||
(error) WRONGTYPE Operation against a key holding the wrong kind of value | ||
``` | ||
|
||
### Invalid Count Argument | ||
|
||
Using an invalid (non-integer) count argument: | ||
|
||
```bash | ||
127.0.0.1:7379> ZADD myzset 1 member1 | ||
(integer) 1 | ||
127.0.0.1:7379> ZPOPMIN myzset INCORRECT_COUNT_ARGUMENT | ||
(error) ERR value is not an integer or out of range | ||
``` | ||
|
||
### Wrong Type of Key (without count argument) | ||
|
||
Attempting to pop from a key that is not a sorted set: | ||
|
||
```bash | ||
127.0.0.1:7379> SET stringkey "string_value" | ||
OK | ||
127.0.0.1:7379> ZPOPMIN stringkey | ||
(error) WRONGTYPE Operation against a key holding the wrong kind of value | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package http | ||
|
||
import ( | ||
"testing" | ||
|
||
"gotest.tools/v3/assert" | ||
) | ||
|
||
func TestZPOPMIN(t *testing.T) { | ||
exec := NewHTTPCommandExecutor() | ||
testCases := []TestCase{ | ||
{ | ||
name: "ZPOPMIN on non-existing key with/without count argument", | ||
commands: []HTTPCommand{ | ||
{Command: "ZPOPMIN", Body: map[string]interface{}{"key": "NON_EXISTENT_KEY"}}, | ||
}, | ||
expected: []interface{}{[]interface{}{}}, | ||
}, | ||
{ | ||
name: "ZPOPMIN with wrong type of key with/without count argument", | ||
commands: []HTTPCommand{ | ||
{Command: "SET", Body: map[string]interface{}{"key": "stringkey", "value": "string_value"}}, | ||
{Command: "ZPOPMIN", Body: map[string]interface{}{"key": "stringkey"}}, | ||
}, | ||
expected: []interface{}{"OK", "WRONGTYPE Operation against a key holding the wrong kind of value", float64(1)}, | ||
}, | ||
{ | ||
name: "ZPOPMIN on existing key (without count argument)", | ||
commands: []HTTPCommand{ | ||
{Command: "ZADD", Body: map[string]interface{}{"key": "myzset", "values": [...]string{"1", "member1", "2", "member2", "3", "member3"}}}, | ||
{Command: "ZPOPMIN", Body: map[string]interface{}{"key": "myzset"}}, | ||
}, | ||
expected: []interface{}{float64(3), []interface{}{"member1", "1"}, float64(1)}, | ||
}, | ||
{ | ||
name: "ZPOPMIN with normal count argument", | ||
commands: []HTTPCommand{ | ||
{Command: "ZADD", Body: map[string]interface{}{"key": "myzset", "values": [...]string{"1", "member1", "2", "member2", "3", "member3"}}}, | ||
{Command: "ZPOPMIN", Body: map[string]interface{}{"key": "myzset", "value": int64(2)}}, | ||
}, | ||
expected: []interface{}{float64(3), []interface{}{"member1", "1", "member2", "2"}, float64(1)}, | ||
}, | ||
{ | ||
name: "ZPOPMIN with count argument but multiple members have the same score", | ||
commands: []HTTPCommand{ | ||
{Command: "ZADD", Body: map[string]interface{}{"key": "myzset", "values": [...]string{"1", "member1", "1", "member2", "1", "member3"}}}, | ||
{Command: "ZPOPMIN", Body: map[string]interface{}{"key": "myzset", "value": int64(2)}}, | ||
}, | ||
expected: []interface{}{float64(3), []interface{}{"member1", "1", "member2", "1"}, float64(1)}, | ||
}, | ||
{ | ||
name: "ZPOPMIN with negative count argument", | ||
commands: []HTTPCommand{ | ||
{Command: "ZADD", Body: map[string]interface{}{"key": "myzset", "values": [...]string{"1", "member1", "2", "member2", "3", "member3"}}}, | ||
{Command: "ZPOPMIN", Body: map[string]interface{}{"key": "myzset", "value": int64(-1)}}, | ||
}, | ||
expected: []interface{}{float64(3), []interface{}{}, float64(1)}, | ||
}, | ||
{ | ||
name: "ZPOPMIN with invalid count argument", | ||
commands: []HTTPCommand{ | ||
{Command: "ZADD", Body: map[string]interface{}{"key": "myzset", "values": [...]string{"1", "member1"}}}, | ||
{Command: "ZPOPMIN", Body: map[string]interface{}{"key": "myzset", "value": "INCORRECT_COUNT_ARGUMENT"}}, | ||
}, | ||
expected: []interface{}{float64(1), "ERR value is not an integer or out of range", float64(1)}, | ||
}, | ||
{ | ||
name: "ZPOPMIN with count argument greater than length of sorted set", | ||
commands: []HTTPCommand{ | ||
{Command: "ZADD", Body: map[string]interface{}{"key": "myzset", "values": [...]string{"1", "member1", "2", "member2", "3", "member3"}}}, | ||
{Command: "ZPOPMIN", Body: map[string]interface{}{"key": "myzset", "value": int64(10)}}, | ||
}, | ||
expected: []interface{}{float64(3), []interface{}{"member1", "1", "member2", "2", "member3", "3"}, float64(1)}, | ||
}, | ||
{ | ||
name: "ZPOPMIN on empty sorted set", | ||
commands: []HTTPCommand{ | ||
{Command: "ZADD", Body: map[string]interface{}{"key": "myzset", "values": [...]string{"1", "member1"}}}, | ||
{Command: "ZPOPMIN", Body: map[string]interface{}{"key": "myzset", "value": int64(1)}}, | ||
{Command: "ZPOPMIN", Body: map[string]interface{}{"key": "myzset"}}, | ||
}, | ||
expected: []interface{}{float64(1), []interface{}{"member1", "1"}, []interface{}{}, float64(1)}, | ||
}, | ||
{ | ||
name: "ZPOPMIN with floating-point scores", | ||
commands: []HTTPCommand{ | ||
{Command: "ZADD", Body: map[string]interface{}{"key": "myzset", "values": [...]string{"1.5", "member1", "2.7", "member2", "3.8", "member3"}}}, | ||
{Command: "ZPOPMIN", Body: map[string]interface{}{"key": "myzset"}}, | ||
}, | ||
expected: []interface{}{float64(3), []interface{}{"member1", "1.5"}, float64(1)}, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
exec.FireCommand(HTTPCommand{ | ||
Command: "DEL", | ||
Body: map[string]interface{}{"key": "myzset"}, | ||
}) | ||
for i, cmd := range tc.commands { | ||
result, _ := exec.FireCommand(cmd) | ||
|
||
assert.DeepEqual(t, tc.expected[i], result) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.