Skip to content

Commit 7f43b7b

Browse files
authored
allowing setting max in sortby (#503)
1 parent 3ab039b commit 7f43b7b

File tree

6 files changed

+92
-4
lines changed

6 files changed

+92
-4
lines changed

src/Redis.OM/Aggregation/AggregationPredicates/AggregateSortBy.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public AggregateSortBy(string property, SortDirection direction, int? max = null
4040
/// <summary>
4141
/// gets the number of arguments of this predicate.
4242
/// </summary>
43-
internal int NumArgs => Max.HasValue ? 4 : 2;
43+
internal static int NumArgs => 2;
4444

4545
/// <inheritdoc/>
4646
public IEnumerable<string> Serialize()

src/Redis.OM/Aggregation/AggregationPredicates/MultiSort.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Generic;
22
using System.Linq;
3+
using Redis.OM.Searching;
34

45
namespace Redis.OM.Aggregation.AggregationPredicates
56
{
@@ -22,11 +23,19 @@ public void InsertPredicate(AggregateSortBy sb)
2223
/// <inheritdoc />
2324
public IEnumerable<string> Serialize()
2425
{
25-
var numArgs = _subPredicates.Sum(x => x.NumArgs);
26-
List<string> args = new List<string>(numArgs) { "SORTBY", numArgs.ToString() };
26+
var numArgs = _subPredicates.Sum(x => AggregateSortBy.NumArgs);
27+
var max = _subPredicates.FirstOrDefault(x => x.Max.HasValue)?.Max;
28+
var args = new List<string>(numArgs) { "SORTBY", numArgs.ToString() };
2729
foreach (var predicate in _subPredicates)
2830
{
29-
args.AddRange(predicate.Serialize().Skip(2));
31+
args.Add($"@{predicate.Property}");
32+
args.Add(predicate.Direction == SortDirection.Ascending ? "ASC" : "DESC");
33+
}
34+
35+
if (max.HasValue)
36+
{
37+
args.Add("MAX");
38+
args.Add(max.ToString());
3039
}
3140

3241
return args;

src/Redis.OM/Common/ExpressionTranslator.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,11 @@ private static AggregateSortBy TranslateSortBy(MethodCallExpression expression,
584584
{
585585
var member = GetFieldName(expression.Arguments[1]);
586586
var sb = new AggregateSortBy(member, dir);
587+
if (expression.Arguments.Count == 3)
588+
{
589+
sb.Max = (int)((ConstantExpression)expression.Arguments[2]).Value;
590+
}
591+
587592
return sb;
588593
}
589594

src/Redis.OM/SearchExtensions.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,42 @@ public static RedisAggregationSet<T> OrderByDescending<T, TField>(this RedisAggr
929929
return new RedisAggregationSet<T>(source, exp);
930930
}
931931

932+
/// <summary>
933+
/// Order the results by the provided field.
934+
/// </summary>
935+
/// <param name="source">The source.</param>
936+
/// <param name="expression">The expression to order by.</param>
937+
/// <param name="max">the number of documents to sort.</param>
938+
/// <typeparam name="T">The Indexed type.</typeparam>
939+
/// <typeparam name="TField">The field type.</typeparam>
940+
/// <returns>A set with the expression applied.</returns>
941+
public static RedisAggregationSet<T> OrderBy<T, TField>(this RedisAggregationSet<T> source, Expression<Func<AggregationResult<T>, TField>> expression, int max)
942+
{
943+
var exp = Expression.Call(
944+
null,
945+
GetMethodInfo(OrderBy, source, expression, max),
946+
new[] { source.Expression, Expression.Quote(expression), Expression.Constant(max) });
947+
return new RedisAggregationSet<T>(source, exp);
948+
}
949+
950+
/// <summary>
951+
/// Order the results by the provided field.
952+
/// </summary>
953+
/// <param name="source">The source.</param>
954+
/// <param name="expression">The expression to order by.</param>
955+
/// <param name="max">The number of documents to sort.</param>
956+
/// <typeparam name="T">The Indexed type.</typeparam>
957+
/// <typeparam name="TField">The field type.</typeparam>
958+
/// <returns>A set with the expression applied.</returns>
959+
public static RedisAggregationSet<T> OrderByDescending<T, TField>(this RedisAggregationSet<T> source, Expression<Func<AggregationResult<T>, TField>> expression, int max)
960+
{
961+
var exp = Expression.Call(
962+
null,
963+
GetMethodInfo(OrderByDescending, source, expression, max),
964+
new[] { source.Expression, Expression.Quote(expression), Expression.Constant(max) });
965+
return new RedisAggregationSet<T>(source, exp);
966+
}
967+
932968
/// <summary>
933969
/// Closes out the group and yields a regular RedisAggregationSet. Use this to flush reductions further
934970
/// down the pipeline.

test/Redis.OM.Unit.Tests/RediSearchTests/AggregationFunctionalTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ public void GetPeopleByAgeOrNameAndDepartment()
147147
[Fact]
148148
public void GetDepartmentBySales()
149149
{
150+
Setup();
150151
var collection = new RedisAggregationSet<Person>(_connection);
151152
var departments = collection
152153
.Apply(x => x.RecordShell.Sales * x.RecordShell.SalesAdjustment, "AdjustedSales")
@@ -159,6 +160,23 @@ public void GetDepartmentBySales()
159160
Assert.Equal(3, (int)departments[2]["DepartmentNumber"]);
160161
Assert.Equal(2, (int)departments[3]["DepartmentNumber"]);
161162
}
163+
164+
[Fact]
165+
public void GetDepartmentBySalesWithMax()
166+
{
167+
Setup();
168+
var collection = new RedisAggregationSet<Person>(_connection);
169+
var departments = collection
170+
.Apply(x => x.RecordShell.Sales * x.RecordShell.SalesAdjustment, "AdjustedSales")
171+
.GroupBy(x => x.RecordShell.DepartmentNumber)
172+
.Sum(x => x["AdjustedSales"])
173+
.OrderByDescending(x => x["AdjustedSales_SUM"], int.MaxValue)
174+
.ToArray();
175+
Assert.Equal(1, (int)departments[0]["DepartmentNumber"]);
176+
Assert.Equal(4, (int)departments[1]["DepartmentNumber"]);
177+
Assert.Equal(3, (int)departments[2]["DepartmentNumber"]);
178+
Assert.Equal(2, (int)departments[3]["DepartmentNumber"]);
179+
}
162180

163181
[Fact]
164182
public void GetHandicappedSales()

test/Redis.OM.Unit.Tests/RediSearchTests/AggregationSetTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,26 @@ public void TestMultipleOrderBys()
402402
_ = collection.OrderBy(x => x.RecordShell.Name).OrderByDescending(x => x.RecordShell.Age).ToList();
403403
_substitute.Received().Execute("FT.AGGREGATE","person-idx", "*", "SORTBY", "4", "@Name", "ASC", "@Age", "DESC", "WITHCURSOR", "COUNT", "10000");
404404
}
405+
406+
[Fact]
407+
public void TestMultipleOrderByWithMax()
408+
{
409+
var collection = new RedisAggregationSet<Person>(_substitute, true, chunkSize: 10000);
410+
_substitute.Execute("FT.AGGREGATE", Arg.Any<object[]>()).Returns(MockedResult);
411+
_substitute.Execute("FT.CURSOR", Arg.Any<object[]>()).Returns(MockedResultCursorEnd);
412+
_ = collection.OrderBy(x => x.RecordShell.Name, 42).OrderByDescending(x=>x.RecordShell.Age).ToList();
413+
_substitute.Received().Execute("FT.AGGREGATE","person-idx", "*", "SORTBY", "4", "@Name", "ASC", "@Age", "DESC", "MAX", "42", "WITHCURSOR", "COUNT", "10000");
414+
}
415+
416+
[Fact]
417+
public void TestOrderByWithMax()
418+
{
419+
var collection = new RedisAggregationSet<Person>(_substitute, true, chunkSize: 10000);
420+
_substitute.Execute("FT.AGGREGATE", Arg.Any<object[]>()).Returns(MockedResult);
421+
_substitute.Execute("FT.CURSOR", Arg.Any<object[]>()).Returns(MockedResultCursorEnd);
422+
_ = collection.OrderBy(x => x.RecordShell.Name, 42).ToList();
423+
_substitute.Received().Execute("FT.AGGREGATE","person-idx", "*", "SORTBY", "2", "@Name", "ASC", "MAX", "42", "WITHCURSOR", "COUNT", "10000");
424+
}
405425

406426
[Fact]
407427
public void TestRightSideStringTypeFilter()

0 commit comments

Comments
 (0)