Skip to content

Add Redis Search Commands #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Oct 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1ba2ff3
Add Alias command
shacharPash Sep 6, 2022
6edac52
Start FT.CERATE Command
shacharPash Sep 7, 2022
8d01781
Start FTCreateParams class for FT.CERATE
shacharPash Sep 8, 2022
45975c2
Add FT.CERATE command
shacharPash Sep 12, 2022
03d6f1f
Fixing Schema and FieldName Classes
shacharPash Sep 13, 2022
6bf4e42
Work on Schema class
shacharPash Sep 18, 2022
90de6ae
Add FT.SEARCH command
shacharPash Sep 22, 2022
845196b
Add FT.ALTER command
shacharPash Sep 22, 2022
5e55a8c
Linking to the latest pre-release (#30)
chayim Sep 6, 2022
083adb5
Updading the version to v0.2.1 (#31)
shacharPash Sep 6, 2022
71f264d
adding JSON commands (#29)
slorello89 Sep 7, 2022
2648aad
Implement new TDIGEST commands and TDIGEST.CREATE compression (#33)
shacharPash Oct 2, 2022
a8846bc
Test Commit
shacharPash Oct 2, 2022
c344d58
Merge branch 'master' into SearchCommands
shacharPash Oct 2, 2022
b7bd388
Add Async Commands & tests
shacharPash Oct 2, 2022
f77ca6f
Working on FT.INFO Command
shacharPash Oct 2, 2022
6475a3d
Finish FT.INFO Command
shacharPash Oct 3, 2022
66491b1
Add AggregationRequest Class for FT.AGGREGATE Command
shacharPash Oct 3, 2022
0368e23
Add FT.AGGREGATE Command + Tests
shacharPash Oct 9, 2022
cba57f0
Adding TODOs to commands that have not yet been implemented
shacharPash Oct 9, 2022
fc5c9a3
Add FT.CONFIG GET/SET Commands + Tests
shacharPash Oct 9, 2022
dac3fa4
Add FT.CURSOR READ/DEL Commands
shacharPash Oct 11, 2022
49ba5bb
Add FT.DICT(ADD/DEL/DUMP) Commands
shacharPash Oct 11, 2022
45309c3
Add FT.DICT(ADD/DEL/DUMP) Async Commands + Tests
shacharPash Oct 11, 2022
eeb870f
Add FT.DROPINDEX Sync/Async Commands + Tests
shacharPash Oct 11, 2022
d8da602
Fix Aggregate & Add more Commands
shacharPash Oct 11, 2022
30330b4
Add FT.TAGVALS Sync/Async Command + Tests
shacharPash Oct 12, 2022
2360158
Add Sync/Async Tests for FT.ALIAS
shacharPash Oct 12, 2022
c3ab0ef
Fixing Tdigest.Add Command and Tests
shacharPash Oct 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/NRedisStack/ResponseParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,33 @@ public static TimeSeriesInformation ToTimeSeriesInfo(this RedisResult result)
lastTimestamp, retentionTime, chunkCount, chunkSize, labels, sourceKey, rules, duplicatePolicy, keySelfName, chunks);
}

public static Dictionary<string, RedisValue> ToFtInfoAsDictionary(this RedisResult value)
{
var res = (RedisResult[])value;
var info = new Dictionary<string, RedisValue>();
for (int i = 0; i < res.Length; i += 2)
{
var val = res[i + 1];
if (val.Type != ResultType.MultiBulk)
{
info.Add((string)res[i], (RedisValue)val);
}
}
return info;
}

public static Dictionary<string, string> ToConfigDictionary(this RedisResult value)
{
var res = (RedisResult[])value;
var dict = new Dictionary<string, string>();
foreach (var pair in res)
{
var arr = (RedisResult[])pair;
dict.Add(arr[0].ToString(), arr[1].ToString());
}
return dict;
}

public static IReadOnlyList<TimeSeriesChunck> ToTimeSeriesChunkArray(this RedisResult result)
{
RedisResult[] redisResults = (RedisResult[])result;
Expand Down
217 changes: 217 additions & 0 deletions src/NRedisStack/Search/AggregationRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
using System;
using System.Collections.Generic;
using System.Text;
// using NRediSearch.Aggregation.Reducers;
using StackExchange.Redis;

namespace NRedisStack.Search.Aggregation
{
public class AggregationRequest
{
private List<object> args = new List<object>(); // Check if Readonly
private bool isWithCursor = false;

public AggregationRequest(string query)
{
args.Add(query);
}

public AggregationRequest() : this("*") { }

// public AggregationRequest load(params string[] fields)
// {
// return load(FieldName.Convert(fields));
// }

public AggregationRequest Load(params FieldName[] fields)
{
args.Add("LOAD");
int loadCountIndex = args.Count();
args.Add(null);
int loadCount = 0;
foreach (FieldName fn in fields)
{
loadCount += fn.AddCommandArguments(args);
}
args.Insert(loadCountIndex, loadCount.ToString());
return this;
}

public AggregationRequest LoadAll()
{
args.Add("LOAD");
args.Add("*");
return this;
}

public AggregationRequest Limit(int offset, int count)
{
Limit limit = new Limit(offset, count);
limit.SerializeRedisArgs(args);
return this;
}

public AggregationRequest Limit(int count)
{
return Limit(0, count);
}

public AggregationRequest SortBy(params SortedField[] Fields)
{
args.Add("SORTBY");
args.Add(Fields.Length * 2);
foreach (SortedField field in Fields)
{
args.Add(field.FieldName);
args.Add(field.Order);
}

return this;
}

public AggregationRequest SortBy(int max, params SortedField[] Fields)
{
SortBy(Fields);
if (max > 0)
{
args.Add("MAX");
args.Add(max);
}
return this;
}

public AggregationRequest SortByAsc(string field)
{
return SortBy(SortedField.Asc(field));
}

public AggregationRequest SortByDesc(string field)
{
return SortBy(SortedField.Desc(field));
}

public AggregationRequest Apply(string projection, string alias)
{
args.Add("APPLY");
args.Add(projection);
args.Add("AS");
args.Add(alias);
return this;
}

public AggregationRequest GroupBy(IList<string> fields, IList<Reducer> reducers)
{
// string[] fieldsArr = new string[fields.size()];
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 string[] { field }, reducers);
}

public AggregationRequest GroupBy(Group group)
{
args.Add("GROUPBY");
group.SerializeRedisArgs(args);
return this;
}

public AggregationRequest Filter(string expression)
{
args.Add("FILTER");
args.Add(expression);
return this;
}

public AggregationRequest Cursor(int count, long maxIdle)
{
isWithCursor = true;
if (count > 0)
{
args.Add("WITHCURSOR");
args.Add("COUNT");
args.Add(count);
if (maxIdle < long.MaxValue && maxIdle >= 0)
{
args.Add("MAXIDLE");
args.Add(maxIdle);
}
}
return this;
}

public AggregationRequest Verbatim()
{
args.Add("VERBATIM");
return this;
}

public AggregationRequest Timeout(long timeout)
{
if (timeout >= 0)
{
args.Add("TIMEOUT");
args.Add(timeout);
}
return this;
}

public AggregationRequest Params(Dictionary<string, object> nameValue)
{
if (nameValue.Count >= 1)
{
args.Add("PARAMS");
args.Add(nameValue.Count * 2);
foreach (var entry in nameValue)
{
args.Add(entry.Key);
args.Add(entry.Value);
}
}

return this;
}

public AggregationRequest Dialect(int dialect)
{
args.Add("DIALECT");
args.Add(dialect);
return this;
}

public List<object> GetArgs()
{
return args;
}

public void SerializeRedisArgs(List<object> redisArgs)
{
foreach (var s in GetArgs())
{
redisArgs.Add(s);
}
}

// public string getArgsstring()
// {
// StringBuilder sj = new StringBuilder(" ");
// foreach (var s in GetArgs())
// {
// sj.Add(s.ToString());
// }
// return sj.tostring();
// }

public bool IsWithCursor()
{
return isWithCursor;
}
}
}
48 changes: 48 additions & 0 deletions src/NRedisStack/Search/AggregationResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Collections.Generic;
using StackExchange.Redis;

namespace NRedisStack.Search.Aggregation
{
public sealed class AggregationResult
{
public long TotalResults { get; }
private readonly Dictionary<string, RedisValue>[] _results;
public long CursorId { get; }


internal AggregationResult(RedisResult result, long cursorId = -1)
{
var arr = (RedisResult[])result;

// the first element is always the number of results
TotalResults = (long)arr[0];

_results = new Dictionary<string, RedisValue>[arr.Length - 1];
for (int i = 1; i < arr.Length; i++)
{
var raw = (RedisResult[])arr[i];
var cur = new Dictionary<string, RedisValue>();
for (int j = 0; j < raw.Length;)
{
var key = (string)raw[j++];
var val = raw[j++];
if (val.Type != ResultType.MultiBulk)
cur.Add(key, (RedisValue)val);
}
_results[i - 1] = cur;
}

CursorId = cursorId;
}
public IReadOnlyList<Dictionary<string, RedisValue>> GetResults() => _results;

public Dictionary<string, RedisValue> this[int index]
=> index >= _results.Length ? null : _results[index];

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