Skip to content

Commit bf66fe6

Browse files
authored
C#: Sorted Set Public Preview Commands (#4467)
Signed-off-by: Edward Liang <edward.liang@improving.com>
1 parent b5e4548 commit bf66fe6

File tree

14 files changed

+1905
-16
lines changed

14 files changed

+1905
-16
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,6 @@ cpp/src/connection_request.pb.cc
7575
**/.claude/settings.local.json
7676
copilot-instructions.md
7777
**/.yarn
78+
79+
# AI agent related files
80+
.kiro/

csharp/sources/Valkey.Glide/BaseClient.SortedSetCommands.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,48 @@ public async Task<bool> SortedSetRemoveAsync(ValkeyKey key, ValkeyValue member,
3030

3131
public async Task<long> SortedSetRemoveAsync(ValkeyKey key, ValkeyValue[] members, CommandFlags flags = CommandFlags.None)
3232
=> await Command(Request.SortedSetRemoveAsync(key, members, flags));
33+
34+
public async Task<long> SortedSetLengthAsync(ValkeyKey key, double min = double.NegativeInfinity, double max = double.PositiveInfinity, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None)
35+
{
36+
// If both min and max are infinity (default values), use ZCARD
37+
if (double.IsNegativeInfinity(min) && double.IsPositiveInfinity(max))
38+
{
39+
return await SortedSetCardAsync(key, flags);
40+
}
41+
42+
// Otherwise use ZCOUNT with the specified range
43+
return await SortedSetCountAsync(key, min, max, exclude, flags);
44+
}
45+
46+
public async Task<long> SortedSetCardAsync(ValkeyKey key, CommandFlags flags = CommandFlags.None)
47+
=> await Command(Request.SortedSetCardAsync(key, flags));
48+
49+
public async Task<long> SortedSetCountAsync(ValkeyKey key, double min = double.NegativeInfinity, double max = double.PositiveInfinity, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None)
50+
=> await Command(Request.SortedSetCountAsync(key, min, max, exclude, flags));
51+
52+
public async Task<ValkeyValue[]> SortedSetRangeByRankAsync(ValkeyKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None)
53+
=> await Command(Request.SortedSetRangeByRankAsync(key, start, stop, order, flags));
54+
55+
public async Task<SortedSetEntry[]> SortedSetRangeByRankWithScoresAsync(ValkeyKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None)
56+
=> await Command(Request.SortedSetRangeByRankWithScoresAsync(key, start, stop, order, flags));
57+
58+
public async Task<ValkeyValue[]> SortedSetRangeByScoreAsync(ValkeyKey key, double start = double.NegativeInfinity, double stop = double.PositiveInfinity, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None)
59+
=> await Command(Request.SortedSetRangeByScoreAsync(key, start, stop, exclude, order, skip, take, flags));
60+
61+
public async Task<SortedSetEntry[]> SortedSetRangeByScoreWithScoresAsync(ValkeyKey key, double start = double.NegativeInfinity, double stop = double.PositiveInfinity, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None)
62+
=> await Command(Request.SortedSetRangeByScoreWithScoresAsync(key, start, stop, exclude, order, skip, take, flags));
63+
64+
public async Task<ValkeyValue[]> SortedSetRangeByValueAsync(ValkeyKey key, ValkeyValue min, ValkeyValue max, Exclude exclude, long skip, long take, CommandFlags flags = CommandFlags.None)
65+
=> await SortedSetRangeByValueAsync(key, min, max, exclude, Order.Ascending, skip, take, flags);
66+
67+
public async Task<ValkeyValue[]> SortedSetRangeByValueAsync(
68+
ValkeyKey key,
69+
ValkeyValue min = default,
70+
ValkeyValue max = default,
71+
Exclude exclude = Exclude.None,
72+
Order order = Order.Ascending,
73+
long skip = 0,
74+
long take = -1,
75+
CommandFlags flags = CommandFlags.None)
76+
=> await Command(Request.SortedSetRangeByValueAsync(key, min, max, exclude, order, skip, take, flags));
3377
}

