Commit c681d979 authored by Marc Gravell's avatar Marc Gravell

cleaner approach for Literals via extension method

parent e06768d8
...@@ -8,8 +8,6 @@ namespace NRediSearch ...@@ -8,8 +8,6 @@ namespace NRediSearch
{ {
public sealed class Client public sealed class Client
{ {
internal static readonly LiteralCache Literals = new LiteralCache();
[Flags] [Flags]
public enum IndexOptions public enum IndexOptions
{ {
...@@ -41,15 +39,15 @@ private static void SerializeRedisArgs(IndexOptions flags, List<object> args) ...@@ -41,15 +39,15 @@ private static void SerializeRedisArgs(IndexOptions flags, List<object> args)
{ {
if ((flags & IndexOptions.UseTermOffsets) == 0) if ((flags & IndexOptions.UseTermOffsets) == 0)
{ {
args.Add(Literals["NOOFFSETS"]); args.Add("NOOFFSETS".Literal());
} }
if ((flags & IndexOptions.KeepFieldFlags) == 0) if ((flags & IndexOptions.KeepFieldFlags) == 0)
{ {
args.Add(Literals["NOFIELDS"]); args.Add("NOFIELDS".Literal());
} }
if ((flags & IndexOptions.UseScoreIndexes) == 0) if ((flags & IndexOptions.UseScoreIndexes) == 0)
{ {
args.Add(Literals["NOSCOREIDX"]); args.Add("NOSCOREIDX".Literal());
} }
} }
IDatabase _db; IDatabase _db;
...@@ -73,7 +71,7 @@ public bool CreateIndex(Schema schema, IndexOptions options) ...@@ -73,7 +71,7 @@ public bool CreateIndex(Schema schema, IndexOptions options)
args.Add(_boxedIndexName); args.Add(_boxedIndexName);
SerializeRedisArgs(options, args); SerializeRedisArgs(options, args);
args.Add(Literals["SCHEMA"]); args.Add("SCHEMA".Literal());
foreach (var f in schema.Fields) foreach (var f in schema.Fields)
{ {
...@@ -112,20 +110,20 @@ public bool AddDocument(string docId, double score, Dictionary<string, RedisValu ...@@ -112,20 +110,20 @@ public bool AddDocument(string docId, double score, Dictionary<string, RedisValu
var args = new List<object> { _boxedIndexName, docId, score }; var args = new List<object> { _boxedIndexName, docId, score };
if (noSave) if (noSave)
{ {
args.Add(Literals["NOSAVE"]); args.Add("NOSAVE".Literal());
} }
if (replace) if (replace)
{ {
args.Add(Literals["REPLACE"]); args.Add("REPLACE".Literal());
} }
if (payload != null) if (payload != null)
{ {
args.Add(Literals["PAYLOAD"]); args.Add("PAYLOAD".Literal());
// TODO: Fix this // TODO: Fix this
args.Add(payload); args.Add(payload);
} }
args.Add(Literals["FIELDS"]); args.Add("FIELDS".Literal());
foreach (var ent in fields) foreach (var ent in fields)
{ {
args.Add(ent.Key); args.Add(ent.Key);
...@@ -161,7 +159,7 @@ public bool AddHash(string docId, double score, bool replace) ...@@ -161,7 +159,7 @@ public bool AddHash(string docId, double score, bool replace)
if (replace) if (replace)
{ {
args.Add(Literals["REPLACE"]); args.Add("REPLACE".Literal());
} }
return (string)_db.Execute("FT.ADDHASH", args.ToArray()) == "OK"; return (string)_db.Execute("FT.ADDHASH", args.ToArray()) == "OK";
......
using StackExchange.Redis;
using System.Collections;
namespace NRediSearch
{
// encode and box literals once only
internal sealed class LiteralCache
{
private static Hashtable _boxed = new Hashtable();
public object this[string value]
{
get
{
if (value == null) return "";
object boxed = _boxed[value];
if (boxed == null)
{
lock (_boxed)
{
boxed = _boxed[value];
if (boxed == null)
{
boxed = (RedisValue)value;
_boxed.Add(value, boxed);
}
}
}
return boxed;
}
}
}
}
using StackExchange.Redis;
using System.Collections;
namespace NRediSearch
{
/// <summary>
/// Cache to ensure we encode and box literals once only
/// </summary>
internal static class Literals
{
private static Hashtable _boxed = new Hashtable();
private static object _null = RedisValue.Null;
/// <summary>
/// Obtain a lazily-cached pre-encoded and boxed representation of a string
/// </summary>
/// <remarks>This shoul donly be used for fixed values, not user data (the cache is never reclaimed, so it will be a memory leak)</remarks>
public static object Literal(this string value)
{
if (value == null) return _null;
object boxed = _boxed[value];
if (boxed == null)
{
lock (_boxed)
{
boxed = _boxed[value];
if (boxed == null)
{
boxed = (RedisValue)value;
_boxed.Add(value, boxed);
}
}
}
return boxed;
}
}
}
...@@ -60,7 +60,7 @@ RedisValue FormatNum(double num, bool exclude) ...@@ -60,7 +60,7 @@ RedisValue FormatNum(double num, bool exclude)
// need to add leading bracket // need to add leading bracket
return "(" + num.ToString("G17", NumberFormatInfo.InvariantInfo); return "(" + num.ToString("G17", NumberFormatInfo.InvariantInfo);
} }
args.Add(Client.Literals["FILTER"]); args.Add("FILTER".Literal());
args.Add(Property); args.Add(Property);
args.Add(FormatNum(min, exclusiveMin)); args.Add(FormatNum(min, exclusiveMin));
args.Add(FormatNum(max, exclusiveMax)); args.Add(FormatNum(max, exclusiveMax));
...@@ -86,7 +86,7 @@ public GeoFilter(string property, double lon, double lat, double radius, GeoUnit ...@@ -86,7 +86,7 @@ public GeoFilter(string property, double lon, double lat, double radius, GeoUnit
internal override void SerializeRedisArgs(List<object> args) internal override void SerializeRedisArgs(List<object> args)
{ {
args.Add(Client.Literals["GEOFILTER"]); args.Add("GEOFILTER".Literal());
args.Add(Property); args.Add(Property);
args.Add(lon); args.Add(lon);
args.Add(lat); args.Add(lat);
...@@ -94,10 +94,10 @@ internal override void SerializeRedisArgs(List<object> args) ...@@ -94,10 +94,10 @@ internal override void SerializeRedisArgs(List<object> args)
switch (unit) switch (unit)
{ {
case GeoUnit.Feet: args.Add(Client.Literals["ft"]); break; case GeoUnit.Feet: args.Add("ft".Literal()); break;
case GeoUnit.Kilometers: args.Add(Client.Literals["km"]); break; case GeoUnit.Kilometers: args.Add("km".Literal()); break;
case GeoUnit.Meters: args.Add(Client.Literals["m"]); break; case GeoUnit.Meters: args.Add("m".Literal()); break;
case GeoUnit.Miles: args.Add(Client.Literals["mi"]); break; case GeoUnit.Miles: args.Add("mi".Literal()); break;
default: throw new InvalidOperationException($"Unknown unit: {unit}"); default: throw new InvalidOperationException($"Unknown unit: {unit}");
} }
} }
...@@ -175,45 +175,45 @@ internal void SerializeRedisArgs(List<object> args) ...@@ -175,45 +175,45 @@ internal void SerializeRedisArgs(List<object> args)
if (Verbatim) if (Verbatim)
{ {
args.Add(Client.Literals["VERBATIM"]); args.Add("VERBATIM".Literal());
} }
if (NoContent) if (NoContent)
{ {
args.Add(Client.Literals["NOCONTENT"]); args.Add("NOCONTENT".Literal());
} }
if (NoStopwords) if (NoStopwords)
{ {
args.Add(Client.Literals["NOSTOPWORDS"]); args.Add("NOSTOPWORDS".Literal());
} }
if (WithScores) if (WithScores)
{ {
args.Add(Client.Literals["WITHSCORES"]); args.Add("WITHSCORES".Literal());
} }
if (WithPayloads) if (WithPayloads)
{ {
args.Add(Client.Literals["WITHPAYLOADS"]); args.Add("WITHPAYLOADS".Literal());
} }
if (Language != null) if (Language != null)
{ {
args.Add(Client.Literals["LANGUAGE"]); args.Add("LANGUAGE".Literal());
args.Add(Language); args.Add(Language);
} }
if (_fields != null && _fields.Length > 0) if (_fields != null && _fields.Length > 0)
{ {
args.Add(Client.Literals["INFIELDS"]); args.Add("INFIELDS".Literal());
args.Add(_fields.Length); args.Add(_fields.Length);
args.AddRange(_fields); args.AddRange(_fields);
} }
if (Payload != null) if (Payload != null)
{ {
args.Add(Client.Literals["PAYLOAD"]); args.Add("PAYLOAD".Literal());
args.Add(Payload); args.Add(Payload);
} }
if (_paging.Offset != 0 || _paging.Count != 10) if (_paging.Offset != 0 || _paging.Count != 10)
{ {
args.Add(Client.Literals["LIMIT"]); args.Add("LIMIT".Literal());
args.Add(_paging.Offset); args.Add(_paging.Offset);
args.Add(_paging.Count); args.Add(_paging.Count);
} }
......
...@@ -35,9 +35,9 @@ object GetForRedis(FieldType type) ...@@ -35,9 +35,9 @@ object GetForRedis(FieldType type)
{ {
switch (type) switch (type)
{ {
case FieldType.FullText: return Client.Literals["TEXT"]; case FieldType.FullText: return "TEXT".Literal();
case FieldType.Geo: return Client.Literals["GEO"]; case FieldType.Geo: return "GEO".Literal();
case FieldType.Numeric: return Client.Literals["NUMERIC"]; case FieldType.Numeric: return "NUMERIC".Literal();
default: throw new ArgumentOutOfRangeException(nameof(type)); default: throw new ArgumentOutOfRangeException(nameof(type));
} }
} }
...@@ -57,7 +57,7 @@ internal override void SerializeRedisArgs(List<object> args) ...@@ -57,7 +57,7 @@ internal override void SerializeRedisArgs(List<object> args)
base.SerializeRedisArgs(args); base.SerializeRedisArgs(args);
if (Weight != 1.0) if (Weight != 1.0)
{ {
args.Add(Client.Literals["WEIGHT"]); args.Add("WEIGHT".Literal());
args.Add(Weight); args.Add(Weight);
} }
} }
......
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