diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index 0fd25d458e..1b99211410 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -1952,16 +1952,14 @@ export class BaseClient { /** * Computes the intersection of sorted sets given by the specified `keys` and returns a list of intersecting elements. - * To get the scores as well, see `zinter_withscores`. - * To store the result in a key as a sorted set, see `zinterstore`. + * To get the scores as well, see `zinterWithScores`. + * To store the result in a key as a sorted set, see `zinterStore`. * * When in cluster mode, all keys in `keys` must map to the same hash slot. * * See https://valkey.io/commands/zinter/ for more details. * - * @param keys - The keys of the sorted sets with possible formats: - * string[] - for keys only. - * KeyWeight[] - for weighted keys with score multipliers. + * @param keys - The keys of the sorted sets. * @returns The resulting array of intersecting elements. * * @example @@ -1972,7 +1970,7 @@ export class BaseClient { * ``` */ public zinter( - keys: string[] | KeyWeight[], + keys: string[], ): Promise { return this.createWritePromise( createZInter(keys), @@ -1982,7 +1980,7 @@ export class BaseClient { /** * Computes the intersection of sorted sets given by the specified `keys` and returns a list of intersecting elements with scores. * To get the elements only, see `zinter`. - * To store the result in a key as a sorted set, see `zinterstore`. + * To store the result in a key as a sorted set, see `zinterStore`. * * When in cluster mode, all keys in `keys` must map to the same hash slot. * @@ -2013,17 +2011,15 @@ export class BaseClient { /** * Computes the union of sorted sets given by the specified `keys` and returns a list of union elements. - * To get the scores as well, see `zunion_withscores`. + * To get the scores as well, see `zunionWithScores`. * - * To store the result in a key as a sorted set, see `zunionstore`. + * To store the result in a key as a sorted set, see `zunionStore`. * * When in cluster mode, all keys in `keys` must map to the same hash slot. * * See https://valkey.io/commands/zunion/ for more details. * - * @param keys - The keys of the sorted sets with possible formats: - * string[] - for keys only. - * KeyWeight[] - for weighted keys with score multipliers. + * @param keys - The keys of the sorted sets. * @returns The resulting array of union elements. * * @example @@ -2033,8 +2029,8 @@ export class BaseClient { * await client.zunion(["key1", "key2"]) // Output: ['member1', 'member2'] * ``` */ - public zunioun( - keys: string[] | KeyWeight[], + public zunion( + keys: string[], ): Promise { return this.createWritePromise( createZUnion(keys), diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index e3ff9041f9..10a7ba01e7 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -1095,13 +1095,11 @@ export class BaseTransaction> { * * See https://valkey.io/commands/zinter/ for more details. * - * @param keys - The keys of the sorted sets with possible formats: - * string[] - for keys only. - * KeyWeight[] - for weighted keys with score multipliers. + * @param keys - The keys of the sorted sets. * Command Response - The resulting array of intersecting elements. */ public zinter( - keys: string[] | KeyWeight[], + keys: string[], ): T { return this.addAndReturn( createZInter(keys), @@ -1142,13 +1140,11 @@ export class BaseTransaction> { * * See https://valkey.io/commands/zunion/ for more details. * - * @param keys - The keys of the sorted sets with possible formats: - * string[] - for keys only. - * KeyWeight[] - for weighted keys with score multipliers. + * @param keys - The keys of the sorted sets. * Command Response - The resulting array of union elements. */ - public zunioun( - keys: string[] | KeyWeight[], + public zunion( + keys: string[], ): T { return this.addAndReturn( createZUnion(keys), diff --git a/node/tests/SharedTests.ts b/node/tests/SharedTests.ts index 01c2ffdb44..fa8058eb63 100644 --- a/node/tests/SharedTests.ts +++ b/node/tests/SharedTests.ts @@ -2074,6 +2074,319 @@ export function runBaseTests(config: { config.timeout, ); + async function zinterBasicTest(client:BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + const key2 = "{testKey}:2-" + uuidv4(); + + const membersScores1 = { one: 1.0, two: 2.0 }; + const membersScores2 = { one: 1.5, two: 2.5, three: 3.5 }; + + expect(await client.zadd(key1, membersScores1)).toEqual(2); + expect(await client.zadd(key2, membersScores2)).toEqual(3); + + const resultZinter = await client.zinter([key1, key2]); + const expectedZinter = ["one", "two"]; + expect(resultZinter).toEqual(expectedZinter); + } + + async function zinterWithScoresBasicTest(client:BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + const key2 = "{testKey}:2-" + uuidv4(); + + const membersScores1 = { one: 1.0, two: 2.0 }; + const membersScores2 = { one: 1.5, two: 2.5, three: 3.5 }; + + expect(await client.zadd(key1, membersScores1)).toEqual(2); + expect(await client.zadd(key2, membersScores2)).toEqual(3); + + const resultZinterWithScores = await client.zinterWithScores([key1, key2]); + const expectedZinterWithScores = { + one: 2.5, + two: 4.5, + }; + expect(resultZinterWithScores).toEqual(expectedZinterWithScores); + } + + async function zinterWithScoresWithMaxAggregation(client:BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + const key2 = "{testKey}:2-" + uuidv4(); + + const membersScores1 = { one: 1.0, two: 2.0 }; + const membersScores2 = { one: 1.5, two: 2.5, three: 3.5 }; + + expect(await client.zadd(key1, membersScores1)).toEqual(2); + expect(await client.zadd(key2, membersScores2)).toEqual(3); + + // Intersection results are aggregated by the MAX score of elements + const zinterWithScoresResults = await client.zinterWithScores([key1, key2], "MAX"); + const expectedMapMax = { + one: 1.5, + two: 2.5, + }; + expect(zinterWithScoresResults).toEqual(expectedMapMax); + } + + async function zinterWithScoresWithMinAggregation(client:BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + const key2 = "{testKey}:2-" + uuidv4(); + + const membersScores1 = { one: 1.0, two: 2.0 }; + const membersScores2 = { one: 1.5, two: 2.5, three: 3.5 }; + + expect(await client.zadd(key1, membersScores1)).toEqual(2); + expect(await client.zadd(key2, membersScores2)).toEqual(3); + + // Intersection results are aggregated by the MIN score of elements + const zinterWithScoresResults = await client.zinterWithScores([key1, key2], "MIN"); + const expectedMapMin = { + one: 1.0, + two: 2.0, + }; + expect(zinterWithScoresResults).toEqual(expectedMapMin); + } + + async function zinterWithScoresWithSumAggregation(client:BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + const key2 = "{testKey}:2-" + uuidv4(); + + const membersScores1 = { one: 1.0, two: 2.0 }; + const membersScores2 = { one: 1.5, two: 2.5, three: 3.5 }; + + expect(await client.zadd(key1, membersScores1)).toEqual(2); + expect(await client.zadd(key2, membersScores2)).toEqual(3); + + // Intersection results are aggregated by the SUM score of elements + const zinterWithScoresResults = await client.zinterWithScores([key1, key2], "SUM"); + const expectedMapSum = { + one: 2.5, + two: 4.5, + }; + expect(zinterWithScoresResults).toEqual(expectedMapSum); + } + + async function zinterWithScoresWithWeightsAndAggregation(client:BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + const key2 = "{testKey}:2-" + uuidv4(); + + const membersScores1 = { one: 1.0, two: 2.0 }; + const membersScores2 = { one: 1.5, two: 2.5, three: 3.5 }; + + expect(await client.zadd(key1, membersScores1)).toEqual(2); + expect(await client.zadd(key2, membersScores2)).toEqual(3); + + // Intersection results are aggregated by the SUM score of elements with weights + const zinterWithScoresResults = await client.zinterWithScores([[key1, 3], [key2, 2]], "SUM"); + const expectedMapSum = { + one: 6, + two: 11, + }; + expect(zinterWithScoresResults).toEqual(expectedMapSum); + } + + async function zinterEmptyCases(client: BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + + // Non existing key zinter + expect( + await client.zinter([ + key1, + "{testKey}-non_existing_key", + ]), + ).toEqual([]); + + // Non existing key zinterWithScores + expect( + await client.zinterWithScores([ + key1, + "{testKey}-non_existing_key", + ]), + ).toEqual({}); + + // Empty list check zinter + await expect(client.zinter([])).rejects.toThrow(); + + // Empty list check zinterWithScores + await expect(client.zinterWithScores([])).rejects.toThrow(); + } + + + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( + `zinter test_%p`, + async (protocol) => { + await runTest(async (client: BaseClient) => { + await zinterBasicTest(client); + await zinterWithScoresBasicTest(client); + await zinterWithScoresWithMaxAggregation(client); + await zinterWithScoresWithMinAggregation(client); + await zinterWithScoresWithSumAggregation(client); + await zinterWithScoresWithWeightsAndAggregation(client); + await zinterEmptyCases(client); + }, protocol); + }, + config.timeout, + ); + + async function zunionBasicTest(client:BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + const key2 = "{testKey}:2-" + uuidv4(); + + const membersScores1 = { one: 1.0, two: 2.0 }; + const membersScores2 = { one: 1.5, two: 2.5, three: 3.5 }; + + expect(await client.zadd(key1, membersScores1)).toEqual(2); + expect(await client.zadd(key2, membersScores2)).toEqual(3); + + const resultZunion = await client.zunion([key1, key2]); + const expectedZunion = ["one", "two", "three"]; + + expect(resultZunion.sort()).toEqual(expectedZunion.sort()); + } + + async function zunionWithScoresBasicTest(client:BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + const key2 = "{testKey}:2-" + uuidv4(); + + const membersScores1 = { one: 1.0, two: 2.0 }; + const membersScores2 = { one: 1.5, two: 2.5, three: 3.5 }; + + expect(await client.zadd(key1, membersScores1)).toEqual(2); + expect(await client.zadd(key2, membersScores2)).toEqual(3); + + const resultZunionWithScores = await client.zunionWithScores([key1, key2]); + const expectedZunionWithScores = { + one: 2.5, + two: 4.5, + three: 3.5 + }; + expect(resultZunionWithScores).toEqual(expectedZunionWithScores); + } + + async function zunionWithScoresWithMaxAggregation(client:BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + const key2 = "{testKey}:2-" + uuidv4(); + + const membersScores1 = { one: 1.0, two: 2.0 }; + const membersScores2 = { one: 1.5, two: 2.5, three: 3.5 }; + + expect(await client.zadd(key1, membersScores1)).toEqual(2); + expect(await client.zadd(key2, membersScores2)).toEqual(3); + + // Union results are aggregated by the MAX score of elements + const zunionWithScoresResults = await client.zunionWithScores([key1, key2], "MAX"); + const expectedMapMax = { + one: 1.5, + two: 2.5, + three: 3.5 + }; + expect(zunionWithScoresResults).toEqual(expectedMapMax); + } + + async function zunionWithScoresWithMinAggregation(client:BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + const key2 = "{testKey}:2-" + uuidv4(); + + const membersScores1 = { one: 1.0, two: 2.0 }; + const membersScores2 = { one: 1.5, two: 2.5, three: 3.5 }; + + expect(await client.zadd(key1, membersScores1)).toEqual(2); + expect(await client.zadd(key2, membersScores2)).toEqual(3); + + // Union results are aggregated by the MIN score of elements + const zunionWithScoresResults = await client.zunionWithScores([key1, key2], "MIN"); + const expectedMapMin = { + one: 1.0, + two: 2.0, + three: 3.5 + }; + expect(zunionWithScoresResults).toEqual(expectedMapMin); + } + + async function zunionWithScoresWithSumAggregation(client:BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + const key2 = "{testKey}:2-" + uuidv4(); + + const membersScores1 = { one: 1.0, two: 2.0 }; + const membersScores2 = { one: 1.5, two: 2.5, three: 3.5 }; + + expect(await client.zadd(key1, membersScores1)).toEqual(2); + expect(await client.zadd(key2, membersScores2)).toEqual(3); + + // Union results are aggregated by the SUM score of elements + const zunionWithScoresResults = await client.zunionWithScores([key1, key2], "SUM"); + const expectedMapSum = { + one: 2.5, + two: 4.5, + three: 3.5 + }; + expect(zunionWithScoresResults).toEqual(expectedMapSum); + } + + async function zunionWithScoresWithWeightsAndAggregation(client:BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + const key2 = "{testKey}:2-" + uuidv4(); + + const membersScores1 = { one: 1.0, two: 2.0 }; + const membersScores2 = { one: 1.5, two: 2.5, three: 3.5 }; + + expect(await client.zadd(key1, membersScores1)).toEqual(2); + expect(await client.zadd(key2, membersScores2)).toEqual(3); + + // Union results are aggregated by the SUM score of elements with weights + const zunionWithScoresResults = await client.zunionWithScores([[key1, 3], [key2, 2]], "SUM"); + const expectedMapSum = { + one: 6, + two: 11, + three: 7 + }; + expect(zunionWithScoresResults).toEqual(expectedMapSum); + } + + async function zunionEmptyCases(client: BaseClient) { + const key1 = "{testKey}:1-" + uuidv4(); + + const membersScores1 = { one: 1.0, two: 2.0 }; + + expect(await client.zadd(key1, membersScores1)).toEqual(2); + + // Non existing key zunion + expect( + await client.zunion([ + key1, + "{testKey}-non_existing_key", + ]), + ).toEqual(["one", "two"]); + + // Non existing key zunionWithScores + expect( + await client.zunionWithScores([ + key1, + "{testKey}-non_existing_key", + ]), + ).toEqual(membersScores1); + + // Empty list check zunion + await expect(client.zunion([])).rejects.toThrow(); + + // Empty list check zunionWithScores + await expect(client.zunionWithScores([])).rejects.toThrow(); + } + + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( + `zunion test_%p`, + async (protocol) => { + await runTest(async (client: BaseClient) => { + await zunionBasicTest(client); + await zunionWithScoresBasicTest(client); + await zunionWithScoresWithMaxAggregation(client); + await zunionWithScoresWithMinAggregation(client); + await zunionWithScoresWithSumAggregation(client); + await zunionWithScoresWithWeightsAndAggregation(client); + await zunionEmptyCases(client); + }, protocol); + }, + config.timeout, + ); + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( `type test_%p`, async (protocol) => { diff --git a/node/tests/TestUtilities.ts b/node/tests/TestUtilities.ts index c56f6965a6..472086f80e 100644 --- a/node/tests/TestUtilities.ts +++ b/node/tests/TestUtilities.ts @@ -232,6 +232,7 @@ export async function transactionTest( const key11 = "{key}" + uuidv4(); // hyper log log const key12 = "{key}" + uuidv4(); const key13 = "{key}" + uuidv4(); + const key14 = "{key}" + uuidv4(); const field = uuidv4(); const value = uuidv4(); const args: ReturnType[] = []; @@ -363,10 +364,18 @@ export async function transactionTest( args.push({ member2: 3, member3: 3.5, member4: 4, member5: 5 }); baseTransaction.zadd(key12, { one: 1, two: 2 }); args.push(2); - baseTransaction.zadd(key13, { one: 1, two: 2, tree: 3.5 }); + baseTransaction.zadd(key13, { one: 1, two: 2, three: 3.5 }); args.push(3); baseTransaction.zinterstore(key12, [key12, key13]); args.push(2); + baseTransaction.zadd(key14, { one: 1, two: 2 }); + args.push(2); + baseTransaction.zinter([key13, key14]); + args.push(["one", "two"]); + baseTransaction.zinterWithScores([key13, key14]); + args.push({one: 2, two: 4}); + baseTransaction.zunionWithScores([key13, key14]); + args.push({one: 2, two: 4, three: 3.5}); baseTransaction.zcount(key8, { value: 2 }, "positiveInfinity"); args.push(4); baseTransaction.zpopmin(key8);