Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/nuget/xunit-2.9.0
Browse files Browse the repository at this point in the history
  • Loading branch information
atakavci authored Dec 31, 2024
2 parents 4a18296 + dfc75d2 commit 33543f5
Show file tree
Hide file tree
Showing 37 changed files with 3,387 additions and 367 deletions.
5 changes: 5 additions & 0 deletions src/NRedisStack/Gears/GearsCommandBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
namespace NRedisStack
{

[Obsolete]
public static class GearsCommandBuilder
{
[Obsolete]
public static SerializedCommand TFunctionLoad(string libraryCode, bool replace = false, string? config = null)
{
var args = new List<object>() { GearsArgs.LOAD };
Expand All @@ -23,11 +25,13 @@ public static SerializedCommand TFunctionLoad(string libraryCode, bool replace =
return new SerializedCommand(RG.TFUNCTION, args);
}

[Obsolete]
public static SerializedCommand TFunctionDelete(string libraryName)
{
return new SerializedCommand(RG.TFUNCTION, GearsArgs.DELETE, libraryName);
}

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

[Obsolete]
public static SerializedCommand TFCall(string libraryName, string functionName, string[]? keys = null, string[]? args = null, bool async = false)
{
string command = async ? RG.TFCALLASYNC : RG.TFCALL;
Expand Down
7 changes: 6 additions & 1 deletion src/NRedisStack/Gears/GearsCommands.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using StackExchange.Redis;
namespace NRedisStack
{

[Obsolete]
public static class GearsCommands //: GearsCommandsAsync, IGearsCommands
{

Expand All @@ -17,6 +17,7 @@ public static class GearsCommands //: GearsCommandsAsync, IGearsCommands
/// <param name="replace">an optional argument, instructs RedisGears to replace the function if its already exists.</param>
/// <returns><see langword="true"/> if everything was done correctly, Error otherwise.</returns>
/// <remarks><seealso href="https://redis.io/commands/tfunction-load/"/></remarks> //TODO: check this link when it's available
[Obsolete]
public static bool TFunctionLoad(this IDatabase db, string libraryCode, bool replace = false, string? config = null)
{
return db.Execute(GearsCommandBuilder.TFunctionLoad(libraryCode, replace, config)).OKtoBoolean();
Expand All @@ -28,6 +29,7 @@ public static bool TFunctionLoad(this IDatabase db, string libraryCode, bool rep
/// <param name="libraryName">the name of the library to delete.</param>
/// <returns><see langword="true"/> if the library was deleted successfully, Error otherwise.</returns>
/// <remarks><seealso href="https://redis.io/commands/tfunction-delete/"/></remarks> //TODO: check this link when it's available
[Obsolete]
public static bool TFunctionDelete(this IDatabase db, string libraryName)
{
return db.Execute(GearsCommandBuilder.TFunctionDelete(libraryName)).OKtoBoolean();
Expand All @@ -42,6 +44,7 @@ public static bool TFunctionDelete(this IDatabase db, string libraryName)
/// multiple times to show multiple libraries in a single command)</param>
/// <returns>Information about the requested libraries.</returns>
/// <remarks><seealso href="https://redis.io/commands/tfunction-list/"/></remarks> //TODO: check this link when it's available
[Obsolete]
public static Dictionary<string, RedisResult>[] TFunctionList(this IDatabase db, bool withCode = false, int verbose = 0, string? libraryName = null)
{
return db.Execute(GearsCommandBuilder.TFunctionList(withCode, verbose, libraryName)).ToDictionarys();
Expand All @@ -56,6 +59,7 @@ public static Dictionary<string, RedisResult>[] TFunctionList(this IDatabase db,
/// <param name="args">Additional argument to pass to the function.</param>
/// <returns>The return value from the sync &amp; async function on error in case of failure.</returns>
/// <remarks><seealso href="https://redis.io/commands/tfcall"/></remarks>
[Obsolete]
public static RedisResult TFCall_(this IDatabase db, string libraryName, string functionName, string[]? keys = null, string[]? args = null)
{
return db.Execute(GearsCommandBuilder.TFCall(libraryName, functionName, keys, args, async: false));
Expand All @@ -70,6 +74,7 @@ public static RedisResult TFCall_(this IDatabase db, string libraryName, string
/// <param name="args">Additional argument to pass to the function.</param>
/// <returns>The return value from the sync &amp; async function on error in case of failure.</returns>
/// <remarks><seealso href="https://redis.io/commands/tfcallasync"/></remarks>
[Obsolete]
public static RedisResult TFCallAsync_(this IDatabase db, string libraryName, string functionName, string[]? keys = null, string[]? args = null)
{
return db.Execute(GearsCommandBuilder.TFCall(libraryName, functionName, keys, args, async: true));
Expand Down
5 changes: 5 additions & 0 deletions src/NRedisStack/Gears/GearsCommandsAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public static class GearsCommandsAsync //: IGearsCommandsAsync
/// <param name="replace">an optional argument, instructs RedisGears to replace the function if its already exists.</param>
/// <returns><see langword="true"/> if everything was done correctly, Error otherwise.</returns>
/// <remarks><seealso href="https://redis.io/commands/"/></remarks> //TODO: add link to the command when it's available
[Obsolete]
public static async Task<bool> TFunctionLoadAsync(this IDatabase db, string libraryCode, string? config = null, bool replace = false)
{
return (await db.ExecuteAsync(GearsCommandBuilder.TFunctionLoad(libraryCode, replace, config))).OKtoBoolean();
Expand All @@ -27,6 +28,7 @@ public static async Task<bool> TFunctionLoadAsync(this IDatabase db, string libr
/// <param name="libraryName">the name of the library to delete.</param>
/// <returns><see langword="true"/> if the library was deleted successfully, Error otherwise.</returns>
/// <remarks><seealso href="https://redis.io/commands/"/></remarks> //TODO: add link to the command when it's available
[Obsolete]
public static async Task<bool> TFunctionDeleteAsync(this IDatabase db, string libraryName)
{
return (await db.ExecuteAsync(GearsCommandBuilder.TFunctionDelete(libraryName))).OKtoBoolean();
Expand All @@ -41,6 +43,7 @@ public static async Task<bool> TFunctionDeleteAsync(this IDatabase db, string li
/// multiple times to show multiple libraries in a single command)</param>
/// <returns>Information about the requested libraries.</returns>
/// <remarks><seealso href="https://redis.io/commands/"/></remarks> //TODO: add link to the command when it's available
[Obsolete]
public static async Task<Dictionary<string, RedisResult>[]> TFunctionListAsync(this IDatabase db, bool withCode = false, int verbose = 0, string? libraryName = null)
{
return (await db.ExecuteAsync(GearsCommandBuilder.TFunctionList(withCode, verbose, libraryName))).ToDictionarys();
Expand All @@ -55,6 +58,7 @@ public static async Task<Dictionary<string, RedisResult>[]> TFunctionListAsync(t
/// <param name="args">Additional argument to pass to the function.</param>
/// <returns>The return value from the sync &amp; async function on error in case of failure.</returns>
/// <remarks><seealso href="https://redis.io/commands/tfcall"/></remarks>
[Obsolete]
public async static Task<RedisResult> TFCall_Async(this IDatabase db, string libraryName, string functionName, string[]? keys = null, string[]? args = null)
{
return await db.ExecuteAsync(GearsCommandBuilder.TFCall(libraryName, functionName, keys, args, async: false));
Expand All @@ -69,6 +73,7 @@ public async static Task<RedisResult> TFCall_Async(this IDatabase db, string lib
/// <param name="args">Additional argument to pass to the function.</param>
/// <returns>The return value from the sync &amp; async function on error in case of failure.</returns>
/// <remarks><seealso href="https://redis.io/commands/tfcallasync"/></remarks>
[Obsolete]
public async static Task<RedisResult> TFCallAsync_Async(this IDatabase db, string libraryName, string functionName, string[]? keys = null, string[]? args = null)
{
return await db.ExecuteAsync(GearsCommandBuilder.TFCall(libraryName, functionName, keys, args, async: true));
Expand Down
2 changes: 1 addition & 1 deletion src/NRedisStack/ModulePrefixes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class ModulePrefixes

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

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

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

Expand Down
8 changes: 4 additions & 4 deletions src/NRedisStack/NRedisStack.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
<Owners>Redis OSS</Owners>
<Description>.Net Client for Redis Stack</Description>
<PackageReadmeFile>README.md</PackageReadmeFile>
<Version>0.12.0</Version>
<ReleaseVersion>0.12.0</ReleaseVersion>
<PackageVersion>0.12.0</PackageVersion>
<Version>0.13.1</Version>
<ReleaseVersion>0.13.1</ReleaseVersion>
<PackageVersion>0.13.1</PackageVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NetTopologySuite" Version="2.5.0" />
<PackageReference Include="System.Text.Json" Version="7.0.2" Condition="'$(TargetFramework)' == 'netstandard2.0'" />
<PackageReference Include="StackExchange.Redis" Version="2.7.33" />
<PackageReference Include="StackExchange.Redis" Version="2.8.16" />
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
</ItemGroup>

Expand Down
8 changes: 7 additions & 1 deletion src/NRedisStack/Search/AggregationRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using NRedisStack.Search.Literals;

namespace NRedisStack.Search;
public class AggregationRequest
public class AggregationRequest : IDialectAwareParam
{
private List<object> args = new List<object>(); // Check if Readonly
private bool isWithCursor = false;
Expand Down Expand Up @@ -184,4 +184,10 @@ public bool IsWithCursor()
{
return isWithCursor;
}

int? IDialectAwareParam.Dialect
{
get { return dialect; }
set { dialect = value; }
}
}
53 changes: 45 additions & 8 deletions src/NRedisStack/Search/AggregationResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ namespace NRedisStack.Search;
public sealed class AggregationResult
{
public long TotalResults { get; }
private readonly Dictionary<string, RedisValue>[] _results;
private readonly Dictionary<string, object>[] _results;
private Dictionary<string, RedisValue>[] _resultsAsRedisValues;

public long CursorId { get; }


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

_results = new Dictionary<string, RedisValue>[arr.Length - 1];
_results = new Dictionary<string, object>[arr.Length - 1];
for (int i = 1; i < arr.Length; i++)
{
var raw = (RedisResult[])arr[i]!;
var cur = new Dictionary<string, RedisValue>();
var cur = new Dictionary<string, object>();
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);
{
cur.Add(key, ConvertMultiBulkToObject((RedisResult[])val!));
}
else
{
cur.Add(key, (RedisValue)val);
}
}

_results[i - 1] = cur;
Expand All @@ -52,17 +59,47 @@ private object ConvertMultiBulkToObject(IEnumerable<RedisResult> multiBulkArray)
{
return multiBulkArray.Select(item => item.Type == ResultType.MultiBulk
? ConvertMultiBulkToObject((RedisResult[])item!)
: item)
: (RedisValue)item)
.ToList();
}

public IReadOnlyList<Dictionary<string, RedisValue>> GetResults() => _results;
/// <summary>
/// Gets the results as a read-only list of dictionaries with string keys and RedisValue values.
/// </summary>
/// <remarks>
/// This method is deprecated and will be removed in future versions.
/// Please use <see cref="GetRow"/> instead.
/// </remarks>
[Obsolete("This method is deprecated and will be removed in future versions. Please use 'GetRow' instead.")]
public IReadOnlyList<Dictionary<string, RedisValue>> GetResults()
{
return getResultsAsRedisValues();
}

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

public Row GetRow(int index)
{
return index >= _results.Length ? default : new Row(_results[index]);
}

private Dictionary<string, RedisValue>[] getResultsAsRedisValues()
{
if (_resultsAsRedisValues == null)
_resultsAsRedisValues = _results.Select(dict => dict.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value is RedisValue value ? value : RedisValue.Null
)).ToArray();
return _resultsAsRedisValues;
}
}
39 changes: 25 additions & 14 deletions src/NRedisStack/Search/DataTypes/InfoResult.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
using StackExchange.Redis;
using System.Reflection.Emit;
using StackExchange.Redis;

namespace NRedisStack.Search.DataTypes;

public class InfoResult
{
private readonly Dictionary<string, RedisResult> _all = new();
private static readonly string[] booleanAttributes = { "SORTABLE", "UNF", "NOSTEM", "NOINDEX", "CASESENSITIVE", "WITHSUFFIXTRIE" };
private Dictionary<string, RedisResult>[] _attributes;
private Dictionary<string, RedisResult> _indexOption;
private Dictionary<string, RedisResult> _gcStats;
private Dictionary<string, RedisResult> _cursorStats;

private static readonly string[] booleanAttributes = { "SORTABLE", "UNF", "NOSTEM", "NOINDEX", "CASESENSITIVE", "WITHSUFFIXTRIE", "INDEXEMPTY", "INDEXMISSING" };
public string IndexName => GetString("index_name")!;
public Dictionary<string, RedisResult> IndexOption => GetRedisResultDictionary("index_options")!;
public Dictionary<string, RedisResult>[] Attributes => GetRedisResultDictionaryArray("attributes")!;
public Dictionary<string, RedisResult> IndexOption => _indexOption = _indexOption ?? GetRedisResultDictionary("index_options")!;
public Dictionary<string, RedisResult>[] Attributes => _attributes = _attributes ?? GetAttributesAsDictionaryArray()!;
public long NumDocs => GetLong("num_docs");
public string MaxDocId => GetString("max_doc_id")!;
public long NumTerms => GetLong("num_terms");
Expand Down Expand Up @@ -48,9 +54,9 @@ public class InfoResult
public long NumberOfUses => GetLong("number_of_uses");


public Dictionary<string, RedisResult> GcStats => GetRedisResultDictionary("gc_stats")!;
public Dictionary<string, RedisResult> GcStats => _gcStats = _gcStats ?? GetRedisResultDictionary("gc_stats")!;

public Dictionary<string, RedisResult> CursorStats => GetRedisResultDictionary("cursor_stats")!;
public Dictionary<string, RedisResult> CursorStats => _cursorStats = _cursorStats ?? GetRedisResultDictionary("cursor_stats")!;

public InfoResult(RedisResult result)
{
Expand Down Expand Up @@ -94,24 +100,29 @@ private double GetDouble(string key)
return result;
}

private Dictionary<string, RedisResult>[]? GetRedisResultDictionaryArray(string key)
private Dictionary<string, RedisResult>[]? GetAttributesAsDictionaryArray()
{
if (!_all.TryGetValue(key, out var value)) return default;
if (!_all.TryGetValue("attributes", out var value)) return default;
var values = (RedisResult[])value!;
var result = new Dictionary<string, RedisResult>[values.Length];
for (int i = 0; i < values.Length; i++)
{
var fv = (RedisResult[])values[i]!;
var dict = new Dictionary<string, RedisResult>();
for (int j = 0; j < fv.Length; j += 2)

IEnumerable<RedisResult> enumerable = (RedisResult[])values[i]!;
IEnumerator<RedisResult> results = enumerable.GetEnumerator();
while (results.MoveNext())
{
if (booleanAttributes.Contains((string)fv[j]!))
string attribute = (string)results.Current;
// if its boolean attributes add itself to the dictionary and continue
if (booleanAttributes.Contains(attribute))
{
dict.Add((string)fv[j]!, fv[j--]);
dict.Add(attribute, results.Current);
}
else
{
dict.Add((string)fv[j]!, fv[j + 1]);
{//if its not a boolean attribute, add the next item as value to the dictionary
results.MoveNext(); ;
dict.Add(attribute, results.Current);
}
}
result[i] = dict;
Expand Down
4 changes: 4 additions & 0 deletions src/NRedisStack/Search/Document.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public static Document Load(string id, double score, byte[]? payload, RedisValue
{
Document ret = new Document(id, score, payload);
if (fields == null) return ret;
if (fields.Length == 1 && fields[0].IsNull)
{
return ret;
}
for (int i = 0; i < fields.Length; i += 2)
{
string fieldName = fields[i]!;
Expand Down
Loading

0 comments on commit 33543f5

Please sign in to comment.