Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sorted set new commands: ZDIFF, ZDIFFSTORE, ZINTER, ZINTERCARD, and ZUNION #2075

Merged
merged 14 commits into from
Apr 12, 2022
1 change: 1 addition & 0 deletions docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Adds: Support for `COPY` with `.KeyCopy()`/`.KeyCopyAsync()` ([#2064 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2064))
- Adds: Support for `LMOVE` with `.ListMove()`/`.ListMoveAsync()` ([#2065 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2065))
- Adds: Support for `SMISMEMBER` with `.SetContains()`/`.SetContainsAsync()` ([#2077 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2077))
- Adds: Support for `ZDIFF`, `ZDIFFSTORE`, `ZINTER`, `ZINTERCARD`, and `ZUNION` with `.SortedSetCombine()`/`.SortedSetCombineAsync()`, `.SortedSetCombineWithScores()`/`.SortedSetCombineWithScoresAsync()`, and `.SortedSetIntersectionLength()`/`.SortedSetIntersectionLengthAsync()` ([#2075 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2075))
- Adds: Support for `SINTERCARD` with `.SetIntersectionLength()`/`.SetIntersectionLengthAsync()` ([#2078 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2078))

## 2.5.61
Expand Down
5 changes: 5 additions & 0 deletions src/StackExchange.Redis/Enums/RedisCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,11 @@ internal enum RedisCommand
ZADD,
ZCARD,
ZCOUNT,
ZDIFF,
ZDIFFSTORE,
ZINCRBY,
ZINTER,
ZINTERCARD,
ZINTERSTORE,
ZLEXCOUNT,
ZPOPMAX,
Expand All @@ -216,6 +220,7 @@ internal enum RedisCommand
ZREVRANK,
ZSCAN,
ZSCORE,
ZUNION,
ZUNIONSTORE,

UNKNOWN,
Expand Down
46 changes: 46 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1355,9 +1355,42 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <remarks>https://redis.io/commands/zadd</remarks>
long SortedSetAdd(RedisKey key, SortedSetEntry[] values, When when = When.Always, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Computes a set operation for multiple sorted sets (optionally using per-set <paramref name="weights"/>),
/// optionally performing a specific aggregation (defaults to <see cref="Aggregate.Sum"/>).
/// <see cref="SetOperation.Difference"/> cannot be used with weights or aggregation.
/// </summary>
/// <param name="operation">The operation to perform.</param>
/// <param name="keys">The keys of the sorted sets.</param>
/// <param name="weights">The optional weights per set that correspond to <paramref name="keys"/>.</param>
/// <param name="aggregate">The aggregation method (defaults to <see cref="Aggregate.Sum"/>).</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <remarks>https://redis.io/commands/zunion</remarks>
/// <remarks>https://redis.io/commands/zinter</remarks>
/// <remarks>https://redis.io/commands/zdiff</remarks>
/// <returns>The resulting sorted set.</returns>
RedisValue[] SortedSetCombine(SetOperation operation, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Computes a set operation for multiple sorted sets (optionally using per-set <paramref name="weights"/>),
/// optionally performing a specific aggregation (defaults to <see cref="Aggregate.Sum"/>).
/// <see cref="SetOperation.Difference"/> cannot be used with weights or aggregation.
/// </summary>
/// <param name="operation">The operation to perform.</param>
/// <param name="keys">The keys of the sorted sets.</param>
/// <param name="weights">The optional weights per set that correspond to <paramref name="keys"/>.</param>
/// <param name="aggregate">The aggregation method (defaults to <see cref="Aggregate.Sum"/>).</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <remarks>https://redis.io/commands/zunion</remarks>
/// <remarks>https://redis.io/commands/zinter</remarks>
/// <remarks>https://redis.io/commands/zdiff</remarks>
/// <returns>The resulting sorted set with scores.</returns>
SortedSetEntry[] SortedSetCombineWithScores(SetOperation operation, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Computes a set operation over two sorted sets, and stores the result in destination, optionally performing
/// a specific aggregation (defaults to sum).
/// <see cref="SetOperation.Difference"/> cannot be used with aggregation.
/// </summary>
/// <param name="operation">The operation to perform.</param>
/// <param name="destination">The key to store the results in.</param>
Expand All @@ -1367,12 +1400,14 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <param name="flags">The flags to use for this operation.</param>
/// <remarks>https://redis.io/commands/zunionstore</remarks>
/// <remarks>https://redis.io/commands/zinterstore</remarks>
/// <remarks>https://redis.io/commands/zdiffstore</remarks>
/// <returns>The number of elements in the resulting sorted set at destination.</returns>
long SortedSetCombineAndStore(SetOperation operation, RedisKey destination, RedisKey first, RedisKey second, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Computes a set operation over multiple sorted sets (optionally using per-set weights), and stores the result in destination, optionally performing
/// a specific aggregation (defaults to sum).
/// <see cref="SetOperation.Difference"/> cannot be used with aggregation.
/// </summary>
/// <param name="operation">The operation to perform.</param>
/// <param name="destination">The key to store the results in.</param>
Expand All @@ -1382,6 +1417,7 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <param name="flags">The flags to use for this operation.</param>
/// <remarks>https://redis.io/commands/zunionstore</remarks>
/// <remarks>https://redis.io/commands/zinterstore</remarks>
/// <remarks>https://redis.io/commands/zdiffstore</remarks>
/// <returns>The number of elements in the resulting sorted set at destination.</returns>
long SortedSetCombineAndStore(SetOperation operation, RedisKey destination, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None);

Expand All @@ -1408,6 +1444,16 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <remarks>https://redis.io/commands/zincrby</remarks>
double SortedSetIncrement(RedisKey key, RedisValue member, double value, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns the cardinality of the intersection of the sorted sets at <paramref name="keys"/>.
/// </summary>
/// <param name="keys">The keys of the sorted sets.</param>
/// <param name="limit">If the intersection cardinality reaches <paramref name="limit"/> partway through the computation, the algorithm will exit and yield <paramref name="limit"/> as the cardinality (defaults to 0 meaning unlimited).</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>The number of elements in the resulting intersection.</returns>
/// <remarks>https://redis.io/commands/zintercard</remarks>
long SortedSetIntersectionLength(RedisKey[] keys, long limit = 0, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns the sorted set cardinality (number of elements) of the sorted set stored at key.
/// </summary>
Expand Down
46 changes: 46 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1319,9 +1319,42 @@ public interface IDatabaseAsync : IRedisAsync
/// <remarks>https://redis.io/commands/zadd</remarks>
Task<long> SortedSetAddAsync(RedisKey key, SortedSetEntry[] values, When when = When.Always, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Computes a set operation for multiple sorted sets (optionally using per-set <paramref name="weights"/>),
/// optionally performing a specific aggregation (defaults to <see cref="Aggregate.Sum"/>).
/// <see cref="SetOperation.Difference"/> cannot be used with weights or aggregation.
/// </summary>
/// <param name="operation">The operation to perform.</param>
/// <param name="keys">The keys of the sorted sets.</param>
/// <param name="weights">The optional weights per set that correspond to <paramref name="keys"/>.</param>
/// <param name="aggregate">The aggregation method (defaults to <see cref="Aggregate.Sum"/>).</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <remarks>https://redis.io/commands/zunion</remarks>
/// <remarks>https://redis.io/commands/zinter</remarks>
/// <remarks>https://redis.io/commands/zdiff</remarks>
/// <returns>The resulting sorted set.</returns>
Task<RedisValue[]> SortedSetCombineAsync(SetOperation operation, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Computes a set operation for multiple sorted sets (optionally using per-set <paramref name="weights"/>),
/// optionally performing a specific aggregation (defaults to <see cref="Aggregate.Sum"/>).
/// <see cref="SetOperation.Difference"/> cannot be used with weights or aggregation.
/// </summary>
/// <param name="operation">The operation to perform.</param>
/// <param name="keys">The keys of the sorted sets.</param>
/// <param name="weights">The optional weights per set that correspond to <paramref name="keys"/>.</param>
/// <param name="aggregate">The aggregation method (defaults to <see cref="Aggregate.Sum"/>).</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <remarks>https://redis.io/commands/zunion</remarks>
/// <remarks>https://redis.io/commands/zinter</remarks>
/// <remarks>https://redis.io/commands/zdiff</remarks>
/// <returns>The resulting sorted set with scores.</returns>
Task<SortedSetEntry[]> SortedSetCombineWithScoresAsync(SetOperation operation, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Computes a set operation over two sorted sets, and stores the result in destination, optionally performing
/// a specific aggregation (defaults to sum).
/// <see cref="SetOperation.Difference"/> cannot be used with aggregation.
/// </summary>
/// <param name="operation">The operation to perform.</param>
/// <param name="destination">The key to store the results in.</param>
Expand All @@ -1331,12 +1364,14 @@ public interface IDatabaseAsync : IRedisAsync
/// <param name="flags">The flags to use for this operation.</param>
/// <remarks>https://redis.io/commands/zunionstore</remarks>
/// <remarks>https://redis.io/commands/zinterstore</remarks>
/// <remarks>https://redis.io/commands/zdiffstore</remarks>
/// <returns>The number of elements in the resulting sorted set at destination.</returns>
Task<long> SortedSetCombineAndStoreAsync(SetOperation operation, RedisKey destination, RedisKey first, RedisKey second, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Computes a set operation over multiple sorted sets (optionally using per-set weights), and stores the result in destination, optionally performing
/// a specific aggregation (defaults to sum).
/// <see cref="SetOperation.Difference"/> cannot be used with aggregation.
/// </summary>
/// <param name="operation">The operation to perform.</param>
/// <param name="destination">The key to store the results in.</param>
Expand All @@ -1346,6 +1381,7 @@ public interface IDatabaseAsync : IRedisAsync
/// <param name="flags">The flags to use for this operation.</param>
/// <remarks>https://redis.io/commands/zunionstore</remarks>
/// <remarks>https://redis.io/commands/zinterstore</remarks>
/// <remarks>https://redis.io/commands/zdiffstore</remarks>
/// <returns>The number of elements in the resulting sorted set at destination.</returns>
Task<long> SortedSetCombineAndStoreAsync(SetOperation operation, RedisKey destination, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None);

Expand All @@ -1372,6 +1408,16 @@ public interface IDatabaseAsync : IRedisAsync
/// <remarks>https://redis.io/commands/zincrby</remarks>
Task<double> SortedSetIncrementAsync(RedisKey key, RedisValue member, double value, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns the cardinality of the intersection of the sorted sets at <paramref name="keys"/>.
/// </summary>
/// <param name="keys">The keys of the sorted sets.</param>
/// <param name="limit">If the intersection cardinality reaches <paramref name="limit"/> partway through the computation, the algorithm will exit and yield <paramref name="limit"/> as the cardinality (defaults to 0 meaning unlimited).</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>The number of elements in the resulting intersection.</returns>
/// <remarks>https://redis.io/commands/zintercard</remarks>
Task<long> SortedSetIntersectionLengthAsync(RedisKey[] keys, long limit = 0, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns the sorted set cardinality (number of elements) of the sorted set stored at key.
/// </summary>
Expand Down
9 changes: 9 additions & 0 deletions src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,12 @@ public bool SortedSetAdd(RedisKey key, RedisValue member, double score, CommandF
public bool SortedSetAdd(RedisKey key, RedisValue member, double score, When when = When.Always, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetAdd(ToInner(key), member, score, when, flags);

public RedisValue[] SortedSetCombine(SetOperation operation, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetCombine(operation, keys, weights, aggregate, flags);

public SortedSetEntry[] SortedSetCombineWithScores(SetOperation operation, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetCombineWithScores(operation, keys, weights, aggregate, flags);

public long SortedSetCombineAndStore(SetOperation operation, RedisKey destination, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetCombineAndStore(operation, ToInner(destination), ToInner(keys), weights, aggregate, flags);

Expand All @@ -357,6 +363,9 @@ public double SortedSetDecrement(RedisKey key, RedisValue member, double value,
public double SortedSetIncrement(RedisKey key, RedisValue member, double value, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetIncrement(ToInner(key), member, value, flags);

public long SortedSetIntersectionLength(RedisKey[] keys, long limit = 0, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetIntersectionLength(keys, limit, flags);

public long SortedSetLength(RedisKey key, double min = -1.0 / 0.0, double max = 1.0 / 0.0, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetLength(ToInner(key), min, max, exclude, flags);

Expand Down
9 changes: 9 additions & 0 deletions src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,12 @@ public Task<bool> SortedSetAddAsync(RedisKey key, RedisValue member, double scor
public Task<bool> SortedSetAddAsync(RedisKey key, RedisValue member, double score, When when = When.Always, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetAddAsync(ToInner(key), member, score, when, flags);

public Task<RedisValue[]> SortedSetCombineAsync(SetOperation operation, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetCombineAsync(operation, keys, weights, aggregate, flags);

public Task<SortedSetEntry[]> SortedSetCombineWithScoresAsync(SetOperation operation, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetCombineWithScoresAsync(operation, keys, weights, aggregate, flags);

public Task<long> SortedSetCombineAndStoreAsync(SetOperation operation, RedisKey destination, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetCombineAndStoreAsync(operation, ToInner(destination), ToInner(keys), weights, aggregate, flags);

Expand All @@ -370,6 +376,9 @@ public Task<double> SortedSetDecrementAsync(RedisKey key, RedisValue member, dou
public Task<double> SortedSetIncrementAsync(RedisKey key, RedisValue member, double value, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetIncrementAsync(ToInner(key), member, value, flags);

public Task<long> SortedSetIntersectionLengthAsync(RedisKey[] keys, long limit = 0, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetIntersectionLengthAsync(keys, limit, flags);

public Task<long> SortedSetLengthAsync(RedisKey key, double min = -1.0 / 0.0, double max = 1.0 / 0.0, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetLengthAsync(ToInner(key), min, max, exclude, flags);

Expand Down
Loading