Skip to content

Commit 33543f5

Browse files
authored
Merge branch 'master' into dependabot/nuget/xunit-2.9.0
2 parents 4a18296 + dfc75d2 commit 33543f5

37 files changed

+3387
-367
lines changed

src/NRedisStack/Gears/GearsCommandBuilder.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
namespace NRedisStack
44
{
55

6+
[Obsolete]
67
public static class GearsCommandBuilder
78
{
9+
[Obsolete]
810
public static SerializedCommand TFunctionLoad(string libraryCode, bool replace = false, string? config = null)
911
{
1012
var args = new List<object>() { GearsArgs.LOAD };
@@ -23,11 +25,13 @@ public static SerializedCommand TFunctionLoad(string libraryCode, bool replace =
2325
return new SerializedCommand(RG.TFUNCTION, args);
2426
}
2527

28+
[Obsolete]
2629
public static SerializedCommand TFunctionDelete(string libraryName)
2730
{
2831
return new SerializedCommand(RG.TFUNCTION, GearsArgs.DELETE, libraryName);
2932
}
3033

34+
[Obsolete]
3135
public static SerializedCommand TFunctionList(bool withCode = false, int verbose = 0, string? libraryName = null)
3236
{
3337
var args = new List<object>() { GearsArgs.LIST };
@@ -55,6 +59,7 @@ public static SerializedCommand TFunctionList(bool withCode = false, int verbose
5559
return new SerializedCommand(RG.TFUNCTION, args);
5660
}
5761

62+
[Obsolete]
5863
public static SerializedCommand TFCall(string libraryName, string functionName, string[]? keys = null, string[]? args = null, bool async = false)
5964
{
6065
string command = async ? RG.TFCALLASYNC : RG.TFCALL;

src/NRedisStack/Gears/GearsCommands.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using StackExchange.Redis;
22
namespace NRedisStack
33
{
4-
4+
[Obsolete]
55
public static class GearsCommands //: GearsCommandsAsync, IGearsCommands
66
{
77

@@ -17,6 +17,7 @@ public static class GearsCommands //: GearsCommandsAsync, IGearsCommands
1717
/// <param name="replace">an optional argument, instructs RedisGears to replace the function if its already exists.</param>
1818
/// <returns><see langword="true"/> if everything was done correctly, Error otherwise.</returns>
1919
/// <remarks><seealso href="https://redis.io/commands/tfunction-load/"/></remarks> //TODO: check this link when it's available
20+
[Obsolete]
2021
public static bool TFunctionLoad(this IDatabase db, string libraryCode, bool replace = false, string? config = null)
2122
{
2223
return db.Execute(GearsCommandBuilder.TFunctionLoad(libraryCode, replace, config)).OKtoBoolean();
@@ -28,6 +29,7 @@ public static bool TFunctionLoad(this IDatabase db, string libraryCode, bool rep
2829
/// <param name="libraryName">the name of the library to delete.</param>
2930
/// <returns><see langword="true"/> if the library was deleted successfully, Error otherwise.</returns>
3031
/// <remarks><seealso href="https://redis.io/commands/tfunction-delete/"/></remarks> //TODO: check this link when it's available
32+
[Obsolete]
3133
public static bool TFunctionDelete(this IDatabase db, string libraryName)
3234
{
3335
return db.Execute(GearsCommandBuilder.TFunctionDelete(libraryName)).OKtoBoolean();
@@ -42,6 +44,7 @@ public static bool TFunctionDelete(this IDatabase db, string libraryName)
4244
/// multiple times to show multiple libraries in a single command)</param>
4345
/// <returns>Information about the requested libraries.</returns>
4446
/// <remarks><seealso href="https://redis.io/commands/tfunction-list/"/></remarks> //TODO: check this link when it's available
47+
[Obsolete]
4548
public static Dictionary<string, RedisResult>[] TFunctionList(this IDatabase db, bool withCode = false, int verbose = 0, string? libraryName = null)
4649
{
4750
return db.Execute(GearsCommandBuilder.TFunctionList(withCode, verbose, libraryName)).ToDictionarys();
@@ -56,6 +59,7 @@ public static Dictionary<string, RedisResult>[] TFunctionList(this IDatabase db,
5659
/// <param name="args">Additional argument to pass to the function.</param>
5760
/// <returns>The return value from the sync &amp; async function on error in case of failure.</returns>
5861
/// <remarks><seealso href="https://redis.io/commands/tfcall"/></remarks>
62+
[Obsolete]
5963
public static RedisResult TFCall_(this IDatabase db, string libraryName, string functionName, string[]? keys = null, string[]? args = null)
6064
{
6165
return db.Execute(GearsCommandBuilder.TFCall(libraryName, functionName, keys, args, async: false));
@@ -70,6 +74,7 @@ public static RedisResult TFCall_(this IDatabase db, string libraryName, string
7074
/// <param name="args">Additional argument to pass to the function.</param>
7175
/// <returns>The return value from the sync &amp; async function on error in case of failure.</returns>
7276
/// <remarks><seealso href="https://redis.io/commands/tfcallasync"/></remarks>
77+
[Obsolete]
7378
public static RedisResult TFCallAsync_(this IDatabase db, string libraryName, string functionName, string[]? keys = null, string[]? args = null)
7479
{
7580
return db.Execute(GearsCommandBuilder.TFCall(libraryName, functionName, keys, args, async: true));

src/NRedisStack/Gears/GearsCommandsAsync.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public static class GearsCommandsAsync //: IGearsCommandsAsync
1616
/// <param name="replace">an optional argument, instructs RedisGears to replace the function if its already exists.</param>
1717
/// <returns><see langword="true"/> if everything was done correctly, Error otherwise.</returns>
1818
/// <remarks><seealso href="https://redis.io/commands/"/></remarks> //TODO: add link to the command when it's available
19+
[Obsolete]
1920
public static async Task<bool> TFunctionLoadAsync(this IDatabase db, string libraryCode, string? config = null, bool replace = false)
2021
{
2122
return (await db.ExecuteAsync(GearsCommandBuilder.TFunctionLoad(libraryCode, replace, config))).OKtoBoolean();
@@ -27,6 +28,7 @@ public static async Task<bool> TFunctionLoadAsync(this IDatabase db, string libr
2728
/// <param name="libraryName">the name of the library to delete.</param>
2829
/// <returns><see langword="true"/> if the library was deleted successfully, Error otherwise.</returns>
2930
/// <remarks><seealso href="https://redis.io/commands/"/></remarks> //TODO: add link to the command when it's available
31+
[Obsolete]
3032
public static async Task<bool> TFunctionDeleteAsync(this IDatabase db, string libraryName)
3133
{
3234
return (await db.ExecuteAsync(GearsCommandBuilder.TFunctionDelete(libraryName))).OKtoBoolean();
@@ -41,6 +43,7 @@ public static async Task<bool> TFunctionDeleteAsync(this IDatabase db, string li
4143
/// multiple times to show multiple libraries in a single command)</param>
4244
/// <returns>Information about the requested libraries.</returns>
4345
/// <remarks><seealso href="https://redis.io/commands/"/></remarks> //TODO: add link to the command when it's available
46+
[Obsolete]
4447
public static async Task<Dictionary<string, RedisResult>[]> TFunctionListAsync(this IDatabase db, bool withCode = false, int verbose = 0, string? libraryName = null)
4548
{
4649
return (await db.ExecuteAsync(GearsCommandBuilder.TFunctionList(withCode, verbose, libraryName))).ToDictionarys();
@@ -55,6 +58,7 @@ public static async Task<Dictionary<string, RedisResult>[]> TFunctionListAsync(t
5558
/// <param name="args">Additional argument to pass to the function.</param>
5659
/// <returns>The return value from the sync &amp; async function on error in case of failure.</returns>
5760
/// <remarks><seealso href="https://redis.io/commands/tfcall"/></remarks>
61+
[Obsolete]
5862
public async static Task<RedisResult> TFCall_Async(this IDatabase db, string libraryName, string functionName, string[]? keys = null, string[]? args = null)
5963
{
6064
return await db.ExecuteAsync(GearsCommandBuilder.TFCall(libraryName, functionName, keys, args, async: false));
@@ -69,6 +73,7 @@ public async static Task<RedisResult> TFCall_Async(this IDatabase db, string lib
6973
/// <param name="args">Additional argument to pass to the function.</param>
7074
/// <returns>The return value from the sync &amp; async function on error in case of failure.</returns>
7175
/// <remarks><seealso href="https://redis.io/commands/tfcallasync"/></remarks>
76+
[Obsolete]
7277
public async static Task<RedisResult> TFCallAsync_Async(this IDatabase db, string libraryName, string functionName, string[]? keys = null, string[]? args = null)
7378
{
7479
return await db.ExecuteAsync(GearsCommandBuilder.TFCall(libraryName, functionName, keys, args, async: true));

src/NRedisStack/ModulePrefixes.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public static class ModulePrefixes
1717

1818
public static TdigestCommands TDIGEST(this IDatabase db) => new TdigestCommands(db);
1919

20-
public static SearchCommands FT(this IDatabase db, int? searchDialect = null) => new SearchCommands(db, searchDialect);
20+
public static SearchCommands FT(this IDatabase db, int? searchDialect = 2) => new SearchCommands(db, searchDialect);
2121

2222
public static JsonCommands JSON(this IDatabase db) => new JsonCommands(db);
2323

src/NRedisStack/NRedisStack.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010
<Owners>Redis OSS</Owners>
1111
<Description>.Net Client for Redis Stack</Description>
1212
<PackageReadmeFile>README.md</PackageReadmeFile>
13-
<Version>0.12.0</Version>
14-
<ReleaseVersion>0.12.0</ReleaseVersion>
15-
<PackageVersion>0.12.0</PackageVersion>
13+
<Version>0.13.1</Version>
14+
<ReleaseVersion>0.13.1</ReleaseVersion>
15+
<PackageVersion>0.13.1</PackageVersion>
1616
</PropertyGroup>
1717

1818
<ItemGroup>
1919
<PackageReference Include="NetTopologySuite" Version="2.5.0" />
2020
<PackageReference Include="System.Text.Json" Version="7.0.2" Condition="'$(TargetFramework)' == 'netstandard2.0'" />
21-
<PackageReference Include="StackExchange.Redis" Version="2.7.33" />
21+
<PackageReference Include="StackExchange.Redis" Version="2.8.16" />
2222
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
2323
</ItemGroup>
2424

src/NRedisStack/Search/AggregationRequest.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using NRedisStack.Search.Literals;
33

44
namespace NRedisStack.Search;
5-
public class AggregationRequest
5+
public class AggregationRequest : IDialectAwareParam
66
{
77
private List<object> args = new List<object>(); // Check if Readonly
88
private bool isWithCursor = false;
@@ -184,4 +184,10 @@ public bool IsWithCursor()
184184
{
185185
return isWithCursor;
186186
}
187+
188+
int? IDialectAwareParam.Dialect
189+
{
190+
get { return dialect; }
191+
set { dialect = value; }
192+
}
187193
}

src/NRedisStack/Search/AggregationResult.cs

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ namespace NRedisStack.Search;
66
public sealed class AggregationResult
77
{
88
public long TotalResults { get; }
9-
private readonly Dictionary<string, RedisValue>[] _results;
9+
private readonly Dictionary<string, object>[] _results;
10+
private Dictionary<string, RedisValue>[] _resultsAsRedisValues;
11+
1012
public long CursorId { get; }
1113

1214

@@ -18,18 +20,23 @@ internal AggregationResult(RedisResult result, long cursorId = -1)
1820
// // the first element is always the number of results
1921
// TotalResults = (long)arr[0];
2022

21-
_results = new Dictionary<string, RedisValue>[arr.Length - 1];
23+
_results = new Dictionary<string, object>[arr.Length - 1];
2224
for (int i = 1; i < arr.Length; i++)
2325
{
2426
var raw = (RedisResult[])arr[i]!;
25-
var cur = new Dictionary<string, RedisValue>();
27+
var cur = new Dictionary<string, object>();
2628
for (int j = 0; j < raw.Length;)
2729
{
2830
var key = (string)raw[j++]!;
2931
var val = raw[j++];
3032
if (val.Type == ResultType.MultiBulk)
31-
continue; // TODO: handle multi-bulk (maybe change to object?)
32-
cur.Add(key, (RedisValue)val);
33+
{
34+
cur.Add(key, ConvertMultiBulkToObject((RedisResult[])val!));
35+
}
36+
else
37+
{
38+
cur.Add(key, (RedisValue)val);
39+
}
3340
}
3441

3542
_results[i - 1] = cur;
@@ -52,17 +59,47 @@ private object ConvertMultiBulkToObject(IEnumerable<RedisResult> multiBulkArray)
5259
{
5360
return multiBulkArray.Select(item => item.Type == ResultType.MultiBulk
5461
? ConvertMultiBulkToObject((RedisResult[])item!)
55-
: item)
62+
: (RedisValue)item)
5663
.ToList();
5764
}
5865

59-
public IReadOnlyList<Dictionary<string, RedisValue>> GetResults() => _results;
66+
/// <summary>
67+
/// Gets the results as a read-only list of dictionaries with string keys and RedisValue values.
68+
/// </summary>
69+
/// <remarks>
70+
/// This method is deprecated and will be removed in future versions.
71+
/// Please use <see cref="GetRow"/> instead.
72+
/// </remarks>
73+
[Obsolete("This method is deprecated and will be removed in future versions. Please use 'GetRow' instead.")]
74+
public IReadOnlyList<Dictionary<string, RedisValue>> GetResults()
75+
{
76+
return getResultsAsRedisValues();
77+
}
6078

79+
/// <summary>
80+
/// Gets the aggregation result at the specified index.
81+
/// </summary>
82+
/// <param name="index">The zero-based index of the aggregation result to retrieve.</param>
83+
/// <returns>
84+
/// A dictionary containing the aggregation result as Redis values if the index is within bounds;
85+
/// otherwise, <c>null</c>.
86+
/// </returns>
87+
[Obsolete("This method is deprecated and will be removed in future versions. Please use 'GetRow' instead.")]
6188
public Dictionary<string, RedisValue>? this[int index]
62-
=> index >= _results.Length ? null : _results[index];
89+
=> index >= getResultsAsRedisValues().Length ? null : getResultsAsRedisValues()[index];
6390

6491
public Row GetRow(int index)
6592
{
6693
return index >= _results.Length ? default : new Row(_results[index]);
6794
}
95+
96+
private Dictionary<string, RedisValue>[] getResultsAsRedisValues()
97+
{
98+
if (_resultsAsRedisValues == null)
99+
_resultsAsRedisValues = _results.Select(dict => dict.ToDictionary(
100+
kvp => kvp.Key,
101+
kvp => kvp.Value is RedisValue value ? value : RedisValue.Null
102+
)).ToArray();
103+
return _resultsAsRedisValues;
104+
}
68105
}

src/NRedisStack/Search/DataTypes/InfoResult.cs

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
1-
using StackExchange.Redis;
1+
using System.Reflection.Emit;
2+
using StackExchange.Redis;
23

34
namespace NRedisStack.Search.DataTypes;
45

56
public class InfoResult
67
{
78
private readonly Dictionary<string, RedisResult> _all = new();
8-
private static readonly string[] booleanAttributes = { "SORTABLE", "UNF", "NOSTEM", "NOINDEX", "CASESENSITIVE", "WITHSUFFIXTRIE" };
9+
private Dictionary<string, RedisResult>[] _attributes;
10+
private Dictionary<string, RedisResult> _indexOption;
11+
private Dictionary<string, RedisResult> _gcStats;
12+
private Dictionary<string, RedisResult> _cursorStats;
13+
14+
private static readonly string[] booleanAttributes = { "SORTABLE", "UNF", "NOSTEM", "NOINDEX", "CASESENSITIVE", "WITHSUFFIXTRIE", "INDEXEMPTY", "INDEXMISSING" };
915
public string IndexName => GetString("index_name")!;
10-
public Dictionary<string, RedisResult> IndexOption => GetRedisResultDictionary("index_options")!;
11-
public Dictionary<string, RedisResult>[] Attributes => GetRedisResultDictionaryArray("attributes")!;
16+
public Dictionary<string, RedisResult> IndexOption => _indexOption = _indexOption ?? GetRedisResultDictionary("index_options")!;
17+
public Dictionary<string, RedisResult>[] Attributes => _attributes = _attributes ?? GetAttributesAsDictionaryArray()!;
1218
public long NumDocs => GetLong("num_docs");
1319
public string MaxDocId => GetString("max_doc_id")!;
1420
public long NumTerms => GetLong("num_terms");
@@ -48,9 +54,9 @@ public class InfoResult
4854
public long NumberOfUses => GetLong("number_of_uses");
4955

5056

51-
public Dictionary<string, RedisResult> GcStats => GetRedisResultDictionary("gc_stats")!;
57+
public Dictionary<string, RedisResult> GcStats => _gcStats = _gcStats ?? GetRedisResultDictionary("gc_stats")!;
5258

53-
public Dictionary<string, RedisResult> CursorStats => GetRedisResultDictionary("cursor_stats")!;
59+
public Dictionary<string, RedisResult> CursorStats => _cursorStats = _cursorStats ?? GetRedisResultDictionary("cursor_stats")!;
5460

5561
public InfoResult(RedisResult result)
5662
{
@@ -94,24 +100,29 @@ private double GetDouble(string key)
94100
return result;
95101
}
96102

97-
private Dictionary<string, RedisResult>[]? GetRedisResultDictionaryArray(string key)
103+
private Dictionary<string, RedisResult>[]? GetAttributesAsDictionaryArray()
98104
{
99-
if (!_all.TryGetValue(key, out var value)) return default;
105+
if (!_all.TryGetValue("attributes", out var value)) return default;
100106
var values = (RedisResult[])value!;
101107
var result = new Dictionary<string, RedisResult>[values.Length];
102108
for (int i = 0; i < values.Length; i++)
103109
{
104-
var fv = (RedisResult[])values[i]!;
105110
var dict = new Dictionary<string, RedisResult>();
106-
for (int j = 0; j < fv.Length; j += 2)
111+
112+
IEnumerable<RedisResult> enumerable = (RedisResult[])values[i]!;
113+
IEnumerator<RedisResult> results = enumerable.GetEnumerator();
114+
while (results.MoveNext())
107115
{
108-
if (booleanAttributes.Contains((string)fv[j]!))
116+
string attribute = (string)results.Current;
117+
// if its boolean attributes add itself to the dictionary and continue
118+
if (booleanAttributes.Contains(attribute))
109119
{
110-
dict.Add((string)fv[j]!, fv[j--]);
120+
dict.Add(attribute, results.Current);
111121
}
112122
else
113-
{
114-
dict.Add((string)fv[j]!, fv[j + 1]);
123+
{//if its not a boolean attribute, add the next item as value to the dictionary
124+
results.MoveNext(); ;
125+
dict.Add(attribute, results.Current);
115126
}
116127
}
117128
result[i] = dict;

src/NRedisStack/Search/Document.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ public static Document Load(string id, double score, byte[]? payload, RedisValue
3131
{
3232
Document ret = new Document(id, score, payload);
3333
if (fields == null) return ret;
34+
if (fields.Length == 1 && fields[0].IsNull)
35+
{
36+
return ret;
37+
}
3438
for (int i = 0; i < fields.Length; i += 2)
3539
{
3640
string fieldName = fields[i]!;

0 commit comments

Comments
 (0)