diff --git a/src/NRedisStack/Auxiliary.cs b/src/NRedisStack/Auxiliary.cs index 3a508c2d..ffac0e27 100644 --- a/src/NRedisStack/Auxiliary.cs +++ b/src/NRedisStack/Auxiliary.cs @@ -2,133 +2,130 @@ using NRedisStack.RedisStackCommands; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public static class Auxiliary { - public static class Auxiliary + private static string? _libraryName = $"NRedisStack(.NET_v{Environment.Version})"; + private static bool _setInfo = true; + public static void ResetInfoDefaults() { - private static string? _libraryName = $"NRedisStack(.NET_v{Environment.Version})"; - private static bool _setInfo = true; - public static void ResetInfoDefaults() - { - _setInfo = true; - _libraryName = $"NRedisStack(.NET_v{Environment.Version})"; - } - public static List MergeArgs(RedisKey key, params RedisValue[] items) - { - var args = new List(items.Length + 1) { key }; - foreach (var item in items) args.Add(item); - return args; - } + _setInfo = true; + _libraryName = $"NRedisStack(.NET_v{Environment.Version})"; + } + public static List MergeArgs(RedisKey key, params RedisValue[] items) + { + var args = new List(items.Length + 1) { key }; + args.AddRange(items.Cast()); + return args; + } - public static object[] AssembleNonNullArguments(params object?[] arguments) + public static object[] AssembleNonNullArguments(params object?[] arguments) + { + var args = new List(); + foreach (var arg in arguments) { - var args = new List(); - foreach (var arg in arguments) + if (arg != null) { - if (arg != null) - { - args.Add(arg); - } + args.Add(arg); } - - return args.ToArray(); } - // TODO: add all the signatures of GetDatabase - public static IDatabase GetDatabase(this ConnectionMultiplexer redis, - string? LibraryName) - { - var _db = redis.GetDatabase(); - if (LibraryName == null) // the user wants to disable the library name and version sending - _setInfo = false; + return args.ToArray(); + } - else // the user set his own the library name - _libraryName = $"NRedisStack({LibraryName};.NET_v{Environment.Version})"; + // TODO: add all the signatures of GetDatabase + public static IDatabase GetDatabase(this ConnectionMultiplexer redis, + string? LibraryName) + { + var _db = redis.GetDatabase(); + if (LibraryName == null) // the user wants to disable the library name and version sending + _setInfo = false; - return _db; - } + else // the user set his own the library name + _libraryName = $"NRedisStack({LibraryName};.NET_v{Environment.Version})"; - private static void SetInfoInPipeline(this IDatabase db) - { - if (_libraryName == null) return; - Pipeline pipeline = new Pipeline(db); - _ = pipeline.Db.ClientSetInfoAsync(SetInfoAttr.LibraryName, _libraryName!); - _ = pipeline.Db.ClientSetInfoAsync(SetInfoAttr.LibraryVersion, GetNRedisStackVersion()); - pipeline.Execute(); - } + return _db; + } - public static RedisResult Execute(this IDatabase db, SerializedCommand command) - { - if (_setInfo) - { - _setInfo = false; - db.SetInfoInPipeline(); - } - return db.Execute(command.Command, command.Args); - } + private static void SetInfoInPipeline(this IDatabase db) + { + if (_libraryName == null) return; + Pipeline pipeline = new Pipeline(db); + _ = pipeline.Db.ClientSetInfoAsync(SetInfoAttr.LibraryName, _libraryName!); + _ = pipeline.Db.ClientSetInfoAsync(SetInfoAttr.LibraryVersion, GetNRedisStackVersion()); + pipeline.Execute(); + } - public async static Task ExecuteAsync(this IDatabaseAsync db, SerializedCommand command) + public static RedisResult Execute(this IDatabase db, SerializedCommand command) + { + if (!_setInfo) return db.Execute(command.Command, command.Args); + _setInfo = false; + db.SetInfoInPipeline(); + return db.Execute(command.Command, command.Args); + } + + public static async Task ExecuteAsync(this IDatabaseAsync db, SerializedCommand command) + { + if (_setInfo) { - if (_setInfo) - { - _setInfo = false; - ((IDatabase)db).SetInfoInPipeline(); - } - return await db.ExecuteAsync(command.Command, command.Args); + _setInfo = false; + ((IDatabase)db).SetInfoInPipeline(); } + return await db.ExecuteAsync(command.Command, command.Args); + } + + public static List ExecuteBroadcast(this IDatabase db, string command) + => db.ExecuteBroadcast(new SerializedCommand(command)); - public static List ExecuteBroadcast(this IDatabase db, string command) - => db.ExecuteBroadcast(new SerializedCommand(command)); + public static List ExecuteBroadcast(this IDatabase db, SerializedCommand command) + { + var redis = db.Multiplexer; + var endpoints = redis.GetEndPoints(); + var results = new List(endpoints.Length); - public static List ExecuteBroadcast(this IDatabase db, SerializedCommand command) + foreach (var endPoint in endpoints) { - var redis = db.Multiplexer; - var endpoints = redis.GetEndPoints(); - var results = new List(endpoints.Length); + var server = redis.GetServer(endPoint); - foreach (var endPoint in endpoints) + if (server.IsReplica) { - var server = redis.GetServer(endPoint); - - if (server.IsReplica) - { - continue; // Skip replica nodes - } - // Send your command to the master node - - results.Add(server.Multiplexer.GetDatabase().Execute(command)); + continue; // Skip replica nodes } - return results; + // Send your command to the master node + + results.Add(server.Multiplexer.GetDatabase().Execute(command)); } + return results; + } + + public static async Task> ExecuteBroadcastAsync(this IDatabaseAsync db, string command) + => await db.ExecuteBroadcastAsync(new SerializedCommand(command)); - public async static Task> ExecuteBroadcastAsync(this IDatabaseAsync db, string command) - => await db.ExecuteBroadcastAsync(new SerializedCommand(command)); + private static async Task> ExecuteBroadcastAsync(this IDatabaseAsync db, SerializedCommand command) + { + var redis = db.Multiplexer; + var endpoints = redis.GetEndPoints(); + var results = new List(endpoints.Length); - public async static Task> ExecuteBroadcastAsync(this IDatabaseAsync db, SerializedCommand command) + foreach (var endPoint in endpoints) { - var redis = db.Multiplexer; - var endpoints = redis.GetEndPoints(); - var results = new List(endpoints.Length); + var server = redis.GetServer(endPoint); - foreach (var endPoint in endpoints) + if (server.IsReplica) { - var server = redis.GetServer(endPoint); - - if (server.IsReplica) - { - continue; // Skip replica nodes - } - // Send your command to the master node - - results.Add(await server.Multiplexer.GetDatabase().ExecuteAsync(command)); + continue; // Skip replica nodes } - return results; - } + // Send your command to the master node - public static string GetNRedisStackVersion() - { - Version version = typeof(Auxiliary).Assembly.GetName().Version!; - return $"{version.Major}.{version.Minor}.{version.Build}"; + results.Add(await server.Multiplexer.GetDatabase().ExecuteAsync(command)); } + return results; + } + + public static string GetNRedisStackVersion() + { + Version version = typeof(Auxiliary).Assembly.GetName().Version!; + return $"{version.Major}.{version.Minor}.{version.Build}"; } -} +} \ No newline at end of file diff --git a/src/NRedisStack/Bloom/BloomAux.cs b/src/NRedisStack/Bloom/BloomAux.cs index c87925e2..84d23152 100644 --- a/src/NRedisStack/Bloom/BloomAux.cs +++ b/src/NRedisStack/Bloom/BloomAux.cs @@ -1,74 +1,64 @@ using NRedisStack.Bloom.Literals; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public static class BloomAux { - public static class BloomAux + public static List BuildInsertArgs(RedisKey key, IEnumerable items, int? capacity, + double? error, int? expansion, bool nocreate, bool nonscaling) { - public static List BuildInsertArgs(RedisKey key, RedisValue[] items, int? capacity, - double? error, int? expansion, bool nocreate, bool nonscaling) - { - var args = new List { key }; - args.AddCapacity(capacity); - args.AddError(error); - args.AddExpansion(expansion); - args.AddNoCreate(nocreate); - args.AddNoScaling(nonscaling); - args.AddItems(items); + var args = new List { key }; + args.AddCapacity(capacity); + args.AddError(error); + args.AddExpansion(expansion); + args.AddNoCreate(nocreate); + args.AddNoScaling(nonscaling); + args.AddItems(items); - return args; - } + return args; + } - private static void AddItems(this List args, RedisValue[] items) - { - args.Add(BloomArgs.ITEMS); - foreach (var item in items) - { - args.Add(item); - } - } + private static void AddItems(this List args, IEnumerable items) + { + args.Add(BloomArgs.ITEMS); + args.AddRange(items.Cast()); + } - private static void AddNoScaling(this List args, bool nonscaling) + private static void AddNoScaling(this ICollection args, bool nonScaling) + { + if (nonScaling) { - if (nonscaling) - { - args.Add(BloomArgs.NONSCALING); - } + args.Add(BloomArgs.NONSCALING); } + } - private static void AddNoCreate(this List args, bool nocreate) + private static void AddNoCreate(this ICollection args, bool nocreate) + { + if (nocreate) { - if (nocreate) - { - args.Add(BloomArgs.NOCREATE); - } + args.Add(BloomArgs.NOCREATE); } + } - private static void AddExpansion(this List args, int? expansion) - { - if (expansion != null) - { - args.Add(BloomArgs.EXPANSION); - args.Add(expansion); - } - } + private static void AddExpansion(this ICollection args, int? expansion) + { + if (expansion == null) return; + args.Add(BloomArgs.EXPANSION); + args.Add(expansion); + } - private static void AddError(this List args, double? error) - { - if (error != null) - { - args.Add(BloomArgs.ERROR); - args.Add(error); - } - } + private static void AddError(this ICollection args, double? error) + { + if (error == null) return; + args.Add(BloomArgs.ERROR); + args.Add(error); + } - private static void AddCapacity(this List args, int? capacity) - { - if (capacity != null) - { - args.Add(BloomArgs.CAPACITY); - args.Add(capacity); - } - } + private static void AddCapacity(this ICollection args, int? capacity) + { + if (capacity == null) return; + args.Add(BloomArgs.CAPACITY); + args.Add(capacity); } -} +} \ No newline at end of file diff --git a/src/NRedisStack/Bloom/BloomCommandBuilder.cs b/src/NRedisStack/Bloom/BloomCommandBuilder.cs index b654134c..49544b7c 100644 --- a/src/NRedisStack/Bloom/BloomCommandBuilder.cs +++ b/src/NRedisStack/Bloom/BloomCommandBuilder.cs @@ -1,100 +1,90 @@ using NRedisStack.RedisStackCommands; using StackExchange.Redis; using NRedisStack.Bloom.Literals; -namespace NRedisStack -{ +namespace NRedisStack; - public static class BloomCommandBuilder +public static class BloomCommandBuilder +{ + public static SerializedCommand Add(RedisKey key, RedisValue item) { - public static SerializedCommand Add(RedisKey key, RedisValue item) - { - return new SerializedCommand(BF.ADD, key, item); - } - - public static SerializedCommand Card(RedisKey key) - { - return new SerializedCommand(BF.CARD, key); - } + return new SerializedCommand(BF.ADD, key, item); + } - public static SerializedCommand Exists(RedisKey key, RedisValue item) - { - return new SerializedCommand(BF.EXISTS, key, item); - } + public static SerializedCommand Card(RedisKey key) + { + return new SerializedCommand(BF.CARD, key); + } - public static SerializedCommand Info(RedisKey key) - { - return new SerializedCommand(BF.INFO, key); - } + public static SerializedCommand Exists(RedisKey key, RedisValue item) + { + return new SerializedCommand(BF.EXISTS, key, item); + } - public static SerializedCommand Insert(RedisKey key, RedisValue[] items, int? capacity = null, - double? error = null, int? expansion = null, - bool nocreate = false, bool nonscaling = false) - { - if (items.Length < 1) - throw new ArgumentOutOfRangeException(nameof(items)); + public static SerializedCommand Info(RedisKey key) + { + return new SerializedCommand(BF.INFO, key); + } - var args = BloomAux.BuildInsertArgs(key, items, capacity, error, expansion, nocreate, nonscaling); + public static SerializedCommand Insert(RedisKey key, RedisValue[] items, int? capacity = null, + double? error = null, int? expansion = null, + bool nocreate = false, bool nonscaling = false) + { + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); - return new SerializedCommand(BF.INSERT, args); - } + var args = BloomAux.BuildInsertArgs(key, items, capacity, error, expansion, nocreate, nonscaling); - public static SerializedCommand LoadChunk(RedisKey key, long iterator, Byte[] data) - { - return new SerializedCommand(BF.LOADCHUNK, key, iterator, data); - } + return new SerializedCommand(BF.INSERT, args); + } - public static SerializedCommand MAdd(RedisKey key, params RedisValue[] items) - { - if (items.Length < 1) - throw new ArgumentOutOfRangeException(nameof(items)); + public static SerializedCommand LoadChunk(RedisKey key, long iterator, Byte[] data) + { + return new SerializedCommand(BF.LOADCHUNK, key, iterator, data); + } - List args = new List { key }; + public static SerializedCommand MAdd(RedisKey key, params RedisValue[] items) + { + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); - foreach (var item in items) - { - args.Add(item); - } + List args = new List { key }; + args.AddRange(items.Cast()); - return new SerializedCommand(BF.MADD, args); - } + return new SerializedCommand(BF.MADD, args); + } - public static SerializedCommand MExists(RedisKey key, RedisValue[] items) - { - if (items.Length < 1) - throw new ArgumentOutOfRangeException(nameof(items)); + public static SerializedCommand MExists(RedisKey key, RedisValue[] items) + { + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); - List args = new List { key }; + List args = new List { key }; + args.AddRange(items.Cast()); - foreach (var item in items) - { - args.Add(item); - } + return new SerializedCommand(BF.MEXISTS, args); - return new SerializedCommand(BF.MEXISTS, args); + } - } + public static SerializedCommand Reserve(RedisKey key, double errorRate, long capacity, + int? expansion = null, bool nonscaling = false) + { + List args = new List { key, errorRate, capacity }; - public static SerializedCommand Reserve(RedisKey key, double errorRate, long capacity, - int? expansion = null, bool nonscaling = false) + if (expansion != null) { - List args = new List { key, errorRate, capacity }; - - if (expansion != null) - { - args.Add(expansion); - } - - if (nonscaling) - { - args.Add(BloomArgs.NONSCALING); - } - - return new SerializedCommand(BF.RESERVE, args); + args.Add(expansion); } - public static SerializedCommand ScanDump(RedisKey key, long iterator) + if (nonscaling) { - return new SerializedCommand(BF.SCANDUMP, key, iterator); + args.Add(BloomArgs.NONSCALING); } + + return new SerializedCommand(BF.RESERVE, args); + } + + public static SerializedCommand ScanDump(RedisKey key, long iterator) + { + return new SerializedCommand(BF.SCANDUMP, key, iterator); } } \ No newline at end of file diff --git a/src/NRedisStack/Bloom/BloomCommands.cs b/src/NRedisStack/Bloom/BloomCommands.cs index d4f3acb9..96a4e2c1 100644 --- a/src/NRedisStack/Bloom/BloomCommands.cs +++ b/src/NRedisStack/Bloom/BloomCommands.cs @@ -1,77 +1,75 @@ using NRedisStack.Bloom.DataTypes; using StackExchange.Redis; -namespace NRedisStack + +namespace NRedisStack; + +public class BloomCommands : BloomCommandsAsync, IBloomCommands { + private readonly IDatabase _db; - public class BloomCommands : BloomCommandsAsync, IBloomCommands + public BloomCommands(IDatabase db) : base(db) { - IDatabase _db; - public BloomCommands(IDatabase db) : base(db) - { - _db = db; - } + _db = db; + } - /// - public bool Add(RedisKey key, RedisValue item) - { - return _db.Execute(BloomCommandBuilder.Add(key, item)).ToString() == "1"; - } + /// + public bool Add(RedisKey key, RedisValue item) => _db.Execute(BloomCommandBuilder.Add(key, item)).ToString() == "1"; - /// - public long Card(RedisKey key) - { - return _db.Execute(BloomCommandBuilder.Card(key)).ToLong(); - } + /// + public long Card(RedisKey key) + { + return _db.Execute(BloomCommandBuilder.Card(key)).ToLong(); + } - /// - public bool Exists(RedisKey key, RedisValue item) - { - return _db.Execute(BloomCommandBuilder.Exists(key, item)).ToString() == "1"; - } + /// + public bool Exists(RedisKey key, RedisValue item) + { + return _db.Execute(BloomCommandBuilder.Exists(key, item)).ToString() == "1"; + } - /// - public BloomInformation Info(RedisKey key) - { - return _db.Execute(BloomCommandBuilder.Info(key)).ToBloomInfo(); - } + /// + public BloomInformation Info(RedisKey key) + { + return _db.Execute(BloomCommandBuilder.Info(key)).ToBloomInfo(); + } - /// - public bool[] Insert(RedisKey key, RedisValue[] items, int? capacity = null, - double? error = null, int? expansion = null, - bool nocreate = false, bool nonscaling = false) - { - return _db.Execute(BloomCommandBuilder.Insert(key, items, capacity, error, expansion, nocreate, nonscaling)).ToBooleanArray(); - } + /// + public bool[] Insert(RedisKey key, RedisValue[] items, int? capacity = null, + double? error = null, int? expansion = null, + bool nocreate = false, bool nonscaling = false) + { + return _db.Execute(BloomCommandBuilder.Insert(key, items, capacity, error, expansion, nocreate, nonscaling)) + .ToBooleanArray(); + } - /// - public bool LoadChunk(RedisKey key, long iterator, Byte[] data) - { - return _db.Execute(BloomCommandBuilder.LoadChunk(key, iterator, data)).OKtoBoolean(); - } + /// + public bool LoadChunk(RedisKey key, long iterator, Byte[] data) + { + return _db.Execute(BloomCommandBuilder.LoadChunk(key, iterator, data)).OKtoBoolean(); + } - /// - public bool[] MAdd(RedisKey key, params RedisValue[] items) - { - return _db.Execute(BloomCommandBuilder.MAdd(key, items)).ToBooleanArray(); - } + /// + public bool[] MAdd(RedisKey key, params RedisValue[] items) + { + return _db.Execute(BloomCommandBuilder.MAdd(key, items)).ToBooleanArray(); + } - /// - public bool[] MExists(RedisKey key, RedisValue[] items) - { - return _db.Execute(BloomCommandBuilder.MExists(key, items)).ToBooleanArray(); - } + /// + public bool[] MExists(RedisKey key, RedisValue[] items) + { + return _db.Execute(BloomCommandBuilder.MExists(key, items)).ToBooleanArray(); + } - /// - public bool Reserve(RedisKey key, double errorRate, long capacity, - int? expansion = null, bool nonscaling = false) - { - return _db.Execute(BloomCommandBuilder.Reserve(key, errorRate, capacity, expansion, nonscaling)).OKtoBoolean(); - } + /// + public bool Reserve(RedisKey key, double errorRate, long capacity, + int? expansion = null, bool nonscaling = false) + { + return _db.Execute(BloomCommandBuilder.Reserve(key, errorRate, capacity, expansion, nonscaling)).OKtoBoolean(); + } - /// - public Tuple ScanDump(RedisKey key, long iterator) - { - return _db.Execute(BloomCommandBuilder.ScanDump(key, iterator)).ToScanDumpTuple(); - } + /// + public Tuple ScanDump(RedisKey key, long iterator) + { + return _db.Execute(BloomCommandBuilder.ScanDump(key, iterator)).ToScanDumpTuple(); } -} +} \ No newline at end of file diff --git a/src/NRedisStack/Bloom/BloomCommandsAsync.cs b/src/NRedisStack/Bloom/BloomCommandsAsync.cs index 6797caa4..11b92336 100644 --- a/src/NRedisStack/Bloom/BloomCommandsAsync.cs +++ b/src/NRedisStack/Bloom/BloomCommandsAsync.cs @@ -1,79 +1,81 @@ using NRedisStack.Bloom.DataTypes; using StackExchange.Redis; -namespace NRedisStack + +namespace NRedisStack; + +public class BloomCommandsAsync : IBloomCommandsAsync { + private readonly IDatabaseAsync _db; - public class BloomCommandsAsync : IBloomCommandsAsync + public BloomCommandsAsync(IDatabaseAsync db) { - IDatabaseAsync _db; - public BloomCommandsAsync(IDatabaseAsync db) - { - _db = db; - } + _db = db; + } - /// - public async Task AddAsync(RedisKey key, RedisValue item) - { - return (await _db.ExecuteAsync(BloomCommandBuilder.Add(key, item))).ToString() == "1"; - } + /// + public async Task AddAsync(RedisKey key, RedisValue item) + { + return (await _db.ExecuteAsync(BloomCommandBuilder.Add(key, item))).ToString() == "1"; + } - /// - public async Task CardAsync(RedisKey key) - { - return (await _db.ExecuteAsync(BloomCommandBuilder.Card(key))).ToLong(); - } + /// + public async Task CardAsync(RedisKey key) + { + return (await _db.ExecuteAsync(BloomCommandBuilder.Card(key))).ToLong(); + } - /// - public async Task ExistsAsync(RedisKey key, RedisValue item) - { - return (await _db.ExecuteAsync(BloomCommandBuilder.Exists(key, item))).ToString() == "1"; - } + /// + public async Task ExistsAsync(RedisKey key, RedisValue item) + { + return (await _db.ExecuteAsync(BloomCommandBuilder.Exists(key, item))).ToString() == "1"; + } - /// - public async Task InfoAsync(RedisKey key) - { - var info = (await _db.ExecuteAsync(BloomCommandBuilder.Info(key))); - return info.ToBloomInfo(); - } + /// + public async Task InfoAsync(RedisKey key) + { + var info = (await _db.ExecuteAsync(BloomCommandBuilder.Info(key))); + return info.ToBloomInfo(); + } - /// - public async Task InsertAsync(RedisKey key, RedisValue[] items, int? capacity = null, - double? error = null, int? expansion = null, - bool nocreate = false, bool nonscaling = false) - { - return (await _db.ExecuteAsync(BloomCommandBuilder.Insert(key, items, capacity, error, expansion, nocreate, nonscaling))).ToBooleanArray(); - } + /// + public async Task InsertAsync(RedisKey key, RedisValue[] items, int? capacity = null, + double? error = null, int? expansion = null, + bool nocreate = false, bool nonscaling = false) + { + return (await _db.ExecuteAsync(BloomCommandBuilder.Insert(key, items, capacity, error, expansion, nocreate, + nonscaling))).ToBooleanArray(); + } - /// - public async Task LoadChunkAsync(RedisKey key, long iterator, Byte[] data) - { - return (await _db.ExecuteAsync(BloomCommandBuilder.LoadChunk(key, iterator, data))).OKtoBoolean(); - } + /// + public async Task LoadChunkAsync(RedisKey key, long iterator, Byte[] data) + { + return (await _db.ExecuteAsync(BloomCommandBuilder.LoadChunk(key, iterator, data))).OKtoBoolean(); + } - /// - public async Task MAddAsync(RedisKey key, params RedisValue[] items) - { - return (await _db.ExecuteAsync(BloomCommandBuilder.MAdd(key, items))).ToBooleanArray(); - } + /// + public async Task MAddAsync(RedisKey key, params RedisValue[] items) + { + return (await _db.ExecuteAsync(BloomCommandBuilder.MAdd(key, items))).ToBooleanArray(); + } - /// - public async Task MExistsAsync(RedisKey key, RedisValue[] items) - { - return (await _db.ExecuteAsync(BloomCommandBuilder.MExists(key, items))).ToBooleanArray(); - } + /// + public async Task MExistsAsync(RedisKey key, RedisValue[] items) + { + return (await _db.ExecuteAsync(BloomCommandBuilder.MExists(key, items))).ToBooleanArray(); + } - /// - public async Task ReserveAsync(RedisKey key, double errorRate, long capacity, - int? expansion = null, bool nonscaling = false) - { - return (await _db.ExecuteAsync(BloomCommandBuilder.Reserve(key, errorRate, capacity, expansion, nonscaling))).OKtoBoolean(); - } + /// + public async Task ReserveAsync(RedisKey key, double errorRate, long capacity, + int? expansion = null, bool nonscaling = false) + { + return (await _db.ExecuteAsync(BloomCommandBuilder.Reserve(key, errorRate, capacity, expansion, nonscaling))) + .OKtoBoolean(); + } - /// - public async Task> ScanDumpAsync(RedisKey key, long iterator) - { - return (await _db.ExecuteAsync(BloomCommandBuilder.ScanDump(key, iterator))).ToScanDumpTuple(); - } + /// + public async Task> ScanDumpAsync(RedisKey key, long iterator) + { + return (await _db.ExecuteAsync(BloomCommandBuilder.ScanDump(key, iterator))).ToScanDumpTuple(); } } \ No newline at end of file diff --git a/src/NRedisStack/Bloom/IBloomCommands.cs b/src/NRedisStack/Bloom/IBloomCommands.cs index 5afb16d7..8ca224f9 100644 --- a/src/NRedisStack/Bloom/IBloomCommands.cs +++ b/src/NRedisStack/Bloom/IBloomCommands.cs @@ -1,117 +1,116 @@ using NRedisStack.Bloom.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public interface IBloomCommands { - public interface IBloomCommands - { - /// - /// Adds an item to a Bloom Filter. - /// - /// The key under which the filter is found. - /// The item to add. - /// if the item did not exist in the filter, otherwise. - /// - bool Add(RedisKey key, RedisValue item); + /// + /// Adds an item to a Bloom Filter. + /// + /// The key under which the filter is found. + /// The item to add. + /// if the item did not exist in the filter, otherwise. + /// + bool Add(RedisKey key, RedisValue item); - /// - /// Returns the cardinality of a Bloom filter. - /// - /// The name of the filter. - /// number of items that were added to a Bloom filter and detected as unique. - /// - long Card(RedisKey key); + /// + /// Returns the cardinality of a Bloom filter. + /// + /// The name of the filter. + /// number of items that were added to a Bloom filter and detected as unique. + /// + long Card(RedisKey key); - /// - /// Checks whether an item exist in the Bloom Filter or not. - /// - /// The name of the filter. - /// The item to check for. - /// means the item may exist in the filter, - /// and means it does not exist in the filter. - /// - bool Exists(RedisKey key, RedisValue item); + /// + /// Checks whether an item exist in the Bloom Filter or not. + /// + /// The name of the filter. + /// The item to check for. + /// means the item may exist in the filter, + /// and means it does not exist in the filter. + /// + bool Exists(RedisKey key, RedisValue item); - /// - /// Return information about a bloom filter. - /// - /// Name of the key to return information about. - /// Information of the filter. - /// - BloomInformation Info(RedisKey key); + /// + /// Return information about a bloom filter. + /// + /// Name of the key to return information about. + /// Information of the filter. + /// + BloomInformation Info(RedisKey key); - /// - /// Adds one or more items to a Bloom Filter. A filter will be created if it does not exist. - /// - /// The name of the filter. - /// One or more items to add. - /// (Optional) Specifies the desired capacity for the filter to be created. - /// (Optional) Specifies the error ratio of the newly created filter if it does not yet exist. - /// (Optional) When capacity is reached, an additional sub-filter is - /// created in size of the last sub-filter multiplied by expansion. - /// (Optional) to indicates that the - /// filter should not be created if it does not already exist. - /// (Optional) toprevent the filter - /// from creating additional sub-filters if initial capacity is reached. - /// 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. - /// - bool[] Insert(RedisKey key, RedisValue[] items, int? capacity = null, - double? error = null, int? expansion = null, - bool nocreate = false, bool nonscaling = false); + /// + /// Adds one or more items to a Bloom Filter. A filter will be created if it does not exist. + /// + /// The name of the filter. + /// One or more items to add. + /// (Optional) Specifies the desired capacity for the filter to be created. + /// (Optional) Specifies the error ratio of the newly created filter if it does not yet exist. + /// (Optional) When capacity is reached, an additional sub-filter is + /// created in size of the last sub-filter multiplied by expansion. + /// (Optional) to indicates that the + /// filter should not be created if it does not already exist. + /// (Optional) toprevent the filter + /// from creating additional sub-filters if initial capacity is reached. + /// 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. + /// + bool[] Insert(RedisKey key, RedisValue[] items, int? capacity = null, + double? error = null, int? expansion = null, + bool nocreate = false, bool nonscaling = false); - /// - /// Restores a filter previosly saved using SCANDUMP. - /// - /// Name of the key to restore. - /// Iterator value associated with data (returned by SCANDUMP). - /// Current data chunk (returned by SCANDUMP). - /// if executed correctly, error otherwise/> - /// - bool LoadChunk(RedisKey key, long iterator, Byte[] data); + /// + /// Restores a filter previously saved using SCANDUMP. + /// + /// Name of the key to restore. + /// Iterator value associated with data (returned by SCANDUMP). + /// Current data chunk (returned by SCANDUMP). + /// if executed correctly, error otherwise/> + /// + bool LoadChunk(RedisKey key, long iterator, byte[] data); - /// - /// Adds one or more items to the Bloom Filter. A filter will be created if it does not exist yet. - /// - /// The name of the filter. - /// One or more items to add. - /// 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. - /// - bool[] MAdd(RedisKey key, params RedisValue[] items); + /// + /// Adds one or more items to the Bloom Filter. A filter will be created if it does not exist yet. + /// + /// The name of the filter. + /// One or more items to add. + /// 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. + /// + bool[] MAdd(RedisKey key, params RedisValue[] items); - /// - /// Checks whether one or more items may exist in the filter or not. - /// - /// The name of the filter. - /// One or more items to check. - /// An array of booleans, for each item means the item may exist in the filter, - /// and means the item may exist in the filter. - /// - bool[] MExists(RedisKey key, RedisValue[] items); + /// + /// Checks whether one or more items may exist in the filter or not. + /// + /// The name of the filter. + /// One or more items to check. + /// An array of booleans, for each item means the item may exist in the filter, + /// and means the item may exist in the filter. + /// + bool[] MExists(RedisKey key, RedisValue[] items); - /// - /// Creates a new Bloom Filter. - /// - /// The key under which the filter is found. - /// The desired probability for false positives (value between 0 to 1). - /// The number of entries intended to be added to the filter. - /// (Optional) When capacity is reached, an additional sub-filter is - /// created in size of the last sub-filter multiplied by expansion. - /// (Optional) toprevent the filter - /// from creating additional sub-filters if initial capacity is reached. - /// if executed correctly, error otherwise/> - /// - bool Reserve(RedisKey key, double errorRate, long capacity, - int? expansion = null, bool nonscaling = false); + /// + /// Creates a new Bloom Filter. + /// + /// The key under which the filter is found. + /// The desired probability for false positives (value between 0 to 1). + /// The number of entries intended to be added to the filter. + /// (Optional) When capacity is reached, an additional sub-filter is + /// created in size of the last sub-filter multiplied by expansion. + /// (Optional) toprevent the filter + /// from creating additional sub-filters if initial capacity is reached. + /// if executed correctly, error otherwise/> + /// + bool Reserve(RedisKey key, double errorRate, long capacity, + int? expansion = null, bool nonscaling = false); - /// - /// Restores a filter previosly saved using SCANDUMP. - /// - /// Name of the filter. - /// Iterator value; either 0 or the iterator from a previous invocation of this command. - /// Tuple of iterator and data. - /// - Tuple ScanDump(RedisKey key, long iterator); - } -} + /// + /// Restores a filter previously saved using SCANDUMP. + /// + /// Name of the filter. + /// Iterator value; either 0 or the iterator from a previous invocation of this command. + /// Tuple of iterator and data. + /// + Tuple ScanDump(RedisKey key, long iterator); +} \ No newline at end of file diff --git a/src/NRedisStack/Bloom/IBloomCommandsAsync.cs b/src/NRedisStack/Bloom/IBloomCommandsAsync.cs index ca7f832d..f4f278bb 100644 --- a/src/NRedisStack/Bloom/IBloomCommandsAsync.cs +++ b/src/NRedisStack/Bloom/IBloomCommandsAsync.cs @@ -1,118 +1,117 @@ using NRedisStack.Bloom.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public interface IBloomCommandsAsync { - public interface IBloomCommandsAsync - { - /// - /// Adds an item to a Bloom Filter. - /// - /// The key under which the filter is found. - /// The item to add. - /// if the item did not exist in the filter, otherwise. - /// - Task AddAsync(RedisKey key, RedisValue item); + /// + /// Adds an item to a Bloom Filter. + /// + /// The key under which the filter is found. + /// The item to add. + /// if the item did not exist in the filter, otherwise. + /// + Task AddAsync(RedisKey key, RedisValue item); - /// - /// Returns the cardinality of a Bloom filter. - /// - /// The name of the filter. - /// number of items that were added to a Bloom filter and detected as unique. - /// - Task CardAsync(RedisKey key); + /// + /// Returns the cardinality of a Bloom filter. + /// + /// The name of the filter. + /// number of items that were added to a Bloom filter and detected as unique. + /// + Task CardAsync(RedisKey key); - /// - /// Checks whether an item exist in the Bloom Filter or not. - /// - /// The name of the filter. - /// The item to check for. - /// means the item may exist in the filter, - /// and means it does not exist in the filter. - /// - Task ExistsAsync(RedisKey key, RedisValue item); + /// + /// Checks whether an item exist in the Bloom Filter or not. + /// + /// The name of the filter. + /// The item to check for. + /// means the item may exist in the filter, + /// and means it does not exist in the filter. + /// + Task ExistsAsync(RedisKey key, RedisValue item); - /// - /// Return information about a bloom filter. - /// - /// Name of the key to return information about. - /// Information of the filter. - /// - Task InfoAsync(RedisKey key); + /// + /// Return information about a bloom filter. + /// + /// Name of the key to return information about. + /// Information of the filter. + /// + Task InfoAsync(RedisKey key); - /// - /// Adds one or more items to a Bloom Filter. A filter will be created if it does not exist. - /// - /// The name of the filter. - /// One or more items to add. - /// (Optional) Specifies the desired capacity for the filter to be created. - /// (Optional) Specifies the error ratio of the newly created filter if it does not yet exist. - /// (Optional) When capacity is reached, an additional sub-filter is - /// created in size of the last sub-filter multiplied by expansion. - /// (Optional) to indicates that the - /// filter should not be created if it does not already exist. - /// (Optional) toprevent the filter - /// from creating additional sub-filters if initial capacity is reached. - /// 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. - /// - Task InsertAsync(RedisKey key, RedisValue[] items, int? capacity = null, - double? error = null, int? expansion = null, - bool nocreate = false, bool nonscaling = false); + /// + /// Adds one or more items to a Bloom Filter. A filter will be created if it does not exist. + /// + /// The name of the filter. + /// One or more items to add. + /// (Optional) Specifies the desired capacity for the filter to be created. + /// (Optional) Specifies the error ratio of the newly created filter if it does not yet exist. + /// (Optional) When capacity is reached, an additional sub-filter is + /// created in size of the last sub-filter multiplied by expansion. + /// (Optional) to indicates that the + /// filter should not be created if it does not already exist. + /// (Optional) toprevent the filter + /// from creating additional sub-filters if initial capacity is reached. + /// 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. + /// + Task InsertAsync(RedisKey key, RedisValue[] items, int? capacity = null, + double? error = null, int? expansion = null, + bool nocreate = false, bool nonscaling = false); - /// - /// Restores a filter previosly saved using SCANDUMP. - /// - /// Name of the key to restore. - /// Iterator value associated with data (returned by SCANDUMP). - /// Current data chunk (returned by SCANDUMP). - /// if executed correctly, error otherwise/> - /// - Task LoadChunkAsync(RedisKey key, long iterator, Byte[] data); + /// + /// Restores a filter previously saved using SCANDUMP. + /// + /// Name of the key to restore. + /// Iterator value associated with data (returned by SCANDUMP). + /// Current data chunk (returned by SCANDUMP). + /// if executed correctly, error otherwise/> + /// + Task LoadChunkAsync(RedisKey key, long iterator, Byte[] data); - /// - /// Adds one or more items to the Bloom Filter. A filter will be created if it does not exist yet. - /// - /// The name of the filter. - /// One or more items to add. - /// 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. - /// - Task MAddAsync(RedisKey key, params RedisValue[] items); + /// + /// Adds one or more items to the Bloom Filter. A filter will be created if it does not exist yet. + /// + /// The name of the filter. + /// One or more items to add. + /// 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. + /// + Task MAddAsync(RedisKey key, params RedisValue[] items); - /// - /// Checks whether one or more items may exist in the filter or not. - /// - /// The name of the filter. - /// One or more items to check. - /// An array of booleans, for each item means the item may exist in the filter, - /// and means the item may exist in the filter. - /// - Task MExistsAsync(RedisKey key, RedisValue[] items); + /// + /// Checks whether one or more items may exist in the filter or not. + /// + /// The name of the filter. + /// One or more items to check. + /// An array of booleans, for each item means the item may exist in the filter, + /// and means the item may exist in the filter. + /// + Task MExistsAsync(RedisKey key, RedisValue[] items); - /// - /// Creates a new Bloom Filter. - /// - /// The key under which the filter is found. - /// The desired probability for false positives (value between 0 to 1). - /// The number of entries intended to be added to the filter. - /// (Optional) When capacity is reached, an additional sub-filter is - /// created in size of the last sub-filter multiplied by expansion. - /// (Optional) toprevent the filter - /// from creating additional sub-filters if initial capacity is reached. - /// if executed correctly, Error otherwise. - /// - Task ReserveAsync(RedisKey key, double errorRate, long capacity, - int? expansion = null, bool nonscaling = false); + /// + /// Creates a new Bloom Filter. + /// + /// The key under which the filter is found. + /// The desired probability for false positives (value between 0 to 1). + /// The number of entries intended to be added to the filter. + /// (Optional) When capacity is reached, an additional sub-filter is + /// created in size of the last sub-filter multiplied by expansion. + /// (Optional) toprevent the filter + /// from creating additional sub-filters if initial capacity is reached. + /// if executed correctly, Error otherwise. + /// + Task ReserveAsync(RedisKey key, double errorRate, long capacity, + int? expansion = null, bool nonscaling = false); - /// - /// Restores a filter previosly saved using SCANDUMP. - /// - /// Name of the filter. - /// Iterator value; either 0 or the iterator from a previous invocation of this command. - /// Tuple of iterator and data. - /// - Task> ScanDumpAsync(RedisKey key, long iterator); - } + /// + /// Restores a filter previously saved using SCANDUMP. + /// + /// Name of the filter. + /// Iterator value; either 0 or the iterator from a previous invocation of this command. + /// Tuple of iterator and data. + /// + Task> ScanDumpAsync(RedisKey key, long iterator); } \ No newline at end of file diff --git a/src/NRedisStack/CoreCommands/CoreCommandBuilder.cs b/src/NRedisStack/CoreCommands/CoreCommandBuilder.cs index a343f3b2..b4189185 100644 --- a/src/NRedisStack/CoreCommands/CoreCommandBuilder.cs +++ b/src/NRedisStack/CoreCommands/CoreCommandBuilder.cs @@ -28,11 +28,13 @@ public static SerializedCommand BZMPop(double timeout, RedisKey[] keys, MinMaxMo throw new ArgumentException("At least one key must be provided."); } - List args = new List(); + List args = new List { + timeout, + keys.Length + }; - args.Add(timeout); - args.Add(keys.Length); args.AddRange(keys.Cast()); + args.Add(minMaxModifier == MinMaxModifier.Min ? CoreArgs.MIN : CoreArgs.MAX); if (count != null) diff --git a/src/NRedisStack/CoreCommands/CoreCommands.cs b/src/NRedisStack/CoreCommands/CoreCommands.cs index d8f5f361..9af50645 100644 --- a/src/NRedisStack/CoreCommands/CoreCommands.cs +++ b/src/NRedisStack/CoreCommands/CoreCommands.cs @@ -2,483 +2,482 @@ using NRedisStack.Core.DataTypes; using StackExchange.Redis; -namespace NRedisStack -{ +namespace NRedisStack; - public static class CoreCommands +public static class CoreCommands +{ + /// + /// Sets information specific to the client or connection. + /// + /// which attribute to set + /// the attribute value + /// if the attribute name was successfully set, Error otherwise. + /// + public static bool ClientSetInfo(this IDatabase db, SetInfoAttr attr, string value) { - /// - /// Sets information specific to the client or connection. - /// - /// which attribute to set - /// the attribute value - /// if the attribute name was successfully set, Error otherwise. - /// - public static bool ClientSetInfo(this IDatabase db, SetInfoAttr attr, string value) - { - var compareVersions = db.Multiplexer.GetServer(db.Multiplexer.GetEndPoints()[0]).Version.CompareTo(new Version(7, 1, 242)); - if (compareVersions < 0) // the server does not support the CLIENT SETNAME command - return false; - return db.Execute(CoreCommandBuilder.ClientSetInfo(attr, value)).OKtoBoolean(); - } + var compareVersions = db.Multiplexer.GetServer(db.Multiplexer.GetEndPoints()[0]).Version.CompareTo(new Version(7, 1, 242)); + if (compareVersions < 0) // the server does not support the CLIENT SETNAME command + return false; + return db.Execute(CoreCommandBuilder.ClientSetInfo(attr, value)).OKtoBoolean(); + } - /// - /// The BZMPOP command. - ///

- /// Removes and returns up to entries from the first non-empty sorted set in - /// . If none of the sets contain elements, the call blocks on the server until elements - /// become available, or the given expires. A of 0 - /// means to wait indefinitely server-side. Returns null if the server timeout expires. - ///

- /// When using this, pay attention to the timeout configured in the client, on the - /// , which by default can be too small: - /// - /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); - /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here - /// configurationOptions.EndPoints.Add("localhost"); - /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); - /// - /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException - /// is thrown. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// The keys to check. - /// Specify from which end of the sorted set to pop values. If set to MinMaxModifier.Min - /// then the minimum elements will be popped, otherwise the maximum values. - /// The maximum number of records to pop out. If set to null then the server default - /// will be used. - /// A collection of sorted set entries paired with their scores, together with the key they were popped - /// from, or null if the server timeout expires. - /// - public static Tuple>? BZMPop(this IDatabase db, double timeout, RedisKey[] keys, MinMaxModifier minMaxModifier, long? count = null) - { - var command = CoreCommandBuilder.BZMPop(timeout, keys, minMaxModifier, count); - return db.Execute(command).ToSortedSetPopResults(); - } + /// + /// The BZMPOP command. + ///

+ /// Removes and returns up to entries from the first non-empty sorted set in + /// . If none of the sets contain elements, the call blocks on the server until elements + /// become available, or the given expires. A of 0 + /// means to wait indefinitely server-side. Returns null if the server timeout expires. + ///

+ /// When using this, pay attention to the timeout configured in the client, on the + /// , which by default can be too small: + /// + /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); + /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here + /// configurationOptions.EndPoints.Add("localhost"); + /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); + /// + /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException + /// is thrown. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// The keys to check. + /// Specify from which end of the sorted set to pop values. If set to MinMaxModifier.Min + /// then the minimum elements will be popped, otherwise the maximum values. + /// The maximum number of records to pop out. If set to null then the server default + /// will be used. + /// A collection of sorted set entries paired with their scores, together with the key they were popped + /// from, or null if the server timeout expires. + /// + public static Tuple>? BZMPop(this IDatabase db, double timeout, RedisKey[] keys, MinMaxModifier minMaxModifier, long? count = null) + { + var command = CoreCommandBuilder.BZMPop(timeout, keys, minMaxModifier, count); + return db.Execute(command).ToSortedSetPopResults(); + } - /// - /// Syntactic sugar for - /// , - /// where only one key is used. - /// - /// The class where this extension method is applied. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// The key to check. - /// Specify from which end of the sorted set to pop values. If set to MinMaxModifier.Min - /// then the minimum elements will be popped, otherwise the maximum values. - /// The maximum number of records to pop out. If set to null then the server default - /// will be used. - /// A collection of sorted set entries paired with their scores, together with the key they were popped - /// from, or null if the server timeout expires. - /// - public static Tuple>? BZMPop(this IDatabase db, double timeout, RedisKey key, MinMaxModifier minMaxModifier, long? count = null) - { - return BZMPop(db, timeout, new[] { key }, minMaxModifier, count); - } + /// + /// Syntactic sugar for + /// , + /// where only one key is used. + /// + /// The class where this extension method is applied. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// The key to check. + /// Specify from which end of the sorted set to pop values. If set to MinMaxModifier.Min + /// then the minimum elements will be popped, otherwise the maximum values. + /// The maximum number of records to pop out. If set to null then the server default + /// will be used. + /// A collection of sorted set entries paired with their scores, together with the key they were popped + /// from, or null if the server timeout expires. + /// + public static Tuple>? BZMPop(this IDatabase db, double timeout, RedisKey key, MinMaxModifier minMaxModifier, long? count = null) + { + return BZMPop(db, timeout, new[] { key }, minMaxModifier, count); + } - /// - /// The BZPOPMIN command. - ///

- /// Removes and returns the entry with the smallest score from the first non-empty sorted set in - /// . If none of the sets contain elements, the call blocks on the server until elements - /// become available, or the given expires. A of 0 - /// means to wait indefinitely server-side. Returns null if the server timeout expires. - ///

- /// When using this, pay attention to the timeout configured in the client, on the - /// , which by default can be too small: - /// - /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); - /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here - /// configurationOptions.EndPoints.Add("localhost"); - /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); - /// - /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException - /// is thrown. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// The keys to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A sorted set entry paired with its score, together with the key it was popped from, or null - /// if the server timeout expires. - /// - public static Tuple? BZPopMin(this IDatabase db, RedisKey[] keys, double timeout) - { - var command = CoreCommandBuilder.BZPopMin(keys, timeout); - return db.Execute(command).ToSortedSetPopResult(); - } + /// + /// The BZPOPMIN command. + ///

+ /// Removes and returns the entry with the smallest score from the first non-empty sorted set in + /// . If none of the sets contain elements, the call blocks on the server until elements + /// become available, or the given expires. A of 0 + /// means to wait indefinitely server-side. Returns null if the server timeout expires. + ///

+ /// When using this, pay attention to the timeout configured in the client, on the + /// , which by default can be too small: + /// + /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); + /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here + /// configurationOptions.EndPoints.Add("localhost"); + /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); + /// + /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException + /// is thrown. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// The keys to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A sorted set entry paired with its score, together with the key it was popped from, or null + /// if the server timeout expires. + /// + public static Tuple? BZPopMin(this IDatabase db, RedisKey[] keys, double timeout) + { + var command = CoreCommandBuilder.BZPopMin(keys, timeout); + return db.Execute(command).ToSortedSetPopResult(); + } - /// - /// Syntactic sugar for , - /// where only one key is used. - /// - /// The class where this extension method is applied. - /// The key to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A sorted set entry paired with its score, together with the key it was popped from, or null - /// if the server timeout expires. - /// - public static Tuple? BZPopMin(this IDatabase db, RedisKey key, double timeout) - { - return BZPopMin(db, new[] { key }, timeout); - } + /// + /// Syntactic sugar for , + /// where only one key is used. + /// + /// The class where this extension method is applied. + /// The key to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A sorted set entry paired with its score, together with the key it was popped from, or null + /// if the server timeout expires. + /// + public static Tuple? BZPopMin(this IDatabase db, RedisKey key, double timeout) + { + return BZPopMin(db, new[] { key }, timeout); + } - /// - /// The BZPOPMAX command. - ///

- /// Removes and returns the entry with the highest score from the first non-empty sorted set in - /// . If none of the sets contain elements, the call blocks on the server until elements - /// become available, or the given expires. A of 0 - /// means to wait indefinitely server-side. Returns null if the server timeout expires. - ///

- /// When using this, pay attention to the timeout configured in the client, on the - /// , which by default can be too small: - /// - /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); - /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here - /// configurationOptions.EndPoints.Add("localhost"); - /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); - /// - /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException - /// is thrown. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// The keys to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A sorted set entry paired with its score, together with the key it was popped from, or null - /// if the server timeout expires. - /// - public static Tuple? BZPopMax(this IDatabase db, RedisKey[] keys, double timeout) - { - var command = CoreCommandBuilder.BZPopMax(keys, timeout); - return db.Execute(command).ToSortedSetPopResult(); - } + /// + /// The BZPOPMAX command. + ///

+ /// Removes and returns the entry with the highest score from the first non-empty sorted set in + /// . If none of the sets contain elements, the call blocks on the server until elements + /// become available, or the given expires. A of 0 + /// means to wait indefinitely server-side. Returns null if the server timeout expires. + ///

+ /// When using this, pay attention to the timeout configured in the client, on the + /// , which by default can be too small: + /// + /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); + /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here + /// configurationOptions.EndPoints.Add("localhost"); + /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); + /// + /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException + /// is thrown. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// The keys to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A sorted set entry paired with its score, together with the key it was popped from, or null + /// if the server timeout expires. + /// + public static Tuple? BZPopMax(this IDatabase db, RedisKey[] keys, double timeout) + { + var command = CoreCommandBuilder.BZPopMax(keys, timeout); + return db.Execute(command).ToSortedSetPopResult(); + } - /// - /// Syntactic sugar for , - /// where only one key is used. - /// - /// The class where this extension method is applied. - /// The key to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A sorted set entry paired with its score, together with the key it was popped from, or null - /// if the server timeout expires. - /// - public static Tuple? BZPopMax(this IDatabase db, RedisKey key, double timeout) - { - return BZPopMax(db, new[] { key }, timeout); - } + /// + /// Syntactic sugar for , + /// where only one key is used. + /// + /// The class where this extension method is applied. + /// The key to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A sorted set entry paired with its score, together with the key it was popped from, or null + /// if the server timeout expires. + /// + public static Tuple? BZPopMax(this IDatabase db, RedisKey key, double timeout) + { + return BZPopMax(db, new[] { key }, timeout); + } - /// - /// The BLMPOP command. - ///

- /// Removes and returns up to entries from the first non-empty list in - /// . If none of the lists contain elements, the call blocks on the server until elements - /// become available, or the given expires. A of 0 - /// means to wait indefinitely server-side. Returns null if the server timeout expires. - ///

- /// When using this, pay attention to the timeout configured in the client, on the - /// , which by default can be too small: - /// - /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); - /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here - /// configurationOptions.EndPoints.Add("localhost"); - /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); - /// - /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException - /// is thrown. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// The keys to check. - /// Specify from which end of the list to pop values: left or right. - /// The maximum number of records to pop. If set to null then the server default - /// will be used. - /// A collection of values, together with the key they were popped from, or null if the - /// server timeout expires. - /// - public static Tuple>? BLMPop(this IDatabase db, double timeout, RedisKey[] keys, ListSide listSide, long? count = null) - { - var command = CoreCommandBuilder.BLMPop(timeout, keys, listSide, count); - return db.Execute(command).ToListPopResults(); - } + /// + /// The BLMPOP command. + ///

+ /// Removes and returns up to entries from the first non-empty list in + /// . If none of the lists contain elements, the call blocks on the server until elements + /// become available, or the given expires. A of 0 + /// means to wait indefinitely server-side. Returns null if the server timeout expires. + ///

+ /// When using this, pay attention to the timeout configured in the client, on the + /// , which by default can be too small: + /// + /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); + /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here + /// configurationOptions.EndPoints.Add("localhost"); + /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); + /// + /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException + /// is thrown. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// The keys to check. + /// Specify from which end of the list to pop values: left or right. + /// The maximum number of records to pop. If set to null then the server default + /// will be used. + /// A collection of values, together with the key they were popped from, or null if the + /// server timeout expires. + /// + public static Tuple>? BLMPop(this IDatabase db, double timeout, RedisKey[] keys, ListSide listSide, long? count = null) + { + var command = CoreCommandBuilder.BLMPop(timeout, keys, listSide, count); + return db.Execute(command).ToListPopResults(); + } - /// - /// Syntactic sugar for - /// , - /// where only one key is used. - /// - /// The class where this extension method is applied. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// The key to check. - /// Specify from which end of the list to pop values: left or right. - /// The maximum number of records to pop. If set to null then the server default - /// will be used. - /// A collection of values, together with the key they were popped from, or null if the - /// server timeout expires. - /// - public static Tuple>? BLMPop(this IDatabase db, double timeout, RedisKey key, ListSide listSide, long? count = null) - { - return BLMPop(db, timeout, new[] { key }, listSide, count); - } + /// + /// Syntactic sugar for + /// , + /// where only one key is used. + /// + /// The class where this extension method is applied. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// The key to check. + /// Specify from which end of the list to pop values: left or right. + /// The maximum number of records to pop. If set to null then the server default + /// will be used. + /// A collection of values, together with the key they were popped from, or null if the + /// server timeout expires. + /// + public static Tuple>? BLMPop(this IDatabase db, double timeout, RedisKey key, ListSide listSide, long? count = null) + { + return BLMPop(db, timeout, new[] { key }, listSide, count); + } - /// - /// The BLPOP command. - ///

- /// Removes and returns an entry from the head (left side) of the first non-empty list in . - /// If none of the lists contain elements, the call blocks on the server until elements - /// become available, or the given expires. A of 0 - /// means to wait indefinitely server-side. Returns null if the server timeout expires. - ///

- /// When using this, pay attention to the timeout configured in the client, on the - /// , which by default can be too small: - /// - /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); - /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here - /// configurationOptions.EndPoints.Add("localhost"); - /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); - /// - /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException - /// is thrown. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// The keys to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A value, together with the key it was popped from, or null if the server timeout - /// expires. - /// - public static Tuple? BLPop(this IDatabase db, RedisKey[] keys, double timeout) - { - var command = CoreCommandBuilder.BLPop(keys, timeout); - return db.Execute(command).ToListPopResult(); - } + /// + /// The BLPOP command. + ///

+ /// Removes and returns an entry from the head (left side) of the first non-empty list in . + /// If none of the lists contain elements, the call blocks on the server until elements + /// become available, or the given expires. A of 0 + /// means to wait indefinitely server-side. Returns null if the server timeout expires. + ///

+ /// When using this, pay attention to the timeout configured in the client, on the + /// , which by default can be too small: + /// + /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); + /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here + /// configurationOptions.EndPoints.Add("localhost"); + /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); + /// + /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException + /// is thrown. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// The keys to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A value, together with the key it was popped from, or null if the server timeout + /// expires. + /// + public static Tuple? BLPop(this IDatabase db, RedisKey[] keys, double timeout) + { + var command = CoreCommandBuilder.BLPop(keys, timeout); + return db.Execute(command).ToListPopResult(); + } - /// - /// Syntactic sugar for , - /// where only one key is used. - /// - /// The class where this extension method is applied. - /// The key to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A value, together with the key it was popped from, or null if the server timeout - /// expires. - /// - public static Tuple? BLPop(this IDatabase db, RedisKey key, double timeout) - { - return BLPop(db, new[] { key }, timeout); - } + /// + /// Syntactic sugar for , + /// where only one key is used. + /// + /// The class where this extension method is applied. + /// The key to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A value, together with the key it was popped from, or null if the server timeout + /// expires. + /// + public static Tuple? BLPop(this IDatabase db, RedisKey key, double timeout) + { + return BLPop(db, new[] { key }, timeout); + } - /// - /// The BRPOP command. - ///

- /// Removes and returns an entry from the tail (right side) of the first non-empty list in . - /// If none of the lists contain elements, the call blocks on the server until elements - /// become available, or the given expires. A of 0 - /// means to wait indefinitely server-side. Returns null if the server timeout expires. - ///

- /// When using this, pay attention to the timeout configured in the client, on the - /// , which by default can be too small: - /// - /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); - /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here - /// configurationOptions.EndPoints.Add("localhost"); - /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); - /// - /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException - /// is thrown. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// The keys to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A value, together with the key it was popped from, or null if the server timeout - /// expires. - /// - public static Tuple? BRPop(this IDatabase db, RedisKey[] keys, double timeout) - { - var command = CoreCommandBuilder.BRPop(keys, timeout); - return db.Execute(command).ToListPopResult(); - } + /// + /// The BRPOP command. + ///

+ /// Removes and returns an entry from the tail (right side) of the first non-empty list in . + /// If none of the lists contain elements, the call blocks on the server until elements + /// become available, or the given expires. A of 0 + /// means to wait indefinitely server-side. Returns null if the server timeout expires. + ///

+ /// When using this, pay attention to the timeout configured in the client, on the + /// , which by default can be too small: + /// + /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); + /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here + /// configurationOptions.EndPoints.Add("localhost"); + /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); + /// + /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException + /// is thrown. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// The keys to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A value, together with the key it was popped from, or null if the server timeout + /// expires. + /// + public static Tuple? BRPop(this IDatabase db, RedisKey[] keys, double timeout) + { + var command = CoreCommandBuilder.BRPop(keys, timeout); + return db.Execute(command).ToListPopResult(); + } - /// - /// Syntactic sugar for , - /// where only one key is used. - /// - /// The class where this extension method is applied. - /// The key to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A value, together with the key it was popped from, or null if the server timeout - /// expires. - /// - public static Tuple? BRPop(this IDatabase db, RedisKey key, double timeout) - { - return BRPop(db, new[] { key }, timeout); - } + /// + /// Syntactic sugar for , + /// where only one key is used. + /// + /// The class where this extension method is applied. + /// The key to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A value, together with the key it was popped from, or null if the server timeout + /// expires. + /// + public static Tuple? BRPop(this IDatabase db, RedisKey key, double timeout) + { + return BRPop(db, new[] { key }, timeout); + } - /// - /// The BLMOVE command. - ///

- /// Atomically returns and removes the first or last element of the list stored at - /// (depending on the value of ), and pushes the element as the first or last - /// element of the list stored at (depending on the value of - /// ). - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// The key of the source list. - /// The key of the destination list. - /// What side of the list to remove from. - /// What side of the list to move to. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// The element being popped and pushed, or null if the server timeout expires. - /// - public static RedisValue? BLMove(this IDatabase db, RedisKey source, RedisKey destination, ListSide sourceSide, ListSide destinationSide, double timeout) - { - var command = CoreCommandBuilder.BLMove(source, destination, sourceSide, destinationSide, timeout); - return db.Execute(command).ToRedisValue(); - } + /// + /// The BLMOVE command. + ///

+ /// Atomically returns and removes the first or last element of the list stored at + /// (depending on the value of ), and pushes the element as the first or last + /// element of the list stored at (depending on the value of + /// ). + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// The key of the source list. + /// The key of the destination list. + /// What side of the list to remove from. + /// What side of the list to move to. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// The element being popped and pushed, or null if the server timeout expires. + /// + public static RedisValue? BLMove(this IDatabase db, RedisKey source, RedisKey destination, ListSide sourceSide, ListSide destinationSide, double timeout) + { + var command = CoreCommandBuilder.BLMove(source, destination, sourceSide, destinationSide, timeout); + return db.Execute(command).ToRedisValue(); + } - /// - /// The BRPOPLPUSH command. - ///

- /// Atomically returns and removes the last element (tail) of the list stored at source, and pushes the element - /// at the first element (head) of the list stored at destination. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// The key of the source list. - /// The key of the destination list. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// The element being popped and pushed, or null if the server timeout expires. - /// - public static RedisValue? BRPopLPush(this IDatabase db, RedisKey source, RedisKey destination, double timeout) - { - var command = CoreCommandBuilder.BRPopLPush(source, destination, timeout); - return db.Execute(command).ToRedisValue(); - } + /// + /// The BRPOPLPUSH command. + ///

+ /// Atomically returns and removes the last element (tail) of the list stored at source, and pushes the element + /// at the first element (head) of the list stored at destination. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// The key of the source list. + /// The key of the destination list. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// The element being popped and pushed, or null if the server timeout expires. + /// + public static RedisValue? BRPopLPush(this IDatabase db, RedisKey source, RedisKey destination, double timeout) + { + var command = CoreCommandBuilder.BRPopLPush(source, destination, timeout); + return db.Execute(command).ToRedisValue(); + } - /// - /// The XREAD command. - /// - /// Read data from one or multiple streams, only returning entries with an ID greater than an ID provided by the caller. - /// - /// The class where this extension method is applied. - /// Keys of the streams where to read from. - /// The positions from which to begin reading for each stream. See - /// for special Ids that can be used. - /// The maximum number of messages to return from each stream. - /// Amount of time in milliseconds to block in case all the streams are empty. - /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. - /// A value of for each stream, or null if the command times out - /// on the server. - /// - /// This is the blocking alternative for . - /// - /// - public static RedisStreamEntries[]? XRead(this IDatabase db, RedisKey[] keys, RedisValue[] positions, int? count = null, int? timeoutMilliseconds = null) - { - var command = CoreCommandBuilder.XRead(keys, positions, count, timeoutMilliseconds); - return db.Execute(command).ToRedisStreamEntries(); - } + /// + /// The XREAD command. + /// + /// Read data from one or multiple streams, only returning entries with an ID greater than an ID provided by the caller. + /// + /// The class where this extension method is applied. + /// Keys of the streams where to read from. + /// The positions from which to begin reading for each stream. See + /// for special Ids that can be used. + /// The maximum number of messages to return from each stream. + /// Amount of time in milliseconds to block in case all the streams are empty. + /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. + /// A value of for each stream, or null if the command times out + /// on the server. + /// + /// This is the blocking alternative for . + /// + /// + public static RedisStreamEntries[]? XRead(this IDatabase db, RedisKey[] keys, RedisValue[] positions, int? count = null, int? timeoutMilliseconds = null) + { + var command = CoreCommandBuilder.XRead(keys, positions, count, timeoutMilliseconds); + return db.Execute(command).ToRedisStreamEntries(); + } - /// - /// Syntactic sugar for , - /// where only one stream is being read from. - /// - /// The class where this extension method is applied. - /// Key of the stream where to read from. - /// The position from which to begin reading. See - /// for special Ids that can be used. - /// The maximum number of messages to return from each stream. - /// Amount of time in milliseconds to block in case all the streams are empty. - /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. - /// A list with the data read from the stream, of null if the command - /// times out on the server. - /// - /// This is the blocking alternative for . - /// - /// - public static StreamEntry[]? XRead(this IDatabase db, RedisKey key, RedisValue position, int? count = null, int? timeoutMilliseconds = null) + /// + /// Syntactic sugar for , + /// where only one stream is being read from. + /// + /// The class where this extension method is applied. + /// Key of the stream where to read from. + /// The position from which to begin reading. See + /// for special Ids that can be used. + /// The maximum number of messages to return from each stream. + /// Amount of time in milliseconds to block in case all the streams are empty. + /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. + /// A list with the data read from the stream, of null if the command + /// times out on the server. + /// + /// This is the blocking alternative for . + /// + /// + public static StreamEntry[]? XRead(this IDatabase db, RedisKey key, RedisValue position, int? count = null, int? timeoutMilliseconds = null) + { + var result = XRead(db, new[] { key }, new[] { position }, count, timeoutMilliseconds); + if (result == null || result.Length == 0) { - var result = XRead(db, new[] { key }, new[] { position }, count, timeoutMilliseconds); - if (result == null || result.Length == 0) - { - return null; - } - return result[0].Entries; + return null; } + return result[0].Entries; + } - /// - /// The XREADGROUP command. - /// - /// Read new or historical messages in one or several streams, for a consumer in a consumer group. - /// - /// The class where this extension method is applied. - /// The consumer group name. - /// The name of the consumer in the consumer group. - /// Keys of the streams where to read from. - /// The positions from which to begin reading for each stream. See - /// for special Ids that can be used. - /// The maximum number of messages to return from each stream. - /// Amount of time in milliseconds to block in case all the streams are empty. - /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. - /// If set to true then inform the server that it should not wait for ACK for the - /// messages it sends to this read call. - /// A value of for each stream, or null if the command times out - /// on the server. - /// - /// This is the blocking alternative for . - /// - /// - public static RedisStreamEntries[]? XReadGroup(this IDatabase db, RedisValue groupName, RedisValue consumerName, RedisKey[] keys, RedisValue[] positions, int? count = null, int? timeoutMilliseconds = null, bool? noAck = null) - { - var command = CoreCommandBuilder.XReadGroup(groupName, consumerName, keys, positions, count, timeoutMilliseconds, noAck); - return db.Execute(command).ToRedisStreamEntries(); - } + /// + /// The XREADGROUP command. + /// + /// Read new or historical messages in one or several streams, for a consumer in a consumer group. + /// + /// The class where this extension method is applied. + /// The consumer group name. + /// The name of the consumer in the consumer group. + /// Keys of the streams where to read from. + /// The positions from which to begin reading for each stream. See + /// for special Ids that can be used. + /// The maximum number of messages to return from each stream. + /// Amount of time in milliseconds to block in case all the streams are empty. + /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. + /// If set to true then inform the server that it should not wait for ACK for the + /// messages it sends to this read call. + /// A value of for each stream, or null if the command times out + /// on the server. + /// + /// This is the blocking alternative for . + /// + /// + public static RedisStreamEntries[]? XReadGroup(this IDatabase db, RedisValue groupName, RedisValue consumerName, RedisKey[] keys, RedisValue[] positions, int? count = null, int? timeoutMilliseconds = null, bool? noAck = null) + { + var command = CoreCommandBuilder.XReadGroup(groupName, consumerName, keys, positions, count, timeoutMilliseconds, noAck); + return db.Execute(command).ToRedisStreamEntries(); + } - /// - /// Syntactic sugar for , - /// where only one stream is being read from. - /// - /// The class where this extension method is applied. - /// The consumer group name. - /// The name of the consumer in the consumer group. - /// Key of the stream where to read from. - /// The position from which to begin reading. See - /// for special Ids that can be used. - /// The maximum number of messages to return from each stream. - /// Amount of time in milliseconds to block in case all the streams are empty. - /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. - /// If set to true then inform the server that it should not wait for ACK for the - /// messages it sends to this read call. - /// A list with the data read from the stream, of null if the command - /// times out on the server. - /// - /// This is the blocking alternative for . - /// - /// - public static StreamEntry[]? XReadGroup(this IDatabase db, RedisValue groupName, RedisValue consumerName, RedisKey key, RedisValue position, int? count = null, int? timeoutMilliseconds = null, bool? noAck = null) + /// + /// Syntactic sugar for , + /// where only one stream is being read from. + /// + /// The class where this extension method is applied. + /// The consumer group name. + /// The name of the consumer in the consumer group. + /// Key of the stream where to read from. + /// The position from which to begin reading. See + /// for special Ids that can be used. + /// The maximum number of messages to return from each stream. + /// Amount of time in milliseconds to block in case all the streams are empty. + /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. + /// If set to true then inform the server that it should not wait for ACK for the + /// messages it sends to this read call. + /// A list with the data read from the stream, of null if the command + /// times out on the server. + /// + /// This is the blocking alternative for . + /// + /// + public static StreamEntry[]? XReadGroup(this IDatabase db, RedisValue groupName, RedisValue consumerName, RedisKey key, RedisValue position, int? count = null, int? timeoutMilliseconds = null, bool? noAck = null) + { + var result = XReadGroup(db, groupName, consumerName, new[] { key }, new[] { position }, count, timeoutMilliseconds, noAck); + if (result == null || result.Length == 0) { - var result = XReadGroup(db, groupName, consumerName, new[] { key }, new[] { position }, count, timeoutMilliseconds, noAck); - if (result == null || result.Length == 0) - { - return null; - } - return result[0].Entries; + return null; } + return result[0].Entries; } } + diff --git a/src/NRedisStack/CountMinSketch/CmsCommandBuilder.cs b/src/NRedisStack/CountMinSketch/CmsCommandBuilder.cs index d8ff2363..7e6299ab 100644 --- a/src/NRedisStack/CountMinSketch/CmsCommandBuilder.cs +++ b/src/NRedisStack/CountMinSketch/CmsCommandBuilder.cs @@ -2,73 +2,73 @@ using NRedisStack.RedisStackCommands; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public static class CmsCommandBuilder { + public static SerializedCommand IncrBy(RedisKey key, RedisValue item, long increment) + { + return new SerializedCommand(CMS.INCRBY, key, item, increment); + } - public static class CmsCommandBuilder + public static SerializedCommand IncrBy(RedisKey key, Tuple[] itemIncrements) { - public static SerializedCommand IncrBy(RedisKey key, RedisValue item, long increment) - { - return new SerializedCommand(CMS.INCRBY, key, item, increment); - } + if (itemIncrements.Length < 1) + throw new ArgumentOutOfRangeException(nameof(itemIncrements)); - public static SerializedCommand IncrBy(RedisKey key, Tuple[] itemIncrements) + List args = new List { key }; + foreach (var pair in itemIncrements) { - if (itemIncrements.Length < 1) - throw new ArgumentOutOfRangeException(nameof(itemIncrements)); - - List args = new List { key }; - foreach (var pair in itemIncrements) - { - args.Add(pair.Item1); - args.Add(pair.Item2); - } - return new SerializedCommand(CMS.INCRBY, args); + args.Add(pair.Item1); + args.Add(pair.Item2); } - public static SerializedCommand Info(RedisKey key) - { - var info = new SerializedCommand(CMS.INFO, key); - return info; - } + return new SerializedCommand(CMS.INCRBY, args); + } - public static SerializedCommand InitByDim(RedisKey key, long width, long depth) - { - return new SerializedCommand(CMS.INITBYDIM, key, width, depth); - } + public static SerializedCommand Info(RedisKey key) + { + var info = new SerializedCommand(CMS.INFO, key); + return info; + } - public static SerializedCommand InitByProb(RedisKey key, double error, double probability) - { - return new SerializedCommand(CMS.INITBYPROB, key, error, probability); - } + public static SerializedCommand InitByDim(RedisKey key, long width, long depth) + { + return new SerializedCommand(CMS.INITBYDIM, key, width, depth); + } - public static SerializedCommand Merge(RedisValue destination, long numKeys, RedisValue[] source, long[]? weight = null) - { - if (source.Length < 1) - throw new ArgumentOutOfRangeException(nameof(source)); + public static SerializedCommand InitByProb(RedisKey key, double error, double probability) + { + return new SerializedCommand(CMS.INITBYPROB, key, error, probability); + } - List args = new List { destination, numKeys }; + public static SerializedCommand Merge(RedisValue destination, long numKeys, RedisValue[] source, + long[]? weight = null) + { + if (source.Length < 1) + throw new ArgumentOutOfRangeException(nameof(source)); - foreach (var s in source) args.Add(s); + List args = new List { destination, numKeys }; - if (weight != null && weight.Length >= 1) - { - args.Add(CmsArgs.WEIGHTS); - foreach (var w in weight) args.Add(w); - } + foreach (var s in source) args.Add(s); - return new SerializedCommand(CMS.MERGE, args); + if (weight != null && weight.Length >= 1) + { + args.Add(CmsArgs.WEIGHTS); + foreach (var w in weight) args.Add(w); } - public static SerializedCommand Query(RedisKey key, params RedisValue[] items) - { - if (items.Length < 1) - throw new ArgumentOutOfRangeException(nameof(items)); + return new SerializedCommand(CMS.MERGE, args); + } - List args = new List { key }; - foreach (var item in items) args.Add(item); + public static SerializedCommand Query(RedisKey key, params RedisValue[] items) + { + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); - return new SerializedCommand(CMS.QUERY, args); - } + List args = new List { key }; + foreach (var item in items) args.Add(item); + + return new SerializedCommand(CMS.QUERY, args); } -} +} \ No newline at end of file diff --git a/src/NRedisStack/CountMinSketch/CmsCommands.cs b/src/NRedisStack/CountMinSketch/CmsCommands.cs index cfb075be..a193cd0b 100644 --- a/src/NRedisStack/CountMinSketch/CmsCommands.cs +++ b/src/NRedisStack/CountMinSketch/CmsCommands.cs @@ -1,57 +1,57 @@ using NRedisStack.CountMinSketch.DataTypes; using StackExchange.Redis; -namespace NRedisStack + +namespace NRedisStack; + +public class CmsCommands : CmsCommandsAsync, ICmsCommands { + private readonly IDatabase _db; + + public CmsCommands(IDatabase db) : base(db) + { + _db = db; + } + + /// + public long IncrBy(RedisKey key, RedisValue item, long increment) + { + return _db.Execute(CmsCommandBuilder.IncrBy(key, item, increment)).ToLong(); + } + + /// + public long[] IncrBy(RedisKey key, Tuple[] itemIncrements) + { + return _db.Execute(CmsCommandBuilder.IncrBy(key, itemIncrements)).ToLongArray(); + } + + /// + public CmsInformation Info(RedisKey key) + { + var info = _db.Execute(CmsCommandBuilder.Info(key)); + return info.ToCmsInfo(); + } + + /// + public bool InitByDim(RedisKey key, long width, long depth) + { + return _db.Execute(CmsCommandBuilder.InitByDim(key, width, depth)).OKtoBoolean(); + } + + /// + public bool InitByProb(RedisKey key, double error, double probability) + { + return _db.Execute(CmsCommandBuilder.InitByProb(key, error, probability)).OKtoBoolean(); + } + + /// + public bool Merge(RedisValue destination, long numKeys, RedisValue[] source, long[]? weight = null) + { + return _db.Execute(CmsCommandBuilder.Merge(destination, numKeys, source, weight)).OKtoBoolean(); + } - public class CmsCommands : CmsCommandsAsync, ICmsCommands - { - IDatabase _db; - public CmsCommands(IDatabase db) : base(db) - { - _db = db; - } - - /// - public long IncrBy(RedisKey key, RedisValue item, long increment) - { - return _db.Execute(CmsCommandBuilder.IncrBy(key, item, increment)).ToLong(); - } - - /// - public long[] IncrBy(RedisKey key, Tuple[] itemIncrements) - { - return _db.Execute(CmsCommandBuilder.IncrBy(key, itemIncrements)).ToLongArray(); - } - - /// - public CmsInformation Info(RedisKey key) - { - var info = _db.Execute(CmsCommandBuilder.Info(key)); - return info.ToCmsInfo(); - } - - /// - public bool InitByDim(RedisKey key, long width, long depth) - { - return _db.Execute(CmsCommandBuilder.InitByDim(key, width, depth)).OKtoBoolean(); - } - - /// - public bool InitByProb(RedisKey key, double error, double probability) - { - return _db.Execute(CmsCommandBuilder.InitByProb(key, error, probability)).OKtoBoolean(); - } - - /// - public bool Merge(RedisValue destination, long numKeys, RedisValue[] source, long[]? weight = null) - { - return _db.Execute(CmsCommandBuilder.Merge(destination, numKeys, source, weight)).OKtoBoolean(); - } - - /// - public long[] Query(RedisKey key, params RedisValue[] items) - { - return _db.Execute(CmsCommandBuilder.Query(key, items)).ToLongArray(); - } + /// + public long[] Query(RedisKey key, params RedisValue[] items) + { + return _db.Execute(CmsCommandBuilder.Query(key, items)).ToLongArray(); } } \ No newline at end of file diff --git a/src/NRedisStack/CountMinSketch/CmsCommandsAsync.cs b/src/NRedisStack/CountMinSketch/CmsCommandsAsync.cs index fcaae3be..7927a153 100644 --- a/src/NRedisStack/CountMinSketch/CmsCommandsAsync.cs +++ b/src/NRedisStack/CountMinSketch/CmsCommandsAsync.cs @@ -1,58 +1,57 @@ using NRedisStack.CountMinSketch.DataTypes; using StackExchange.Redis; -namespace NRedisStack + +namespace NRedisStack; + +public class CmsCommandsAsync : ICmsCommandsAsync { + private readonly IDatabaseAsync _db; + + public CmsCommandsAsync(IDatabaseAsync db) + { + _db = db; + } + + /// + public async Task IncrByAsync(RedisKey key, RedisValue item, long increment) + { + return (await _db.ExecuteAsync(CmsCommandBuilder.IncrBy(key, item, increment))).ToLong(); + } + + /// + public async Task IncrByAsync(RedisKey key, Tuple[] itemIncrements) + { + return (await _db.ExecuteAsync(CmsCommandBuilder.IncrBy(key, itemIncrements))).ToLongArray(); + } + + /// + public async Task InfoAsync(RedisKey key) + { + var info = await _db.ExecuteAsync(CmsCommandBuilder.Info(key)); + return info.ToCmsInfo(); + } + + /// + public async Task InitByDimAsync(RedisKey key, long width, long depth) + { + return (await _db.ExecuteAsync(CmsCommandBuilder.InitByDim(key, width, depth))).OKtoBoolean(); + } + + /// + public async Task InitByProbAsync(RedisKey key, double error, double probability) + { + return (await _db.ExecuteAsync(CmsCommandBuilder.InitByProb(key, error, probability))).OKtoBoolean(); + } + + /// + public async Task MergeAsync(RedisValue destination, long numKeys, RedisValue[] source, long[]? weight = null) + { + return (await _db.ExecuteAsync(CmsCommandBuilder.Merge(destination, numKeys, source, weight))).OKtoBoolean(); + } - public class CmsCommandsAsync : ICmsCommandsAsync - { - IDatabaseAsync _db; - public CmsCommandsAsync(IDatabaseAsync db) - { - _db = db; - } - - /// - public async Task IncrByAsync(RedisKey key, RedisValue item, long increment) - { - return (await _db.ExecuteAsync(CmsCommandBuilder.IncrBy(key, item, increment))).ToLong(); - } - - /// - public async Task IncrByAsync(RedisKey key, Tuple[] itemIncrements) - { - return (await _db.ExecuteAsync(CmsCommandBuilder.IncrBy(key, itemIncrements))).ToLongArray(); - - } - - /// - public async Task InfoAsync(RedisKey key) - { - var info = await _db.ExecuteAsync(CmsCommandBuilder.Info(key)); - return info.ToCmsInfo(); - } - - /// - public async Task InitByDimAsync(RedisKey key, long width, long depth) - { - return (await _db.ExecuteAsync(CmsCommandBuilder.InitByDim(key, width, depth))).OKtoBoolean(); - } - - /// - public async Task InitByProbAsync(RedisKey key, double error, double probability) - { - return (await _db.ExecuteAsync(CmsCommandBuilder.InitByProb(key, error, probability))).OKtoBoolean(); - } - - /// - public async Task MergeAsync(RedisValue destination, long numKeys, RedisValue[] source, long[]? weight = null) - { - return (await _db.ExecuteAsync(CmsCommandBuilder.Merge(destination, numKeys, source, weight))).OKtoBoolean(); - } - - /// - public async Task QueryAsync(RedisKey key, params RedisValue[] items) - { - return (await _db.ExecuteAsync(CmsCommandBuilder.Query(key, items))).ToLongArray(); - } + /// + public async Task QueryAsync(RedisKey key, params RedisValue[] items) + { + return (await _db.ExecuteAsync(CmsCommandBuilder.Query(key, items))).ToLongArray(); } } \ No newline at end of file diff --git a/src/NRedisStack/CuckooFilter/DataTypes/CuckooInformation.cs b/src/NRedisStack/CuckooFilter/DataTypes/CuckooInformation.cs index 74be500c..bcbbac76 100644 --- a/src/NRedisStack/CuckooFilter/DataTypes/CuckooInformation.cs +++ b/src/NRedisStack/CuckooFilter/DataTypes/CuckooInformation.cs @@ -16,8 +16,8 @@ public class CuckooInformation public long MaxIterations { get; private set; } internal CuckooInformation(long size, long numberOfBuckets, long numberOfFilter, - long numberOfItemsInserted, long numberOfItemsDeleted, - long bucketSize, long expansionRate, long maxIteration) + long numberOfItemsInserted, long numberOfItemsDeleted, + long bucketSize, long expansionRate, long maxIteration) { Size = size; NumberOfBuckets = numberOfBuckets; diff --git a/src/NRedisStack/Json/DataTypes/KeyValuePath.cs b/src/NRedisStack/Json/DataTypes/KeyValuePath.cs index a5801e7e..302485bb 100644 --- a/src/NRedisStack/Json/DataTypes/KeyValuePath.cs +++ b/src/NRedisStack/Json/DataTypes/KeyValuePath.cs @@ -4,22 +4,19 @@ namespace NRedisStack.Json.DataTypes; public struct KeyPathValue { - public string Key { get; set; } - public string Path { get; set; } - public object Value { get; set; } - public KeyPathValue(string key, string path, object value) { Key = key; Path = path; Value = value; } - public string[] ToArray() + + private string Key { get; set; } + private string Path { get; set; } + private object Value { get; set; } + + public IEnumerable ToArray() { - if (Value is string) - { - return new string[] { Key, Path, Value.ToString()! }; - } - return new string[] { Key, Path, JsonSerializer.Serialize(Value) }; + return Value is string ? new string[] { Key, Path, Value.ToString()! } : new string[] { Key, Path, JsonSerializer.Serialize(Value) }; } } \ No newline at end of file diff --git a/src/NRedisStack/Json/IJsonCommands.cs b/src/NRedisStack/Json/IJsonCommands.cs index 377084e5..069a9237 100644 --- a/src/NRedisStack/Json/IJsonCommands.cs +++ b/src/NRedisStack/Json/IJsonCommands.cs @@ -136,7 +136,7 @@ public interface IJsonCommands /// The key to pull from. /// The path to pull. /// The type. - /// An enumerable of the requested tyep + /// An enumerable of the requested type /// IEnumerable GetEnumerable(RedisKey key, string path = "$"); diff --git a/src/NRedisStack/Json/IJsonCommandsAsync.cs b/src/NRedisStack/Json/IJsonCommandsAsync.cs index 309db723..76913eed 100644 --- a/src/NRedisStack/Json/IJsonCommandsAsync.cs +++ b/src/NRedisStack/Json/IJsonCommandsAsync.cs @@ -136,7 +136,7 @@ public interface IJsonCommandsAsync /// The key to pull from. /// The path to pull. /// The type. - /// An enumerable of the requested tyep + /// An enumerable of the requested type /// Task> GetEnumerableAsync(RedisKey key, string path = "$"); diff --git a/src/NRedisStack/Json/JsonCommandBuilder.cs b/src/NRedisStack/Json/JsonCommandBuilder.cs index c78845f0..c62c4570 100644 --- a/src/NRedisStack/Json/JsonCommandBuilder.cs +++ b/src/NRedisStack/Json/JsonCommandBuilder.cs @@ -11,12 +11,9 @@ public static class JsonCommandBuilder { public static SerializedCommand Resp(RedisKey key, string? path = null) { - if (string.IsNullOrEmpty(path)) - { - return new SerializedCommand(JSON.RESP, key); - } - - return new SerializedCommand(JSON.RESP, key, path!); + return string.IsNullOrEmpty(path) + ? new SerializedCommand(JSON.RESP, key) + : new SerializedCommand(JSON.RESP, key, path!); } public static SerializedCommand Set(RedisKey key, RedisValue path, RedisValue json, When when = When.Always) @@ -45,36 +42,37 @@ public static SerializedCommand Merge(RedisKey key, RedisValue path, RedisValue public static SerializedCommand StrAppend(RedisKey key, string value, string? path = null) { - if (path == null) - { - return new SerializedCommand(JSON.STRAPPEND, key, JsonSerializer.Serialize(value)); - } - - return new SerializedCommand(JSON.STRAPPEND, key, path, JsonSerializer.Serialize(value)); + return path == null + ? new SerializedCommand(JSON.STRAPPEND, key, JsonSerializer.Serialize(value)) + : new SerializedCommand(JSON.STRAPPEND, key, path, JsonSerializer.Serialize(value)); } public static SerializedCommand StrLen(RedisKey key, string? path = null) { - return (path != null) ? new SerializedCommand(JSON.STRLEN, key, path) - : new SerializedCommand(JSON.STRLEN, key); + return path != null + ? new SerializedCommand(JSON.STRLEN, key, path) + : new SerializedCommand(JSON.STRLEN, key); } public static SerializedCommand Toggle(RedisKey key, string? path = null) { - return (path != null) ? new SerializedCommand(JSON.TOGGLE, key, path) - : new SerializedCommand(JSON.TOGGLE, key, "$"); + return path != null + ? new SerializedCommand(JSON.TOGGLE, key, path) + : new SerializedCommand(JSON.TOGGLE, key, "$"); } public static SerializedCommand Type(RedisKey key, string? path = null) { - return (path != null) ? new SerializedCommand(JSON.TYPE, key, path) - : new SerializedCommand(JSON.TYPE, key); + return (path != null) + ? new SerializedCommand(JSON.TYPE, key, path) + : new SerializedCommand(JSON.TYPE, key); } public static SerializedCommand DebugMemory(string key, string? path = null) { - return (path != null) ? new SerializedCommand(JSON.DEBUG, JSON.MEMORY, key, path) - : new SerializedCommand(JSON.DEBUG, JSON.MEMORY, key); + return (path != null) + ? new SerializedCommand(JSON.DEBUG, JSON.MEMORY, key, path) + : new SerializedCommand(JSON.DEBUG, JSON.MEMORY, key); } public static SerializedCommand ArrAppend(RedisKey key, string? path = null, params object[] values) @@ -93,7 +91,8 @@ public static SerializedCommand ArrAppend(RedisKey key, string? path = null, par return new SerializedCommand(JSON.ARRAPPEND, args.ToArray()); } - public static SerializedCommand ArrIndex(RedisKey key, string path, object value, long? start = null, long? stop = null) + public static SerializedCommand ArrIndex(RedisKey key, string path, object value, long? start = null, + long? stop = null) { if (start == null && stop != null) throw new ArgumentException("stop cannot be defined without start"); @@ -107,10 +106,7 @@ public static SerializedCommand ArrInsert(RedisKey key, string path, long index, if (values.Length < 1) throw new ArgumentOutOfRangeException(nameof(values)); var args = new List { key, path, index }; - foreach (var val in values) - { - args.Add(JsonSerializer.Serialize(val)); - } + args.AddRange(values.Select(val => JsonSerializer.Serialize(val))); return new SerializedCommand(JSON.ARRINSERT, args); } @@ -145,9 +141,10 @@ public static SerializedCommand Del(RedisKey key, string? path = null) return new SerializedCommand(JSON.DEL, args); } - public static SerializedCommand Get(RedisKey key, RedisValue? indent = null, RedisValue? newLine = null, RedisValue? space = null, RedisValue? path = null) + public static SerializedCommand Get(RedisKey key, RedisValue? indent = null, RedisValue? newLine = null, + RedisValue? space = null, RedisValue? path = null) { - List args = new List() { key }; + List args = new List { key }; if (indent != null) { @@ -175,7 +172,8 @@ public static SerializedCommand Get(RedisKey key, RedisValue? indent = null, Red return new SerializedCommand(JSON.GET, args); } - public static SerializedCommand Get(RedisKey key, string[] paths, RedisValue? indent = null, RedisValue? newLine = null, RedisValue? space = null) + public static SerializedCommand Get(RedisKey key, string[] paths, RedisValue? indent = null, + RedisValue? newLine = null, RedisValue? space = null) { List args = new List() { key }; @@ -197,10 +195,7 @@ public static SerializedCommand Get(RedisKey key, string[] paths, RedisValue? in args.Add(space); } - foreach (var path in paths) - { - args.Add(path); - } + args.AddRange(paths); return new SerializedCommand(JSON.GET, args); } @@ -208,16 +203,11 @@ public static SerializedCommand Get(RedisKey key, string[] paths, RedisValue? in public static SerializedCommand Get(RedisKey key, string path = "$") { return new SerializedCommand(JSON.GET, key, path); - } public static SerializedCommand MGet(RedisKey[] keys, string path) { - var args = new List(); - foreach (var key in keys) - { - args.Add(key); - } + var args = keys.Cast().ToList(); args.Add(path); return new SerializedCommand(JSON.MGET, args); diff --git a/src/NRedisStack/Json/JsonCommands.cs b/src/NRedisStack/Json/JsonCommands.cs index e16bc701..fd783737 100644 --- a/src/NRedisStack/Json/JsonCommands.cs +++ b/src/NRedisStack/Json/JsonCommands.cs @@ -7,7 +7,7 @@ namespace NRedisStack; public class JsonCommands : JsonCommandsAsync, IJsonCommands { - IDatabase _db; + private readonly IDatabase _db; public JsonCommands(IDatabase db) : base(db) { @@ -28,7 +28,8 @@ public RedisResult[] Resp(RedisKey key, string? path = null) } /// - public bool Set(RedisKey key, RedisValue path, object obj, When when = When.Always, JsonSerializerOptions? serializerOptions = default) + public bool Set(RedisKey key, RedisValue path, object obj, When when = When.Always, + JsonSerializerOptions? serializerOptions = default) { string json = JsonSerializer.Serialize(obj, options: serializerOptions); return Set(key, path, json, when); @@ -90,7 +91,6 @@ public int SetFromDirectory(RedisValue path, string filesPath, When when = When. { inserted += SetFromDirectory(path, dirPath, when); } - return inserted; } @@ -210,13 +210,15 @@ public long Del(RedisKey key, string? path = null) public long Forget(RedisKey key, string? path = null) => Del(key, path); /// - public RedisResult Get(RedisKey key, RedisValue? indent = null, RedisValue? newLine = null, RedisValue? space = null, RedisValue? path = null) + public RedisResult Get(RedisKey key, RedisValue? indent = null, RedisValue? newLine = null, + RedisValue? space = null, RedisValue? path = null) { return _db.Execute(JsonCommandBuilder.Get(key, indent, newLine, space, path)); } /// - public RedisResult Get(RedisKey key, string[] paths, RedisValue? indent = null, RedisValue? newLine = null, RedisValue? space = null) + public RedisResult Get(RedisKey key, string[] paths, RedisValue? indent = null, RedisValue? newLine = null, + RedisValue? space = null) { return _db.Execute(JsonCommandBuilder.Get(key, paths, indent, newLine, space)); } diff --git a/src/NRedisStack/Json/JsonCommandsAsync.cs b/src/NRedisStack/Json/JsonCommandsAsync.cs index 1e3126a8..ce24f73a 100644 --- a/src/NRedisStack/Json/JsonCommandsAsync.cs +++ b/src/NRedisStack/Json/JsonCommandsAsync.cs @@ -7,7 +7,7 @@ namespace NRedisStack; public class JsonCommandsAsync : IJsonCommandsAsync { - IDatabaseAsync _db; + private readonly IDatabaseAsync _db; public JsonCommandsAsync(IDatabaseAsync db) { @@ -19,9 +19,11 @@ public JsonCommandsAsync(IDatabaseAsync db) return (await _db.ExecuteAsync(JsonCommandBuilder.ArrAppend(key, path, values))).ToNullableLongArray(); } - public async Task ArrIndexAsync(RedisKey key, string path, object value, long? start = null, long? stop = null) + public async Task ArrIndexAsync(RedisKey key, string path, object value, long? start = null, + long? stop = null) { - return (await _db.ExecuteAsync(JsonCommandBuilder.ArrIndex(key, path, value, start, stop))).ToNullableLongArray(); + return (await _db.ExecuteAsync(JsonCommandBuilder.ArrIndex(key, path, value, start, stop))) + .ToNullableLongArray(); } public async Task ArrInsertAsync(RedisKey key, string path, long index, params object[] values) @@ -66,13 +68,15 @@ public async Task DelAsync(RedisKey key, string? path = null) public Task ForgetAsync(RedisKey key, string? path = null) => DelAsync(key, path); - public async Task GetAsync(RedisKey key, RedisValue? indent = null, RedisValue? newLine = null, RedisValue? space = null, + public async Task GetAsync(RedisKey key, RedisValue? indent = null, RedisValue? newLine = null, + RedisValue? space = null, RedisValue? path = null) { return await _db.ExecuteAsync(JsonCommandBuilder.Get(key, indent, newLine, space, path)); } - public async Task GetAsync(RedisKey key, string[] paths, RedisValue? indent = null, RedisValue? newLine = null, + public async Task GetAsync(RedisKey key, string[] paths, RedisValue? indent = null, + RedisValue? newLine = null, RedisValue? space = null) { return await _db.ExecuteAsync(JsonCommandBuilder.Get(key, paths, indent, newLine, space)); @@ -134,7 +138,8 @@ public async Task RespAsync(RedisKey key, string? path = null) } /// - public Task SetAsync(RedisKey key, RedisValue path, object obj, When when = When.Always, JsonSerializerOptions? serializerOptions = default) + public Task SetAsync(RedisKey key, RedisValue path, object obj, When when = When.Always, + JsonSerializerOptions? serializerOptions = default) { string json = JsonSerializer.Serialize(obj, options: serializerOptions); return SetAsync(key, path, json, when); @@ -157,7 +162,8 @@ public async Task MergeAsync(RedisKey key, RedisValue path, RedisValue jso } /// - public async Task MergeAsync(RedisKey key, RedisValue path, object obj, JsonSerializerOptions? serializerOptions = default) + public async Task MergeAsync(RedisKey key, RedisValue path, object obj, + JsonSerializerOptions? serializerOptions = default) { string json = JsonSerializer.Serialize(obj, options: serializerOptions); return (await _db.ExecuteAsync(JsonCommandBuilder.Merge(key, path, json))).OKtoBoolean(); @@ -181,7 +187,7 @@ public async Task SetFromDirectoryAsync(RedisValue path, string filesPath, var files = Directory.EnumerateFiles(filesPath, "*.json"); foreach (var filePath in files) { - key = filePath.Substring(0, filePath.IndexOf(".")); + key = filePath.Substring(0, filePath.IndexOf(".", StringComparison.Ordinal)); if (await SetFromFileAsync(key, path, filePath, when)) { inserted++; diff --git a/src/NRedisStack/Json/Literals/CommandArgs.cs b/src/NRedisStack/Json/Literals/CommandArgs.cs index 86e51ec6..3b2a2e33 100644 --- a/src/NRedisStack/Json/Literals/CommandArgs.cs +++ b/src/NRedisStack/Json/Literals/CommandArgs.cs @@ -5,6 +5,5 @@ internal class JsonArgs public const string INDENT = "INDENT"; public const string NEWLINE = "NEWLINE"; public const string SPACE = "SPACE"; - } } \ No newline at end of file diff --git a/src/NRedisStack/Search/AggregationRequest.cs b/src/NRedisStack/Search/AggregationRequest.cs index 705b1b66..68d4a3c4 100644 --- a/src/NRedisStack/Search/AggregationRequest.cs +++ b/src/NRedisStack/Search/AggregationRequest.cs @@ -1,194 +1,187 @@ -using NRedisStack.Search.Literals; +using NRedisStack.Search.Aggregation; +using NRedisStack.Search.Literals; -namespace NRedisStack.Search.Aggregation +namespace NRedisStack.Search; +public class AggregationRequest { - public class AggregationRequest - { - private List args = new List(); // Check if Readonly - private bool isWithCursor = false; + private List args = new List(); // Check if Readonly + private bool isWithCursor = false; - public int? dialect { get; private set; } = null; + public int? dialect { get; private set; } = null; - public AggregationRequest(string query, int? defaultDialect = null) - { - this.dialect = defaultDialect; - args.Add(query); - } + public AggregationRequest(string query, int? defaultDialect = null) + { + this.dialect = defaultDialect; + args.Add(query); + } - public AggregationRequest() : this("*") { } + public AggregationRequest() : this("*") { } - public AggregationRequest Verbatim() - { - args.Add(SearchArgs.VERBATIM); - return this; - } - - public AggregationRequest Load(params FieldName[] fields) - { - if (fields.Length > 0) - { - args.Add(SearchArgs.LOAD); - int loadCountIndex = args.Count; - int loadCount = 0; - foreach (FieldName fn in fields) - { - loadCount += fn.AddCommandArguments(args); - } - - args.Insert(loadCountIndex, loadCount); - } - return this; - } + public AggregationRequest Verbatim() + { + args.Add(SearchArgs.VERBATIM); + return this; + } - public AggregationRequest LoadAll() + public AggregationRequest Load(params FieldName[] fields) + { + if (fields.Length > 0) { args.Add(SearchArgs.LOAD); - args.Add("*"); - return this; - } + int loadCountIndex = args.Count; + int loadCount = fields.Sum(fn => fn.AddCommandArguments(args)); - public AggregationRequest Timeout(long timeout) - { - args.Add(SearchArgs.TIMEOUT); - args.Add(timeout); - return this; + args.Insert(loadCountIndex, loadCount); } + return this; + } + public AggregationRequest LoadAll() + { + args.Add(SearchArgs.LOAD); + args.Add("*"); + return this; + } + public AggregationRequest Timeout(long timeout) + { + args.Add(SearchArgs.TIMEOUT); + args.Add(timeout); + return this; + } - public AggregationRequest GroupBy(string field, params Reducer[] reducers) - { - return GroupBy(new string[] { field }, reducers); - } - - public AggregationRequest GroupBy(IList fields, IList reducers) - { - Group g = new Group(fields); - foreach (Reducer r in reducers) - { - g.Reduce(r); - } - GroupBy(g); - return this; - } + public AggregationRequest GroupBy(string field, params Reducer[] reducers) + { + return GroupBy(new[] { field }, reducers); + } - public AggregationRequest GroupBy(Group group) + public AggregationRequest GroupBy(IList fields, IList reducers) + { + Group g = new Group(fields); + foreach (Reducer r in reducers) { - args.Add(SearchArgs.GROUPBY); - group.SerializeRedisArgs(args); - return this; + g.Reduce(r); } + GroupBy(g); + return this; + } - public AggregationRequest SortBy(string property) => SortBy(SortedField.Asc(property)); - - public AggregationRequest SortBy(params SortedField[] fields) => SortBy(-1, fields); + public AggregationRequest GroupBy(Group group) + { + args.Add(SearchArgs.GROUPBY); + group.SerializeRedisArgs(args); + return this; + } - public AggregationRequest SortBy(int max, params SortedField[] fields) - { - args.Add(SearchArgs.SORTBY); - args.Add(fields.Length * 2); + public AggregationRequest SortBy(string property) => SortBy(SortedField.Asc(property)); - foreach (SortedField field in fields) - { - args.Add(field.FieldName); - args.Add(field.Order.ToString()); - } + public AggregationRequest SortBy(params SortedField[] fields) => SortBy(-1, fields); - if (max > 0) - { - args.Add(SearchArgs.MAX); - args.Add(max); - } + public AggregationRequest SortBy(int max, params SortedField[] fields) + { + args.Add(SearchArgs.SORTBY); + args.Add(fields.Length * 2); - return this; + foreach (SortedField field in fields) + { + args.Add(field.FieldName); + args.Add(field.Order.ToString()); } - public AggregationRequest Apply(string projection, string alias) + if (max > 0) { - args.Add(SearchArgs.APPLY); - args.Add(projection); - args.Add(SearchArgs.AS); - args.Add(alias); - return this; + args.Add(SearchArgs.MAX); + args.Add(max); } - public AggregationRequest Limit(int count) => Limit(0, count); + return this; + } - public AggregationRequest Limit(int offset, int count) - { - new Limit(offset, count).SerializeRedisArgs(args); - return this; - } + public AggregationRequest Apply(string projection, string alias) + { + args.Add(SearchArgs.APPLY); + args.Add(projection); + args.Add(SearchArgs.AS); + args.Add(alias); + return this; + } - public AggregationRequest Filter(string filter) - { - args.Add(SearchArgs.FILTER); - args.Add(filter!); - return this; - } + public AggregationRequest Limit(int count) => Limit(0, count); - public AggregationRequest Cursor(int? count = null, long? maxIdle = null) - { - isWithCursor = true; - args.Add(SearchArgs.WITHCURSOR); + public AggregationRequest Limit(int offset, int count) + { + new Limit(offset, count).SerializeRedisArgs(args); + return this; + } - if (count != null) - { - args.Add(SearchArgs.COUNT); - args.Add(count); - } + public AggregationRequest Filter(string filter) + { + args.Add(SearchArgs.FILTER); + args.Add(filter!); + return this; + } - if (maxIdle != null && maxIdle < long.MaxValue && maxIdle >= 0) - { - args.Add(SearchArgs.MAXIDLE); - args.Add(maxIdle); - } - return this; - } + public AggregationRequest Cursor(int? count = null, long? maxIdle = null) + { + isWithCursor = true; + args.Add(SearchArgs.WITHCURSOR); - public AggregationRequest Params(Dictionary nameValue) + if (count != null) { - if (nameValue.Count > 0) - { - args.Add(SearchArgs.PARAMS); - args.Add(nameValue.Count * 2); - foreach (var entry in nameValue) - { - args.Add(entry.Key); - args.Add(entry.Value); - } - } - return this; + args.Add(SearchArgs.COUNT); + args.Add(count); } - public AggregationRequest Dialect(int dialect) + if (maxIdle != null && maxIdle < long.MaxValue && maxIdle >= 0) { - this.dialect = dialect; - return this; + args.Add(SearchArgs.MAXIDLE); + args.Add(maxIdle); } + return this; + } - private void Dialect() + public AggregationRequest Params(Dictionary nameValue) + { + if (nameValue.Count > 0) { - if (dialect != null) + args.Add(SearchArgs.PARAMS); + args.Add(nameValue.Count * 2); + foreach (var entry in nameValue) { - args.Add(SearchArgs.DIALECT); - args.Add(dialect); + args.Add(entry.Key); + args.Add(entry.Value); } } + return this; + } - public List GetArgs() - { - return args; - } + public AggregationRequest Dialect(int dialect) + { + this.dialect = dialect; + return this; + } - public void SerializeRedisArgs() + private void Dialect() + { + if (dialect != null) { - Dialect(); + args.Add(SearchArgs.DIALECT); + args.Add(dialect); } + } - public bool IsWithCursor() - { - return isWithCursor; - } + public List GetArgs() + { + return args; + } + + public void SerializeRedisArgs() + { + Dialect(); + } + + public bool IsWithCursor() + { + return isWithCursor; } } diff --git a/src/NRedisStack/Search/AggregationResult.cs b/src/NRedisStack/Search/AggregationResult.cs index b8e4d38e..34ace0f3 100644 --- a/src/NRedisStack/Search/AggregationResult.cs +++ b/src/NRedisStack/Search/AggregationResult.cs @@ -1,48 +1,67 @@ -using StackExchange.Redis; +using NRedisStack.Search.Aggregation; +using StackExchange.Redis; -namespace NRedisStack.Search.Aggregation +namespace NRedisStack.Search; + +public sealed class AggregationResult { - public sealed class AggregationResult - { - public long TotalResults { get; } - private readonly Dictionary[] _results; - public long CursorId { get; } + public long TotalResults { get; } + private readonly Dictionary[] _results; + public long CursorId { get; } - internal AggregationResult(RedisResult result, long cursorId = -1) - { - var arr = (RedisResult[])result!; + internal AggregationResult(RedisResult result, long cursorId = -1) + { + var arr = (RedisResult[])result!; - // the first element is always the number of results - TotalResults = (long)arr[0]; + // the first element is always the number of results + TotalResults = (long)arr[0]; - _results = new Dictionary[arr.Length - 1]; - for (int i = 1; i < arr.Length; i++) + _results = new Dictionary[arr.Length - 1]; + for (int i = 1; i < arr.Length; i++) + { + var raw = (RedisResult[])arr[i]!; + var cur = new Dictionary(); + for (int j = 0; j < raw.Length;) { - var raw = (RedisResult[])arr[i]!; - var cur = new Dictionary(); - for (int j = 0; j < raw.Length;) - { - var key = (string)raw[j++]!; - var val = raw[j++]; - if (val.Type == ResultType.MultiBulk) - continue; // TODO: handle multi-bulk (maybe change to object?) - cur.Add(key, (RedisValue)val); - } - _results[i - 1] = cur; + var key = (string)raw[j++]!; + var val = raw[j++]; + if (val.Type == ResultType.MultiBulk) + continue; // TODO: handle multi-bulk (maybe change to object?) + cur.Add(key, (RedisValue)val); } - CursorId = cursorId; + _results[i - 1] = cur; } - public IReadOnlyList> GetResults() => _results; - public Dictionary? this[int index] - => index >= _results.Length ? null : _results[index]; + CursorId = cursorId; + } - public Row GetRow(int index) - { - if (index >= _results.Length) return default; - return new Row(_results[index]); - } + + /// + /// takes a Redis multi-bulk array represented by a RedisResult[] and recursively processes its elements. + /// For each element in the array, it checks if it's another multi-bulk array, and if so, it recursively calls itself. + /// If the element is not a multi-bulk array, it's added directly to a List. + /// The method returns a nested list structure, reflecting the hierarchy of the original multi-bulk array, + /// with each element either being a direct value or a nested list. + /// + /// + /// object + private object ConvertMultiBulkToObject(IEnumerable multiBulkArray) + { + return multiBulkArray.Select(item => item.Type == ResultType.MultiBulk + ? ConvertMultiBulkToObject((RedisResult[])item!) + : item) + .ToList(); + } + + public IReadOnlyList> GetResults() => _results; + + public Dictionary? this[int index] + => index >= _results.Length ? null : _results[index]; + + public Row GetRow(int index) + { + return index >= _results.Length ? default : new Row(_results[index]); } } \ No newline at end of file diff --git a/src/NRedisStack/Search/DataTypes/InfoResult.cs b/src/NRedisStack/Search/DataTypes/InfoResult.cs index f245b5d8..ac39a3a8 100644 --- a/src/NRedisStack/Search/DataTypes/InfoResult.cs +++ b/src/NRedisStack/Search/DataTypes/InfoResult.cs @@ -1,147 +1,116 @@ using StackExchange.Redis; -namespace NRedisStack.Search.DataTypes -{ - public class InfoResult - { - private readonly Dictionary _all = new Dictionary(); - - public string IndexName => GetString("index_name")!; - public Dictionary IndexOption => GetRedisResultDictionary("index_options")!; - - public Dictionary[] Attributes => GetRedisResultDictionaryArray("attributes")!; - +namespace NRedisStack.Search.DataTypes; - public long NumDocs => GetLong("num_docs"); - - public string MaxDocId => GetString("max_doc_id")!; - - public long NumTerms => GetLong("num_terms"); - - public long NumRecords => GetLong("num_records"); +public class InfoResult +{ + private readonly Dictionary _all = new(); + public string IndexName => GetString("index_name")!; + public Dictionary IndexOption => GetRedisResultDictionary("index_options")!; + public Dictionary[] Attributes => GetRedisResultDictionaryArray("attributes")!; + public long NumDocs => GetLong("num_docs"); + public string MaxDocId => GetString("max_doc_id")!; + public long NumTerms => GetLong("num_terms"); + public long NumRecords => GetLong("num_records"); + public double InvertedSzMebibytes => GetDouble("inverted_sz_mb"); + public double VectorIndexSzMebibytes => GetDouble("vector_index_sz_mb"); // TODO: check if double or long - public double InvertedSzMebibytes => GetDouble("inverted_sz_mb"); + public double TotalInvertedIndexBlocks => GetDouble("total_inverted_index_blocks"); - public double VectorIndexSzMebibytes => GetDouble("vector_index_sz_mb"); // TODO: check if double or long + // public double InvertedCapOvh => GetDouble("inverted_cap_ovh"); + public double OffsetVectorsSzMebibytes => GetDouble("offset_vectors_sz_mb"); + public double DocTableSizeMebibytes => GetDouble("doc_table_size_mb"); + public double SortableValueSizeMebibytes => GetDouble("sortable_value_size_mb"); - public double TotalInvertedIndexBlocks => GetDouble("total_inverted_index_blocks"); + public double KeyTableSizeMebibytes => GetDouble("key_table_size_mb"); - // public double InvertedCapOvh => GetDouble("inverted_cap_ovh"); + // public double SkipIndexSizeMebibytes => GetDouble("skip_index_size_mb"); - public double OffsetVectorsSzMebibytes => GetDouble("offset_vectors_sz_mb"); + // public double ScoreIndexSizeMebibytes => GetDouble("score_index_size_mb"); - public double DocTableSizeMebibytes => GetDouble("doc_table_size_mb"); + public double RecordsPerDocAvg => GetDouble("records_per_doc_avg"); - public double SortableValueSizeMebibytes => GetDouble("sortable_value_size_mb"); + public double BytesPerRecordAvg => GetDouble("bytes_per_record_avg"); - public double KeyTableSizeMebibytes => GetDouble("key_table_size_mb"); + public double OffsetsPerTermAvg => GetDouble("offsets_per_term_avg"); - // public double SkipIndexSizeMebibytes => GetDouble("skip_index_size_mb"); + public double OffsetBitsPerRecordAvg => GetDouble("offset_bits_per_record_avg"); - // public double ScoreIndexSizeMebibytes => GetDouble("score_index_size_mb"); + public long HashIndexingFailures => GetLong("hash_indexing_failures"); - public double RecordsPerDocAvg => GetDouble("records_per_doc_avg"); + public double TotalIndexingTime => GetDouble("total_indexing_time"); - public double BytesPerRecordAvg => GetDouble("bytes_per_record_avg"); + public long Indexing => GetLong("indexing"); - public double OffsetsPerTermAvg => GetDouble("offsets_per_term_avg"); + public double PercentIndexed => GetDouble("percent_indexed"); - public double OffsetBitsPerRecordAvg => GetDouble("offset_bits_per_record_avg"); + public long NumberOfUses => GetLong("number_of_uses"); - public long HashIndexingFailures => GetLong("hash_indexing_failures"); - public double TotalIndexingTime => GetDouble("total_indexing_time"); + public Dictionary GcStats => GetRedisResultDictionary("gc_stats")!; - public long Indexing => GetLong("indexing"); + public Dictionary CursorStats => GetRedisResultDictionary("cursor_stats")!; - public double PercentIndexed => GetDouble("percent_indexed"); + public InfoResult(RedisResult result) + { + var results = (RedisResult[])result!; - public long NumberOfUses => GetLong("number_of_uses"); + for (var i = 0; i < results.Length; i += 2) + { + var key = (string)results[i]!; + var value = results[i + 1]; + _all.Add(key, value); + } + } - public Dictionary GcStats => GetRedisResultDictionary("gc_stats")!; + private string? GetString(string key) => _all.TryGetValue(key, out var value) ? (string)value! : default; - public Dictionary CursorStats => GetRedisResultDictionary("cursor_stats")!; + private long GetLong(string key) => _all.TryGetValue(key, out var value) ? (long)value : default; - public InfoResult(RedisResult result) + private double GetDouble(string key) + { + if (!_all.TryGetValue(key, out var value)) return default; + if ((string)value! == "-nan") { - var results = (RedisResult[])result!; - - for (var i = 0; i < results.Length; i += 2) - { - var key = (string)results[i]!; - var value = results[i + 1]; - - _all.Add(key, value); - } + return default; } - private string? GetString(string key) => _all.TryGetValue(key, out var value) ? (string)value! : default; + return (double)value; + } - private long GetLong(string key) => _all.TryGetValue(key, out var value) ? (long)value : default; + private Dictionary? GetRedisResultDictionary(string key) + { + if (!_all.TryGetValue(key, out var value)) return default; + var values = (RedisResult[])value!; + var result = new Dictionary(); - private double GetDouble(string key) + for (var ii = 0; ii < values.Length; ii += 2) { - if (_all.TryGetValue(key, out var value)) - { - if ((string)value! == "-nan") - { - return default; - } - else - { - return (double)value; - } - } - else - { - return default; - } + result.Add((string)values[ii]!, values[ii + 1]); } - private Dictionary? GetRedisResultDictionary(string key) - { - if (_all.TryGetValue(key, out var value)) - { - var values = (RedisResult[])value!; - var result = new Dictionary(); - - for (var ii = 0; ii < values.Length; ii += 2) - { - result.Add((string)values[ii]!, values[ii + 1]); - } + return result; - return result; - } - else - { - return default; - } - } + } - private Dictionary[]? GetRedisResultDictionaryArray(string key) + private Dictionary[]? GetRedisResultDictionaryArray(string key) + { + if (!_all.TryGetValue(key, out var value)) return default; + var values = (RedisResult[])value!; + var result = new Dictionary[values.Length]; + for (int i = 0; i < values.Length; i++) { - if (_all.TryGetValue(key, out var value)) + var fv = (RedisResult[])values[i]!; + var dict = new Dictionary(); + for (int j = 0; j < fv.Length; j += 2) { - var values = (RedisResult[])value!; - var result = new Dictionary[values.Length]; - for (int i = 0; i < values.Length; i++) - { - var fv = (RedisResult[])values[i]!; - var dict = new Dictionary(); - for (int j = 0; j < fv.Length; j += 2) - { - dict.Add((string)fv[j]!, fv[j + 1]); - } - result[i] = dict; - } - return result; + dict.Add((string)fv[j]!, fv[j + 1]); } - else - { - return default; - } + result[i] = dict; } + + return result; } } \ No newline at end of file diff --git a/src/NRedisStack/Search/Document.cs b/src/NRedisStack/Search/Document.cs index 159071d4..3223054f 100644 --- a/src/NRedisStack/Search/Document.cs +++ b/src/NRedisStack/Search/Document.cs @@ -1,79 +1,76 @@ using StackExchange.Redis; -namespace NRedisStack.Search +namespace NRedisStack.Search; + +/// +/// Document represents a single indexed document or entity in the engine +/// +public class Document { - /// - /// Document represents a single indexed document or entity in the engine - /// - public class Document - { - public string Id { get; } - public double Score { get; set; } - public byte[]? Payload { get; } - public string[]? ScoreExplained { get; private set; } // TODO: check if this is needed (Jedis does not have it) - internal readonly Dictionary _properties; - public Document(string id, double score, byte[]? payload) : this(id, null, score, payload) { } - public Document(string id) : this(id, null, 1.0, null) { } + public string Id { get; } + public double Score { get; set; } + public byte[]? Payload { get; } + public string[]? ScoreExplained { get; private set; } // TODO: check if this is needed (Jedis does not have it) + internal readonly Dictionary _properties; + public Document(string id, double score, byte[]? payload) : this(id, null, score, payload) { } + public Document(string id) : this(id, null, 1.0, null) { } - public Document(string id, Dictionary fields, double score = 1.0) : this(id, fields, score, null) { } + public Document(string id, Dictionary fields, double score = 1.0) : this(id, fields, score, null) { } - public Document(string id, Dictionary? fields, double score, byte[]? payload) - { - Id = id; - _properties = fields ?? new Dictionary(); - Score = score; - Payload = payload; - } + public Document(string id, Dictionary? fields, double score, byte[]? payload) + { + Id = id; + _properties = fields ?? new Dictionary(); + Score = score; + Payload = payload; + } - public IEnumerable> GetProperties() => _properties; + public IEnumerable> GetProperties() => _properties; - public static Document Load(string id, double score, byte[]? payload, RedisValue[]? fields) + public static Document Load(string id, double score, byte[]? payload, RedisValue[]? fields) + { + Document ret = new Document(id, score, payload); + if (fields == null) return ret; + for (int i = 0; i < fields.Length; i += 2) { - Document ret = new Document(id, score, payload); - if (fields != null) + string fieldName = fields[i]!; + if (fieldName == "$") { - for (int i = 0; i < fields.Length; i += 2) - { - string fieldName = (string)fields[i]!; - if (fieldName == "$") - { - ret["json"] = fields[i + 1]; - } - else - { - ret[fieldName] = fields[i + 1]; - } - } + ret["json"] = fields[i + 1]; } - return ret; - } - - public static Document Load(string id, double score, byte[]? payload, RedisValue[]? fields, string[]? scoreExplained) - { - Document ret = Document.Load(id, score, payload, fields); - if (scoreExplained != null) + else { - ret.ScoreExplained = scoreExplained; + ret[fieldName] = fields[i + 1]; } - return ret; } + return ret; + } - public RedisValue this[string key] + public static Document Load(string id, double score, byte[]? payload, RedisValue[]? fields, string[]? scoreExplained) + { + Document ret = Load(id, score, payload, fields); + if (scoreExplained != null) { - get { return _properties.TryGetValue(key, out var val) ? val : default(RedisValue); } - internal set { _properties[key] = value; } + ret.ScoreExplained = scoreExplained; } + return ret; + } - public Document Set(string field, RedisValue value) - { - this[field] = value; - return this; - } + public RedisValue this[string key] + { + get => _properties.TryGetValue(key, out var val) ? val : default(RedisValue); + internal set => _properties[key] = value; + } - public Document SetScore(double score) - { - Score = score; - return this; - } + public Document Set(string field, RedisValue value) + { + this[field] = value; + return this; + } + + public Document SetScore(double score) + { + Score = score; + return this; } } \ No newline at end of file diff --git a/src/NRedisStack/Search/Literals/AttributeOptions.cs b/src/NRedisStack/Search/Literals/AttributeOptions.cs index 5510151b..41a13714 100644 --- a/src/NRedisStack/Search/Literals/AttributeOptions.cs +++ b/src/NRedisStack/Search/Literals/AttributeOptions.cs @@ -1,12 +1,11 @@ -namespace NRedisStack.Search.Literals +namespace NRedisStack.Search.Literals; + +internal class AttributeOptions { - internal class AttributeOptions - { - public const string SORTABLE = "SORTABLE"; - public const string UNF = "UNF"; - public const string NOSTEM = "NOSTEM"; - public const string NOINDEX = "NOINDEX"; + public const string SORTABLE = "SORTABLE"; + public const string UNF = "UNF"; + public const string NOSTEM = "NOSTEM"; + public const string NOINDEX = "NOINDEX"; - //TODO: add all options - } + //TODO: add all options } \ No newline at end of file diff --git a/src/NRedisStack/Search/Literals/CommandArgs.cs b/src/NRedisStack/Search/Literals/CommandArgs.cs index 7910bc53..a139d65c 100644 --- a/src/NRedisStack/Search/Literals/CommandArgs.cs +++ b/src/NRedisStack/Search/Literals/CommandArgs.cs @@ -1,75 +1,75 @@ -namespace NRedisStack.Search.Literals +namespace NRedisStack.Search.Literals; + +internal class SearchArgs { - internal class SearchArgs - { - public const string AGGREGATE = "AGGREGATE"; - public const string APPLY = "APPLY"; - public const string AS = "AS"; - public const string ASC = "ASC"; - public const string CASESENSITIVE = "CASESENSITIVE"; - public const string COUNT = "COUNT"; - public const string DESC = "DESC"; - public const string DIALECT = "DIALECT"; - public const string DISTANCE = "DISTANCE"; - public const string EXCLUDE = "EXCLUDE"; - public const string EXPANDER = "EXPANDER"; - public const string FIELDS = "FIELDS"; - public const string FILTER = "FILTER"; - public const string FRAGS = "FRAGS"; - public const string FUZZY = "FUZZY"; - public const string GROUPBY = "GROUPBY"; - public const string HIGHLIGHT = "HIGHLIGHT"; - public const string INCLUDE = "INCLUDE"; - public const string INCR = "INCR"; - public const string INFIELDS = "INFIELDS"; - public const string INKEYS = "INKEYS"; - public const string INORDER = "INORDER"; - public const string JSON = "JSON"; - public const string LANGUAGE = "LANGUAGE"; - public const string LANGUAGE_FIELD = "LANGUAGE_FIELD"; - public const string LEN = "LEN"; - public const string LIMIT = "LIMIT"; - public const string LIMITED = "LIMITED"; - public const string LOAD = "LOAD"; - public const string MAX = "MAX"; - public const string MAXIDLE = "MAXIDLE"; - public const string MAXTEXTFIELDS = "MAXTEXTFIELDS"; - public const string NOCONTENT = "NOCONTENT"; - public const string NOFIELDS = "NOFIELDS"; - public const string NOFREQS = "NOFREQS"; - public const string NOHL = "NOHL"; - public const string NOINDEX = "NOINDEX"; - public const string NOOFFSETS = "NOOFFSETS"; - public const string NOSTEM = "NOSTEM"; - public const string NOSTOPWORDS = "NOSTOPWORDS"; - public const string ON_HASH = "ON HASH"; - public const string PARAMS = "PARAMS"; - public const string PAYLOAD = "PAYLOAD"; - public const string PAYLOAD_FIELD = "PAYLOAD_FIELD"; - public const string PHONETIC = "PHONETIC"; - public const string PREFIX = "PREFIX"; - public const string QUERY = "QUERY"; - public const string RETURN = "RETURN"; - public const string SCORE = "SCORE"; - public const string SCORE_FIELD = "SCORE_FIELD"; - public const string SCORER = "SCORER"; - public const string SEARCH = "SEARCH"; - public const string SEPARATOR = "SEPARATOR"; - public const string SKIPINITIALSCAN = "SKIPINITIALSCAN"; - public const string SLOP = "SLOP"; - public const string SORTBY = "SORTBY"; - public const string STOPWORDS = "STOPWORDS"; - public const string SUMMARIZE = "SUMMARIZE"; - public const string TAGS = "TAGS"; - public const string TEMPORARY = "TEMPORARY"; - public const string TERMS = "TERMS"; - public const string TIMEOUT = "TIMEOUT"; - public const string UNF = "UNF"; - public const string VERBATIM = "VERBATIM"; - public const string WEIGHT = "WEIGHT"; - public const string WITHCURSOR = "WITHCURSOR"; - public const string WITHPAYLOADS = "WITHPAYLOADS"; - public const string WITHSCORES = "WITHSCORES"; - public const string WITHSUFFIXTRIE = "WITHSUFFIXTRIE"; - } + public const string AGGREGATE = "AGGREGATE"; + public const string APPLY = "APPLY"; + public const string AS = "AS"; + public const string ASC = "ASC"; + public const string CASESENSITIVE = "CASESENSITIVE"; + public const string COUNT = "COUNT"; + public const string DESC = "DESC"; + public const string DIALECT = "DIALECT"; + public const string DISTANCE = "DISTANCE"; + public const string EXCLUDE = "EXCLUDE"; + public const string EXPANDER = "EXPANDER"; + public const string FIELDS = "FIELDS"; + public const string FILTER = "FILTER"; + public const string FRAGS = "FRAGS"; + public const string FUZZY = "FUZZY"; + public const string GROUPBY = "GROUPBY"; + public const string HIGHLIGHT = "HIGHLIGHT"; + public const string INCLUDE = "INCLUDE"; + public const string INCR = "INCR"; + public const string INFIELDS = "INFIELDS"; + public const string INKEYS = "INKEYS"; + public const string INORDER = "INORDER"; + public const string JSON = "JSON"; + public const string LANGUAGE = "LANGUAGE"; + public const string LANGUAGE_FIELD = "LANGUAGE_FIELD"; + public const string LEN = "LEN"; + public const string LIMIT = "LIMIT"; + public const string LIMITED = "LIMITED"; + public const string LOAD = "LOAD"; + public const string MAX = "MAX"; + public const string MAXIDLE = "MAXIDLE"; + public const string MAXTEXTFIELDS = "MAXTEXTFIELDS"; + public const string NOCONTENT = "NOCONTENT"; + public const string NOFIELDS = "NOFIELDS"; + public const string NOFREQS = "NOFREQS"; + public const string NOHL = "NOHL"; + public const string NOINDEX = "NOINDEX"; + public const string NOOFFSETS = "NOOFFSETS"; + public const string NOSTEM = "NOSTEM"; + public const string NOSTOPWORDS = "NOSTOPWORDS"; + public const string ON_HASH = "ON HASH"; + public const string PARAMS = "PARAMS"; + public const string PAYLOAD = "PAYLOAD"; + public const string PAYLOAD_FIELD = "PAYLOAD_FIELD"; + public const string PHONETIC = "PHONETIC"; + public const string PREFIX = "PREFIX"; + public const string QUERY = "QUERY"; + public const string RETURN = "RETURN"; + public const string SCORE = "SCORE"; + public const string SCORE_FIELD = "SCORE_FIELD"; + public const string SCORER = "SCORER"; + public const string SEARCH = "SEARCH"; + public const string SEPARATOR = "SEPARATOR"; + public const string SKIPINITIALSCAN = "SKIPINITIALSCAN"; + public const string SLOP = "SLOP"; + public const string SORTBY = "SORTBY"; + public const string STOPWORDS = "STOPWORDS"; + public const string SUMMARIZE = "SUMMARIZE"; + public const string TAGS = "TAGS"; + public const string TEMPORARY = "TEMPORARY"; + public const string TERMS = "TERMS"; + public const string TIMEOUT = "TIMEOUT"; + public const string UNF = "UNF"; + public const string VERBATIM = "VERBATIM"; + public const string WEIGHT = "WEIGHT"; + public const string WITHCURSOR = "WITHCURSOR"; + public const string WITHPAYLOADS = "WITHPAYLOADS"; + public const string WITHSCORES = "WITHSCORES"; + public const string WITHSUFFIXTRIE = "WITHSUFFIXTRIE"; } + diff --git a/src/NRedisStack/Search/Literals/Commands.cs b/src/NRedisStack/Search/Literals/Commands.cs index 8d94b306..ab024cf2 100644 --- a/src/NRedisStack/Search/Literals/Commands.cs +++ b/src/NRedisStack/Search/Literals/Commands.cs @@ -1,32 +1,31 @@ -namespace NRedisStack.Search.Literals +namespace NRedisStack.Search.Literals; + +internal class FT { - internal class FT - { - public const string _LIST = "FT._LIST"; - public const string AGGREGATE = "FT.AGGREGATE"; - public const string ALIASADD = "FT.ALIASADD"; - public const string ALIASDEL = "FT.ALIASDEL"; - public const string ALIASUPDATE = "FT.ALIASUPDATE"; - public const string ALTER = "FT.ALTER"; - public const string CONFIG = "FT.CONFIG"; - public const string CREATE = "FT.CREATE"; - public const string CURSOR = "FT.CURSOR"; - public const string DICTADD = "FT.DICTADD"; - public const string DICTDEL = "FT.DICTDEL"; - public const string DICTDUMP = "FT.DICTDUMP"; - public const string DROPINDEX = "FT.DROPINDEX"; - public const string EXPLAIN = "FT.EXPLAIN"; - public const string EXPLAINCLI = "FT.EXPLAINCLI"; - public const string INFO = "FT.INFO"; - public const string PROFILE = "FT.PROFILE"; - public const string SEARCH = "FT.SEARCH"; - public const string SPELLCHECK = "FT.SPELLCHECK"; - public const string SUGADD = "FT.SUGADD"; - public const string SUGDEL = "FT.SUGDEL"; - public const string SUGGET = "FT.SUGGET"; - public const string SUGLEN = "FT.SUGLEN"; - public const string SYNDUMP = "FT.SYNDUMP"; - public const string SYNUPDATE = "FT.SYNUPDATE"; - public const string TAGVALS = "FT.TAGVALS"; - } + public const string _LIST = "FT._LIST"; + public const string AGGREGATE = "FT.AGGREGATE"; + public const string ALIASADD = "FT.ALIASADD"; + public const string ALIASDEL = "FT.ALIASDEL"; + public const string ALIASUPDATE = "FT.ALIASUPDATE"; + public const string ALTER = "FT.ALTER"; + public const string CONFIG = "FT.CONFIG"; + public const string CREATE = "FT.CREATE"; + public const string CURSOR = "FT.CURSOR"; + public const string DICTADD = "FT.DICTADD"; + public const string DICTDEL = "FT.DICTDEL"; + public const string DICTDUMP = "FT.DICTDUMP"; + public const string DROPINDEX = "FT.DROPINDEX"; + public const string EXPLAIN = "FT.EXPLAIN"; + public const string EXPLAINCLI = "FT.EXPLAINCLI"; + public const string INFO = "FT.INFO"; + public const string PROFILE = "FT.PROFILE"; + public const string SEARCH = "FT.SEARCH"; + public const string SPELLCHECK = "FT.SPELLCHECK"; + public const string SUGADD = "FT.SUGADD"; + public const string SUGDEL = "FT.SUGDEL"; + public const string SUGGET = "FT.SUGGET"; + public const string SUGLEN = "FT.SUGLEN"; + public const string SYNDUMP = "FT.SYNDUMP"; + public const string SYNUPDATE = "FT.SYNUPDATE"; + public const string TAGVALS = "FT.TAGVALS"; } \ No newline at end of file diff --git a/tests/Doc/HashExample.cs b/tests/Doc/HashExample.cs index 38c279fd..10c108cd 100644 --- a/tests/Doc/HashExample.cs +++ b/tests/Doc/HashExample.cs @@ -1,10 +1,11 @@ // EXAMPLE: hash_tutorial // HIDE_START + using NRedisStack.Tests; using StackExchange.Redis; //REMOVE_START -namespace NRedisStack.Doc; +namespace Doc; [Collection("DocsTests")] //REMOVE_END public class HashExample diff --git a/tests/Doc/SearchQuickstartExample.cs b/tests/Doc/SearchQuickstartExample.cs index 256e3833..c7a1f5b9 100644 --- a/tests/Doc/SearchQuickstartExample.cs +++ b/tests/Doc/SearchQuickstartExample.cs @@ -1,4 +1,5 @@ // EXAMPLE: search_quickstart + using NRedisStack.RedisStackCommands; using NRedisStack.Search; using NRedisStack.Search.Aggregation; @@ -7,7 +8,7 @@ using StackExchange.Redis; // REMOVE_START -namespace NRedisStack.Doc; +namespace Doc; [Collection("DocsTests")] // REMOVE_END public class SearchQuickstartExample @@ -29,6 +30,7 @@ public void run() } catch { + // ignored } // REMOVE_END diff --git a/tests/Doc/SetGetExample.cs b/tests/Doc/SetGetExample.cs index 447d1dbc..3d9af1e2 100644 --- a/tests/Doc/SetGetExample.cs +++ b/tests/Doc/SetGetExample.cs @@ -1,15 +1,16 @@ // EXAMPLE: set_and_get // HIDE_START -using System; + using NRedisStack.Tests; using StackExchange.Redis; //REMOVE_START -namespace NRedisStack.Doc; +namespace Doc; [Collection("DocsTests")] //REMOVE_END public class SetGetExample { + [SkipIfRedis(Is.OSSCluster)] public void run() { diff --git a/tests/Doc/StringSnippets.cs b/tests/Doc/StringSnippets.cs index eaa269ce..c7f3bade 100644 --- a/tests/Doc/StringSnippets.cs +++ b/tests/Doc/StringSnippets.cs @@ -6,7 +6,7 @@ using NRedisStack.Tests; using StackExchange.Redis; -namespace NRedisStack.Doc; +namespace Doc; [Collection("DocsTests")] //REMOVE_END public class StringSnippets diff --git a/tests/NRedisStack.Tests/AbstractNRedisStackTest.cs b/tests/NRedisStack.Tests/AbstractNRedisStackTest.cs index 3de0168b..e51aa449 100644 --- a/tests/NRedisStack.Tests/AbstractNRedisStackTest.cs +++ b/tests/NRedisStack.Tests/AbstractNRedisStackTest.cs @@ -1,58 +1,56 @@ using NRedisStack.DataTypes; -using StackExchange.Redis; using System.Runtime.CompilerServices; using Xunit; -namespace NRedisStack.Tests +namespace NRedisStack.Tests; + +public abstract class AbstractNRedisStackTest : IClassFixture, IAsyncLifetime { - public abstract class AbstractNRedisStackTest : IClassFixture, IAsyncLifetime - { - protected internal RedisFixture redisFixture; + protected internal RedisFixture redisFixture; - protected internal AbstractNRedisStackTest(RedisFixture redisFixture) => this.redisFixture = redisFixture; + protected internal AbstractNRedisStackTest(RedisFixture redisFixture) => this.redisFixture = redisFixture; - private List keyNames = new List(); + private List keyNames = new List(); - protected internal string CreateKeyName([CallerMemberName] string memberName = "") => CreateKeyNames(1, memberName)[0]; + protected internal string CreateKeyName([CallerMemberName] string memberName = "") => CreateKeyNames(1, memberName)[0]; - protected internal string[] CreateKeyNames(int count, [CallerMemberName] string memberName = "") - { - if (count < 1) throw new ArgumentOutOfRangeException(nameof(count), "Must be greater than zero."); + protected internal string[] CreateKeyNames(int count, [CallerMemberName] string memberName = "") + { + if (count < 1) throw new ArgumentOutOfRangeException(nameof(count), "Must be greater than zero."); - var newKeys = new string[count]; - for (var i = 0; i < count; i++) - { - newKeys[i] = $"{GetType().Name}:{memberName}:{i}"; - } + var newKeys = new string[count]; + for (var i = 0; i < count; i++) + { + newKeys[i] = $"{GetType().Name}:{memberName}:{i}"; + } - keyNames.AddRange(newKeys); + keyNames.AddRange(newKeys); - return newKeys; - } + return newKeys; + } - protected internal static List ReverseData(List data) + protected internal static List ReverseData(List data) + { + var tuples = new List(data.Count); + for (var i = data.Count - 1; i >= 0; i--) { - var tuples = new List(data.Count); - for (var i = data.Count - 1; i >= 0; i--) - { - tuples.Add(data[i]); - } - - return tuples; + tuples.Add(data[i]); } - public Task InitializeAsync() => Task.CompletedTask; + return tuples; + } - public void Dispose() - { - redisFixture.Redis.GetDatabase().ExecuteBroadcast("FLUSHALL"); - } + public Task InitializeAsync() => Task.CompletedTask; - public async Task DisposeAsync() - { - var redis = redisFixture.Redis.GetDatabase(); - // await redis.KeyDeleteAsync(keyNames.Select(i => (RedisKey)i).ToArray()); - await redis.ExecuteBroadcastAsync("FLUSHALL"); - } + public void Dispose() + { + redisFixture.Redis.GetDatabase().ExecuteBroadcast("FLUSHALL"); + } + + public async Task DisposeAsync() + { + var redis = redisFixture.Redis.GetDatabase(); + // await redis.KeyDeleteAsync(keyNames.Select(i => (RedisKey)i).ToArray()); + await redis.ExecuteBroadcastAsync("FLUSHALL"); } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/Examples/ExampleTests.cs b/tests/NRedisStack.Tests/Examples/ExampleTests.cs index 1082fb0d..40e9fd21 100644 --- a/tests/NRedisStack.Tests/Examples/ExampleTests.cs +++ b/tests/NRedisStack.Tests/Examples/ExampleTests.cs @@ -1,15 +1,8 @@ -using System.Net.Security; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; using NRedisStack.Search; using NRedisStack.Search.Aggregation; using NRedisStack.Search.Literals.Enums; -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Math; -using Org.BouncyCastle.OpenSsl; using StackExchange.Redis; using Xunit; using Xunit.Abstractions; @@ -39,7 +32,7 @@ public void HSETandSearch() var ft = db.FT(); // Use HSET to add a field-value pair to a hash - db.HashSet("profesor:5555", new HashEntry[] { new("first", "Albert"), new("last", "Blue"), new("age", "55") }); + db.HashSet("professor:5555", new HashEntry[] { new("first", "Albert"), new("last", "Blue"), new("age", "55") }); db.HashSet("student:1111", new HashEntry[] { new("first", "Joe"), new("last", "Dod"), new("age", "18") }); db.HashSet("pupil:2222", new HashEntry[] { new("first", "Jen"), new("last", "Rod"), new("age", "14") }); db.HashSet("student:3333", new HashEntry[] { new("first", "El"), new("last", "Mark"), new("age", "17") }); @@ -102,7 +95,8 @@ public void PipelineExample() var pipeline = new Pipeline(db); // Add JsonSet to pipeline - pipeline.Json.SetAsync("person", "$", new { name = "John", age = 30, city = "New York", nicknames = new[] { "John", "Johny", "Jo" } }); + pipeline.Json.SetAsync("person", "$", + new { name = "John", age = 30, city = "New York", nicknames = new[] { "John", "Johny", "Jo" } }); // Increase age by 2 _ = pipeline.Json.NumIncrbyAsync("person", "$.age", 2); @@ -185,7 +179,7 @@ public async Task PipelineWithAsync() var pipeline = new Pipeline(db); - // Create metedata lables for time-series. + // Create metadata labels for time-series. TimeSeriesLabel label1 = new TimeSeriesLabel("temp", "TLV"); TimeSeriesLabel label2 = new TimeSeriesLabel("temp", "JLM"); var labels1 = new List { label1 }; @@ -195,23 +189,25 @@ public async Task PipelineWithAsync() _ = pipeline.Ts.CreateAsync("temp:TLV", labels: labels1); _ = pipeline.Ts.CreateAsync("temp:JLM", labels: labels2); - // Adding multiple sequenece of time-series data. - List<(string, TimeStamp, double)> sequence1 = new List<(string, TimeStamp, double)>() - { - ("temp:TLV",1000,30), - ("temp:TLV", 1010 ,35), - ("temp:TLV", 1020, 9999), - ("temp:TLV", 1030, 40) - }; - List<(string, TimeStamp, double)> sequence2 = new List<(string, TimeStamp, double)>() - { - ("temp:JLM",1005,30), - ("temp:JLM", 1015 ,35), - ("temp:JLM", 1025, 9999), - ("temp:JLM", 1035, 40) - }; + // Adding multiple sequence of time-series data. + List<(string, TimeStamp, double)> sequence1 = + new() + { + ("temp:TLV", 1000, 30), + ("temp:TLV", 1010, 35), + ("temp:TLV", 1020, 9999), + ("temp:TLV", 1030, 40) + }; + List<(string, TimeStamp, double)> sequence2 = + new() + { + ("temp:JLM", 1005, 30), + ("temp:JLM", 1015, 35), + ("temp:JLM", 1025, 9999), + ("temp:JLM", 1035, 40) + }; - // Adding mutiple samples to mutiple series. + // Adding multiple samples to multiple series. _ = pipeline.Ts.MAddAsync(sequence1); _ = pipeline.Ts.MAddAsync(sequence2); @@ -222,11 +218,12 @@ public async Task PipelineWithAsync() var ts = db.TS(); // Get only the location label for each last sample, use SELECTED_LABELS. - var respons = await ts.MGetAsync(new List { "temp=JLM" }, selectedLabels: new List { "location" }); + var response = await ts.MGetAsync(new List { "temp=JLM" }, + selectedLabels: new List { "location" }); - // Assert the respons - Assert.Equal(1, respons.Count); - Assert.Equal("temp:JLM", respons[0].key); + // Assert the response + Assert.Equal(1, response.Count); + Assert.Equal("temp:JLM", response[0].key); } [SkipIfRedis(Is.OSSCluster, Is.Enterprise)] @@ -246,7 +243,8 @@ public void TransactionExample() // Add account details with Json.Set to transaction _ = tran.Json.SetAsync("accdetails:Jeeva", "$", new { name = "Jeeva", totalAmount = 1000, bankName = "City" }); - _ = tran.Json.SetAsync("accdetails:Shachar", "$", new { name = "Shachar", totalAmount = 1000, bankName = "City" }); + _ = tran.Json.SetAsync("accdetails:Shachar", "$", + new { name = "Shachar", totalAmount = 1000, bankName = "City" }); // Get the Json response var getShachar = tran.Json.GetAsync("accdetails:Shachar"); @@ -290,6 +288,7 @@ public void TestJsonConvert() { json.Set("doc:" + i, "$", "{\"name\":\"foo\"}"); } + var res = ft.Search("test", new Query("@name:{foo}")); var docs = res.ToJson(); @@ -298,15 +297,14 @@ public void TestJsonConvert() } #if CI_RUN_TESTS - #if NET481 [Fact] public void TestRedisCloudConnection_net481() { var root = Path.GetFullPath(Directory.GetCurrentDirectory()); var redisCaPath = Path.GetFullPath(Path.Combine(root, "redis_ca.pem")); - var redisUserCrtPath = Path.GetFullPath(Path.Combine(root, "redis_user.crt")); - var redisUserPrivateKeyPath = Path.GetFullPath(Path.Combine(root, "redis_user_private.key")); + var redisUserCrtPath = Path.GetFullPath(Path.Combine(root, "redis_user.crt")); + var redisUserPrivateKeyPath = Path.GetFullPath(Path.Combine(root, "redis_user_private.key")); var password = Environment.GetEnvironmentVariable("PASSWORD") ?? throw new Exception("PASSWORD is not set."); var endpoint = Environment.GetEnvironmentVariable("ENDPOINT") ?? throw new Exception("ENDPOINT is not set."); @@ -330,7 +328,8 @@ public void TestRedisCloudConnection_net481() Password = password }; - redisConfiguration.CertificateSelection += (_, _, _, _, _) => new X509Certificate2(clientCert.Export(X509ContentType.Pfx)); + redisConfiguration.CertificateSelection += + (_, _, _, _, _) => new X509Certificate2(clientCert.Export(X509ContentType.Pfx)); redisConfiguration.CertificateValidation += (_, cert, _, errors) => { @@ -416,8 +415,8 @@ public void TestRedisCloudConnection() { var root = Path.GetFullPath(Directory.GetCurrentDirectory()); var redisCaPath = Path.GetFullPath(Path.Combine(root, "redis_ca.pem")); - var redisUserCrtPath = Path.GetFullPath(Path.Combine(root, "redis_user.crt")); - var redisUserPrivateKeyPath = Path.GetFullPath(Path.Combine(root, "redis_user_private.key")); + var redisUserCrtPath = Path.GetFullPath(Path.Combine(root, "redis_user.crt")); + var redisUserPrivateKeyPath = Path.GetFullPath(Path.Combine(root, "redis_user_private.key")); var password = Environment.GetEnvironmentVariable("PASSWORD") ?? throw new Exception("PASSWORD is not set."); var endpoint = Environment.GetEnvironmentVariable("ENDPOINT") ?? throw new Exception("ENDPOINT is not set."); @@ -489,8 +488,8 @@ public void TestRedisCloudConnection_DotnetCore3() // Replace this with your own Redis Cloud credentials var root = Path.GetFullPath(Directory.GetCurrentDirectory()); var redisCaPath = Path.GetFullPath(Path.Combine(root, "redis_ca.pem")); - var redisUserCrtPath = Path.GetFullPath(Path.Combine(root, "redis_user.crt")); - var redisUserPrivateKeyPath = Path.GetFullPath(Path.Combine(root, "redis_user_private.key")); + var redisUserCrtPath = Path.GetFullPath(Path.Combine(root, "redis_user.crt")); + var redisUserPrivateKeyPath = Path.GetFullPath(Path.Combine(root, "redis_user_private.key")); var password = Environment.GetEnvironmentVariable("PASSWORD") ?? throw new Exception("PASSWORD is not set."); var endpoint = Environment.GetEnvironmentVariable("ENDPOINT") ?? throw new Exception("ENDPOINT is not set."); @@ -639,10 +638,10 @@ public void BasicJsonExamplesTest() field1 = "val1" }); res = json.Get(key: "ex2:2", - path: "$.field1", - indent: "\t", - newLine: "\n" - ); + path: "$.field1", + indent: "\t", + newLine: "\n" + ); Assert.Equal("[\n\t\"val1\"\n]", res.ToString()); // Fetch multiple properties: @@ -834,124 +833,136 @@ public void AdvancedJsonExamplesTest() { city = "Boston", location = "42.361145, -71.057083", - inventory = new[] { - new { - id = 15970, - gender = "Men", - season = new[] {"Fall", "Winter"}, - description = "Turtle Check Men Navy Blue Shirt", - price = 34.95 - }, - new { - id = 59263, - gender = "Women", - season = new[] {"Fall", "Winter", "Spring", "Summer"}, - description = "Titan Women Silver Watch", - price = 129.99 - }, - new { - id = 46885, - gender = "Boys", - season = new[] {"Fall"}, - description = "Ben 10 Boys Navy Blue Slippers", - price = 45.99 - } + inventory = new[] + { + new + { + id = 15970, + gender = "Men", + season = new[] { "Fall", "Winter" }, + description = "Turtle Check Men Navy Blue Shirt", + price = 34.95 + }, + new + { + id = 59263, + gender = "Women", + season = new[] { "Fall", "Winter", "Spring", "Summer" }, + description = "Titan Women Silver Watch", + price = 129.99 + }, + new + { + id = 46885, + gender = "Boys", + season = new[] { "Fall" }, + description = "Ben 10 Boys Navy Blue Slippers", + price = 45.99 } + } }); // Fetch all properties of an array: var res = json.Get(key: "warehouse:1", - path: "$.inventory[*]", - indent: "\t", - newLine: "\n" - ); - var expected = "[\n\t{\n\t\t\"id\":15970,\n\t\t\"gender\":\"Men\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\"\n\t\t],\n\t\t\"description\":\"Turtle Check Men Navy Blue Shirt\",\n\t\t\"price\":34.95\n\t},\n\t{\n\t\t\"id\":59263,\n\t\t\"gender\":\"Women\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\",\n\t\t\t\"Spring\",\n\t\t\t\"Summer\"\n\t\t],\n\t\t\"description\":\"Titan Women Silver Watch\",\n\t\t\"price\":129.99\n\t},\n\t{\n\t\t\"id\":46885,\n\t\t\"gender\":\"Boys\",\n\t\t\"season\":[\n\t\t\t\"Fall\"\n\t\t],\n\t\t\"description\":\"Ben 10 Boys Navy Blue Slippers\",\n\t\t\"price\":45.99\n\t}\n]"; + path: "$.inventory[*]", + indent: "\t", + newLine: "\n" + ); + var expected = + "[\n\t{\n\t\t\"id\":15970,\n\t\t\"gender\":\"Men\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\"\n\t\t],\n\t\t\"description\":\"Turtle Check Men Navy Blue Shirt\",\n\t\t\"price\":34.95\n\t},\n\t{\n\t\t\"id\":59263,\n\t\t\"gender\":\"Women\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\",\n\t\t\t\"Spring\",\n\t\t\t\"Summer\"\n\t\t],\n\t\t\"description\":\"Titan Women Silver Watch\",\n\t\t\"price\":129.99\n\t},\n\t{\n\t\t\"id\":46885,\n\t\t\"gender\":\"Boys\",\n\t\t\"season\":[\n\t\t\t\"Fall\"\n\t\t],\n\t\t\"description\":\"Ben 10 Boys Navy Blue Slippers\",\n\t\t\"price\":45.99\n\t}\n]"; Assert.Equal(expected, res.ToString()); // TODO: fine nicer way to compare the two JSON strings // Fetch all values of a field within an array: res = json.Get( - key: "warehouse:1", - path: "$.inventory[*].price", - indent: "\t", - newLine: "\n" + key: "warehouse:1", + path: "$.inventory[*].price", + indent: "\t", + newLine: "\n" ); expected = "[\n\t34.95,\n\t129.99,\n\t45.99\n]"; Assert.Equal(expected, res.ToString()); // Fetch all items within an array where a text field matches a given value: res = json.Get( - key: "warehouse:1", - path: "$.inventory[?(@.description==\"Turtle Check Men Navy Blue Shirt\")]", - indent: "\t", - newLine: "\n" + key: "warehouse:1", + path: "$.inventory[?(@.description==\"Turtle Check Men Navy Blue Shirt\")]", + indent: "\t", + newLine: "\n" ); - expected = "[\n\t{\n\t\t\"id\":15970,\n\t\t\"gender\":\"Men\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\"\n\t\t],\n\t\t\"description\":\"Turtle Check Men Navy Blue Shirt\",\n\t\t\"price\":34.95\n\t}\n]"; + expected = + "[\n\t{\n\t\t\"id\":15970,\n\t\t\"gender\":\"Men\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\"\n\t\t],\n\t\t\"description\":\"Turtle Check Men Navy Blue Shirt\",\n\t\t\"price\":34.95\n\t}\n]"; Assert.Equal(expected, res.ToString()); // Fetch all items within an array where a numeric field is less than a given value: res = json.Get(key: "warehouse:1", - path: "$.inventory[?(@.price<100)]", - indent: "\t", - newLine: "\n" - ); - expected = "[\n\t{\n\t\t\"id\":15970,\n\t\t\"gender\":\"Men\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\"\n\t\t],\n\t\t\"description\":\"Turtle Check Men Navy Blue Shirt\",\n\t\t\"price\":34.95\n\t},\n\t{\n\t\t\"id\":46885,\n\t\t\"gender\":\"Boys\",\n\t\t\"season\":[\n\t\t\t\"Fall\"\n\t\t],\n\t\t\"description\":\"Ben 10 Boys Navy Blue Slippers\",\n\t\t\"price\":45.99\n\t}\n]"; + path: "$.inventory[?(@.price<100)]", + indent: "\t", + newLine: "\n" + ); + expected = + "[\n\t{\n\t\t\"id\":15970,\n\t\t\"gender\":\"Men\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\"\n\t\t],\n\t\t\"description\":\"Turtle Check Men Navy Blue Shirt\",\n\t\t\"price\":34.95\n\t},\n\t{\n\t\t\"id\":46885,\n\t\t\"gender\":\"Boys\",\n\t\t\"season\":[\n\t\t\t\"Fall\"\n\t\t],\n\t\t\"description\":\"Ben 10 Boys Navy Blue Slippers\",\n\t\t\"price\":45.99\n\t}\n]"; Assert.Equal(expected, res.ToString()); // Fetch all items within an array where a numeric field is less than a given value: res = json.Get(key: "warehouse:1", - path: "$.inventory[?(@.id>=20000)]", - indent: "\t", - newLine: "\n" - ); - expected = "[\n\t{\n\t\t\"id\":59263,\n\t\t\"gender\":\"Women\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\",\n\t\t\t\"Spring\",\n\t\t\t\"Summer\"\n\t\t],\n\t\t\"description\":\"Titan Women Silver Watch\",\n\t\t\"price\":129.99\n\t},\n\t{\n\t\t\"id\":46885,\n\t\t\"gender\":\"Boys\",\n\t\t\"season\":[\n\t\t\t\"Fall\"\n\t\t],\n\t\t\"description\":\"Ben 10 Boys Navy Blue Slippers\",\n\t\t\"price\":45.99\n\t}\n]"; + path: "$.inventory[?(@.id>=20000)]", + indent: "\t", + newLine: "\n" + ); + expected = + "[\n\t{\n\t\t\"id\":59263,\n\t\t\"gender\":\"Women\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\",\n\t\t\t\"Spring\",\n\t\t\t\"Summer\"\n\t\t],\n\t\t\"description\":\"Titan Women Silver Watch\",\n\t\t\"price\":129.99\n\t},\n\t{\n\t\t\"id\":46885,\n\t\t\"gender\":\"Boys\",\n\t\t\"season\":[\n\t\t\t\"Fall\"\n\t\t],\n\t\t\"description\":\"Ben 10 Boys Navy Blue Slippers\",\n\t\t\"price\":45.99\n\t}\n]"; Assert.Equal(expected, res.ToString()); // Fetch all items within an array where a numeric field is less than a given value: res = json.Get(key: "warehouse:1", - path: "$.inventory[?(@.gender==\"Men\"&&@.price>20)]", - indent: "\t", - newLine: "\n" - ); - expected = "[\n\t{\n\t\t\"id\":15970,\n\t\t\"gender\":\"Men\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\"\n\t\t],\n\t\t\"description\":\"Turtle Check Men Navy Blue Shirt\",\n\t\t\"price\":34.95\n\t}\n]"; + path: "$.inventory[?(@.gender==\"Men\"&&@.price>20)]", + indent: "\t", + newLine: "\n" + ); + expected = + "[\n\t{\n\t\t\"id\":15970,\n\t\t\"gender\":\"Men\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\"\n\t\t],\n\t\t\"description\":\"Turtle Check Men Navy Blue Shirt\",\n\t\t\"price\":34.95\n\t}\n]"; Assert.Equal(expected, res.ToString()); // Fetch all items within an array that meet at least one relational operation. // In this case, return only the ids of those items: res = json.Get(key: "warehouse:1", - path: "$.inventory[?(@.price<100||@.gender==\"Women\")].id", - indent: "\t", - newLine: "\n" - ); + path: "$.inventory[?(@.price<100||@.gender==\"Women\")].id", + indent: "\t", + newLine: "\n" + ); expected = "[\n\t15970,\n\t59263,\n\t46885\n]"; Assert.Equal(expected, res.ToString()); // Fetch all items within an array that match a given regex pattern. res = json.Get(key: "warehouse:1", - path: "$.inventory[?(@.description =~ \"Blue\")]", - indent: "\t", - newLine: "\n" - ); - expected = "[\n\t{\n\t\t\"id\":15970,\n\t\t\"gender\":\"Men\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\"\n\t\t],\n\t\t\"description\":\"Turtle Check Men Navy Blue Shirt\",\n\t\t\"price\":34.95\n\t},\n\t{\n\t\t\"id\":46885,\n\t\t\"gender\":\"Boys\",\n\t\t\"season\":[\n\t\t\t\"Fall\"\n\t\t],\n\t\t\"description\":\"Ben 10 Boys Navy Blue Slippers\",\n\t\t\"price\":45.99\n\t}\n]"; + path: "$.inventory[?(@.description =~ \"Blue\")]", + indent: "\t", + newLine: "\n" + ); + expected = + "[\n\t{\n\t\t\"id\":15970,\n\t\t\"gender\":\"Men\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\"\n\t\t],\n\t\t\"description\":\"Turtle Check Men Navy Blue Shirt\",\n\t\t\"price\":34.95\n\t},\n\t{\n\t\t\"id\":46885,\n\t\t\"gender\":\"Boys\",\n\t\t\"season\":[\n\t\t\t\"Fall\"\n\t\t],\n\t\t\"description\":\"Ben 10 Boys Navy Blue Slippers\",\n\t\t\"price\":45.99\n\t}\n]"; Assert.Equal(expected, res.ToString()); // Fetch all items within an array where a field contains a term, case insensitive res = json.Get(key: "warehouse:1", - path: "$.inventory[?(@.description =~ \"(?i)watch\")]", - indent: "\t", - newLine: "\n" - ); - expected = "[\n\t{\n\t\t\"id\":59263,\n\t\t\"gender\":\"Women\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\",\n\t\t\t\"Spring\",\n\t\t\t\"Summer\"\n\t\t],\n\t\t\"description\":\"Titan Women Silver Watch\",\n\t\t\"price\":129.99\n\t}\n]"; + path: "$.inventory[?(@.description =~ \"(?i)watch\")]", + indent: "\t", + newLine: "\n" + ); + expected = + "[\n\t{\n\t\t\"id\":59263,\n\t\t\"gender\":\"Women\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\",\n\t\t\t\"Spring\",\n\t\t\t\"Summer\"\n\t\t],\n\t\t\"description\":\"Titan Women Silver Watch\",\n\t\t\"price\":129.99\n\t}\n]"; Assert.Equal(expected, res.ToString()); // Fetch all items within an array where a field begins with a given expression res = json.Get(key: "warehouse:1", - path: "$.inventory[?(@.description =~ \"^T\")]", - indent: "\t", - newLine: "\n" - ); - expected = "[\n\t{\n\t\t\"id\":15970,\n\t\t\"gender\":\"Men\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\"\n\t\t],\n\t\t\"description\":\"Turtle Check Men Navy Blue Shirt\",\n\t\t\"price\":34.95\n\t},\n\t{\n\t\t\"id\":59263,\n\t\t\"gender\":\"Women\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\",\n\t\t\t\"Spring\",\n\t\t\t\"Summer\"\n\t\t],\n\t\t\"description\":\"Titan Women Silver Watch\",\n\t\t\"price\":129.99\n\t}\n]"; + path: "$.inventory[?(@.description =~ \"^T\")]", + indent: "\t", + newLine: "\n" + ); + expected = + "[\n\t{\n\t\t\"id\":15970,\n\t\t\"gender\":\"Men\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\"\n\t\t],\n\t\t\"description\":\"Turtle Check Men Navy Blue Shirt\",\n\t\t\"price\":34.95\n\t},\n\t{\n\t\t\"id\":59263,\n\t\t\"gender\":\"Women\",\n\t\t\"season\":[\n\t\t\t\"Fall\",\n\t\t\t\"Winter\",\n\t\t\t\"Spring\",\n\t\t\t\"Summer\"\n\t\t],\n\t\t\"description\":\"Titan Women Silver Watch\",\n\t\t\"price\":129.99\n\t}\n]"; Assert.Equal(expected, res.ToString()); } @@ -996,16 +1007,25 @@ public void BasicQueryOperationsTest() coords = "-104.991531, 39.742043" }); - try { ft.DropIndex("idx1"); } catch { }; + try + { + ft.DropIndex("idx1"); + } + catch + { + // ignored + } + + ; ft.Create("idx1", new FTCreateParams().On(IndexDataType.JSON) - .Prefix("product:"), - new Schema().AddNumericField(new FieldName("$.id", "id")) - .AddTagField(new FieldName("$.gender", "gender")) - .AddTagField(new FieldName("$.season.*", "season")) - .AddTextField(new FieldName("$.description", "description")) - .AddNumericField(new FieldName("$.price", "price")) - .AddTextField(new FieldName("$.city", "city")) - .AddGeoField(new FieldName("$.coords", "coords"))); + .Prefix("product:"), + new Schema().AddNumericField(new FieldName("$.id", "id")) + .AddTagField(new FieldName("$.gender", "gender")) + .AddTagField(new FieldName("$.season.*", "season")) + .AddTextField(new FieldName("$.description", "description")) + .AddNumericField(new FieldName("$.price", "price")) + .AddTextField(new FieldName("$.city", "city")) + .AddGeoField(new FieldName("$.coords", "coords"))); // sleep: Thread.Sleep(2000); @@ -1015,7 +1035,7 @@ public void BasicQueryOperationsTest() Assert.NotNull(res); // Assert.Equal(3, res!.Count); - var expectedList = new List() + var expectedList = new List { "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}", "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}", @@ -1025,93 +1045,102 @@ public void BasicQueryOperationsTest() SortAndCompare(expectedList, res); - // Find all documents with a given word in a text field: res = ft.Search("idx1", new Query("@description:Slippers")).ToJson(); - var expected = "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}"; + var expected = + "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}"; Assert.Equal(expected, res![0].ToString()); // Find all documents with a given phrase in a text field: res = ft.Search("idx1", new Query("@description:(\"Blue Shirt\")")).ToJson(); - expected = "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}"; - Assert.Equal(expected, res![0].ToString()); + expected = + "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}"; + Assert.Equal(expected, res![0]); // Find all documents with a numeric field in a given range: res = ft.Search("idx1", new Query("@price:[40,130]")).ToJson(); - expectedList = new() - { - "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}", - "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" - }; + expectedList = + new List + { + "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}", + "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" + }; SortAndCompare(expectedList, res); - // Find all documents that contain a given value in an array field (tag): res = ft.Search("idx1", new Query("@season:{Spring}")).ToJson(); - expected = "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}"; - Assert.Equal(expected, res[0].ToString()); + expected = + "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}"; + Assert.Equal(expected, res[0]); // Find all documents contain both a numeric field in a range and a word in a text field: res = ft.Search("idx1", new Query("@price:[40, 100] @description:Blue")).ToJson(); - expected = "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}"; - Assert.Equal(expected, res[0].ToString()); + expected = + "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}"; + Assert.Equal(expected, res[0]); // Find all documents that either match tag value or text value: res = ft.Search("idx1", new Query("(@gender:{Women})|(@city:Boston)")).ToJson(); - expectedList = new() - { - "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}", - "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}" - }; + expectedList = + new List + { + "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}", + "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}" + }; SortAndCompare(expectedList, res); // Find all documents that do not contain a given word in a text field: res = ft.Search("idx1", new Query("-(@description:Shirt)")).ToJson(); - expectedList = new() - { - "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}", - "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" - }; + expectedList = + new List + { + "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}", + "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" + }; SortAndCompare(expectedList, res); // Find all documents that have a word that begins with a given prefix value: res = ft.Search("idx1", new Query("@description:Nav*")).ToJson(); - expectedList = new() - { - "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}", - "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" - }; + expectedList = + new List + { + "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}", + "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" + }; SortAndCompare(expectedList, res); // Find all documents that contain a word that ends with a given suffix value: res = ft.Search("idx1", new Query("@description:*Watch")).ToJson(); - expected = "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}"; + expected = + "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}"; Assert.Equal(expected, res[0].ToString()); // Find all documents that contain a word that is within 1 Levenshtein distance of a given word: res = ft.Search("idx1", new Query("@description:%wavy%")).ToJson(); - expectedList = new() - { - "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}", - "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" - }; + expectedList = + new List + { + "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}", + "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" + }; SortAndCompare(expectedList, res); // Find all documents that have geographic coordinates within a given range of a given coordinate. // Colorado Springs coords(long, lat) = -104.800644, 38.846127: res = ft.Search("idx1", new Query("@coords:[-104.800644 38.846127 100 mi]")).ToJson(); - expected = "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}"; + expected = + "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}"; Assert.Equal(expected, res[0].ToString()); } @@ -1149,18 +1178,26 @@ public void AdvancedQueryOperationsTest() }); // Index creation: - try { ft.DropIndex("vss_idx"); } catch { }; + try + { + ft.DropIndex("vss_idx"); + } + catch + { + //Todo: Check When Exception Catch + } + Assert.True(ft.Create("vss_idx", new FTCreateParams().On(IndexDataType.HASH).Prefix("vec:"), new Schema() - .AddTagField("tag") - .AddVectorField("vector", VectorField.VectorAlgo.FLAT, - new Dictionary() - { - ["TYPE"] = "FLOAT32", - ["DIM"] = "4", - ["DISTANCE_METRIC"] = "L2" - } - ))); + .AddTagField("tag") + .AddVectorField("vector", VectorField.VectorAlgo.FLAT, + new Dictionary() + { + ["TYPE"] = "FLOAT32", + ["DIM"] = "4", + ["DISTANCE_METRIC"] = "L2" + } + ))); // Sleep: Thread.Sleep(2000); @@ -1168,10 +1205,10 @@ public void AdvancedQueryOperationsTest() // Search: float[] vec = new[] { 2f, 3f, 3f, 3f }; var res = ft.Search("vss_idx", - new Query("*=>[KNN 2 @vector $query_vec]") - .AddParam("query_vec", vec.SelectMany(BitConverter.GetBytes).ToArray()) - .SetSortBy("__vector_score") - .Dialect(2)); + new Query("*=>[KNN 2 @vector $query_vec]") + .AddParam("query_vec", vec.SelectMany(BitConverter.GetBytes).ToArray()) + .SetSortBy("__vector_score") + .Dialect(2)); HashSet resSet = new HashSet(); foreach (var doc in res.Documents) { @@ -1194,10 +1231,10 @@ public void AdvancedQueryOperationsTest() // hybrid query - search only documents with tag A: res = ft.Search("vss_idx", - new Query("@tag:{A}=>[KNN 2 @vector $query_vec]") - .AddParam("query_vec", vec.SelectMany(BitConverter.GetBytes).ToArray()) - .SetSortBy("__vector_score") - .Dialect(2)); + new Query("@tag:{A}=>[KNN 2 @vector $query_vec]") + .AddParam("query_vec", vec.SelectMany(BitConverter.GetBytes).ToArray()) + .SetSortBy("__vector_score") + .Dialect(2)); resSet.Clear(); foreach (var doc in res.Documents) @@ -1211,11 +1248,12 @@ public void AdvancedQueryOperationsTest() } } - expectedResSet = new HashSet() - { - "id: vec:2, score: 3", - "id: vec:4, score: 7", - }; + expectedResSet = + new HashSet + { + "id: vec:2, score: 3", + "id: vec:4, score: 7" + }; //Advanced Search Queries: // data load: @@ -1223,25 +1261,29 @@ public void AdvancedQueryOperationsTest() { city = "Boston", location = "-71.057083, 42.361145", - inventory = new[] { - new { + inventory = new[] + { + new + { id = 15970, gender = "Men", - season = new[] {"Fall", "Winter"}, + season = new[] { "Fall", "Winter" }, description = "Turtle Check Men Navy Blue Shirt", price = 34.95 }, - new { + new + { id = 59263, gender = "Women", - season = new[] {"Fall", "Winter", "Spring", "Summer"}, + season = new[] { "Fall", "Winter", "Spring", "Summer" }, description = "Titan Women Silver Watch", price = 129.99 }, - new { + new + { id = 46885, gender = "Boys", - season = new[] {"Fall"}, + season = new[] { "Fall" }, description = "Ben 10 Boys Navy Blue Slippers", price = 45.99 } @@ -1251,25 +1293,29 @@ public void AdvancedQueryOperationsTest() { city = "Dallas", location = "-96.808891, 32.779167", - inventory = new[] { - new { + inventory = new[] + { + new + { id = 51919, gender = "Women", - season = new[] {"Summer"}, + season = new[] { "Summer" }, description = "Nyk Black Horado Handbag", price = 52.49 }, - new { + new + { id = 4602, gender = "Unisex", - season = new[] {"Fall", "Winter"}, + season = new[] { "Fall", "Winter" }, description = "Wildcraft Red Trailblazer Backpack", price = 50.99 }, - new { + new + { id = 37561, gender = "Girls", - season = new[] {"Spring", "Summer"}, + season = new[] { "Spring", "Summer" }, description = "Madagascar3 Infant Pink Snapsuit Romper", price = 23.95 } @@ -1277,29 +1323,38 @@ public void AdvancedQueryOperationsTest() }); // Index creation: - try { ft.DropIndex("wh_idx"); } catch { }; + try + { + ft.DropIndex("wh_idx"); + } + catch + { + //Todo: Check When Exception Catch + } + Assert.True(ft.Create("wh_idx", new FTCreateParams() - .On(IndexDataType.JSON) - .Prefix("warehouse:"), - new Schema().AddTextField(new FieldName("$.city", "city")))); + .On(IndexDataType.JSON) + .Prefix("warehouse:"), + new Schema().AddTextField(new FieldName("$.city", "city")))); // Sleep: Thread.Sleep(2000); // Find all inventory ids from all the Boston warehouse that have a price > $50: res = ft.Search("wh_idx", - new Query("@city:Boston") - .ReturnFields(new FieldName("$.inventory[?(@.price>50)].id", "result")) - .Dialect(3)); + new Query("@city:Boston") + .ReturnFields(new FieldName("$.inventory[?(@.price>50)].id", "result")) + .Dialect(3)); Assert.Equal("[59263]", res.Documents[0]["result"].ToString()); // Find all inventory items in Dallas that are for Women or Girls: res = ft.Search("wh_idx", - new Query("@city:(Dallas)") - .ReturnFields(new FieldName("$.inventory[?(@.gender==\"Women\" || @.gender==\"Girls\")]", "result")) - .Dialect(3)); - var expected = "[{\"id\":51919,\"gender\":\"Women\",\"season\":[\"Summer\"],\"description\":\"Nyk Black Horado Handbag\",\"price\":52.49},{\"id\":37561,\"gender\":\"Girls\",\"season\":[\"Spring\",\"Summer\"],\"description\":\"Madagascar3 Infant Pink Snapsuit Romper\",\"price\":23.95}]"; + new Query("@city:(Dallas)") + .ReturnFields(new FieldName("$.inventory[?(@.gender==\"Women\" || @.gender==\"Girls\")]", "result")) + .Dialect(3)); + var expected = + "[{\"id\":51919,\"gender\":\"Women\",\"season\":[\"Summer\"],\"description\":\"Nyk Black Horado Handbag\",\"price\":52.49},{\"id\":37561,\"gender\":\"Girls\",\"season\":[\"Spring\",\"Summer\"],\"description\":\"Madagascar3 Infant Pink Snapsuit Romper\",\"price\":23.95}]"; Assert.Equal(expected, res.Documents[0]["result"].ToString()); // Aggregation @@ -1324,17 +1379,17 @@ public void AdvancedQueryOperationsTest() }); json.Set("book:4", "$", new { - title = "Superintelligence: Path, Dangers, Stategies", + title = "Superintelligence: Path, Dangers, Strategies", year = 2016, price = 14.36 }); Assert.True(ft.Create("book_idx", new FTCreateParams() - .On(IndexDataType.JSON) - .Prefix("book:"), - new Schema().AddTextField(new FieldName("$.title", "title")) - .AddNumericField(new FieldName("$.year", "year")) - .AddNumericField(new FieldName("$.price", "price")))); + .On(IndexDataType.JSON) + .Prefix("book:"), + new Schema().AddTextField(new FieldName("$.title", "title")) + .AddNumericField(new FieldName("$.year", "year")) + .AddNumericField(new FieldName("$.price", "price")))); // sleep: Thread.Sleep(2000); @@ -1348,6 +1403,7 @@ public void AdvancedQueryOperationsTest() var row = result.GetRow(i); resSet.Add($"{row["year"]}: {row["count"]}"); } + expectedResSet.Clear(); expectedResSet.Add("2016: 1"); expectedResSet.Add("2020: 2"); @@ -1365,6 +1421,7 @@ public void AdvancedQueryOperationsTest() var row = result.GetRow(i); resSet.Add($"{row["year"]}: {row["sum"]}"); } + expectedResSet.Clear(); expectedResSet.Add("2016: 14.36"); expectedResSet.Add("2020: 56.98"); @@ -1385,4 +1442,4 @@ private static void SortAndCompare(List expectedList, List res) Assert.Equal(expectedList[i], res[i].ToString()); } } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/Person.cs b/tests/NRedisStack.Tests/Person.cs index eed41b9e..c0f0c4f4 100644 --- a/tests/NRedisStack.Tests/Person.cs +++ b/tests/NRedisStack.Tests/Person.cs @@ -1,9 +1,8 @@ -namespace NRedisStack.Tests +namespace NRedisStack.Tests; + +public class Person { - public class Person - { - public string? Name { get; set; } - public int Age { get; set; } - public DateTime? Birthday; - } + public string? Name { get; set; } + public int Age { get; set; } + public DateTime? Birthday; } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/PipelineTests.cs b/tests/NRedisStack.Tests/PipelineTests.cs index 6c77b0bf..cf4826fc 100644 --- a/tests/NRedisStack.Tests/PipelineTests.cs +++ b/tests/NRedisStack.Tests/PipelineTests.cs @@ -8,12 +8,12 @@ namespace NRedisStack.Tests; public class PipelineTests : AbstractNRedisStackTest, IDisposable { - private readonly string key = "PIPELINE_TESTS"; + private const string key = "PIPELINE_TESTS"; public PipelineTests(RedisFixture redisFixture) : base(redisFixture) { } [SkipIfRedis(Is.OSSCluster, Comparison.GreaterThanOrEqual, "7.1.242")] [Obsolete] - public void TestModulsPipeline() + public void TestModulesPipeline() { IDatabase db = redisFixture.Redis.GetDatabase(); db.Execute("FLUSHALL"); @@ -65,7 +65,7 @@ public void TestModulsPipeline() [SkipIfRedis(Is.OSSCluster)] [Obsolete] - public void TestModulsPipelineWithotGraph() + public void TestModulesPipelineWithoutGraph() { IDatabase db = redisFixture.Redis.GetDatabase(); db.Execute("FLUSHALL"); diff --git a/tests/NRedisStack.Tests/RedisFixture.cs b/tests/NRedisStack.Tests/RedisFixture.cs index dac4b6f5..81aca9ab 100644 --- a/tests/NRedisStack.Tests/RedisFixture.cs +++ b/tests/NRedisStack.Tests/RedisFixture.cs @@ -1,68 +1,66 @@ using StackExchange.Redis; -namespace NRedisStack.Tests -{ - public class RedisFixture : IDisposable - { - // Set the enviroment variable to specify your own alternet host and port: - readonly string redisStandalone = Environment.GetEnvironmentVariable("REDIS") ?? "localhost:6379"; - readonly string? redisCluster = Environment.GetEnvironmentVariable("REDIS_CLUSTER"); - readonly string? numRedisClusterNodesEnv = Environment.GetEnvironmentVariable("NUM_REDIS_CLUSTER_NODES"); +namespace NRedisStack.Tests; - public bool isEnterprise = Environment.GetEnvironmentVariable("IS_ENTERPRISE") == "true"; - public bool isOSSCluster; +public class RedisFixture : IDisposable +{ + // Set the environment variable to specify your own alternate host and port: + private readonly string redisStandalone = Environment.GetEnvironmentVariable("REDIS") ?? "localhost:6379"; + private readonly string? redisCluster = Environment.GetEnvironmentVariable("REDIS_CLUSTER"); + private readonly string? numRedisClusterNodesEnv = Environment.GetEnvironmentVariable("NUM_REDIS_CLUSTER_NODES"); + public bool isEnterprise = Environment.GetEnvironmentVariable("IS_ENTERPRISE") == "true"; + public bool isOSSCluster; - public RedisFixture() + public RedisFixture() + { + ConfigurationOptions clusterConfig = new ConfigurationOptions { - ConfigurationOptions clusterConfig = new ConfigurationOptions - { - AsyncTimeout = 10000, - SyncTimeout = 10000 - }; - Redis = Connect(clusterConfig, out isOSSCluster); - } + AsyncTimeout = 10000, + SyncTimeout = 10000 + }; + Redis = Connect(clusterConfig, out isOSSCluster); + } - public void Dispose() - { - Redis.Close(); - } + public void Dispose() + { + Redis.Close(); + } - public ConnectionMultiplexer Redis { get; } + public ConnectionMultiplexer Redis { get; } - public ConnectionMultiplexer CustomRedis(ConfigurationOptions configurationOptions, out bool isOssCluster) - { - return Connect(configurationOptions, out isOssCluster); - } + public ConnectionMultiplexer CustomRedis(ConfigurationOptions configurationOptions, out bool isOssCluster) + { + return Connect(configurationOptions, out isOssCluster); + } - private ConnectionMultiplexer Connect(ConfigurationOptions configurationOptions, out bool isOssCluster) + private ConnectionMultiplexer Connect(ConfigurationOptions configurationOptions, out bool isOssCluster) + { + // Redis Cluster + if (redisCluster != null && numRedisClusterNodesEnv != null) { - // Redis Cluster - if (redisCluster != null && numRedisClusterNodesEnv != null) - { - // Split to host and port - string[] parts = redisCluster!.Split(':'); - string host = parts[0]; - int startPort = int.Parse(parts[1]); - - var endpoints = new EndPointCollection(); // TODO: checl if needed + // Split to host and port + string[] parts = redisCluster!.Split(':'); + string host = parts[0]; + int startPort = int.Parse(parts[1]); - configurationOptions.EndPoints.Clear(); - int numRedisClusterNodes = int.Parse(numRedisClusterNodesEnv!); - for (int i = 0; i < numRedisClusterNodes; i++) - { - configurationOptions.EndPoints.Add(host, startPort + i); - } + var endpoints = new EndPointCollection(); // TODO: check if needed - isOssCluster = true; - return ConnectionMultiplexer.Connect(configurationOptions); - } - - // Redis Standalone configurationOptions.EndPoints.Clear(); - configurationOptions.EndPoints.Add($"{redisStandalone}"); + int numRedisClusterNodes = int.Parse(numRedisClusterNodesEnv!); + for (int i = 0; i < numRedisClusterNodes; i++) + { + configurationOptions.EndPoints.Add(host, startPort + i); + } - isOssCluster = false; + isOssCluster = true; return ConnectionMultiplexer.Connect(configurationOptions); } + + // Redis Standalone + configurationOptions.EndPoints.Clear(); + configurationOptions.EndPoints.Add($"{redisStandalone}"); + + isOssCluster = false; + return ConnectionMultiplexer.Connect(configurationOptions); } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TransactionsTests.cs b/tests/NRedisStack.Tests/TransactionsTests.cs index 498ed77c..0883bcf1 100644 --- a/tests/NRedisStack.Tests/TransactionsTests.cs +++ b/tests/NRedisStack.Tests/TransactionsTests.cs @@ -4,131 +4,132 @@ using System.Text.Json; using Xunit; -namespace NRedisStack.Tests +namespace NRedisStack.Tests; + +public class TransactionTests : AbstractNRedisStackTest, IDisposable { - public class TransactionTests : AbstractNRedisStackTest, IDisposable + private readonly string key = "TRX_TESTS"; + + public TransactionTests(RedisFixture redisFixture) : base(redisFixture) + { + } + + [Fact] + public void TestJsonTransaction() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + var transaction = new Transaction(db); + string jsonPerson = JsonSerializer.Serialize(new Person { Name = "Shachar", Age = 23 }); + var setResponse = transaction.Json.SetAsync(key, "$", jsonPerson); + var getResponse = transaction.Json.GetAsync(key); + + transaction.Execute(); + + setResponse.Wait(); + getResponse.Wait(); + + Assert.True(setResponse.Result); + Assert.Equal("{\"Name\":\"Shachar\",\"Age\":23}", getResponse.Result.ToString()); + } + + [SkipIfRedis(Comparison.GreaterThanOrEqual, "7.1.242")] + [Obsolete] + public void TestModulesTransaction() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + var tran = new Transaction(db); + + _ = tran.Bf.ReserveAsync("bf-key", 0.001, 100); + _ = tran.Bf.AddAsync("bf-key", "1"); + _ = tran.Cms.InitByDimAsync("cms-key", 100, 5); + _ = tran.Cf.ReserveAsync("cf-key", 100); + _ = tran.Graph.QueryAsync("graph-key", "CREATE ({name:'shachar',age:23})"); + _ = tran.Json.SetAsync("json-key", "$", "{}"); + _ = tran.Ft.CreateAsync("ft-key", new FTCreateParams(), new Schema().AddTextField("txt")); + _ = tran.Tdigest.CreateAsync("tdigest-key", 100); + _ = tran.Ts.CreateAsync("ts-key", 100); + _ = tran.TopK.ReserveAsync("topk-key", 100, 100, 100); + + Assert.False(db.KeyExists("bf-key")); + Assert.False(db.KeyExists("cms-key")); + Assert.False(db.KeyExists("cf-key")); + Assert.False(db.KeyExists("graph-key")); + Assert.False(db.KeyExists("json-key")); + Assert.Empty(db.FT()._List()); + Assert.False(db.KeyExists("tdigest-key")); + Assert.False(db.KeyExists("ts-key")); + Assert.False(db.KeyExists("topk-key")); + + tran.Execute(); + + Assert.True(db.KeyExists("bf-key")); + Assert.True(db.KeyExists("cms-key")); + Assert.True(db.KeyExists("cf-key")); + Assert.True(db.KeyExists("graph-key")); + Assert.True(db.KeyExists("json-key")); + Assert.True(db.FT()._List().Length == 1); + Assert.True(db.KeyExists("tdigest-key")); + Assert.True(db.KeyExists("ts-key")); + Assert.True(db.KeyExists("topk-key")); + + Assert.True(db.BF().Exists("bf-key", "1")); + Assert.True(db.CMS().Info("cms-key").Width == 100); + Assert.True(db.CF().Info("cf-key").Size > 0); + Assert.True(db.GRAPH().List().Count > 0); + Assert.False(db.JSON().Get("json-key").IsNull); + Assert.NotNull(db.FT().Info("ft-key")); + Assert.NotNull(db.TDIGEST().Info("tdigest-key")); + Assert.NotNull(db.TS().Info("ts-key")); + Assert.NotNull(db.TOPK().Info("topk-key")); + } + + [SkipIfRedis(Is.OSSCluster, Is.Enterprise)] + [Obsolete] + public void TestModulesTransactionWithoutGraph() { - private readonly string key = "TRX_TESTS"; - public TransactionTests(RedisFixture redisFixture) : base(redisFixture) { } - - - [Fact] - public void TestJsonTransaction() - { - IDatabase db = redisFixture.Redis.GetDatabase(); - db.Execute("FLUSHALL"); - var transaction = new Transaction(db); - string jsonPerson = JsonSerializer.Serialize(new Person { Name = "Shachar", Age = 23 }); - var setResponse = transaction.Json.SetAsync(key, "$", jsonPerson); - var getResponse = transaction.Json.GetAsync(key); - - transaction.Execute(); - - setResponse.Wait(); - getResponse.Wait(); - - Assert.True(setResponse.Result); - Assert.Equal("{\"Name\":\"Shachar\",\"Age\":23}", getResponse.Result.ToString()); - } - - [SkipIfRedis(Comparison.GreaterThanOrEqual, "7.1.242")] - [Obsolete] - public void TestModulsTransaction() - { - IDatabase db = redisFixture.Redis.GetDatabase(); - db.Execute("FLUSHALL"); - var tran = new Transaction(db); - - _ = tran.Bf.ReserveAsync("bf-key", 0.001, 100); - _ = tran.Bf.AddAsync("bf-key", "1"); - _ = tran.Cms.InitByDimAsync("cms-key", 100, 5); - _ = tran.Cf.ReserveAsync("cf-key", 100); - _ = tran.Graph.QueryAsync("graph-key", "CREATE ({name:'shachar',age:23})"); - _ = tran.Json.SetAsync("json-key", "$", "{}"); - _ = tran.Ft.CreateAsync("ft-key", new FTCreateParams(), new Schema().AddTextField("txt")); - _ = tran.Tdigest.CreateAsync("tdigest-key", 100); - _ = tran.Ts.CreateAsync("ts-key", 100); - _ = tran.TopK.ReserveAsync("topk-key", 100, 100, 100); - - Assert.False(db.KeyExists("bf-key")); - Assert.False(db.KeyExists("cms-key")); - Assert.False(db.KeyExists("cf-key")); - Assert.False(db.KeyExists("graph-key")); - Assert.False(db.KeyExists("json-key")); - Assert.Empty(db.FT()._List()); - Assert.False(db.KeyExists("tdigest-key")); - Assert.False(db.KeyExists("ts-key")); - Assert.False(db.KeyExists("topk-key")); - - tran.Execute(); - - Assert.True(db.KeyExists("bf-key")); - Assert.True(db.KeyExists("cms-key")); - Assert.True(db.KeyExists("cf-key")); - Assert.True(db.KeyExists("graph-key")); - Assert.True(db.KeyExists("json-key")); - Assert.True(db.FT()._List().Length == 1); - Assert.True(db.KeyExists("tdigest-key")); - Assert.True(db.KeyExists("ts-key")); - Assert.True(db.KeyExists("topk-key")); - - Assert.True(db.BF().Exists("bf-key", "1")); - Assert.True(db.CMS().Info("cms-key").Width == 100); - Assert.True(db.CF().Info("cf-key").Size > 0); - Assert.True(db.GRAPH().List().Count > 0); - Assert.False(db.JSON().Get("json-key").IsNull); - Assert.NotNull(db.FT().Info("ft-key")); - Assert.NotNull(db.TDIGEST().Info("tdigest-key")); - Assert.NotNull(db.TS().Info("ts-key")); - Assert.NotNull(db.TOPK().Info("topk-key")); - } - - [SkipIfRedis(Is.OSSCluster, Is.Enterprise)] - [Obsolete] - public void TestModulsTransactionWithoutGraph() - { - IDatabase db = redisFixture.Redis.GetDatabase(); - db.Execute("FLUSHALL"); - var tran = new Transaction(db); - - _ = tran.Bf.ReserveAsync("bf-key", 0.001, 100); - _ = tran.Bf.AddAsync("bf-key", "1"); - _ = tran.Cms.InitByDimAsync("cms-key", 100, 5); - _ = tran.Cf.ReserveAsync("cf-key", 100); - _ = tran.Json.SetAsync("json-key", "$", "{}"); - _ = tran.Ft.CreateAsync("ft-key", new FTCreateParams(), new Schema().AddTextField("txt")); - _ = tran.Tdigest.CreateAsync("tdigest-key", 100); - _ = tran.Ts.CreateAsync("ts-key", 100); - _ = tran.TopK.ReserveAsync("topk-key", 100, 100, 100); - - Assert.False(db.KeyExists("bf-key")); - Assert.False(db.KeyExists("cms-key")); - Assert.False(db.KeyExists("cf-key")); - Assert.False(db.KeyExists("json-key")); - Assert.Empty(db.FT()._List()); - Assert.False(db.KeyExists("tdigest-key")); - Assert.False(db.KeyExists("ts-key")); - Assert.False(db.KeyExists("topk-key")); - - tran.Execute(); - - Assert.True(db.KeyExists("bf-key")); - Assert.True(db.KeyExists("cms-key")); - Assert.True(db.KeyExists("cf-key")); - Assert.True(db.KeyExists("json-key")); - Assert.True(db.FT()._List().Length == 1); - Assert.True(db.KeyExists("tdigest-key")); - Assert.True(db.KeyExists("ts-key")); - Assert.True(db.KeyExists("topk-key")); - - Assert.True(db.BF().Exists("bf-key", "1")); - Assert.True(db.CMS().Info("cms-key").Width == 100); - Assert.True(db.CF().Info("cf-key").Size > 0); - Assert.False(db.JSON().Get("json-key").IsNull); - Assert.NotNull(db.FT().Info("ft-key")); - Assert.NotNull(db.TDIGEST().Info("tdigest-key")); - Assert.NotNull(db.TS().Info("ts-key")); - Assert.NotNull(db.TOPK().Info("topk-key")); - } + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + var tran = new Transaction(db); + + _ = tran.Bf.ReserveAsync("bf-key", 0.001, 100); + _ = tran.Bf.AddAsync("bf-key", "1"); + _ = tran.Cms.InitByDimAsync("cms-key", 100, 5); + _ = tran.Cf.ReserveAsync("cf-key", 100); + _ = tran.Json.SetAsync("json-key", "$", "{}"); + _ = tran.Ft.CreateAsync("ft-key", new FTCreateParams(), new Schema().AddTextField("txt")); + _ = tran.Tdigest.CreateAsync("tdigest-key", 100); + _ = tran.Ts.CreateAsync("ts-key", 100); + _ = tran.TopK.ReserveAsync("topk-key", 100, 100, 100); + + Assert.False(db.KeyExists("bf-key")); + Assert.False(db.KeyExists("cms-key")); + Assert.False(db.KeyExists("cf-key")); + Assert.False(db.KeyExists("json-key")); + Assert.Empty(db.FT()._List()); + Assert.False(db.KeyExists("tdigest-key")); + Assert.False(db.KeyExists("ts-key")); + Assert.False(db.KeyExists("topk-key")); + + tran.Execute(); + + Assert.True(db.KeyExists("bf-key")); + Assert.True(db.KeyExists("cms-key")); + Assert.True(db.KeyExists("cf-key")); + Assert.True(db.KeyExists("json-key")); + Assert.True(db.FT()._List().Length == 1); + Assert.True(db.KeyExists("tdigest-key")); + Assert.True(db.KeyExists("ts-key")); + Assert.True(db.KeyExists("topk-key")); + + Assert.True(db.BF().Exists("bf-key", "1")); + Assert.True(db.CMS().Info("cms-key").Width == 100); + Assert.True(db.CF().Info("cf-key").Size > 0); + Assert.False(db.JSON().Get("json-key").IsNull); + Assert.NotNull(db.FT().Info("ft-key")); + Assert.NotNull(db.TDIGEST().Info("tdigest-key")); + Assert.NotNull(db.TS().Info("ts-key")); + Assert.NotNull(db.TOPK().Info("topk-key")); } -} +} \ No newline at end of file