Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit f27b5e3

Browse files
committed
Add ZRangeByLex, ZLexCount and ZRemRangeByLex to RedisClient and RedisNativeClient
1 parent 00e3805 commit f27b5e3

File tree

5 files changed

+191
-1
lines changed

5 files changed

+191
-1
lines changed

src/ServiceStack.Redis/Commands.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ public static class Commands
141141
public readonly static byte[] ZRemRangeByScore = "ZREMRANGEBYSCORE".ToUtf8Bytes();
142142
public readonly static byte[] ZUnionStore = "ZUNIONSTORE".ToUtf8Bytes();
143143
public readonly static byte[] ZInterStore = "ZINTERSTORE".ToUtf8Bytes();
144+
public static readonly byte[] ZRangeByLex = "ZRANGEBYLEX".ToUtf8Bytes();
145+
public static readonly byte[] ZLexCount = "ZLEXCOUNT".ToUtf8Bytes();
146+
public static readonly byte[] ZRemRangeByLex = "ZREMRANGEBYLEX".ToUtf8Bytes();
144147

145148
public readonly static byte[] HSet = "HSET".ToUtf8Bytes();
146149
public readonly static byte[] HSetNx = "HSETNX".ToUtf8Bytes();

src/ServiceStack.Redis/RedisClient_SortedSet.cs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,5 +417,42 @@ public long StoreUnionFromSortedSets(string intoSetId, params string[] setIds)
417417
{
418418
return base.ZUnionStore(intoSetId, setIds);
419419
}
420-
}
420+
421+
private static string GetSearchStart(string start)
422+
{
423+
return start == null
424+
? "-"
425+
: start.IndexOfAny("[", "(", "-") != 0
426+
? "[" + start
427+
: start;
428+
}
429+
430+
private static string GetSearchEnd(string end)
431+
{
432+
return end == null
433+
? "+"
434+
: end.IndexOfAny("[", "(", "+") != 0
435+
? "[" + end
436+
: end;
437+
}
438+
439+
public List<string> SearchSortedSet(string setId, string start = null, string end = null, int? skip=null, int? take=null)
440+
{
441+
start = GetSearchStart(start);
442+
end = GetSearchEnd(end);
443+
444+
var ret = base.ZRangeByLex(setId, start, end, skip, take);
445+
return ret.ToStringList();
446+
}
447+
448+
public long SearchSortedSetCount(string setId, string start = null, string end = null)
449+
{
450+
return base.ZLexCount(setId, GetSearchStart(start), GetSearchEnd(end));
451+
}
452+
453+
public long RemoveRangeFromSortedSetBySearch(string setId, string start = null, string end = null)
454+
{
455+
return base.ZRemRangeByLex(setId, GetSearchStart(start), GetSearchEnd(end));
456+
}
457+
}
421458
}

src/ServiceStack.Redis/RedisNativeClient.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,6 +1647,44 @@ public long ZInterStore(string intoSetId, params string[] setIds)
16471647
return SendExpectLong(cmdWithArgs);
16481648
}
16491649

1650+
public byte[][] ZRangeByLex(string setId, string min, string max, int? skip=null, int? take=null)
1651+
{
1652+
if (setId == null)
1653+
throw new ArgumentNullException("setId");
1654+
1655+
var cmdWithArgs = new List<byte[]>
1656+
{
1657+
Commands.ZRangeByLex, setId.ToUtf8Bytes(), min.ToUtf8Bytes(), max.ToUtf8Bytes()
1658+
};
1659+
1660+
if (skip.HasValue || take.HasValue)
1661+
{
1662+
cmdWithArgs.Add(Commands.Limit);
1663+
cmdWithArgs.Add(skip.GetValueOrDefault(0).ToUtf8Bytes());
1664+
cmdWithArgs.Add(take.GetValueOrDefault(0).ToUtf8Bytes());
1665+
}
1666+
1667+
return SendExpectMultiData(cmdWithArgs.ToArray());
1668+
}
1669+
1670+
public long ZLexCount(string setId, string min, string max)
1671+
{
1672+
if (setId == null)
1673+
throw new ArgumentNullException("setId");
1674+
1675+
return SendExpectLong(
1676+
Commands.ZLexCount, setId.ToUtf8Bytes(), min.ToUtf8Bytes(), max.ToUtf8Bytes());
1677+
}
1678+
1679+
public long ZRemRangeByLex(string setId, string min, string max)
1680+
{
1681+
if (setId == null)
1682+
throw new ArgumentNullException("setId");
1683+
1684+
return SendExpectLong(
1685+
Commands.ZRemRangeByLex, setId.ToUtf8Bytes(), min.ToUtf8Bytes(), max.ToUtf8Bytes());
1686+
}
1687+
16501688
#endregion
16511689

