diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index 742e646363..ab0c8a7149 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -28,6 +28,7 @@ import { createHGetAll, createHIncrBy, createHIncrByFloat, + createHLen, createHMGet, createHSet, createIncr, @@ -616,6 +617,16 @@ export class BaseClient { return this.createWritePromise(createHIncrByFloat(key, field, amount)); } + /** Returns the number of fields contained in the hash stored at `key`. + * See https://redis.io/commands/hlen/ for more details. + * + * @param key - The key of the hash. + * @returns The number of fields in the hash, or 0 when the key does not exist. + */ + public hlen(key: string): Promise { + return this.createWritePromise(createHLen(key)); + } + /** Inserts all the specified values at the head of the list stored at `key`. * `elements` are inserted one after the other to the head of the list, from the leftmost element to the rightmost element. * If `key` does not exist, it is created as empty list before performing the push operations. diff --git a/node/src/Commands.ts b/node/src/Commands.ts index 9f6996312d..d46317c542 100644 --- a/node/src/Commands.ts +++ b/node/src/Commands.ts @@ -585,6 +585,13 @@ export function createHIncrByFloat( ]); } +/** + * @internal + */ +export function createHLen(key: string): redis_request.Command { + return createCommand(RequestType.HLen, [key]); +} + /** * @internal */ diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index 691dc7b8e6..afa6f678f2 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -28,6 +28,7 @@ import { createHGetAll, createHIncrBy, createHIncrByFloat, + createHLen, createHMGet, createHSet, createIncr, @@ -409,6 +410,17 @@ export class BaseTransaction> { return this.addAndReturn(createHIncrByFloat(key, field, amount)); } + /** Returns the number of fields contained in the hash stored at `key`. + * See https://redis.io/commands/hlen/ for more details. + * + * @param key - The key of the hash. + * + * Command Response - The number of fields in the hash, or 0 when the key does not exist. + */ + public hlen(key: string): T { + return this.addAndReturn(createHLen(key)); + } + /** Inserts all the specified values at the head of the list stored at `key`. * `elements` are inserted one after the other to the head of the list, from the leftmost element to the rightmost element. * If `key` does not exist, it is created as empty list before performing the push operations. diff --git a/node/tests/SharedTests.ts b/node/tests/SharedTests.ts index 6e6b047afc..bbe84a111d 100644 --- a/node/tests/SharedTests.ts +++ b/node/tests/SharedTests.ts @@ -750,6 +750,28 @@ export function runBaseTests(config: { config.timeout ); + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( + `hlen test_%p`, + async (protocol) => { + await runTest(async (client: BaseClient) => { + const key1 = uuidv4(); + const field1 = uuidv4(); + const field2 = uuidv4(); + const fieldValueMap = { + [field1]: "value1", + [field2]: "value2", + }; + + expect(await client.hset(key1, fieldValueMap)).toEqual(2); + expect(await client.hlen(key1)).toEqual(2); + expect(await client.hdel(key1, [field1])).toEqual(1); + expect(await client.hlen(key1)).toEqual(1); + expect(await client.hlen("nonExistingHash")).toEqual(0); + }, protocol); + }, + config.timeout + ); + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( `lpush, lpop and lrange with existing and non existing key_%p`, async (protocol) => { diff --git a/node/tests/TestUtilities.ts b/node/tests/TestUtilities.ts index a4ff1df332..6e88ffb819 100644 --- a/node/tests/TestUtilities.ts +++ b/node/tests/TestUtilities.ts @@ -82,6 +82,8 @@ export function transactionTest( args.push(1); baseTransaction.hset(key4, { [field]: value }); args.push(1); + baseTransaction.hlen(key4); + args.push(1); baseTransaction.hget(key4, field); args.push(value); baseTransaction.hgetall(key4);