Skip to content

Commit

Permalink
Node: Add ZINCRBY command (valkey-io#2009)
Browse files Browse the repository at this point in the history
* Node: Add ZINCRBY command

---------

Signed-off-by: Andrew Carbonetto <[email protected]>
  • Loading branch information
acarbonetto authored Jul 25, 2024
1 parent 4e7e7c3 commit b778d35
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* Node: Added FUNCTION FLUSH command ([#1984](https://github.com/valkey-io/valkey-glide/pull/1984))
* Node: Added FCALL and FCALL_RO commands ([#2011](https://github.com/valkey-io/valkey-glide/pull/2011))
* Node: Added ZMPOP command ([#1994](https://github.com/valkey-io/valkey-glide/pull/1994))
* Node: Added ZINCRBY command ([#2009](https://github.com/valkey-io/valkey-glide/pull/2009))

#### Fixes
* Java: Add overloads for XADD to allow duplicate entry keys ([#1970](https://github.com/valkey-io/valkey-glide/pull/1970))
Expand Down
34 changes: 34 additions & 0 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ import {
createZDiff,
createZDiffStore,
createZDiffWithScores,
createZIncrBy,
createZInterCard,
createZInterstore,
createZMPop,
Expand Down Expand Up @@ -3695,6 +3696,39 @@ export class BaseClient {
return this.createWritePromise(createZMPop(key, modifier, count));
}

/**
* Increments the score of `member` in the sorted set stored at `key` by `increment`.
* If `member` does not exist in the sorted set, it is added with `increment` as its score.
* If `key` does not exist, a new sorted set is created with the specified member as its sole member.
*
* See https://valkey.io/commands/zincrby/ for details.
*
* @param key - The key of the sorted set.
* @param increment - The score increment.
* @param member - A member of the sorted set.
*
* @returns The new score of `member`.
*
* @example
* ```typescript
* // Example usage of zincrBy method to increment the value of a member's score
* await client.zadd("my_sorted_set", {"member": 10.5, "member2": 8.2});
* console.log(await client.zincrby("my_sorted_set", 1.2, "member"));
* // Output: 11.7 - The member existed in the set before score was altered, the new score is 11.7.
* console.log(await client.zincrby("my_sorted_set", -1.7, "member"));
* // Output: 10.0 - Negative increment, decrements the score.
* console.log(await client.zincrby("my_sorted_set", 5.5, "non_existing_member"));
* // Output: 5.5 - A new member is added to the sorted set with the score of 5.5.
* ```
*/
public async zincrby(
key: string,
increment: number,
member: string,
): Promise<number> {
return this.createWritePromise(createZIncrBy(key, increment, member));
}

/**
* Returns the distance between `member1` and `member2` saved in the geospatial index stored at `key`.
*
Expand Down
15 changes: 15 additions & 0 deletions node/src/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2082,3 +2082,18 @@ export function createZMPop(

return createCommand(RequestType.ZMPop, args);
}

/**
* @internal
*/
export function createZIncrBy(
key: string,
increment: number,
member: string,
): command_request.Command {
return createCommand(RequestType.ZIncrBy, [
key,
increment.toString(),
member,
]);
}
18 changes: 18 additions & 0 deletions node/src/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ import {
createZRevRank,
createZRevRankWithScore,
createZScore,
createZIncrBy,
} from "./Commands";
import { command_request } from "./ProtobufMessage";
import { BitOffsetOptions } from "./commands/BitOffsetOptions";
Expand Down Expand Up @@ -2181,6 +2182,23 @@ export class BaseTransaction<T extends BaseTransaction<T>> {
return this.addAndReturn(createZMPop(keys, modifier, count));
}

/**
* Increments the score of `member` in the sorted set stored at `key` by `increment`.
* If `member` does not exist in the sorted set, it is added with `increment` as its score.
* If `key` does not exist, a new sorted set is created with the specified member as its sole member.
*
* See https://valkey.io/commands/zincrby/ for details.
*
* @param key - The key of the sorted set.
* @param increment - The score increment.
* @param member - A member of the sorted set.
*
* Command Response - The new score of `member`.
*/
public zincrby(key: string, increment: number, member: string): T {
return this.addAndReturn(createZIncrBy(key, increment, member));
}

/**
* Returns the distance between `member1` and `member2` saved in the geospatial index stored at `key`.
*
Expand Down
33 changes: 33 additions & 0 deletions node/tests/SharedTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4968,6 +4968,39 @@ export function runBaseTests<Context>(config: {
config.timeout,
);

it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
`zincrby test_%p`,
async (protocol) => {
await runTest(async (client: BaseClient) => {
const key = "{key}" + uuidv4();
const member = "{member}-1" + uuidv4();
const othermember = "{member}-1" + uuidv4();
const stringKey = "{key}-string" + uuidv4();

// key does not exist
expect(await client.zincrby(key, 2.5, member)).toEqual(2.5);
expect(await client.zscore(key, member)).toEqual(2.5);

// key exists, but value doesn't
expect(await client.zincrby(key, -3.3, othermember)).toEqual(
-3.3,
);
expect(await client.zscore(key, othermember)).toEqual(-3.3);

// updating existing value in existing key
expect(await client.zincrby(key, 1.0, member)).toEqual(3.5);
expect(await client.zscore(key, member)).toEqual(3.5);

// Key exists, but it is not a sorted set
expect(await client.set(stringKey, "value")).toEqual("OK");
await expect(
client.zincrby(stringKey, 0.5, "_"),
).rejects.toThrow(RequestError);
}, protocol);
},
config.timeout,
);

it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
`geodist test_%p`,
async (protocol) => {
Expand Down
2 changes: 2 additions & 0 deletions node/tests/TestUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,8 @@ export async function transactionTest(

baseTransaction.zaddIncr(key8, "member2", 1);
responseData.push(['zaddIncr(key8, "member2", 1)', 3]);
baseTransaction.zincrby(key8, 0.3, "member1");
responseData.push(['zincrby(key8, 0.3, "member1")', 1.3]);
baseTransaction.zrem(key8, ["member1"]);
responseData.push(['zrem(key8, ["member1"])', 1]);
baseTransaction.zcard(key8);
Expand Down
4 changes: 2 additions & 2 deletions python/python/glide/async_commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -4202,9 +4202,9 @@ async def zincrby(
>>> await client.zincrby("my_sorted_set", 1.2, "member")
11.7 # The member existed in the set before score was altered, the new score is 11.7.
>>> await client.zincrby("my_sorted_set", -1.7, "member")
10.0 # Negetive increment, decrements the score.
10.0 # Negative increment, decrements the score.
>>> await client.zincrby("my_sorted_set", 5.5, "non_existing_member")
5.5 # A new memeber is added to the sorted set with the score being 5.5.
5.5 # A new member is added to the sorted set with the score being 5.5.
"""
return cast(
float,
Expand Down

0 comments on commit b778d35

Please sign in to comment.