csharp/sources/Valkey.Glide/Commands/Constants/Constants.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,29 @@ public static class Constants
1313
public const string AbsttlKeyword = "ABSTTL";
1414
public const string IdletimeKeyword = "IDLETIME";
1515
public const string FreqKeyword = "FREQ";
16+
public const string WithScoresKeyword = "WITHSCORES";
17+
public const string ReverseKeyword = "REV";
18+
public const string ByLexKeyword = "BYLEX";
19+
public const string ByScoreKeyword = "BYSCORE";
20+
21+
/// <summary>
22+
/// The highest bound in the sorted set for lexicographical operations.
23+
/// </summary>
24+
public const string PositiveInfinity = "+";
25+
26+
/// <summary>
27+
/// The lowest bound in the sorted set for lexicographical operations.
28+
/// </summary>
29+
public const string NegativeInfinity = "-";
30+
31+
/// <summary>
32+
/// The highest bound in the sorted set for score operations.
33+
/// </summary>
34+
public const string PositiveInfinityScore = "+inf";
35+
36+
/// <summary>
37+
/// The lowest bound in the sorted set for score operations.
38+
/// </summary>
39+
public const string NegativeInfinityScore = "-inf";
40+
1641
}

csharp/sources/Valkey.Glide/Commands/ISortedSetCommands.cs

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,260 @@ public interface ISortedSetCommands
106106
/// </example>
107107
/// </remarks>
108108
Task<long> SortedSetRemoveAsync(ValkeyKey key, ValkeyValue[] members, CommandFlags flags = CommandFlags.None);
109+
110+
/// <summary>
111+
/// Returns the sorted set cardinality (number of elements) of the sorted set stored at key.
112+
/// </summary>
113+
/// <seealso href="https://valkey.io/commands/zcard"/>
114+
/// <seealso href="https://valkey.io/commands/zcount"/>
115+
/// <param name="key">The key of the sorted set.</param>
116+
/// <param name="min">The min score to filter by (defaults to negative infinity).</param>
117+
/// <param name="max">The max score to filter by (defaults to positive infinity).</param>
118+
/// <param name="exclude">Whether to exclude <paramref name="min"/> and <paramref name="max"/> from the range check (defaults to both inclusive).</param>
119+
/// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param>
120+
/// <returns>The cardinality (number of elements) of the sorted set, or 0 if key does not exist.</returns>
121+
/// <remarks>
122+
/// <example>
123+
/// <code>
124+
/// // Get total cardinality
125+
/// long totalCount = await client.SortedSetLengthAsync(key);
126+
///
127+
/// // Count elements in score range
128+
/// long rangeCount = await client.SortedSetLengthAsync(key, 1.0, 10.0);
129+
/// </code>
130+
/// </example>
131+
/// </remarks>
132+
Task<long> SortedSetLengthAsync(ValkeyKey key, double min = double.NegativeInfinity, double max = double.PositiveInfinity, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None);
133+
134+
/// <summary>
135+
/// Returns the cardinality (number of elements) of the sorted set stored at key.
136+
/// </summary>
137+
/// <seealso href="https://valkey.io/commands/zcard"/>
138+
/// <param name="key">The key of the sorted set.</param>
139+
/// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param>
140+
/// <returns>
141+
/// The number of elements in the sorted set.
142+
/// If key does not exist, it is treated as an empty sorted set, and this command returns 0.
143+
/// If key holds a value that is not a sorted set, an error is returned.
144+
/// </returns>
145+
/// <remarks>
146+
/// <example>
147+
/// <code>
148+
/// long result = await client.SortedSetCardAsync(key);
149+
/// </code>
150+
/// </example>
151+
/// </remarks>
152+
Task<long> SortedSetCardAsync(ValkeyKey key, CommandFlags flags = CommandFlags.None);
153+
154+
/// <summary>
155+
/// Returns the number of members in the sorted set stored at key with scores between min and max score.
156+
/// </summary>
157+
/// <seealso href="https://valkey.io/commands/zcount"/>
158+
/// <param name="key">The key of the sorted set.</param>
159+
/// <param name="min">The minimum score to count from (defaults to negative infinity).</param>
160+
/// <param name="max">The maximum score to count up to (defaults to positive infinity).</param>
161+
/// <param name="exclude">Whether to exclude min and max from the range check (defaults to both inclusive).</param>
162+
/// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param>
163+
/// <returns>The number of members in the specified score range.</returns>
164+
/// <remarks>
165+
/// <example>
166+
/// <code>
167+
/// long result = await client.SortedSetCountAsync(key, 1.0, 10.0);
168+
/// </code>
169+
/// </example>
170+
/// </remarks>
171+
Task<long> SortedSetCountAsync(ValkeyKey key, double min = double.NegativeInfinity, double max = double.PositiveInfinity, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None);
172+
173+
/// <summary>
174+
/// Returns the specified range of elements in the sorted set stored at key by their index (rank).
175+
/// By default the elements are considered to be ordered from the lowest to the highest score.
176+
/// Both start and stop are zero-based indexes, where 0 is the first element, 1 is the next element and so on.<br/>
177+
/// To get the elements with their scores, <see cref="SortedSetRangeByRankWithScoresAsync" />.
178+
/// </summary>
179+
/// <seealso href="https://valkey.io/commands/zrange"/>
180+
/// <param name="key">The key of the sorted set.</param>
181+
/// <param name="start">The start index to get.</param>
182+
/// <param name="stop">The stop index to get.</param>
183+
/// <param name="order">The order to sort by (defaults to ascending).</param>
184+
/// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param>
185+
/// <returns>
186+
/// An array of elements within the specified range.
187+
/// If key does not exist, it is treated as an empty sorted set, and the command returns an empty array.
188+
/// </returns>
189+
/// <remarks>
190+
/// <example>
191+
/// <code>
192+
/// ValkeyValue[] result = await client.SortedSetRangeByRankAsync(key, 0, 10);
193+
/// </code>
194+
/// </example>
195+
/// </remarks>
196+
Task<ValkeyValue[]> SortedSetRangeByRankAsync(ValkeyKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);
197+
198+
/// <summary>
199+
/// Returns the specified range of elements with their scores in the sorted set stored at key by their index (rank).
200+
/// By default the elements are considered to be ordered from the lowest to the highest score.
201+
/// Both start and stop are zero-based indexes, where 0 is the first element, 1 is the next element and so on.<br/>
202+
/// To get the elements without their scores, <see cref="SortedSetRangeByRankAsync" />.
203+
/// </summary>
204+
/// <seealso href="https://valkey.io/commands/zrange"/>
205+
/// <seealso href="https://redis.io/commands/zrevrange"/>.
206+
/// <param name="key">The key of the sorted set.</param>
207+
/// <param name="start">The start index to get.</param>
208+
/// <param name="stop">The stop index to get.</param>
209+
/// <param name="order">The order to sort by (defaults to ascending).</param>
210+
/// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param>
211+
/// <returns>
212+
/// An array of elements and their scores within the specified range.
213+
/// If key does not exist, it is treated as an empty sorted set, and the command returns an empty array.
214+
/// </returns>
215+
/// <remarks>
216+
/// <example>
217+
/// <code>
218+
/// SortedSetEntry[] result = await client.SortedSetRangeByRankWithScoresAsync(key, 0, 10);
219+
/// </code>
220+
/// </example>
221+
/// </remarks>
222+
Task<SortedSetEntry[]> SortedSetRangeByRankWithScoresAsync(ValkeyKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);
223+
224+
/// <summary>
225+
/// Returns the specified range of elements in the sorted set stored at key by their score.
226+
/// By default the elements are considered to be ordered from the lowest to the highest score.
227+
/// Start and stop are used to specify the min and max range for score values.
228+
/// To get the elements with their scores, <see cref="SortedSetRangeByScoreWithScoresAsync" />.
229+
/// </summary>
230+
/// <seealso href="https://valkey.io/commands/zrange"/>
231+
/// <seealso href="https://redis.io/commands/zrevrange"/>.
232+
/// <param name="key">The key of the sorted set.</param>
233+
/// <param name="start">The minimum score to filter by.</param>
234+
/// <param name="stop">The maximum score to filter by.</param>
235+
/// <param name="exclude">Which of start and stop to exclude (defaults to both inclusive).</param>
236+
/// <param name="order">The order to sort by (defaults to ascending).</param>
237+
/// <param name="skip">How many items to skip.</param>
238+
/// <param name="take">How many items to take.</param>
239+
/// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param>
240+
/// <returns>
241+
/// An array of elements within the specified range.
242+
/// If key does not exist, it is treated as an empty sorted set, and the command returns an empty array.
243+
/// </returns>
244+
/// <remarks>
245+
/// <example>
246+
/// <code>
247+
/// ValkeyValue[] result = await client.SortedSetRangeByScoreAsync(key, 1.0, 10.0);
248+
/// </code>
249+
/// </example>
250+
/// </remarks>
251+
Task<ValkeyValue[]> SortedSetRangeByScoreAsync(
252+
ValkeyKey key,
253+
double start = double.NegativeInfinity,
254+
double stop = double.PositiveInfinity,
255+
Exclude exclude = Exclude.None,
256+
Order order = Order.Ascending,
257+
long skip = 0,
258+
long take = -1,
259+
CommandFlags flags = CommandFlags.None);
260+
261+
/// <summary>
262+
/// Returns the specified range of elements in the sorted set stored at key with their scores by their score.
263+
/// By default the elements are considered to be ordered from the lowest to the highest score.
264+
/// Start and stop are used to specify the min and max range for score values
265+
/// To get the elements without their scores, <see cref="SortedSetRangeByScoreAsync" />.
266+
/// </summary>.
267+
/// <seealso href="https://valkey.io/commands/zrange"/>
268+
/// <seealso href="https://redis.io/commands/zrevrange"/>.
269+
/// <param name="key">The key of the sorted set.</param>
270+
/// <param name="start">The minimum score to filter by.</param>
271+
/// <param name="stop">The maximum score to filter by.</param>
272+
/// <param name="exclude">Which of start and stop to exclude (defaults to both inclusive).</param>
273+
/// <param name="order">The order to sort by (defaults to ascending).</param>
274+
/// <param name="skip">How many items to skip.</param>
275+
/// <param name="take">How many items to take.</param>
276+
/// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param>
277+
/// <returns>
278+
/// An array of elements and their scores within the specified range.
279+
/// If key does not exist, it is treated as an empty sorted set, and the command returns an empty array.
280+
/// </returns>
281+
/// <remarks>
282+
/// <example>
283+
/// <code>
284+
/// SortedSetEntry[] result = await client.SortedSetRangeByScoreWithScoresAsync(key, 1.0, 10.0);
285+
/// </code>
286+
/// </example>
287+
/// </remarks>
288+
Task<SortedSetEntry[]> SortedSetRangeByScoreWithScoresAsync(
289+
ValkeyKey key,
290+
double start = double.NegativeInfinity,
291+
double stop = double.PositiveInfinity,
292+
Exclude exclude = Exclude.None,
293+
Order order = Order.Ascending,
294+
long skip = 0,
295+
long take = -1,
296+
CommandFlags flags = CommandFlags.None);
297+
298+
/// <summary>
299+
/// Returns the specified range of elements in the sorted set stored at key by their lexicographical order.
300+
/// This command returns all the elements in the sorted set at key with a value between min and max.
301+
/// </summary>
302+
/// <seealso href="https://valkey.io/commands/zrange"/>
303+
/// <seealso href="https://redis.io/commands/zrevrange"/>.
304+
/// <param name="key">The key of the sorted set.</param>
305+
/// <param name="min">The min value to filter by.</param>
306+
/// <param name="max">The max value to filter by.</param>
307+
/// <param name="exclude">Which of min and max to exclude.</param>
308+
/// <param name="skip">How many items to skip.</param>
309+
/// <param name="take">How many items to take.</param>
310+
/// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param>
311+
/// <returns>
312+
/// An array of elements within the specified range.
313+
/// If key does not exist, it is treated as an empty sorted set, and the command returns an empty array.
314+
/// </returns>
315+
/// <remarks>
316+
/// <example>
317+
/// <code>
318+
/// ValkeyValue[] result = await client.SortedSetRangeByValueAsync(key, "a", "z", Exclude.None, 0, -1);
319+
/// </code>
320+
/// </example>
321+
/// </remarks>
322+
Task<ValkeyValue[]> SortedSetRangeByValueAsync(
323+
ValkeyKey key,
324+
ValkeyValue min,
325+
ValkeyValue max,
326+
Exclude exclude,
327+
long skip,
328+
long take = -1,
329+
CommandFlags flags = CommandFlags.None);
330+
331+
/// <summary>
332+
/// Returns the specified range of elements in the sorted set stored at key by their lexicographical order.
333+
/// This command returns all the elements in the sorted set at key with a value between min and max.
334+
/// </summary>
335+
/// <seealso href="https://valkey.io/commands/zrange"/>
336+
/// <seealso href="https://redis.io/commands/zrevrange"/>.
337+
/// <param name="key">The key of the sorted set.</param>
338+
/// <param name="min">The min value to filter by.</param>
339+
/// <param name="max">The max value to filter by.</param>
340+
/// <param name="exclude">Which of min and max to exclude (defaults to both inclusive).</param>
341+
/// <param name="order">The order to sort by (defaults to ascending).</param>
342+
/// <param name="skip">How many items to skip.</param>
343+
/// <param name="take">How many items to take.</param>
344+
/// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param>
345+
/// <returns>
346+
/// An array of elements within the specified range.
347+
/// If key does not exist, it is treated as an empty sorted set, and the command returns an empty array.
348+
/// </returns>
349+
/// <remarks>
350+
/// <example>
351+
/// <code>
352+
/// ValkeyValue[] result = await client.SortedSetRangeByValueAsync(key, "a", "z", order: Order.Descending);
353+
/// </code>
354+
/// </example>
355+
/// </remarks>
356+
Task<ValkeyValue[]> SortedSetRangeByValueAsync(
357+
ValkeyKey key,
358+
ValkeyValue min = default,
359+
ValkeyValue max = default,
360+
Exclude exclude = Exclude.None,
361+
Order order = Order.Ascending,
362+
long skip = 0,
363+
long take = -1,
364+
CommandFlags flags = CommandFlags.None);
109365
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
2+
3+
namespace Valkey.Glide.Commands.Options;
4+
5+
/// <summary>
6+
/// Represents the range options for the ZCOUNT command.
7+
/// </summary>
8+
/// <param name="min">The minimum score boundary.</param>
9+
/// <param name="max">The maximum score boundary.</param>
10+
public readonly struct ZCountRange(ScoreBoundary min, ScoreBoundary max)
11+
{
12+
/// <summary>
13+
/// The minimum score boundary.
14+
/// </summary>
15+
public ScoreBoundary Min { get; } = min;
16+
17+
/// <summary>
18+
/// The maximum score boundary.
19+
/// </summary>
20+
public ScoreBoundary Max { get; } = max;
21+
22+
/// <summary>
23+
/// Converts the range to command arguments.
24+
/// </summary>
25+
/// <returns>An array of string arguments for the command.</returns>
26+
internal string[] ToArgs() => [Min.ToString(), Max.ToString()];
27+
}

0 commit comments

Comments
 (0)