Skip to content

Commit 62dbedd

Browse files
shacharPashchayimslorello89
authored
Add Redis Search Commands (#32)
* Add Alias command * Start FT.CERATE Command * Start FTCreateParams class for FT.CERATE * Add FT.CERATE command * Fixing Schema and FieldName Classes * Work on Schema class * Add FT.SEARCH command * Add FT.ALTER command * Linking to the latest pre-release (#30) * Linking to the latest pre-release * spelling and a link * Updading the version to v0.2.1 (#31) * adding JSON commands (#29) * adding JSON commands * Change commands names * some fixes * adding missing commands, removing visibility modifiers in interface * async breakout Co-authored-by: shacharPash <s.pashchur@gmail.com> * Implement new TDIGEST commands and TDIGEST.CREATE compression (#33) * Update Tdigest Commands * Fix Rank Commands Tests * Test Commit * Add Async Commands & tests * Working on FT.INFO Command * Finish FT.INFO Command * Add AggregationRequest Class for FT.AGGREGATE Command * Add FT.AGGREGATE Command + Tests * Adding TODOs to commands that have not yet been implemented * Add FT.CONFIG GET/SET Commands + Tests * Add FT.CURSOR READ/DEL Commands * Add FT.DICT(ADD/DEL/DUMP) Commands * Add FT.DICT(ADD/DEL/DUMP) Async Commands + Tests * Add FT.DROPINDEX Sync/Async Commands + Tests * Fix Aggregate & Add more Commands * Add FT.TAGVALS Sync/Async Command + Tests * Add Sync/Async Tests for FT.ALIAS * Fixing Tdigest.Add Command and Tests Co-authored-by: Chayim <chayim@users.noreply.github.com> Co-authored-by: Steve Lorello <42971704+slorello89@users.noreply.github.com>
1 parent 3a4bb42 commit 62dbedd

26 files changed

+4735
-241
lines changed

src/NRedisStack/ResponseParser.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,33 @@ public static TimeSeriesInformation ToTimeSeriesInfo(this RedisResult result)
485485
lastTimestamp, retentionTime, chunkCount, chunkSize, labels, sourceKey, rules, duplicatePolicy, keySelfName, chunks);
486486
}
487487