16521690

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
using NUnit.Framework;
2+
3+
namespace ServiceStack.Redis.Tests
4+
{
5+
[TestFixture]
6+
public class LexTests
7+
: RedisClientTestsBase
8+
{
9+
readonly string[] values = "a,b,c,d,e,f,g".Split(',');
10+
11+
[SetUp]
12+
public void SetUp()
13+
{
14+
Redis.FlushAll();
15+
values.Each(x => Redis.ZAdd("zset", 0, x.ToUtf8Bytes()));
16+
}
17+
18+
[Test]
19+
public void Can_ZRangeByLex_all_entries()
20+
{
21+
var results = Redis.ZRangeByLex("zset", "-", "+");
22+
23+
Assert.That(results.Map(x => x.FromUtf8Bytes()), Is.EquivalentTo(values));
24+
25+
results = Redis.ZRangeByLex("zset", "-", "+", 1, 3);
26+
Assert.That(results.Map(x => x.FromUtf8Bytes()), Is.EquivalentTo(new[] { "b", "c", "d" }));
27+
}
28+
29+
[Test]
30+
public void Can_ZRangeByLex_Desc()
31+
{
32+
var descInclusive = Redis.ZRangeByLex("zset", "-", "[c");
33+
Assert.That(descInclusive.Map(x => x.FromUtf8Bytes()), Is.EquivalentTo(new[] { "a", "b", "c" }));
34+
35+
var descExclusive = Redis.ZRangeByLex("zset", "-", "(c");
36+
Assert.That(descExclusive.Map(x => x.FromUtf8Bytes()), Is.EquivalentTo(new[] { "a", "b" }));
37+
}
38+
39+
[Test]
40+
public void Can_ZRangeByLex_Min_and_Max()
41+
{
42+
var range = Redis.ZRangeByLex("zset", "[aaa", "(g");
43+
Assert.That(range.Map(x => x.FromUtf8Bytes()),
44+
Is.EquivalentTo(new[] { "b", "c", "d", "e", "f" }));
45+
}
46+
47+
[Test]
48+
public void Can_ZlexCount()
49+
{
50+
var total = Redis.ZLexCount("zset", "-", "+");
51+
Assert.That(total, Is.EqualTo(values.Length));
52+
53+
Assert.That(Redis.ZLexCount("zset", "-", "[c"), Is.EqualTo(3));
54+
Assert.That(Redis.ZLexCount("zset", "-", "(c"), Is.EqualTo(2));
55+
}
56+
57+
[Test]
58+
public void Can_ZRemRangeByLex()
59+
{
60+
var removed = Redis.ZRemRangeByLex("zset", "[aaa", "(g");
61+
Assert.That(removed, Is.EqualTo(5));
62+
63+
var remainder = Redis.ZRangeByLex("zset", "-", "+");
64+
Assert.That(remainder.Map(x => x.FromUtf8Bytes()), Is.EqualTo(new[] { "a", "g" }));
65+
}
66+
67+
[Test]
68+
public void Can_SearchSortedSet()
69+
{
70+
Assert.That(Redis.SearchSortedSet("zset"), Is.EquivalentTo(values));
71+
Assert.That(Redis.SearchSortedSet("zset", start: "-"), Is.EquivalentTo(values));
72+
Assert.That(Redis.SearchSortedSet("zset", end: "+"), Is.EquivalentTo(values));
73+
74+
Assert.That(Redis.SearchSortedSet("zset", start: "[aaa").Count, Is.EqualTo(values.Length - 1));
75+
Assert.That(Redis.SearchSortedSet("zset", end: "(g").Count, Is.EqualTo(values.Length - 1));
76+
Assert.That(Redis.SearchSortedSet("zset", "[aaa", "(g").Count, Is.EqualTo(values.Length - 2));
77+
78+
Assert.That(Redis.SearchSortedSet("zset", "a", "c").Count, Is.EqualTo(3));
79+
Assert.That(Redis.SearchSortedSet("zset", "[a", "[c").Count, Is.EqualTo(3));
80+
Assert.That(Redis.SearchSortedSet("zset", "a", "(c").Count, Is.EqualTo(2));
81+
Assert.That(Redis.SearchSortedSet("zset", "(a", "(c").Count, Is.EqualTo(1));
82+
}
83+
84+
[Test]
85+
public void Can_SearchSortedSetCount()
86+
{
87+
Assert.That(Redis.SearchSortedSet("zset"), Is.EquivalentTo(values));
88+
Assert.That(Redis.SearchSortedSetCount("zset", start: "-"), Is.EqualTo(values.Length));
89+
Assert.That(Redis.SearchSortedSetCount("zset", end: "+"), Is.EqualTo(values.Length));
90+
91+
Assert.That(Redis.SearchSortedSetCount("zset", start: "[aaa"), Is.EqualTo(values.Length - 1));
92+
Assert.That(Redis.SearchSortedSetCount("zset", end: "(g"), Is.EqualTo(values.Length - 1));
93+
Assert.That(Redis.SearchSortedSetCount("zset", "[aaa", "(g"), Is.EqualTo(values.Length - 2));
94+
95+
Assert.That(Redis.SearchSortedSetCount("zset", "a", "c"), Is.EqualTo(3));
96+
Assert.That(Redis.SearchSortedSetCount("zset", "[a", "[c"), Is.EqualTo(3));
97+
Assert.That(Redis.SearchSortedSetCount("zset", "a", "(c"), Is.EqualTo(2));
98+
Assert.That(Redis.SearchSortedSetCount("zset", "(a", "(c"), Is.EqualTo(1));
99+
}
100+
101+
[Test]
102+
public void Can_RemoveRangeFromSortedSetBySearch()
103+
{
104+
var removed = Redis.RemoveRangeFromSortedSetBySearch("zset", "[aaa", "(g");
105+
Assert.That(removed, Is.EqualTo(5));
106+
107+
var remainder = Redis.SearchSortedSet("zset");
108+
Assert.That(remainder, Is.EqualTo(new[] { "a", "g" }));
109+
}
110+
}
111+
}

tests/ServiceStack.Redis.Tests/ServiceStack.Redis.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@
179179
<Compile Include="DiagnosticTests.cs" />
180180
<Compile Include="Examples\ServiceStack_Redis_UseCase.cs" />
181181
<Compile Include="Generic\RedisClientListTestExtra.cs" />
182+
<Compile Include="LexTests.cs" />
182183
<Compile Include="LicenseUsageTests.cs" />
183184
<Compile Include="ManagedListGenericTests.cs" />
184185
<Compile Include="RedisExtensionTests.cs" />

0 commit comments

Comments
 (0)