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

Support ZRANDMEMBER #2076

Merged
merged 9 commits into from
Apr 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Note: does *not* increment a major version (as these are warnings to consumers), because: they're warnings (errors are opt-in), removing obsolete types with a 3.0 rev _would_ be binary breaking (this isn't), and reving to 3.0 would cause binding redirect pain for consumers. Bumping from 2.5 to 2.6 only for this change.
- 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 `ZRANDMEMBER` with `.SortedSetRandomMember()`/`.SortedSetRandomMemberAsync()`, `.SortedSetRandomMembers()`/`.SortedSetRandomMembersAsync()`, and `.SortedSetRandomMembersWithScores()`/`.SortedSetRandomMembersWithScoresAsync()` ([#2076 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2076))
- Adds: Support for `SMISMEMBER` with `.SetContains()`/`.SetContainsAsync()` ([#2077 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2077))
- Adds: Support for `SINTERCARD` with `.SetIntersectionLength()`/`.SetIntersectionLengthAsync()` ([#2078 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2078))

Expand Down
1 change: 1 addition & 0 deletions src/StackExchange.Redis/Enums/RedisCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ internal enum RedisCommand
ZLEXCOUNT,
ZPOPMAX,
ZPOPMIN,
ZRANDMEMBER,
ZRANGE,
ZRANGEBYLEX,
ZRANGEBYSCORE,
Expand Down
53 changes: 50 additions & 3 deletions src/StackExchange.Redis/Interfaces/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1199,11 +1199,11 @@ public interface IDatabase : IRedis, IDatabaseAsync
RedisValue[] SetPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Return a random element from the set value stored at key.
/// Return a random element from the set value stored at <paramref name="key"/>.
/// </summary>
/// <param name="key">The key of the set.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>The randomly selected element, or nil when key does not exist.</returns>
/// <returns>The randomly selected element, or <see cref="RedisValue.Null"/> when <paramref name="key"/> does not exist.</returns>
/// <remarks>https://redis.io/commands/srandmember</remarks>
RedisValue SetRandomMember(RedisKey key, CommandFlags flags = CommandFlags.None);

Expand All @@ -1215,7 +1215,7 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <param name="key">The key of the set.</param>
/// <param name="count">The count of members to get.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>An array of elements, or an empty array when key does not exist.</returns>
/// <returns>An array of elements, or an empty array when <paramref name="key"/> does not exist.</returns>
/// <remarks>https://redis.io/commands/srandmember</remarks>
RedisValue[] SetRandomMembers(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

Expand Down Expand Up @@ -1433,6 +1433,53 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <remarks>https://redis.io/commands/zlexcount</remarks>
long SortedSetLengthByValue(RedisKey key, RedisValue min, RedisValue max, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns a random element from the sorted set value stored at <paramref name="key"/>.
/// </summary>
/// <param name="key">The key of the sorted set.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>The randomly selected element, or <see cref="RedisValue.Null"/> when <paramref name="key"/> does not exist.</returns>
/// <remarks>https://redis.io/commands/zrandmember</remarks>
RedisValue SortedSetRandomMember(RedisKey key, CommandFlags flags = CommandFlags.None);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noodling on this, probably want to have a SortedSetRandomMemberWithScore method? Where you just pass in COUNT 1 and the WITHSCORES argument to yield a single SortedSetResult.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking: it's rare enough I'm okay leaving it off - if there was ever a complaint, we could add it later.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@slorello89 If good with the above, I'll go ahead and get this in - thoughts?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


/// <summary>
/// Returns an array of random elements from the sorted set value stored at <paramref name="key"/>.
/// </summary>
/// <param name="key">The key of the sorted set.</param>
/// <param name="count">
/// <para>
/// If the provided count argument is positive, returns an array of distinct elements.
/// The array's length is either <paramref name="count"/> or the sorted set's cardinality (ZCARD), whichever is lower.
/// </para>
/// <para>
/// If called with a negative count, the behavior changes and the command is allowed to return the same element multiple times.
/// In this case, the number of returned elements is the absolute value of the specified count.
/// </para>
/// </param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>The randomly selected elements, or an empty array when <paramref name="key"/> does not exist.</returns>
/// <remarks>https://redis.io/commands/zrandmember</remarks>
RedisValue[] SortedSetRandomMembers(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns an array of random elements from the sorted set value stored at <paramref name="key"/>.
/// </summary>
/// <param name="key">The key of the sorted set.</param>
/// <param name="count">
/// <para>
/// If the provided count argument is positive, returns an array of distinct elements.
/// The array's length is either <paramref name="count"/> or the sorted set's cardinality (ZCARD), whichever is lower.
/// </para>
/// <para>
/// If called with a negative count, the behavior changes and the command is allowed to return the same element multiple times.
/// In this case, the number of returned elements is the absolute value of the specified count.
/// </para>
/// </param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>The randomly selected elements with scores, or an empty array when <paramref name="key"/> does not exist.</returns>
/// <remarks>https://redis.io/commands/zrandmember</remarks>
SortedSetEntry[] SortedSetRandomMembersWithScores(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns the specified range of elements in the sorted set stored at key.
/// By default the elements are considered to be ordered from the lowest to the highest score.
Expand Down
47 changes: 47 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1397,6 +1397,53 @@ public interface IDatabaseAsync : IRedisAsync
/// <remarks>https://redis.io/commands/zlexcount</remarks>
Task<long> SortedSetLengthByValueAsync(RedisKey key, RedisValue min, RedisValue max, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns a random element from the sorted set value stored at <paramref name="key"/>.
/// </summary>
/// <param name="key">The key of the sorted set.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>The randomly selected element, or <see cref="RedisValue.Null"/> when <paramref name="key"/> does not exist.</returns>
/// <remarks>https://redis.io/commands/zrandmember</remarks>
Task<RedisValue> SortedSetRandomMemberAsync(RedisKey key, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns an array of random elements from the sorted set value stored at <paramref name="key"/>.
/// </summary>
/// <param name="key">The key of the sorted set.</param>
/// <param name="count">
/// <para>
/// If the provided count argument is positive, returns an array of distinct elements.
/// The array's length is either <paramref name="count"/> or the sorted set's cardinality (ZCARD), whichever is lower.
/// </para>
/// <para>
/// If called with a negative count, the behavior changes and the command is allowed to return the same element multiple times.
/// In this case, the number of returned elements is the absolute value of the specified count.
/// </para>
/// </param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>The randomly selected elements, or an empty array when <paramref name="key"/> does not exist.</returns>
/// <remarks>https://redis.io/commands/zrandmember</remarks>
Task<RedisValue[]> SortedSetRandomMembersAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns an array of random elements from the sorted set value stored at <paramref name="key"/>.
/// </summary>
/// <param name="key">The key of the sorted set.</param>
/// <param name="count">
/// <para>
/// If the provided count argument is positive, returns an array of distinct elements.
/// The array's length is either <paramref name="count"/> or the sorted set's cardinality (ZCARD), whichever is lower.
/// </para>
/// <para>
/// If called with a negative count, the behavior changes and the command is allowed to return the same element multiple times.
/// In this case, the number of returned elements is the absolute value of the specified count.
/// </para>
/// </param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>The randomly selected elements with scores, or an empty array when <paramref name="key"/> does not exist.</returns>
/// <remarks>https://redis.io/commands/zrandmember</remarks>
Task<SortedSetEntry[]> SortedSetRandomMembersWithScoresAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns the specified range of elements in the sorted set stored at key.
/// By default the elements are considered to be ordered from the lowest to the highest score.
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 @@ -363,6 +363,15 @@ public long SortedSetLength(RedisKey key, double min = -1.0 / 0.0, double max =
public long SortedSetLengthByValue(RedisKey key, RedisValue min, RedisValue max, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetLengthByValue(ToInner(key), min, max, exclude, flags);

public RedisValue SortedSetRandomMember(RedisKey key, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetRandomMember(ToInner(key), flags);

public RedisValue[] SortedSetRandomMembers(RedisKey key, long count, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetRandomMembers(ToInner(key), count, flags);

public SortedSetEntry[] SortedSetRandomMembersWithScores(RedisKey key, long count, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetRandomMembersWithScores(ToInner(key), count, flags);

public RedisValue[] SortedSetRangeByRank(RedisKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetRangeByRank(ToInner(key), start, stop, order, 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 @@ -376,6 +376,15 @@ public Task<long> SortedSetLengthAsync(RedisKey key, double min = -1.0 / 0.0, do
public Task<long> SortedSetLengthByValueAsync(RedisKey key, RedisValue min, RedisValue max, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetLengthByValueAsync(ToInner(key), min, max, exclude, flags);

public Task<RedisValue> SortedSetRandomMemberAsync(RedisKey key, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetRandomMemberAsync(ToInner(key), flags);

public Task<RedisValue[]> SortedSetRandomMembersAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetRandomMembersAsync(ToInner(key), count, flags);

public Task<SortedSetEntry[]> SortedSetRandomMembersWithScoresAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetRandomMembersWithScoresAsync(ToInner(key), count, flags);

public Task<long> SortedSetRangeAndStoreAsync(
RedisKey sourceKey,
RedisKey destinationKey,
Expand Down
6 changes: 6 additions & 0 deletions src/StackExchange.Redis/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,9 @@ StackExchange.Redis.IDatabase.SortedSetLength(StackExchange.Redis.RedisKey key,
StackExchange.Redis.IDatabase.SortedSetLengthByValue(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue min, StackExchange.Redis.RedisValue max, StackExchange.Redis.Exclude exclude = StackExchange.Redis.Exclude.None, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> long
StackExchange.Redis.IDatabase.SortedSetPop(StackExchange.Redis.RedisKey key, long count, StackExchange.Redis.Order order = StackExchange.Redis.Order.Ascending, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.SortedSetEntry[]!
StackExchange.Redis.IDatabase.SortedSetPop(StackExchange.Redis.RedisKey key, StackExchange.Redis.Order order = StackExchange.Redis.Order.Ascending, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.SortedSetEntry?
StackExchange.Redis.IDatabase.SortedSetRandomMember(StackExchange.Redis.RedisKey key, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.RedisValue
StackExchange.Redis.IDatabase.SortedSetRandomMembers(StackExchange.Redis.RedisKey key, long count, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.RedisValue[]!
StackExchange.Redis.IDatabase.SortedSetRandomMembersWithScores(StackExchange.Redis.RedisKey key, long count, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.SortedSetEntry[]!
StackExchange.Redis.IDatabase.SortedSetRangeByRank(StackExchange.Redis.RedisKey key, long start = 0, long stop = -1, StackExchange.Redis.Order order = StackExchange.Redis.Order.Ascending, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.RedisValue[]!
StackExchange.Redis.IDatabase.SortedSetRangeAndStore(StackExchange.Redis.RedisKey sourceKey, StackExchange.Redis.RedisKey destinationKey, StackExchange.Redis.RedisValue start, StackExchange.Redis.RedisValue stop, StackExchange.Redis.SortedSetOrder sortedSetOrder = StackExchange.Redis.SortedSetOrder.ByRank, StackExchange.Redis.Exclude exclude = StackExchange.Redis.Exclude.None, StackExchange.Redis.Order order = StackExchange.Redis.Order.Ascending, long skip = 0, long? take = null, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> long
StackExchange.Redis.IDatabase.SortedSetRangeByRankWithScores(StackExchange.Redis.RedisKey key, long start = 0, long stop = -1, StackExchange.Redis.Order order = StackExchange.Redis.Order.Ascending, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.SortedSetEntry[]!
Expand Down Expand Up @@ -791,6 +794,9 @@ StackExchange.Redis.IDatabaseAsync.SortedSetLengthAsync(StackExchange.Redis.Redi
StackExchange.Redis.IDatabaseAsync.SortedSetLengthByValueAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue min, StackExchange.Redis.RedisValue max, StackExchange.Redis.Exclude exclude = StackExchange.Redis.Exclude.None, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<long>!
StackExchange.Redis.IDatabaseAsync.SortedSetPopAsync(StackExchange.Redis.RedisKey key, long count, StackExchange.Redis.Order order = StackExchange.Redis.Order.Ascending, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.SortedSetEntry[]!>!
StackExchange.Redis.IDatabaseAsync.SortedSetPopAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.Order order = StackExchange.Redis.Order.Ascending, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.SortedSetEntry?>!
StackExchange.Redis.IDatabaseAsync.SortedSetRandomMemberAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.RedisValue>!
StackExchange.Redis.IDatabaseAsync.SortedSetRandomMembersAsync(StackExchange.Redis.RedisKey key, long count, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.RedisValue[]!>!
StackExchange.Redis.IDatabaseAsync.SortedSetRandomMembersWithScoresAsync(StackExchange.Redis.RedisKey key, long count, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.SortedSetEntry[]!>!
StackExchange.Redis.IDatabaseAsync.SortedSetRangeAndStoreAsync(StackExchange.Redis.RedisKey sourceKey, StackExchange.Redis.RedisKey destinationKey, StackExchange.Redis.RedisValue start, StackExchange.Redis.RedisValue stop, StackExchange.Redis.SortedSetOrder sortedSetOrder = StackExchange.Redis.SortedSetOrder.ByRank, StackExchange.Redis.Exclude exclude = StackExchange.Redis.Exclude.None, StackExchange.Redis.Order order = StackExchange.Redis.Order.Ascending, long skip = 0, long? take = null, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<long>!
StackExchange.Redis.IDatabaseAsync.SortedSetRangeByRankAsync(StackExchange.Redis.RedisKey key, long start = 0, long stop = -1, StackExchange.Redis.Order order = StackExchange.Redis.Order.Ascending, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.RedisValue[]!>!
StackExchange.Redis.IDatabaseAsync.SortedSetRangeByRankWithScoresAsync(StackExchange.Redis.RedisKey key, long start = 0, long stop = -1, StackExchange.Redis.Order order = StackExchange.Redis.Order.Ascending, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.SortedSetEntry[]!>!
Expand Down
Loading