Commit 39ff4e5a authored by William Davis's avatar William Davis

Added GeoAdd command and briefly tested. Need to build unit tests. Need to fix GeoAdd [] command.

Added in GeoDist command and tested using the example online, also needs unit tests.

Added in geohash command - needs unit tests.

Added geo pos - needs tests.

started work on tests - moved new types to new files.

Spelling fix. Replaced 'paramter' with 'parameter'

Fixed build error caused by TryGetAzureRoleInstanceIdNoThrow test

Refactoring.

Implemented GeoPosition type and methods.

Updated naming of geodistance

created types needed for geo radius command.

working on GeoRadius method. - needs some more testing.
parent 3f120d27
...@@ -24,7 +24,7 @@ An example use of the `LuaScript`: ...@@ -24,7 +24,7 @@ An example use of the `LuaScript`:
The `LuaScript` class rewrites variables in scripts of the form `@myVar` into the appropriate `ARGV[someIndex]` required by redis. If the The `LuaScript` class rewrites variables in scripts of the form `@myVar` into the appropriate `ARGV[someIndex]` required by redis. If the
parameter passed is of type `RedisKey` it will be sent as part of the `KEYS` collection automatically. parameter passed is of type `RedisKey` it will be sent as part of the `KEYS` collection automatically.
Any object that exposes field or property members with the same name as @-prefixed variables in the Lua script can be used as a paramter hash to Any object that exposes field or property members with the same name as @-prefixed variables in the Lua script can be used as a parameter hash to
`Evaluate` calls. Supported member types are the following: `Evaluate` calls. Supported member types are the following:
- int(?) - int(?)
......
...@@ -138,14 +138,7 @@ public void DefaultClientName() ...@@ -138,14 +138,7 @@ public void DefaultClientName()
#endif #endif
} }
} }
[Test]
public void TryGetAzureRoleInstanceIdNoThrow()
{
ConfigurationOptions config = new ConfigurationOptions();
Assert.IsNull(config.TryGetAzureRoleInstanceIdNoThrow());
}
[Test] [Test]
public void ReadConfigWithConfigDisabled() public void ReadConfigWithConfigDisabled()
{ {
......
...@@ -116,6 +116,12 @@ public void CheckFailureRecovered() ...@@ -116,6 +116,12 @@ public void CheckFailureRecovered()
SocketManager.ConnectCompletionType = CompletionType.Any; SocketManager.ConnectCompletionType = CompletionType.Any;
ClearAmbientFailures(); ClearAmbientFailures();
} }
}
[Test]
public void TryGetAzureRoleInstanceIdNoThrow()
{
Assert.IsNull(ConnectionMultiplexer.TryGetAzureRoleInstanceIdNoThrow());
} }
} }
} }
using System.Linq;
using System.Runtime.Remoting;
using NUnit.Framework;
namespace StackExchange.Redis.Tests
{
[TestFixture]
public class GeoTests : TestBase
{
[Test]
public void GeoAddEveryWay()
{
using (var conn = Create())
{
var db = conn.GetDatabase(3);
var added1 = db.GeoAdd("Sicily", 14.361389, 39.115556, "PalermoPlusOne");
var geo1 = new GeoEntry(13.361389, 38.115556, "Palermo");
var geo2 = new GeoEntry(15.087269, 37.502669, "Catania");
var added2 = db.GeoAdd("Sicily",new GeoEntry[] {geo1,geo2});
Assert.IsTrue(added1 & (added2==2));
}
}
[Test]
public void GetGeoDist()
{
using (var conn = Create())
{
var db = conn.GetDatabase(3);
var geo1 = new GeoEntry(13.361389, 38.115556, "Palermo");
var geo2 = new GeoEntry(15.087269, 37.502669, "Catania");
var added2 = db.GeoAdd("Sicily", new GeoEntry[] { geo1, geo2 });
var val = db.GeoDistance("Sicily", "Palermo", "Catania",GeoUnit.Meters);
Assert.Equals(166274.15156960039, (double) val);
}
}
[Test]
public void AddSetEveryWay()
{
using (var conn = Create())
{
var db = conn.GetDatabase(3);
RedisKey key = Me();
db.KeyDelete(key);
db.SetAdd(key, "a");
db.SetAdd(key, new RedisValue[] { "b" });
db.SetAdd(key, new RedisValue[] { "c", "d" });
db.SetAdd(key, new RedisValue[] { "e", "f", "g" });
db.SetAdd(key, new RedisValue[] { "h", "i", "j", "k" });
var vals = db.SetMembers(key);
string s = string.Join(",", vals.OrderByDescending(x => x));
Assert.AreEqual("k,j,i,h,g,f,e,d,c,b,a", s);
}
}
[Test]
public void AddSetEveryWayNumbers()
{
using (var conn = Create())
{
var db = conn.GetDatabase(3);
RedisKey key = Me();
db.KeyDelete(key);
db.SetAdd(key, "a");
db.SetAdd(key, new RedisValue[] { "1" });
db.SetAdd(key, new RedisValue[] { "11", "2" });
db.SetAdd(key, new RedisValue[] { "10", "3", "1.5" });
db.SetAdd(key, new RedisValue[] { "2.2", "-1", "s", "t" });
var vals = db.SetMembers(key);
string s = string.Join(",", vals.OrderByDescending(x => x));
Assert.AreEqual("t,s,a,11,10,3,2.2,2,1.5,1,-1", s);
}
}
}
}
...@@ -135,7 +135,7 @@ public void Teardown() ...@@ -135,7 +135,7 @@ public void Teardown()
} }
protected const int PrimaryPort = 6379, SlavePort = 6380, SecurePort = 6381; protected const int PrimaryPort = 6379, SlavePort = 6380, SecurePort = 6381;
protected const string PrimaryServer = "127.0.0.1", SecurePassword = "changeme", PrimaryPortString = "6379", SlavePortString = "6380", SecurePortString = "6381"; protected const string PrimaryServer = "192.168.10.120", SecurePassword = "changeme", PrimaryPortString = "6379", SlavePortString = "6380", SecurePortString = "6381";
internal static Task Swallow(Task task) internal static Task Swallow(Task task)
{ {
if (task != null) task.ContinueWith(swallowErrors, TaskContinuationOptions.OnlyOnFaulted); if (task != null) task.ContinueWith(swallowErrors, TaskContinuationOptions.OnlyOnFaulted);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
namespace StackExchange.Redis namespace StackExchange.Redis
{ {
/// <summary> /// <summary>
/// Behaviour markers associated with a given command /// Behaviour markers associated with a given command
/// </summary> /// </summary>
[Flags] [Flags]
......
using System;
using System.Collections.Generic;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
namespace StackExchange.Redis
{
/// <summary>
/// GeoRadius command options.
/// </summary>
[Flags]
public enum GeoRadiusOptions
{
/// <summary>
/// No Options
/// </summary>
None = 0,
/// <summary>
/// Redis will return the coordinates of any results.
/// </summary>
WITHCOORD = 1,
/// <summary>
/// Redis will return the distance from center for all results.
/// </summary>
WITHDIST = 2,
/// <summary>
/// Redis will return the geo hash value as an integer. (This is the score in the sorted set)
/// </summary>
WITHHASH = 4
}
/// <summary>
/// The result of a GeoRadius command.
/// </summary>
public struct GeoRadiusResult
{
internal readonly RedisValue member;
internal readonly GeoRadius geoRadius;
internal readonly double? distanceFromCenter;
internal readonly long? geoHash;
internal readonly GeoPosition? geoPosition;
/// <summary>
/// The matched member.
/// </summary>
public RedisValue Member => member;
/// <summary>
/// The original GeoRadius command
/// </summary>
public GeoRadius GeoRadius => geoRadius;
/// <summary>
/// The distance of the matched member from the center of the geo radius command.
/// </summary>
public double? DistanceFromCenter => distanceFromCenter;
/// <summary>
/// The Geo Hash of the matched member as an integer. (The key in the sorted set)
/// </summary>
public long? GeoHash => geoHash;
/// <summary>
/// The coordinates of the matched member.
/// </summary>
public GeoPosition? GeoPosition => geoPosition;
/// <summary>
/// Returns a new GeoRadiusResult
/// </summary>
public GeoRadiusResult(RedisValue member,GeoRadius geoRadius,double? distanceFromCenter,long? geoHash,GeoPosition? geoPosition)
{
this.member = member;
this.geoRadius = geoRadius;
this.distanceFromCenter = distanceFromCenter;
this.geoHash = geoHash;
this.geoPosition = geoPosition;
}
}
/// <summary>
/// Represents a GeoRadius command and its options.
/// </summary>
public class GeoRadius
{
internal readonly GeoUnit geoUnit;
internal readonly GeoRadiusOptions geoRadiusOptions ;
internal readonly int maxReturnCount;
internal readonly RedisKey key;
internal readonly GeoPosition geoPosition;
internal readonly double radius;
/// <summary>
/// The Radius size of this GeoRadius command.
/// </summary>
public double Radius => radius;
/// <summary>
/// The center point to base the search.
/// </summary>
public GeoPosition GeoPosition => geoPosition;
/// <summary>
/// The key to use.
/// </summary>
public RedisKey Key => key;
/// <summary>
/// The unit to return distance measurments in.
/// </summary>
public GeoUnit GeoUnit => geoUnit;
/// <summary>
/// The possible options for the GeoRadius command
/// </summary>
public GeoRadiusOptions GeoRadiusOptions => geoRadiusOptions;
/// <summary>
/// The maximum number of results to return.
/// However note that internally the command needs to perform an effort proportional to the number of items matching the specified area, so to query very large areas with a very small COUNT option may be slow even if just a few results are returned.
/// </summary>
public int MaxReturnCount => maxReturnCount;
/// <summary>
/// Creates a new GeoRadius
/// </summary>
public GeoRadius(RedisKey key,GeoPosition geoPosition,double radius,int maxReturnCount =-1,GeoUnit geoUnit = GeoUnit.Meters,GeoRadiusOptions geoRadiusOptions = (GeoRadiusOptions.WITHCOORD | GeoRadiusOptions.WITHDIST | GeoRadiusOptions.WITHHASH))
{
this.key = key;
this.geoPosition = geoPosition;
this.radius = radius;
this.geoUnit = geoUnit;
this.geoRadiusOptions = geoRadiusOptions;
this.maxReturnCount = maxReturnCount;
}
}
/// <summary>
/// Describes the longitude and latitude of a GeoEntry
/// </summary>
public struct GeoPosition
{
internal readonly double longitude;
internal readonly double latitude;
/// <summary>
/// The Latitude of the GeoPosition
/// </summary>
public double Latitude => latitude;
/// <summary>
/// The Logitude of the GeoPosition
/// </summary>
public double Longitude => longitude;
/// <summary>
/// Creates a new GeoPosition
/// </summary>
/// <param name="longitude"></param>
/// <param name="latitude"></param>
public GeoPosition(double longitude,double latitude)
{
this.longitude = longitude;
this.latitude = latitude;
}
/// <summary>
/// See Object.ToString()
/// </summary>
public override string ToString()
{
return string.Format("{0} {1}", longitude, latitude);
}
/// <summary>
/// See Object.GetHashCode()
/// </summary>
public override int GetHashCode()
{
return longitude.GetHashCode() ^ latitude.GetHashCode();
}
/// <summary>
/// Compares two values for equality
/// </summary>
public override bool Equals(object obj)
{
return obj is GeoPosition && Equals((GeoPosition)obj);
}
/// <summary>
/// Compares two values for equality
/// </summary>
public bool Equals(GeoPosition value)
{
return Equals(longitude, value.Longitude) && Equals(latitude, value.latitude);
}
/// <summary>
/// Compares two values for equality
/// </summary>
public static bool operator ==(GeoPosition x, GeoPosition y)
{
return Equals(x.longitude, y.longitude) && Equals(x.latitude, y.latitude);
}
/// <summary>
/// Compares two values for non-equality
/// </summary>
public static bool operator !=(GeoPosition x, GeoPosition y)
{
return !Equals(x.longitude, y.longitude) || !Equals(x.latitude, y.latitude);
}
}
/// <summary>
/// Describes a GeoEntry element with the corresponding value
/// GeoEntries are stored in redis as SortedSetEntries
/// </summary>
public struct GeoEntry : IEquatable<GeoEntry>
{
internal readonly RedisValue member;
internal readonly GeoPosition geoPos;
/// <summary>
/// Initializes a GeoEntry value
/// </summary>
public GeoEntry(double longitude,double latitude,RedisValue member)
{
this.member = member;
geoPos = new GeoPosition(longitude, latitude);
}
/// <summary>
/// The name of the geo entry
/// </summary>
public string Member => member;
/// <summary>
/// The longitude of the geo entry
/// </summary>
public double Longitude => geoPos.Longitude;
/// <summary>
/// The latitude of the geo entry
/// </summary>
public double Latitude => geoPos.Latitude;
/// <summary>
/// Describes the longitude and latitude of a GeoEntry
/// </summary>
public GeoPosition GeoPosition => geoPos;
/// <summary>
/// See Object.ToString()
/// </summary>
public override string ToString()
{
return string.Format("{0} {1} {2}", geoPos.Latitude, geoPos.Latitude, member);
}
/// <summary>
/// See Object.GetHashCode()
/// </summary>
public override int GetHashCode()
{
return geoPos.GetHashCode() ^ member.GetHashCode();
}
/// <summary>
/// Compares two values for equality
/// </summary>
public override bool Equals(object obj)
{
return obj is GeoEntry && Equals((GeoEntry)obj);
}
/// <summary>
/// Compares two values for equality
/// </summary>
public bool Equals(GeoEntry value)
{
return Equals(geoPos, value.geoPos) && member == value.member;
}
/// <summary>
/// Compares two values for equality
/// </summary>
public static bool operator ==(GeoEntry x, GeoEntry y)
{
return Equals(x.geoPos,y.geoPos) && x.member == y.member;
}
/// <summary>
/// Compares two values for non-equality
/// </summary>
public static bool operator !=(GeoEntry x, GeoEntry y)
{
return !Equals(x.geoPos , y.geoPos) || x.member != y.member;
}
}
}
\ No newline at end of file
using System;
using System.ComponentModel;
namespace StackExchange.Redis
{
/// <summary>
/// Units associated with Geo Commands
/// </summary>
public enum GeoUnit
{
/// <summary>
/// Meters
/// </summary>
Meters,
/// <summary>
/// Kilometers
/// </summary>
KiloMeters,
/// <summary>
/// Miles
/// </summary>
Miles,
/// <summary>
/// Feet
/// </summary>
Feet
}
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -27,6 +27,55 @@ public RedisValue DebugObject(RedisKey key, CommandFlags flags = CommandFlags.No ...@@ -27,6 +27,55 @@ public RedisValue DebugObject(RedisKey key, CommandFlags flags = CommandFlags.No
return Inner.DebugObject(ToInner(key), flags); return Inner.DebugObject(ToInner(key), flags);
} }
public bool GeoAdd(RedisKey key, double longitude, double latitude, RedisValue member, CommandFlags flags = CommandFlags.None)
{
return Inner.GeoAdd(ToInner(key), longitude, latitude, member, flags);
}
public long GeoAdd(RedisKey key, GeoEntry[] geoEntries, CommandFlags flags = CommandFlags.None)
{
return Inner.GeoAdd(ToInner(key), geoEntries, flags);
}
public bool GeoAdd(RedisKey key, GeoPosition geoPosition, RedisValue member, CommandFlags flags = CommandFlags.None)
{
return Inner.GeoAdd(key, geoPosition, member, flags);
}
public bool GeoRemove(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None)
{
return Inner.GeoRemove(key, member, flags);
}
public RedisValue GeoDistance(RedisKey key, RedisValue value0, RedisValue value1, GeoUnit geoUnit = GeoUnit.Meters,CommandFlags flags = CommandFlags.None)
{
return Inner.GeoDistance(ToInner(key), value0, value1, geoUnit, flags);
}
public string[] GeoHash(RedisKey key, string[] members, CommandFlags flags = CommandFlags.None)
{
return Inner.GeoHash(key, members, flags);
}
public string[] GeoHash(RedisKey key, string member, CommandFlags flags = CommandFlags.None)
{
return Inner.GeoHash(key, member, flags);
}
public GeoPosition?[] GeoPos(RedisKey key, string[] members, CommandFlags flags = CommandFlags.None)
{
return Inner.GeoPos(key, members, flags);
}
public GeoPosition? GeoPos(RedisKey key, string member, CommandFlags flags = CommandFlags.None)
{
return Inner.GeoPos(key, member, flags);
}
public GeoRadiusResult[] GeoRadius(RedisKey key, GeoRadius geoRadius, CommandFlags flags = CommandFlags.None)
{
return Inner.GeoRadius(key, geoRadius, flags);
}
public double HashDecrement(RedisKey key, RedisValue hashField, double value, CommandFlags flags = CommandFlags.None) public double HashDecrement(RedisKey key, RedisValue hashField, double value, CommandFlags flags = CommandFlags.None)
{ {
return Inner.HashDecrement(ToInner(key), hashField, value, flags); return Inner.HashDecrement(ToInner(key), hashField, value, flags);
......
...@@ -350,6 +350,18 @@ public static Message Create(int db, CommandFlags flags, RedisCommand command, R ...@@ -350,6 +350,18 @@ public static Message Create(int db, CommandFlags flags, RedisCommand command, R
return new CommandKeyValueValueValueMessage(db, flags, command, key, value0, value1, value2); return new CommandKeyValueValueValueMessage(db, flags, command, key, value0, value1, value2);
} }
public static Message Create(int db, CommandFlags flags, RedisCommand command, RedisKey key, GeoEntry[] values)
{
var redisValues = new List<RedisValue>();
foreach (var value in values)
{
redisValues.Add(value.geoPos.longitude);
redisValues.Add(value.geoPos.latitude);
redisValues.Add(value.member);
}
return new CommandKeyValuesMessage(db,flags,command,key,redisValues.ToArray());
}
public static Message Create(int db, CommandFlags flags, RedisCommand command, RedisKey key, RedisValue value0, RedisValue value1, RedisValue value2, RedisValue value3) public static Message Create(int db, CommandFlags flags, RedisCommand command, RedisKey key, RedisValue value0, RedisValue value1, RedisValue value2, RedisValue value3)
{ {
return new CommandKeyValueValueValueValueMessage(db, flags, command, key, value0, value1, value2, value3); return new CommandKeyValueValueValueValueMessage(db, flags, command, key, value0, value1, value2, value3);
...@@ -571,6 +583,20 @@ internal static Message Create(int db, CommandFlags flags, RedisCommand command, ...@@ -571,6 +583,20 @@ internal static Message Create(int db, CommandFlags flags, RedisCommand command,
} }
} }
internal static Message Create(int db, CommandFlags flags, RedisCommand command, RedisKey key, RedisValue[] values,GeoRadius geoRadius)
{
if (values == null) throw new ArgumentNullException(nameof(values));
switch (values.Length)
{
case 0: return new CommandKeyMessage(db, flags, command, key);
case 1: return new CommandKeyValueMessage(db, flags, command, key, values[0]);
case 2: return new CommandKeyValueValueMessage(db, flags, command, key, values[0], values[1]);
case 3: return new CommandKeyValueValueValueMessage(db, flags, command, key, values[0], values[1], values[2]);
case 4: return new CommandKeyValueValueValueValueMessage(db, flags, command, key, values[0], values[1], values[2], values[3]);
default: return new CommandKeyValuesMessage(db, flags, command, key, values);
}
}
internal static Message Create(int db, CommandFlags flags, RedisCommand command, RedisKey key0, RedisValue[] values, RedisKey key1) internal static Message Create(int db, CommandFlags flags, RedisCommand command, RedisKey key0, RedisValue[] values, RedisKey key1)
{ {
if (values == null) throw new ArgumentNullException(nameof(values)); if (values == null) throw new ArgumentNullException(nameof(values));
......
...@@ -230,6 +230,42 @@ internal RedisValue[] GetItemsAsValues() ...@@ -230,6 +230,42 @@ internal RedisValue[] GetItemsAsValues()
return arr; return arr;
} }
} }
internal GeoPosition?[] GetItemsAsGeoPositionArray()
{
RawResult[] items = GetItems();
if (items == null)
{
return null;
}
else if (items.Length == 0)
{
return new GeoPosition?[0];
}
else
{
var arr = new GeoPosition?[items.Length];
for (int i = 0; i < arr.Length; i++)
{
RawResult[] item = items[i].GetArrayOfRawResults();
if (item == null)
{
arr[i] = null;
}
else
{
arr[i] = new GeoPosition((double)item[0].AsRedisValue(), (double)item[1].AsRedisValue());
}
}
return arr;
}
}
internal RawResult[] GetItemsAsRawResults()
{
return GetItems();
}
// returns an array of RawResults // returns an array of RawResults
internal RawResult[] GetArrayOfRawResults() internal RawResult[] GetArrayOfRawResults()
......
...@@ -38,6 +38,13 @@ enum RedisCommand ...@@ -38,6 +38,13 @@ enum RedisCommand
FLUSHALL, FLUSHALL,
FLUSHDB, FLUSHDB,
GEOADD,
GEODIST,
GEOHASH,
GEOPOS,
GEORADIUS,
GEORADIUSBYMEMBER,
GET, GET,
GETBIT, GETBIT,
GETRANGE, GETRANGE,
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
...@@ -13,6 +14,7 @@ internal RedisDatabase(ConnectionMultiplexer multiplexer, int db, object asyncSt ...@@ -13,6 +14,7 @@ internal RedisDatabase(ConnectionMultiplexer multiplexer, int db, object asyncSt
Database = db; Database = db;
} }
private static string[] _redisUnits = new[] {"m", "km", "mi", "ft"};
public object AsyncState => asyncState; public object AsyncState => asyncState;
public int Database { get; } public int Database { get; }
...@@ -45,6 +47,134 @@ public RedisValue DebugObject(RedisKey key, CommandFlags flags = CommandFlags.No ...@@ -45,6 +47,134 @@ public RedisValue DebugObject(RedisKey key, CommandFlags flags = CommandFlags.No
return ExecuteSync(msg, ResultProcessor.RedisValue); return ExecuteSync(msg, ResultProcessor.RedisValue);
} }
public bool GeoAdd(RedisKey key, double longitude,double latitude,RedisValue member,CommandFlags flags = CommandFlags.None)
{
return GeoAdd(key, new GeoPosition(longitude, latitude), member, flags);
}
public bool GeoAdd(RedisKey key, GeoPosition geoPosition, RedisValue member, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.GEOADD, key, geoPosition.Longitude, geoPosition.Latitude, member);
return ExecuteSync(msg, ResultProcessor.Boolean);
}
public long GeoAdd(RedisKey key, GeoEntry[] geoEntries, CommandFlags flags = CommandFlags.None)
{
if(geoEntries == null) throw new ArgumentNullException(nameof(geoEntries));
var msg = Message.Create(Database,flags, RedisCommand.GEOADD, key, geoEntries);
return ExecuteSync(msg, ResultProcessor.Int64);
}
public bool GeoRemove(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None)
{
return SortedSetRemove(key, member, flags);
}
public RedisValue GeoDistance(RedisKey key, RedisValue value0, RedisValue value1, GeoUnit geoUnit = GeoUnit.Meters,CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.GEODIST, key,value0,value1,_redisUnits[(int)geoUnit]);
return ExecuteSync(msg, ResultProcessor.RedisValue);
}
public string[] GeoHash(RedisKey key, string[] members, CommandFlags flags = CommandFlags.None)
{
if(members == null)throw new ArgumentNullException(nameof(members));
var redisValues = new RedisValue[members.Length];
for (var i = 0; i < members.Length; i++) redisValues[i] = members[i];
var msg = Message.Create(Database, flags, RedisCommand.GEOHASH, key, redisValues);
var results = ExecuteSync(msg, ResultProcessor.RedisValueArray);
var retArray = new string[results.Length];
for (int i = 0; i < results.Length; i++)
{
retArray[i] = (string)results[i];
}
return retArray;
}
public string[] GeoHash(RedisKey key, string member, CommandFlags flags = CommandFlags.None)
{
return GeoHash(key, new[] {member}, flags);
}
public GeoPosition?[] GeoPos(RedisKey key, string[] members, CommandFlags flags = CommandFlags.None)
{
if (members == null) throw new ArgumentNullException(nameof(members));
var redisValues = new RedisValue[members.Length];
for (var i = 0; i < members.Length; i++) redisValues[i] = members[i];
var msg = Message.Create(Database, flags, RedisCommand.GEOPOS, key, redisValues);
return ExecuteSync(msg, ResultProcessor.RedisGeoPosition);
}
public GeoPosition? GeoPos(RedisKey key, string member, CommandFlags flags = CommandFlags.None)
{
return GeoPos(key, new string[] {member}, flags).FirstOrDefault();
}
public GeoRadiusResult[] GeoRadius(RedisKey key, GeoRadius geoRadius,CommandFlags flags = CommandFlags.None)
{
var redisValues = new List<RedisValue>();
redisValues.Add(geoRadius.geoPosition.longitude);
redisValues.Add(geoRadius.geoPosition.latitude);
redisValues.Add(geoRadius.radius);
redisValues.Add(_redisUnits[(int)geoRadius.geoUnit]);
if(geoRadius.geoRadiusOptions.HasFlag(GeoRadiusOptions.WITHCOORD))
redisValues.Add(GeoRadiusOptions.WITHCOORD.ToString());
if (geoRadius.geoRadiusOptions.HasFlag(GeoRadiusOptions.WITHDIST))
redisValues.Add(GeoRadiusOptions.WITHDIST.ToString());
if (geoRadius.geoRadiusOptions.HasFlag(GeoRadiusOptions.WITHHASH))
redisValues.Add(GeoRadiusOptions.WITHHASH.ToString());
if(geoRadius.maxReturnCount >0)
redisValues.Add(geoRadius.maxReturnCount);
var msg = Message.Create(Database, flags, RedisCommand.GEORADIUS, key, redisValues.ToArray());
var items = ExecuteSync(msg, ResultProcessor.RedisGeoRadius);
var arr = new GeoRadiusResult[items.Length];
for (int i = 0; i < arr.Length; i++)
{
RawResult[] item = items[i].GetArrayOfRawResults();
if (item == null)
{
continue;
}
else
{
var x = 0;
var member = item[x++].AsRedisValue();
var distance = geoRadius.geoRadiusOptions.HasFlag(GeoRadiusOptions.WITHDIST) ? new double?((double)item[x++].AsRedisValue()) : null;
GeoPosition? geoPosition;
long? geoHash;
if (geoRadius.geoRadiusOptions.HasFlag(GeoRadiusOptions.WITHHASH))
{
long tempL;
if (item[x++].TryGetInt64(out tempL))
geoHash = new long?(tempL);
else
geoHash = new long?();
}
else
{
geoHash =null;
}
if (geoRadius.geoRadiusOptions.HasFlag(GeoRadiusOptions.WITHCOORD))
{
var radIem = item[x++].GetItemsAsRawResults();
var longitude = (double)radIem[0].AsRedisValue();
var latitude = (double)radIem[1].AsRedisValue();
geoPosition = new GeoPosition?(new GeoPosition(longitude, latitude));
}
else
{
geoPosition = null;
}
var newRadiusResult = new GeoRadiusResult(member, geoRadius, distance, geoHash, geoPosition);
arr[i] = newRadiusResult;
}
}
return arr;
}
public Task<RedisValue> DebugObjectAsync(RedisKey key, CommandFlags flags = CommandFlags.None) public Task<RedisValue> DebugObjectAsync(RedisKey key, CommandFlags flags = CommandFlags.None)
{ {
var msg = Message.Create(Database, flags, RedisCommand.DEBUG, RedisLiterals.OBJECT, key); var msg = Message.Create(Database, flags, RedisCommand.DEBUG, RedisLiterals.OBJECT, key);
...@@ -926,7 +1056,6 @@ public Task<RedisResult> ScriptEvaluateAsync(LoadedLuaScript script, object para ...@@ -926,7 +1056,6 @@ public Task<RedisResult> ScriptEvaluateAsync(LoadedLuaScript script, object para
{ {
return script.EvaluateAsync(this, parameters, null, flags); return script.EvaluateAsync(this, parameters, null, flags);
} }
public bool SetAdd(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) public bool SetAdd(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None)
{ {
var msg = Message.Create(Database, flags, RedisCommand.SADD, key, value); var msg = Message.Create(Database, flags, RedisCommand.SADD, key, value);
......
...@@ -66,6 +66,13 @@ abstract class ResultProcessor ...@@ -66,6 +66,13 @@ abstract class ResultProcessor
public static readonly ResultProcessor<RedisValue[]> public static readonly ResultProcessor<RedisValue[]>
RedisValueArray = new RedisValueArrayProcessor(); RedisValueArray = new RedisValueArrayProcessor();
public static readonly ResultProcessor<GeoPosition?[]>
RedisGeoPosition = new RedisValueGeoPositionProcessor();
public static readonly ResultProcessor<RawResult[]>
RedisGeoRadius = new RedisGeoRadiusProcessor();
public static readonly ResultProcessor<TimeSpan> public static readonly ResultProcessor<TimeSpan>
ResponseTimer = new TimingProcessor(); ResponseTimer = new TimingProcessor();
...@@ -1079,6 +1086,39 @@ protected override bool SetResultCore(PhysicalConnection connection, Message mes ...@@ -1079,6 +1086,39 @@ protected override bool SetResultCore(PhysicalConnection connection, Message mes
return false; return false;
} }
} }
sealed class RedisValueGeoPositionProcessor : ResultProcessor<GeoPosition?[]>
{
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
{
switch (result.Type)
{
case ResultType.MultiBulk:
var arr = result.GetItemsAsGeoPositionArray();
SetResult(message, arr);
return true;
}
return false;
}
}
sealed class RedisGeoRadiusProcessor : ResultProcessor<RawResult[]>
{
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
{
switch (result.Type)
{
case ResultType.MultiBulk:
var arr = result.GetItemsAsRawResults();
SetResult(message, arr);
return true;
}
return false;
}
}
sealed class RedisValueProcessor : ResultProcessor<RedisValue> sealed class RedisValueProcessor : ResultProcessor<RedisValue>
{ {
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
......
...@@ -6,37 +6,7 @@ namespace StackExchange.Redis ...@@ -6,37 +6,7 @@ namespace StackExchange.Redis
{ {
public struct GeoEntry : IEquatable<SortedSetEntry>, IComparable, IComparable<SortedSetEntry>
{
internal readonly RedisValue element;
internal readonly double latitude;
internal readonly double longitude;
/// <summary>
/// Initializes a GeoEntry value
/// </summary>
public GeoEntry(RedisValue element, double latitude, double longitude)
{
this.element = element;
this.latitude = latitude;
this.longitude = longitude;
}
public bool Equals(SortedSetEntry other)
{
throw new NotImplementedException();
}
public int CompareTo(object obj)
{
throw new NotImplementedException();
}
public int CompareTo(SortedSetEntry other)
{
throw new NotImplementedException();
}
}
/// <summary> /// <summary>
/// Describes a sorted-set element with the corresponding value /// Describes a sorted-set element with the corresponding value
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment