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

Commit b04225a

Browse files
committed
Add in remaining Redis GEO API's
1 parent 15e8e41 commit b04225a

File tree

4 files changed

+235
-5
lines changed

4 files changed

+235
-5
lines changed

lib/ServiceStack.Interfaces.dll

512 Bytes
Binary file not shown.

src/ServiceStack.Redis/Commands.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using ServiceStack.Text;
23

34
namespace ServiceStack.Redis
@@ -219,5 +220,34 @@ public static class Commands
219220
public readonly static byte[] GeoPos = "GEOPOS".ToUtf8Bytes();
220221
public readonly static byte[] GeoRadius = "GEORADIUS".ToUtf8Bytes();
221222
public readonly static byte[] GeoRadiusByMember = "GEORADIUSBYMEMBER".ToUtf8Bytes();
223+
224+
public readonly static byte[] WithCoord = "WITHCOORD".ToUtf8Bytes();
225+
public readonly static byte[] WithDist = "WITHDIST".ToUtf8Bytes();
226+
public readonly static byte[] WithHash = "WITHHASH".ToUtf8Bytes();
227+
228+
public readonly static byte[] Meters = RedisGeoUnit.Meters.ToUtf8Bytes();
229+
public readonly static byte[] Kilometers = RedisGeoUnit.Kilometers.ToUtf8Bytes();
230+
public readonly static byte[] Miles = RedisGeoUnit.Miles.ToUtf8Bytes();
231+
public readonly static byte[] Feet = RedisGeoUnit.Feet.ToUtf8Bytes();
232+
233+
public static byte[] GetUnit(string unit)
234+
{
235+
if (unit == null)
236+
throw new ArgumentNullException("unit");
237+
238+
switch (unit)
239+
{
240+
case RedisGeoUnit.Meters:
241+
return Meters;
242+
case RedisGeoUnit.Kilometers:
243+
return Kilometers;
244+
case RedisGeoUnit.Miles:
245+
return Miles;
246+
case RedisGeoUnit.Feet:
247+
return Feet;
248+
default:
249+
throw new NotSupportedException("Unit '{0}' is not a valid unit".Fmt(unit));
250+
}
251+
}
222252
}
223253
}

src/ServiceStack.Redis/RedisNativeClient.cs

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2215,6 +2215,9 @@ public long GeoAdd(string key, double longitude, double latitude, string member)
22152215

