Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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 @@ -13,6 +13,7 @@
- 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))
- Adds: Support for `LPOS` with `.ListPosition()`/`.ListPositionAsync()` and `.ListPositions()`/`.ListPositionsAsync()` ([#2080 by slorello89](https://github.com/StackExchange/StackExchange.Redis/pull/2080))
- Adds: Support for `ZMSCORE` with `.SortedSetScores()`/.`SortedSetScoresAsync()` ([#2082 by ttingen](https://github.com/StackExchange/StackExchange.Redis/pull/2082))

## 2.5.61

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 @@ -200,6 +200,7 @@ internal enum RedisCommand
ZINCRBY,
ZINTERSTORE,
ZLEXCOUNT,
ZMSCORE,
ZPOPMAX,
ZPOPMIN,
ZRANDMEMBER,
Expand Down
14 changes: 14 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1783,6 +1783,20 @@ IEnumerable<SortedSetEntry> SortedSetScan(RedisKey key,
/// <remarks>https://redis.io/commands/zscore</remarks>
double? SortedSetScore(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns the scores of members in the sorted set at <paramref name="key"/>.
/// If a member does not exist in the sorted set, or key does not exist, <see langword="null"/> is returned.
/// </summary>
/// <param name="key">The key of the sorted set.</param>
/// <param name="members">The members to get a score for.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>
/// The scores of the members in the same order as the <paramref name="members"/> array.
/// If a member does not exist in the set, <see langword="null"/> is returned.
/// </returns>
/// <remarks>https://redis.io/commands/zmscore</remarks>
double?[] SortedSetScores(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns the first element from the sorted set stored at key, by default with the scores ordered from low to high.
/// </summary>
Expand Down
14 changes: 14 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1735,6 +1735,20 @@ IAsyncEnumerable<SortedSetEntry> SortedSetScanAsync(RedisKey key,
/// <remarks>https://redis.io/commands/zscore</remarks>
Task<double?> SortedSetScoreAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns the scores of members in the sorted set at <paramref name="key"/>.
/// If a member does not exist in the sorted set, or key does not exist, <see langword="null"/> is returned.
/// </summary>
/// <param name="key">The key of the sorted set.</param>
/// <param name="members">The members to get a score for.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>
/// The scores of the members in the same order as the <paramref name="members"/> array.
/// If a member does not exist in the set, <see langword="null"/> is returned.
/// </returns>
/// <remarks>https://redis.io/commands/zmscore</remarks>
Task<double?[]> SortedSetScoresAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Removes and returns the first element from the sorted set stored at key, by default with the scores ordered from low to high.
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,9 @@ public long SortedSetRemoveRangeByValue(RedisKey key, RedisValue min, RedisValue
public double? SortedSetScore(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetScore(ToInner(key), member, flags);

public double?[] SortedSetScores(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetScores(ToInner(key), members, flags);

public SortedSetEntry? SortedSetPop(RedisKey key, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetPop(ToInner(key), order, flags);

Expand Down
3 changes: 3 additions & 0 deletions src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,9 @@ public Task<long> SortedSetRemoveRangeByValueAsync(RedisKey key, RedisValue min,
public Task<double?> SortedSetScoreAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetScoreAsync(ToInner(key), member, flags);

public Task<double?[]> SortedSetScoresAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) =>
Inner.SortedSetScoresAsync(ToInner(key), members, flags);

public IAsyncEnumerable<SortedSetEntry> SortedSetScanAsync(RedisKey key, RedisValue pattern, int pageSize, long cursor, int pageOffset, CommandFlags flags) =>
Inner.SortedSetScanAsync(ToInner(key), pattern, pageSize, cursor, pageOffset, flags);

Expand Down
2 changes: 2 additions & 0 deletions src/StackExchange.Redis/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@ StackExchange.Redis.IDatabase.SortedSetRemoveRangeByValue(StackExchange.Redis.Re
StackExchange.Redis.IDatabase.SortedSetScan(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern = default(StackExchange.Redis.RedisValue), int pageSize = 250, long cursor = 0, int pageOffset = 0, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Collections.Generic.IEnumerable<StackExchange.Redis.SortedSetEntry>!
StackExchange.Redis.IDatabase.SortedSetScan(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern, int pageSize, StackExchange.Redis.CommandFlags flags) -> System.Collections.Generic.IEnumerable<StackExchange.Redis.SortedSetEntry>!
StackExchange.Redis.IDatabase.SortedSetScore(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue member, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> double?
StackExchange.Redis.IDatabase.SortedSetScores(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! members, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> double?[]!
StackExchange.Redis.IDatabase.StreamAcknowledge(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue messageId, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> long
StackExchange.Redis.IDatabase.StreamAcknowledge(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue[]! messageIds, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> long
StackExchange.Redis.IDatabase.StreamAdd(StackExchange.Redis.RedisKey key, StackExchange.Redis.NameValueEntry[]! streamPairs, StackExchange.Redis.RedisValue? messageId = null, int? maxLength = null, bool useApproximateMaxLength = false, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.RedisValue
Expand Down Expand Up @@ -816,6 +817,7 @@ StackExchange.Redis.IDatabaseAsync.SortedSetRemoveRangeByScoreAsync(StackExchang
StackExchange.Redis.IDatabaseAsync.SortedSetRemoveRangeByValueAsync(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.SortedSetScanAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue pattern = default(StackExchange.Redis.RedisValue), int pageSize = 250, long cursor = 0, int pageOffset = 0, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Collections.Generic.IAsyncEnumerable<StackExchange.Redis.SortedSetEntry>!
StackExchange.Redis.IDatabaseAsync.SortedSetScoreAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue member, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<double?>!
StackExchange.Redis.IDatabaseAsync.SortedSetScoresAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! members, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<double?[]!>!
StackExchange.Redis.IDatabaseAsync.StreamAcknowledgeAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue messageId, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<long>!
StackExchange.Redis.IDatabaseAsync.StreamAcknowledgeAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue[]! messageIds, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<long>!
StackExchange.Redis.IDatabaseAsync.StreamAddAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.NameValueEntry[]! streamPairs, StackExchange.Redis.RedisValue? messageId = null, int? maxLength = null, bool useApproximateMaxLength = false, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.RedisValue>!
Expand Down
3 changes: 3 additions & 0 deletions src/StackExchange.Redis/RawResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ internal bool GetBoolean()
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Sequence<RawResult> GetItems() => _items.Cast<RawResult>();

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal double?[]? GetItemsAsDoubles() => this.ToArray<double?>((in RawResult x) => x.TryGetDouble(out double val) ? val : null);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal RedisKey[]? GetItemsAsKeys() => this.ToArray<RedisKey>((in RawResult x) => x.AsRedisKey());

Expand Down
12 changes: 12 additions & 0 deletions src/StackExchange.Redis/RedisDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1899,12 +1899,24 @@ private CursorEnumerable<SortedSetEntry> SortedSetScanAsync(RedisKey key, RedisV
return ExecuteSync(msg, ResultProcessor.NullableDouble);
}

public double?[] SortedSetScores(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.ZMSCORE, key, members);
return ExecuteSync(msg, ResultProcessor.NullableDoubleArray, defaultValue: Array.Empty<double?>());
}

public Task<double?> SortedSetScoreAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.ZSCORE, key, member);
return ExecuteAsync(msg, ResultProcessor.NullableDouble);
}

public Task<double?[]> SortedSetScoresAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.ZMSCORE, key, members);
return ExecuteAsync(msg, ResultProcessor.NullableDoubleArray, defaultValue: Array.Empty<double?>());
}

public SortedSetEntry? SortedSetPop(RedisKey key, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, order == Order.Descending ? RedisCommand.ZPOPMAX : RedisCommand.ZPOPMIN, key);
Expand Down
18 changes: 18 additions & 0 deletions src/StackExchange.Redis/ResultProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ public static readonly ResultProcessor<long>

public static readonly ResultProcessor<double?>
NullableDouble = new NullableDoubleProcessor();

public static readonly ResultProcessor<double?[]>
NullableDoubleArray = new NullableDoubleArrayProcessor();

public static readonly ResultProcessor<long?>
NullableInt64 = new NullableInt64Processor();

Expand Down Expand Up @@ -1112,6 +1116,20 @@ protected override bool SetResultCore(PhysicalConnection connection, Message mes
}
}

private sealed class NullableDoubleArrayProcessor : ResultProcessor<double?[]>
{
protected override bool SetResultCore(PhysicalConnection connection, Message message, in RawResult result)
{
if (result.Type == ResultType.MultiBulk && !result.IsNull)
{
var arr = result.GetItemsAsDoubles()!;
SetResult(message, arr);
return true;
}
return false;
}
}

private sealed class NullableDoubleProcessor : ResultProcessor<double?>
{
protected override bool SetResultCore(PhysicalConnection connection, Message message, in RawResult result)
Expand Down
7 changes: 7 additions & 0 deletions tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,13 @@ public void SortedSetScore()
mock.Verify(_ => _.SortedSetScore("prefix:key", "member", CommandFlags.None));
}

[Fact]
public void SortedSetScore_Multiple()
{
wrapper.SortedSetScores("key", new RedisValue[] { "member1", "member2" }, CommandFlags.None);
mock.Verify(_ => _.SortedSetScores("prefix:key", new RedisValue[] { "member1", "member2" }, CommandFlags.None));
}

[Fact]
public void StreamAcknowledge_1()
{
Expand Down
Loading