diff --git a/src/NRedisStack.Core/Bloom/BloomCommands.cs b/src/NRedisStack.Core/Bloom/BloomCommands.cs index 3c196f71..76277b54 100644 --- a/src/NRedisStack.Core/Bloom/BloomCommands.cs +++ b/src/NRedisStack.Core/Bloom/BloomCommands.cs @@ -65,7 +65,7 @@ public bool Exists(RedisKey key, RedisValue item) /// An array of booleans. Each element is either true or false depending on whether the /// corresponding input element was newly added to the filter or may have previously existed. /// - public bool[] Insert(RedisKey key, RedisValue[] items, int? capacity = null, + public bool[] Insert(RedisKey key, RedisValue[] items, int? capacity = null, //TODO: create enother function that get one item, because right now if the user want to insert one item he needs to insert this as RedisValue[] double? error = null, int? expansion = null, bool nocreate = false, bool nonscaling = false) { diff --git a/src/NRedisStack.Core/CountMinSketch/CmsCommands.cs b/src/NRedisStack.Core/CountMinSketch/CmsCommands.cs new file mode 100644 index 00000000..aa5112ca --- /dev/null +++ b/src/NRedisStack.Core/CountMinSketch/CmsCommands.cs @@ -0,0 +1,135 @@ +using NRedisStack.Core.CountMinSketch.DataTypes; +using NRedisStack.Core.Literals; +using StackExchange.Redis; +namespace NRedisStack.Core +{ + + public class CmsCommands + { + IDatabase _db; + public CmsCommands(IDatabase db) + { + _db = db; + } + + /// + /// Increases the count of item by increment. + /// + /// The name of the sketch. + /// The item which counter is to be increased. + /// Amount by which the item counter is to be increased. + /// Count of each item after increment. + /// + public long IncrBy(RedisKey key, RedisValue item, long increment) + { + return ResponseParser.ToLong(_db.Execute(CMS.INCRBY, key, item, increment)); + } + + /// + /// Increases the count of item by increment. + /// + /// The name of the sketch. + /// Tuple of The items which counter is to be increased + /// and the Amount by which the item counter is to be increased. + /// Count of each item after increment. + /// + public long[]? IncrBy(RedisKey key, Tuple[] itemIncrements) + { + if (itemIncrements.Length < 1) + throw new ArgumentException(nameof(itemIncrements)); + + List args = new List { key }; + foreach (var pair in itemIncrements) + { + args.Add(pair.Item1); + args.Add(pair.Item2); + } + return ResponseParser.ToLongArray(_db.Execute(CMS.INCRBY, args)); + } + + /// + /// Return information about a sketch. + /// + /// Name of the key to return information about. + /// Information of the sketch. + /// + public CmsInformation? Info(RedisKey key) + { + var info = _db.Execute(CMS.INFO, key); + return ResponseParser.ToCmsInfo(info); + } + + //TODO: functions that returns OK cannot return false, they return OK or ERROR. fix this (the Redis functions that can return also false - will return 1 for true ans 0 for false) + /// + /// Initializes a Count-Min Sketch to dimensions specified by user. + /// + /// TThe name of the sketch. + /// Number of counters in each array. Reduces the error size. + /// Number of counter-arrays. Reduces the probability for an error + /// of a certain size (percentage of total count). + /// if if executed correctly, Error otherwise. + /// + public bool InitByDim(RedisKey key, long width, long depth) + { + return ResponseParser.ParseOKtoBoolean(_db.Execute(CMS.INITBYDIM, key, width, depth)); + } + + /// + /// Initializes a Count-Min Sketch to accommodate requested tolerances. + /// + /// The name of the sketch. + /// Estimate size of error. + /// The desired probability for inflated count. + /// if if executed correctly, Error otherwise. + /// + public bool InitByProb(RedisKey key, double error, double probability) + { + return ResponseParser.ParseOKtoBoolean(_db.Execute(CMS.INITBYPROB, key, error, probability)); + } + + /// + /// Merges several sketches into one sketch. + /// + /// The name of destination sketch. Must be initialized + /// Number of sketches to be merged. + /// Names of source sketches to be merged. + /// Multiple of each sketch. Default = 1. + /// if if executed correctly, Error otherwise. + /// + public bool Merge(RedisValue destination, long numKeys, RedisValue[] source, long[]? weight = null) + { + if (source.Length < 1) + throw new ArgumentNullException(nameof(source)); + + List args = new List { destination, numKeys }; + + foreach (var s in source) args.Add(s); + + if (weight != null && weight.Length >= 1) + { + args.Add(CmsArgs.WEIGHTS); + foreach (var w in weight) args.Add(w); + } + + return ResponseParser.ParseOKtoBoolean(_db.Execute(CMS.MERGE, args)); + } + + /// + /// Returns the count for one or more items in a sketch. + /// + /// The name of the sketch + /// One or more items for which to return the count. + /// Array with a min-count of each of the items in the sketch + /// + public long[]? Query(RedisKey key, RedisValue[] items) //TODO: Create second version of this function using params for items input + { + if (items.Length < 1) + throw new ArgumentNullException(nameof(items)); + + List args = new List { key }; + foreach (var item in items) args.Add(item); + + return ResponseParser.ToLongArray(_db.Execute(CMS.QUERY, args)); + } + } +} diff --git a/src/NRedisStack.Core/CountMinSketch/DataTypes/CmsInformation.cs b/src/NRedisStack.Core/CountMinSketch/DataTypes/CmsInformation.cs new file mode 100644 index 00000000..da7c7c7b --- /dev/null +++ b/src/NRedisStack.Core/CountMinSketch/DataTypes/CmsInformation.cs @@ -0,0 +1,21 @@ +namespace NRedisStack.Core.CountMinSketch.DataTypes +{ + /// + /// This class represents the response for CMS.INFO command. + /// This object has Read-only properties and cannot be generated outside a CMS.INFO response. + /// + public class CmsInformation + { + public long Width { get; private set; } + public long Depth { get; private set; } + public long Count { get; private set; } + + + internal CmsInformation(long width, long depth, long count) + { + Width = width; + Depth = depth; + Count = count; + } + } +} \ No newline at end of file diff --git a/src/NRedisStack.Core/CountMinSketch/Literals/CommandArgs.cs b/src/NRedisStack.Core/CountMinSketch/Literals/CommandArgs.cs new file mode 100644 index 00000000..c350eae9 --- /dev/null +++ b/src/NRedisStack.Core/CountMinSketch/Literals/CommandArgs.cs @@ -0,0 +1,13 @@ +namespace NRedisStack.Core.Literals +{ + internal class CmsArgs + { + public static string WEIGHTS => "WEIGHTS"; + // public static string CAPACITY => "CAPACITY"; + // public static string EXPANSION => "EXPANSION"; + // public static string NOCREATE => "NOCREATE"; + // public static string ITEMS => "ITEMS"; + // public static string BUCKETSIZE => "BUCKETSIZE"; + // public static string MAXITERATIONS => "MAXITERATIONS"; + } +} \ No newline at end of file diff --git a/src/NRedisStack.Core/CountMinSketch/Literals/Commands.cs b/src/NRedisStack.Core/CountMinSketch/Literals/Commands.cs new file mode 100644 index 00000000..a1e16ac8 --- /dev/null +++ b/src/NRedisStack.Core/CountMinSketch/Literals/Commands.cs @@ -0,0 +1,12 @@ +namespace NRedisStack.Core.Literals +{ + internal class CMS + { + public static string INITBYDIM => "CMS.INITBYDIM"; + public static string INITBYPROB => "CMS.INITBYPROB"; + public static string INCRBY => "CMS.INCRBY"; + public static string QUERY => "CMS.QUERY"; + public static string MERGE => "CMS.MERGE"; + public static string INFO => "CMS.INFO"; + } +} \ No newline at end of file diff --git a/src/NRedisStack.Core/ModulPrefixes.cs b/src/NRedisStack.Core/ModulPrefixes.cs index 398be06f..6a6cf175 100644 --- a/src/NRedisStack.Core/ModulPrefixes.cs +++ b/src/NRedisStack.Core/ModulPrefixes.cs @@ -10,6 +10,9 @@ public static class ModulPrefixes static bool cuckooCreated = false; static CuckooCommands cuckooCommands; + static bool cmsCreated = false; + static CmsCommands cmsCommands; + static bool searchCreated = false; static SearchCommands searchCommands; @@ -41,6 +44,17 @@ static public CuckooCommands CF(this IDatabase db) return cuckooCommands; } + static public CmsCommands CMS(this IDatabase db) + { + if (!cmsCreated) + { + cmsCommands = new CmsCommands(db); + cmsCreated = true; + } + + return cmsCommands; + } + static public SearchCommands FT(this IDatabase db) { if (!searchCreated) diff --git a/src/NRedisStack.Core/ResponseParser.cs b/src/NRedisStack.Core/ResponseParser.cs index 15136d23..a5f8bb52 100644 --- a/src/NRedisStack.Core/ResponseParser.cs +++ b/src/NRedisStack.Core/ResponseParser.cs @@ -6,6 +6,7 @@ using StackExchange.Redis; using NRedisStack.Core.Bloom.DataTypes; using NRedisStack.Core.CuckooFilter.DataTypes; +using NRedisStack.Core.CountMinSketch.DataTypes; namespace NRedisStack.Core { @@ -41,6 +42,12 @@ public static long ToLong(RedisResult result) return (long)result; } + public static long[]? ToLongArray(RedisResult result) + { + if (result.Type == ResultType.None) return null; + return (long[])result; + } + public static TimeStamp ToTimeStamp(RedisResult result) { if (result.Type == ResultType.None) return null; @@ -206,6 +213,7 @@ public static IReadOnlyList ToRuleArray(RedisResult result) return new BloomInformation(capacity, size, numberOfFilters, numberOfItemsInserted, expansionRate); } + public static CuckooInformation? ToCuckooInfo(RedisResult result) //TODO: Think about a different implementation, because if the output of BF.INFO changes or even just the names of the labels then the parsing will not work { long size, numberOfBuckets, numberOfFilter, numberOfItemsInserted, @@ -256,6 +264,37 @@ public static IReadOnlyList ToRuleArray(RedisResult result) numberOfItemsDeleted, bucketSize, expansionRate, maxIteration); } + public static CmsInformation? ToCmsInfo(RedisResult result) //TODO: Think about a different implementation, because if the output of CMS.INFO changes or even just the names of the labels then the parsing will not work + { + long width, depth, count; + + width = depth = count = -1; + + RedisResult[]? redisResults = (RedisResult[]?)result; + + if (redisResults == null) return null; + + for (int i = 0; i < redisResults.Length; ++i) + { + string? label = redisResults[i++].ToString(); + + switch (label) + { + case "width": + width = (long)redisResults[i]; + break; + case "depth": + depth = (long)redisResults[i]; + break; + case "count": + count = (long)redisResults[i]; + break; + } + } + + return new CmsInformation(width, depth, count); + } + public static TimeSeriesInformation ToTimeSeriesInfo(RedisResult result) { long totalSamples = -1, memoryUsage = -1, retentionTime = -1, chunkSize = -1, chunkCount = -1; diff --git a/tests/NRedisStack.Tests/Bloom/BloomTests.cs b/tests/NRedisStack.Tests/Bloom/BloomTests.cs index 8e8ca6b9..ce1adf76 100644 --- a/tests/NRedisStack.Tests/Bloom/BloomTests.cs +++ b/tests/NRedisStack.Tests/Bloom/BloomTests.cs @@ -20,6 +20,8 @@ public void Dispose() public void TestReserveBasic() { IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + db.BF().Reserve(key, 0.001, 100L); @@ -32,6 +34,8 @@ public void TestReserveBasic() public void TestAddWhenExist() { IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + Assert.True((db.BF().Add(key, "item1"))); // first time Assert.False(db.BF().Add(key, "item1")); // second time @@ -41,6 +45,8 @@ public void TestAddWhenExist() public void TestAddExists() { IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + db.BF().Add(key, "item1"); Assert.True(db.BF().Exists(key, "item1")); @@ -50,46 +56,51 @@ public void TestAddExists() public void TestAddExistsMulti() { IDatabase db = redisFixture.Redis.GetDatabase(); - var items = new RedisValue[]{"foo", "bar", "baz"}; - var items2 = new RedisValue[]{"newElement", "bar", "baz"}; + db.Execute("FLUSHALL"); + var items = new RedisValue[] { "foo", "bar", "baz" }; + var items2 = new RedisValue[] { "newElement", "bar", "baz" }; var result = db.BF().MAdd(key, items); - Assert.Equal(new bool[] {true, true, true}, result); + Assert.Equal(new bool[] { true, true, true }, result); result = db.BF().MAdd(key, items2); - Assert.Equal(new bool[] {true, false, false}, result); + Assert.Equal(new bool[] { true, false, false }, result); } [Fact] - public void TestExample() { - IDatabase db = redisFixture.Redis.GetDatabase(); - - // Simple bloom filter using default module settings - db.BF().Add("simpleBloom", "Mark"); - // Does "Mark" now exist? - db.BF().Exists("simpleBloom", "Mark"); // true - db.BF().Exists("simpleBloom", "Farnsworth"); // False - - // If you have a long list of items to check/add, you can use the - // "multi" methods - var items = new RedisValue[]{"foo", "bar", "baz", "bat", "bag"}; - db.BF().MAdd("simpleBloom", items); - - // Check if they exist: - var allItems = new RedisValue[]{"foo", "bar", "baz", "bat", "Mark", "nonexist"}; - var rv = db.BF().MExists("simpleBloom", allItems); - // All items except the last one will be 'true' - Assert.Equal(new bool[] {true, true, true, true, true, false}, rv); - - // Reserve a "customized" bloom filter - db.BF().Reserve("specialBloom", 0.0001, 10000); - db.BF().Add("specialBloom", "foo"); - } + public void TestExample() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + + // Simple bloom filter using default module settings + db.BF().Add("simpleBloom", "Mark"); + // Does "Mark" now exist? + db.BF().Exists("simpleBloom", "Mark"); // true + db.BF().Exists("simpleBloom", "Farnsworth"); // False + + // If you have a long list of items to check/add, you can use the + // "multi" methods + var items = new RedisValue[] { "foo", "bar", "baz", "bat", "bag" }; + db.BF().MAdd("simpleBloom", items); + + // Check if they exist: + var allItems = new RedisValue[] { "foo", "bar", "baz", "bat", "Mark", "nonexist" }; + var rv = db.BF().MExists("simpleBloom", allItems); + // All items except the last one will be 'true' + Assert.Equal(new bool[] { true, true, true, true, true, false }, rv); + + // Reserve a "customized" bloom filter + db.BF().Reserve("specialBloom", 0.0001, 10000); + db.BF().Add("specialBloom", "foo"); + } [Fact] public void TestInsert() { IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + RedisValue[] items = new RedisValue[] { "item1", "item2", "item3" }; db.BF().Insert("key", items); @@ -103,6 +114,7 @@ public void TestInsert() public void TestExistsNonExist() { IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); RedisValue item = new RedisValue("item"); Assert.False(db.BF().Exists("NonExistKey", item)); @@ -112,13 +124,15 @@ public void TestExistsNonExist() public void TestInfo() //TODO: think again about the returned value of BF.INFO, maybe creating a new returned type { IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + db.BF().Add(key, "item"); var info = db.BF().Info(key); Assert.NotNull(info); Assert.Equal(info.NumberOfItemsInserted, (long)1); - Assert.Throws( () => db.BF().Info("notExistKey")); + Assert.Throws(() => db.BF().Info("notExistKey")); } [Fact] @@ -127,15 +141,15 @@ public void TestScanDumpAndLoadChunk() IDatabase db = redisFixture.Redis.GetDatabase(); db.Execute("FLUSHALL"); - db.BF().Reserve("bloom-dump",0.1, 10); + db.BF().Reserve("bloom-dump", 0.1, 10); db.BF().Add("bloom-dump", "a"); long iterator = 0; - while(true) + while (true) { var chunkData = db.BF().ScanDump("bloom-dump", iterator); iterator = chunkData.Item1; - if(iterator == 0) break; + if (iterator == 0) break; Assert.True(db.BF().LoadChunk("bloom-load", iterator, chunkData.Item2)); } diff --git a/tests/NRedisStack.Tests/CountMinSketch/CmsTests.cs b/tests/NRedisStack.Tests/CountMinSketch/CmsTests.cs new file mode 100644 index 00000000..f618b9ea --- /dev/null +++ b/tests/NRedisStack.Tests/CountMinSketch/CmsTests.cs @@ -0,0 +1,162 @@ +using Xunit; +using StackExchange.Redis; +using NRedisStack.Core.RedisStackCommands; +using Moq; + +namespace NRedisStack.Tests.CuckooFilter; + +public class CmsTests : AbstractNRedisStackTest, IDisposable +{ + Mock _mock = new Mock(); + private readonly string key = "CMS_TESTS"; + public CmsTests(RedisFixture redisFixture) : base(redisFixture) { } + + public void Dispose() + { + redisFixture.Redis.GetDatabase().KeyDelete(key); + } + + [Fact] + public void TestInitByDim() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + + db.CMS().InitByDim(key, 16, 4); + var info = db.CMS().Info(key); + + Assert.Equal(16, info.Width); + Assert.Equal(4, info.Depth); + Assert.Equal(0, info.Count); + } + + [Fact] + public void TestInitByProb() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + + db.CMS().InitByProb(key, 0.01, 0.01); + var info = db.CMS().Info(key); + + Assert.Equal(200, info.Width); + Assert.Equal(7, info.Depth); + Assert.Equal(0, info.Count); + } + + [Fact] + public void TestKeyAlreadyExists() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + + db.CMS().InitByDim("dup", 16, 4); + Assert.Throws(() => db.CMS().InitByDim("dup", 8, 6)); + } + + [Fact] + public void TestIncrBy() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + + db.CMS().InitByDim(key, 1000, 5); + var resp = db.CMS().IncrBy(key, "foo", 5); + Assert.Equal(5, resp); + + var info = db.CMS().Info(key); + Assert.Equal(1000, info.Width); + Assert.Equal(5, info.Depth); + Assert.Equal(5, info.Count); + + } + + [Fact] + public void TestIncrByMultipleArgs() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + + db.CMS().InitByDim(key, 1000, 5); + db.CMS().IncrBy(key, "foo", 5L); + + var itemIncrements = new Tuple[2]; + itemIncrements[0] = new Tuple("foo", 5); + itemIncrements[1] = new Tuple("bar", 15); + + var resp = db.CMS().IncrBy(key, itemIncrements); + Assert.Equal(new long[] { 10, 15 }, resp); + + var info = db.CMS().Info(key); + Assert.Equal(1000, info.Width); + Assert.Equal(5, info.Depth); + Assert.Equal(25, info.Count); + + } + + + [Fact] + public void TestQuery() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + db.CMS().InitByDim(key, 1000, 5); + + var itemIncrements = new Tuple[2]; + itemIncrements[0] = new Tuple("foo", 10); + itemIncrements[1] = new Tuple("bar", 15); + + db.CMS().IncrBy(key, itemIncrements); + + var resp = db.CMS().Query(key, new RedisValue[] { "foo", "bar" }); + Assert.Equal(new long[] { 10, 15 }, resp); + } + + [Fact] + public void TestMerge() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + + db.CMS().InitByDim("A", 1000, 5); + db.CMS().InitByDim("B", 1000, 5); + db.CMS().InitByDim("C", 1000, 5); + + var aValues = new Tuple[3]; + aValues[0] = new Tuple("foo", 5); + aValues[1] = new Tuple("bar", 3); + aValues[2] = new Tuple("baz", 9); + + db.CMS().IncrBy("A", aValues); + + var bValues = new Tuple[3]; + bValues[0] = new Tuple("foo", 2); + bValues[1] = new Tuple("bar", 3); + bValues[2] = new Tuple("baz", 1); + + db.CMS().IncrBy("B", bValues); + + var q1 = db.CMS().Query("A", new RedisValue[] { "foo", "bar", "baz" }); + Assert.Equal(new long[] { 5L, 3L, 9L }, q1); + + var q2 = db.CMS().Query("B", new RedisValue[] { "foo", "bar", "baz" }); + Assert.Equal(new long[] { 2L, 3L, 1L }, q2); + + db.CMS().Merge("C", 2, new RedisValue[] { "A", "B" }); + + var q3 = db.CMS().Query("C", new RedisValue[] { "foo", "bar", "baz" }); + Assert.Equal(new long[] { 7L, 6L, 10L }, q3); + + db.CMS().Merge("C", 2, new RedisValue[] { "A", "B" }, new long[] { 1, 2 }); + + var q4 = db.CMS().Query("C", new RedisValue[] { "foo", "bar", "baz" }); + Assert.Equal(new long[] { 9L, 9L, 11L }, q4); + + db.CMS().Merge("C", 2, new RedisValue[] { "A", "B" }, new long[] { 2, 3 }); + + + var q5 = db.CMS().Query("C", new RedisValue[] { "foo", "bar", "baz" }); + Assert.Equal(new long[] { 16L, 15L, 21L }, q5); + } +} + diff --git a/tests/NRedisStack.Tests/CuckooFilter/CuckooTests.cs b/tests/NRedisStack.Tests/CuckooFilter/CuckooTests.cs index bf7fb7f7..d803c458 100644 --- a/tests/NRedisStack.Tests/CuckooFilter/CuckooTests.cs +++ b/tests/NRedisStack.Tests/CuckooFilter/CuckooTests.cs @@ -55,6 +55,7 @@ public void TestCountFilterDoesNotExist() { IDatabase db = redisFixture.Redis.GetDatabase(); db.Execute("FLUSHALL"); + Assert.Equal(db.CF().Count("notExistFilter", "notExistItem"), 0); } @@ -63,6 +64,7 @@ public void TestCountFilterExist() { IDatabase db = redisFixture.Redis.GetDatabase(); db.Execute("FLUSHALL"); + db.CF().Insert(key, new RedisValue[]{"foo"}); Assert.Equal(db.CF().Count(key, "notExistItem"), 0); } @@ -95,6 +97,7 @@ public void TestDelete() { IDatabase db = redisFixture.Redis.GetDatabase(); db.Execute("FLUSHALL"); + db.CF().Add(key, "item"); var info = db.CF().Info(key); @@ -108,6 +111,8 @@ public void TestDelete() public void TestInsert() { IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + RedisValue[] items = new RedisValue[] { "item1", "item2", "item3" }; db.CF().Insert("key", items); @@ -121,9 +126,10 @@ public void TestInsert() public void TestInsertNX() { IDatabase db = redisFixture.Redis.GetDatabase(); - RedisValue[] items = new RedisValue[] { "item1", "item2", "item3" }; db.Execute("FLUSHALL"); + RedisValue[] items = new RedisValue[] { "item1", "item2", "item3" }; + var result = db.CF().InsertNX(key, items); var trues = new bool[] {true, true, true}; Assert.Equal(result, trues); @@ -142,6 +148,7 @@ public void TestInsertNX() public void TestExistsNonExist() { IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); RedisValue item = new RedisValue("item"); Assert.False(db.CF().Exists("NonExistKey", item)); diff --git a/tests/NRedisStack.Tests/Json/JsonTests.cs b/tests/NRedisStack.Tests/Json/JsonTests.cs index cd86d48f..443efcf7 100644 --- a/tests/NRedisStack.Tests/Json/JsonTests.cs +++ b/tests/NRedisStack.Tests/Json/JsonTests.cs @@ -40,6 +40,7 @@ public void TestJsonSetNotExist() // { // var obj = new Person { Name = "Shachar", Age = 23 }; // IDatabase db = redisFixture.Redis.GetDatabase(); + // db.Execute("FLUSHALL"); // db.JSON().Set(key, "$", obj); // string expected = "{\"Name\":\"Shachar\",\"Age\":23}"; @@ -55,6 +56,7 @@ public void TestJsonSetNotExist() // { // var obj = new Person { Name = "Shachar", Age = 23 }; // IDatabase db = redisFixture.Redis.GetDatabase(); + // db.Execute("FLUSHALL"); // db.JSON().Set(key, "$", obj);