488+
public static Dictionary<string, RedisValue> ToFtInfoAsDictionary(this RedisResult value)
489+
{
490+
var res = (RedisResult[])value;
491+
var info = new Dictionary<string, RedisValue>();
492+
for (int i = 0; i < res.Length; i += 2)
493+
{
494+
var val = res[i + 1];
495+
if (val.Type != ResultType.MultiBulk)
496+
{
497+
info.Add((string)res[i], (RedisValue)val);
498+
}
499+
}
500+
return info;
501+
}
502+
503+
public static Dictionary<string, string> ToConfigDictionary(this RedisResult value)
504+
{
505+
var res = (RedisResult[])value;
506+
var dict = new Dictionary<string, string>();
507+
foreach (var pair in res)
508+
{
509+
var arr = (RedisResult[])pair;
510+
dict.Add(arr[0].ToString(), arr[1].ToString());
511+
}
512+
return dict;
513+
}
514+
488515
public static IReadOnlyList<TimeSeriesChunck> ToTimeSeriesChunkArray(this RedisResult result)
489516
{
490517
RedisResult[] redisResults = (RedisResult[])result;
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
// using NRediSearch.Aggregation.Reducers;
5+
using StackExchange.Redis;
6+
7+
namespace NRedisStack.Search.Aggregation
8+
{
9+
public class AggregationRequest
10+
{
11+
private List<object> args = new List<object>(); // Check if Readonly
12+
private bool isWithCursor = false;
13+
14+
public AggregationRequest(string query)
15+
{
16+
args.Add(query);
17+
}
18+
19+
public AggregationRequest() : this("*") { }
20+
21+
// public AggregationRequest load(params string[] fields)
22+
// {
23+
// return load(FieldName.Convert(fields));
24+
// }
25+
26+
public AggregationRequest Load(params FieldName[] fields)
27+
{
28+
args.Add("LOAD");
29+
int loadCountIndex = args.Count();
30+
args.Add(null);
31+
int loadCount = 0;
32+
foreach (FieldName fn in fields)
33+
{
34+
loadCount += fn.AddCommandArguments(args);
35+
}
36+
args.Insert(loadCountIndex, loadCount.ToString());
37+
return this;
38+
}
39+
40+
public AggregationRequest LoadAll()
41+
{
42+
args.Add("LOAD");
43+
args.Add("*");
44+
return this;
45+
}
46+
47+
public AggregationRequest Limit(int offset, int count)
48+
{
49+
Limit limit = new Limit(offset, count);
50+
limit.SerializeRedisArgs(args);
51+
return this;
52+
}
53+
54+
public AggregationRequest Limit(int count)
55+
{
56+
return Limit(0, count);
57+
}
58+
59+
public AggregationRequest SortBy(params SortedField[] Fields)
60+
{
61+
args.Add("SORTBY");
62+
args.Add(Fields.Length * 2);
63+
foreach (SortedField field in Fields)
64+
{
65+
args.Add(field.FieldName);
66+
args.Add(field.Order);
67+
}
68+
69+
return this;
70+
}
71+
72+
public AggregationRequest SortBy(int max, params SortedField[] Fields)
73+
{
74+
SortBy(Fields);
75+
if (max > 0)
76+
{
77+
args.Add("MAX");
78+
args.Add(max);
79+
}
80+
return this;
81+
}
82+
83+
public AggregationRequest SortByAsc(string field)
84+
{
85+
return SortBy(SortedField.Asc(field));
86+
}
87+
88+
public AggregationRequest SortByDesc(string field)
89+
{
90+
return SortBy(SortedField.Desc(field));
91+
}
92+
93+
public AggregationRequest Apply(string projection, string alias)
94+
{
95+
args.Add("APPLY");
96+
args.Add(projection);
97+
args.Add("AS");
98+
args.Add(alias);
99+
return this;
100+
}
101+
102+
public AggregationRequest GroupBy(IList<string> fields, IList<Reducer> reducers)
103+
{
104+
// string[] fieldsArr = new string[fields.size()];
105+
Group g = new Group(fields);
106+
foreach (Reducer r in reducers)
107+
{
108+
g.Reduce(r);
109+
}
110+
GroupBy(g);
111+
return this;
112+
}
113+
114+
public AggregationRequest GroupBy(string field, params Reducer[] reducers)
115+
{
116+
return GroupBy(new string[] { field }, reducers);
117+
}
118+
119+
public AggregationRequest GroupBy(Group group)
120+
{
121+
args.Add("GROUPBY");
122+
group.SerializeRedisArgs(args);
123+
return this;
124+
}
125+
126+
public AggregationRequest Filter(string expression)
127+
{
128+
args.Add("FILTER");
129+
args.Add(expression);
130+
return this;
131+
}
132+
133+
public AggregationRequest Cursor(int count, long maxIdle)
134+
{
135+
isWithCursor = true;
136+
if (count > 0)
137+
{
138+
args.Add("WITHCURSOR");
139+
args.Add("COUNT");
140+
args.Add(count);
141+
if (maxIdle < long.MaxValue && maxIdle >= 0)
142+
{
143+
args.Add("MAXIDLE");
144+
args.Add(maxIdle);
145+
}
146+
}
147+
return this;
148+
}
149+
150+
public AggregationRequest Verbatim()
151+
{
152+
args.Add("VERBATIM");
153+
return this;
154+
}
155+
156+
public AggregationRequest Timeout(long timeout)
157+
{
158+
if (timeout >= 0)
159+
{
160+
args.Add("TIMEOUT");
161+
args.Add(timeout);
162+
}
163+
return this;
164+
}
165+
166+
public AggregationRequest Params(Dictionary<string, object> nameValue)
167+
{
168+
if (nameValue.Count >= 1)
169+
{
170+
args.Add("PARAMS");
171+
args.Add(nameValue.Count * 2);
172+
foreach (var entry in nameValue)
173+
{
174+
args.Add(entry.Key);
175+
args.Add(entry.Value);
176+
}
177+
}
178+
179+
return this;
180+
}
181+
182+
public AggregationRequest Dialect(int dialect)
183+
{
184+
args.Add("DIALECT");
185+
args.Add(dialect);
186+
return this;
187+
}
188+
189+
public List<object> GetArgs()
190+
{
191+
return args;
192+
}
193+
194+
public void SerializeRedisArgs(List<object> redisArgs)
195+
{
196+
foreach (var s in GetArgs())
197+
{
198+
redisArgs.Add(s);
199+
}
200+
}
201+
202+
// public string getArgsstring()
203+
// {
204+
// StringBuilder sj = new StringBuilder(" ");
205+
// foreach (var s in GetArgs())
206+
// {
207+
// sj.Add(s.ToString());
208+
// }
209+
// return sj.tostring();
210+
// }
211+
212+
public bool IsWithCursor()
213+
{
214+
return isWithCursor;
215+
}
216+
}
217+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using System.Collections.Generic;
2+
using StackExchange.Redis;
3+
4+
namespace NRedisStack.Search.Aggregation
5+
{
6+
public sealed class AggregationResult
7+
{
8+
public long TotalResults { get; }
9+
private readonly Dictionary<string, RedisValue>[] _results;
10+
public long CursorId { get; }
11+
12+
13+
internal AggregationResult(RedisResult result, long cursorId = -1)
14+
{
15+
var arr = (RedisResult[])result;
16+
17+
// the first element is always the number of results
18+
TotalResults = (long)arr[0];
19+
20+
_results = new Dictionary<string, RedisValue>[arr.Length - 1];
21+
for (int i = 1; i < arr.Length; i++)
22+
{
23+
var raw = (RedisResult[])arr[i];
24+
var cur = new Dictionary<string, RedisValue>();
25+
for (int j = 0; j < raw.Length;)
26+
{
27+
var key = (string)raw[j++];
28+
var val = raw[j++];
29+
if (val.Type != ResultType.MultiBulk)
30+
cur.Add(key, (RedisValue)val);
31+
}
32+
_results[i - 1] = cur;
33+
}
34+
35+
CursorId = cursorId;
36+
}
37+
public IReadOnlyList<Dictionary<string, RedisValue>> GetResults() => _results;
38+
39+
public Dictionary<string, RedisValue> this[int index]
40+
=> index >= _results.Length ? null : _results[index];
41+
42+
public Row GetRow(int index)
43+
{
44+
if (index >= _results.Length) return default;
45+
return new Row(_results[index]);
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)