22162216
public long GeoAdd(string key, params RedisGeo[] geoPoints)
22172217
{
2218+
if (key == null)
2219+
throw new ArgumentNullException("key");
2220+
22182221
var members = new byte[geoPoints.Length * 3][];
22192222
for (var i = 0; i < geoPoints.Length; i++)
22202223
{
@@ -2230,19 +2233,28 @@ public long GeoAdd(string key, params RedisGeo[] geoPoints)
22302233

22312234
public double GeoDist(string key, string fromMember, string toMember, string unit = null)
22322235
{
2236+
if (key == null)
2237+
throw new ArgumentNullException("key");
2238+
22332239
return unit == null
22342240
? SendExpectDouble(Commands.GeoDist, key.ToUtf8Bytes(), fromMember.ToUtf8Bytes(), toMember.ToUtf8Bytes())
22352241
: SendExpectDouble(Commands.GeoDist, key.ToUtf8Bytes(), fromMember.ToUtf8Bytes(), toMember.ToUtf8Bytes(), unit.ToUtf8Bytes());
22362242
}
22372243

22382244
public string[] GeoHash(string key, params string[] members)
22392245
{
2246+
if (key == null)
2247+
throw new ArgumentNullException("key");
2248+
22402249
var cmdWithArgs = MergeCommandWithArgs(Commands.GeoHash, key.ToUtf8Bytes(), members.Map(x => x.ToUtf8Bytes()).ToArray());
22412250
return SendExpectMultiData(cmdWithArgs).ToStringArray();
22422251
}
22432252

22442253
public List<RedisGeo> GeoPos(string key, params string[] members)
22452254
{
2255+
if (key == null)
2256+
throw new ArgumentNullException("key");
2257+
22462258
var cmdWithArgs = MergeCommandWithArgs(Commands.GeoPos, key.ToUtf8Bytes(), members.Map(x => x.ToUtf8Bytes()).ToArray());
22472259
var data = SendExpectComplexResponse(cmdWithArgs);
22482260
var to = new List<RedisGeo>();
@@ -2261,10 +2273,76 @@ public List<RedisGeo> GeoPos(string key, params string[] members)
22612273
return to;
22622274
}
22632275

2264-
public List<RedisGeoResult> GeoRadius(string key, double longitude, double latitude, double radius,
2265-
string unit = null, bool withCoords = false, bool withHash = false, int count = 0, bool? asc = null)
2276+
public List<RedisGeoResult> GeoRadius(string key, double longitude, double latitude, double radius, string unit,
2277+
bool withCoords = false, bool withDist = false, bool withHash = false, int? count = null, bool? asc = null)
22662278
{
2267-
throw new NotImplementedException();
2279+
if (key == null)
2280+
throw new ArgumentNullException("key");
2281+
2282+
var args = new List<byte[]>
2283+
{
2284+
longitude.ToUtf8Bytes(),
2285+
latitude.ToUtf8Bytes(),
2286+
radius.ToUtf8Bytes(),
2287+
Commands.GetUnit(unit),
2288+
};
2289+
2290+
if (withCoords)
2291+
args.Add(Commands.WithCoord);
2292+
if (withDist)
2293+
args.Add(Commands.WithDist);
2294+
if (withHash)
2295+
args.Add(Commands.WithHash);
2296+
2297+
if (count != null)
2298+
{
2299+
args.Add(Commands.Count);
2300+
args.Add(count.Value.ToUtf8Bytes());
2301+
}
2302+
2303+
if (asc == true)
2304+
args.Add(Commands.Asc);
2305+
else if (asc == false)
2306+
args.Add(Commands.Desc);
2307+
2308+
var cmdWithArgs = MergeCommandWithArgs(Commands.GeoRadius, key.ToUtf8Bytes(), args.ToArray());
2309+
2310+
var to = new List<RedisGeoResult>();
2311+
2312+
if (!(withCoords || withDist || withHash))
2313+
{
2314+
var members = SendExpectMultiData(cmdWithArgs).ToStringArray();
2315+
foreach (var member in members)
2316+
{
2317+
to.Add(new RedisGeoResult { Member = member });
2318+
}
2319+
}
2320+
else
2321+
{
2322+
var data = SendExpectComplexResponse(cmdWithArgs);
2323+
2324+
foreach (var child in data.Children)
2325+
{
2326+
var i = 0;
2327+
var result = new RedisGeoResult { Unit = unit, Member = child.Children[i++].Data.FromUtf8Bytes() };
2328+
2329+
if (withDist)
2330+
result.Distance = double.Parse(child.Children[i++].Data.FromUtf8Bytes());
2331+
2332+
if (withHash)
2333+
result.Hash = long.Parse(child.Children[i++].Data.FromUtf8Bytes());
2334+
2335+
if (withCoords)
2336+
{
2337+
result.Longitude = double.Parse(child.Children[i].Children[0].Data.FromUtf8Bytes());
2338+
result.Latitude = double.Parse(child.Children[i].Children[1].Data.FromUtf8Bytes());
2339+
}
2340+
2341+
to.Add(result);
2342+
}
2343+
}
2344+
2345+
return to;
22682346
}
22692347

22702348
public List<RedisGeoResult> GeoRadiusByMember(string key, double longitude, double latitude, double radius,

tests/ServiceStack.Redis.Tests/RedisGeoTests.cs

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
using NUnit.Framework;
2+
using ServiceStack.Text;
23

34
namespace ServiceStack.Redis.Tests
45
{
56
[TestFixture]
7+
[Explicit, Ignore("CI requires redis-server v3.2.0")]
68
public class RedisGeoTests
79
{
810
private readonly RedisNativeClient redis;
@@ -22,7 +24,8 @@ public void TestFixtureTearDown()
2224
public void Can_GeoAdd_and_GeoPos()
2325
{
2426
redis.FlushDb();
25-
redis.GeoAdd("Sicily", 13.361389, 38.115556, "Palermo");
27+
var count = redis.GeoAdd("Sicily", 13.361389, 38.115556, "Palermo");
28+
Assert.That(count, Is.EqualTo(1));
2629
var results = redis.GeoPos("Sicily", "Palermo");
2730

2831
Assert.That(results.Count, Is.EqualTo(1));
@@ -35,9 +38,10 @@ public void Can_GeoAdd_and_GeoPos()
3538
public void Can_GeoAdd_and_GeoPos_multiple()
3639
{
3740
redis.FlushDb();
38-
redis.GeoAdd("Sicily",
41+
var count = redis.GeoAdd("Sicily",
3942
new RedisGeo(13.361389, 38.115556, "Palermo"),
4043
new RedisGeo(15.087269, 37.502669, "Catania"));
44+
Assert.That(count, Is.EqualTo(2));
4145

4246
var results = redis.GeoPos("Sicily", "Palermo", "Catania");
4347

@@ -66,6 +70,7 @@ public void Can_GeoDist()
6670
[Test]
6771
public void Can_GeoHash()
6872
{
73+
redis.FlushDb();
6974
redis.GeoAdd("Sicily",
7075
new RedisGeo(13.361389, 38.115556, "Palermo"),
7176
new RedisGeo(15.087269, 37.502669, "Catania"));
@@ -74,5 +79,122 @@ public void Can_GeoHash()
7479
Assert.That(hashes[0], Is.EqualTo("sqc8b49rny0"));
7580
Assert.That(hashes[1], Is.EqualTo("sqdtr74hyu0"));
7681
}
82+
83+
[Test]
84+
public void Can_GeoRadius_default()
85+
{
86+
redis.FlushDb();
87+
redis.GeoAdd("Sicily",
88+
new RedisGeo(13.361389, 38.115556, "Palermo"),
89+
new RedisGeo(15.087269, 37.502669, "Catania"));
90+
91+
var results = redis.GeoRadius("Sicily", 15, 37, 200, RedisGeoUnit.Kilometers);
92+
93+
Assert.That(results.Count, Is.EqualTo(2));
94+
Assert.That(results[0].Member, Is.EqualTo("Palermo"));
95+
Assert.That(results[0].Unit, Is.Null);
96+
Assert.That(results[1].Member, Is.EqualTo("Catania"));
97+
Assert.That(results[1].Unit, Is.Null);
98+
}
99+
100+
[Test]
101+
public void Can_GeoRadius_WithCoord()
102+
{
103+
redis.FlushDb();
104+
redis.GeoAdd("Sicily",
105+
new RedisGeo(13.361389, 38.115556, "Palermo"),
106+
new RedisGeo(15.087269, 37.502669, "Catania"));
107+
108+
var results = redis.GeoRadius("Sicily", 15, 37, 200, RedisGeoUnit.Kilometers, withCoords: true);
109+
110+
Assert.That(results.Count, Is.EqualTo(2));
111+
Assert.That(results[0].Member, Is.EqualTo("Palermo"));
112+
Assert.That(results[0].Unit, Is.EqualTo(RedisGeoUnit.Kilometers));
113+
Assert.That(results[0].Longitude, Is.EqualTo(13.361389).Within(.1));
114+
Assert.That(results[0].Latitude, Is.EqualTo(38.115556).Within(.1));
115+
116+
Assert.That(results[1].Member, Is.EqualTo("Catania"));
117+
Assert.That(results[1].Unit, Is.EqualTo(RedisGeoUnit.Kilometers));
118+
Assert.That(results[1].Longitude, Is.EqualTo(15.087269).Within(.1));
119+
Assert.That(results[1].Latitude, Is.EqualTo(37.502669).Within(.1));
120+
}
121+
122+
[Test]
123+
public void Can_GeoRadius_WithDist()
124+
{
125+
redis.FlushDb();
126+
redis.GeoAdd("Sicily",
127+
new RedisGeo(13.361389, 38.115556, "Palermo"),
128+
new RedisGeo(15.087269, 37.502669, "Catania"));
129+
130+
var results = redis.GeoRadius("Sicily", 15, 37, 200, RedisGeoUnit.Kilometers, withDist: true);
131+
132+
Assert.That(results.Count, Is.EqualTo(2));
133+
Assert.That(results[0].Member, Is.EqualTo("Palermo"));
134+
Assert.That(results[0].Unit, Is.EqualTo(RedisGeoUnit.Kilometers));
135+
Assert.That(results[0].Distance, Is.EqualTo(190.4424).Within(.1));
136+
137+
Assert.That(results[1].Member, Is.EqualTo("Catania"));
138+
Assert.That(results[1].Unit, Is.EqualTo(RedisGeoUnit.Kilometers));
139+
Assert.That(results[1].Distance, Is.EqualTo(56.4413).Within(.1));
140+
}
141+
142+
[Test]
143+
public void Can_GeoRadius_WithCoord_WithDist_WithHash()
144+
{
145+
redis.FlushDb();
146+
redis.GeoAdd("Sicily",
147+
new RedisGeo(13.361389, 38.115556, "Palermo"),
148+
new RedisGeo(15.087269, 37.502669, "Catania"));
149+
150+
var results = redis.GeoRadius("Sicily", 15, 37, 200, RedisGeoUnit.Kilometers,
151+
withCoords: true, withDist: true, withHash: true);
152+
153+
Assert.That(results.Count, Is.EqualTo(2));
154+
Assert.That(results[0].Member, Is.EqualTo("Palermo"));
155+
Assert.That(results[0].Unit, Is.EqualTo(RedisGeoUnit.Kilometers));
156+
Assert.That(results[0].Longitude, Is.EqualTo(13.361389).Within(.1));
157+
Assert.That(results[0].Latitude, Is.EqualTo(38.115556).Within(.1));
158+
Assert.That(results[0].Distance, Is.EqualTo(190.4424).Within(.1));
159+
Assert.That(results[0].Hash, Is.EqualTo(3479099956230698));
160+
161+
Assert.That(results[1].Member, Is.EqualTo("Catania"));
162+
Assert.That(results[1].Unit, Is.EqualTo(RedisGeoUnit.Kilometers));
163+
Assert.That(results[1].Longitude, Is.EqualTo(15.087269).Within(.1));
164+
Assert.That(results[1].Latitude, Is.EqualTo(37.502669).Within(.1));
165+
Assert.That(results[1].Distance, Is.EqualTo(56.4413).Within(.1));
166+
Assert.That(results[1].Hash, Is.EqualTo(3479447370796909));
167+
}
168+
169+
[Test]
170+
public void Can_GeoRadius_WithCoord_WithDist_WithHash_Count_and_Asc()
171+
{
172+
redis.FlushDb();
173+
redis.GeoAdd("Sicily",
174+
new RedisGeo(13.361389, 38.115556, "Palermo"),
175+
new RedisGeo(15.087269, 37.502669, "Catania"));
176+
177+
var results = redis.GeoRadius("Sicily", 15, 37, 200, RedisGeoUnit.Kilometers,
178+
withCoords: true, withDist: true, withHash: true, count:1, asc:false);
179+
180+
Assert.That(results.Count, Is.EqualTo(1));
181+
Assert.That(results[0].Member, Is.EqualTo("Palermo"));
182+
Assert.That(results[0].Unit, Is.EqualTo(RedisGeoUnit.Kilometers));
183+
Assert.That(results[0].Longitude, Is.EqualTo(13.361389).Within(.1));
184+
Assert.That(results[0].Latitude, Is.EqualTo(38.115556).Within(.1));
185+
Assert.That(results[0].Distance, Is.EqualTo(190.4424).Within(.1));
186+
Assert.That(results[0].Hash, Is.EqualTo(3479099956230698));
187+
188+
results = redis.GeoRadius("Sicily", 15, 37, 200, RedisGeoUnit.Kilometers,
189+
withCoords: true, withDist: true, withHash: true, count: 1, asc: true);
190+
191+
Assert.That(results.Count, Is.EqualTo(1));
192+
Assert.That(results[0].Member, Is.EqualTo("Catania"));
193+
Assert.That(results[0].Unit, Is.EqualTo(RedisGeoUnit.Kilometers));
194+
Assert.That(results[0].Longitude, Is.EqualTo(15.087269).Within(.1));
195+
Assert.That(results[0].Latitude, Is.EqualTo(37.502669).Within(.1));
196+
Assert.That(results[0].Distance, Is.EqualTo(56.4413).Within(.1));
197+
Assert.That(results[0].Hash, Is.EqualTo(3479447370796909));
198+
}
77199
}
78200
}

0 commit comments

Comments
 (0)