Skip to content

Commit dbb71b8

Browse files
Cannot translate complex object filter on the right of where clause in aggregation sets (#344)
1 parent d6982ee commit dbb71b8

File tree

5 files changed

+70
-10
lines changed

5 files changed

+70
-10
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ protected override void ValidateAndPushOperand(Expression expression, Stack<stri
6767
var val = ExpressionParserUtilities.GetValue(mem.Member, frame.Value);
6868
stack.Push(BuildQueryPredicate(binaryExpression.NodeType, memberExpression.Member, System.Linq.Expressions.Expression.Constant(val)));
6969
}
70+
else
71+
{
72+
var val = ExpressionParserUtilities.GetOperandStringForQueryArgs(binaryExpression.Right);
73+
stack.Push(BuildQueryPredicate(binaryExpression.NodeType, memberExpression.Member, System.Linq.Expressions.Expression.Constant(val)));
74+
}
75+
7076
}
7177
else if (expression is ConstantExpression c
7278
&& c.Value.ToString() == "*")

src/Redis.OM/Aggregation/RedisAggregation.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using System.Linq;
23
using Redis.OM.Aggregation.AggregationPredicates;
34

45
namespace Redis.OM.Aggregation
@@ -27,6 +28,10 @@ public RedisAggregation(string indexName)
2728
/// </summary>
2829
public QueryPredicate Query { get; set; } = new ();
2930

31+
/// <summary>
32+
/// Gets or sets the query predicate.
33+
/// </summary>
34+
public List<QueryPredicate> Queries { get; set; } = new();
3035
/// <summary>
3136
/// Gets or sets the limit.
3237
/// </summary>
@@ -43,8 +48,20 @@ public RedisAggregation(string indexName)
4348
/// <returns>The serialized arguments.</returns>
4449
public string[] Serialize()
4550
{
51+
var queries = new List<string>();
4652
var ret = new List<string>() { IndexName };
47-
ret.AddRange(Query.Serialize());
53+
if (Queries.Any())
54+
{
55+
foreach (var query in Queries)
56+
{
57+
queries.AddRange(query.Serialize());
58+
}
59+
ret.AddRange(new[] { string.Join(" ", queries) });
60+
}
61+
else
62+
{
63+
ret.Add("*");
64+
}
4865
foreach (var predicate in Predicates)
4966
{
5067
ret.AddRange(predicate.Serialize());

src/Redis.OM/Common/ExpressionTranslator.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,7 @@ public static RedisAggregation BuildAggregationFromExpression(Expression express
6161
break;
6262
case "Where":
6363
lambda = (LambdaExpression)((UnaryExpression)exp.Arguments[1]).Operand;
64-
if (i == expressions.Count - 1)
65-
{
66-
aggregation.Query = new QueryPredicate(lambda);
67-
}
68-
else
69-
{
70-
aggregation.Predicates.Push(new FilterPredicate(lambda.Body));
71-
}
72-
64+
aggregation.Queries.Add(new QueryPredicate(lambda));
7365
break;
7466
case "Average":
7567
case "AverageAsync":
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Redis.OM.Unit.Tests
8+
{
9+
internal class CustomerFilterDto
10+
{
11+
public string FirstName { get; set; }
12+
public string LastName { get; set; }
13+
14+
}
15+
}

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,5 +448,35 @@ public void TestMissedBinExpression()
448448
.Apply(x=>x.RecordShell.Age + x["house_num_modified"] * 4 + x.RecordShell.Sales, "arbitrary_calculation").ToList();
449449
_mock.Verify(x=>x.Execute("FT.AGGREGATE","person-idx", "*", "APPLY", "@Address_HouseNumber + 4", "AS", "house_num_modified", "APPLY", "@Age + @house_num_modified * 4 + @Sales", "AS", "arbitrary_calculation", "WITHCURSOR", "COUNT", "10000"));
450450
}
451+
452+
[Fact]
453+
public void TestWhereByComplexObjectOnTheRightSide()
454+
{
455+
var customerFilter = new CustomerFilterDto()
456+
{
457+
FirstName = "James",
458+
LastName = "Bond"
459+
};
460+
var collection = new RedisAggregationSet<Person>(_mock.Object, true, chunkSize: 10000);
461+
_mock.Setup(x => x.Execute("FT.AGGREGATE", It.IsAny<string[]>())).Returns(MockedResult);
462+
_mock.Setup(x => x.Execute("FT.CURSOR", It.IsAny<string[]>())).Returns(MockedResultCursorEnd);
463+
_ = collection.Where(x =>x.RecordShell.FirstName==customerFilter.FirstName) .ToList();
464+
_mock.Verify(x => x.Execute("FT.AGGREGATE", "person-idx", "@FirstName:{James}", "WITHCURSOR", "COUNT", "10000"));
465+
}
466+
467+
[Fact]
468+
public void TestSequentialWhereClauseTranslation()
469+
{
470+
var customerFilter = new CustomerFilterDto()
471+
{
472+
FirstName = "James",
473+
LastName = "Bond"
474+
};
475+
var collection = new RedisAggregationSet<Person>(_mock.Object, true, chunkSize: 10000);
476+
_mock.Setup(x => x.Execute("FT.AGGREGATE", It.IsAny<string[]>())).Returns(MockedResult);
477+
_mock.Setup(x => x.Execute("FT.CURSOR", It.IsAny<string[]>())).Returns(MockedResultCursorEnd);
478+
_ = collection.Where(x => x.RecordShell.FirstName == customerFilter.FirstName).Where(p=>p.RecordShell.LastName==customerFilter.LastName).ToList();
479+
_mock.Verify(x => x.Execute("FT.AGGREGATE", "person-idx", "@LastName:{Bond} @FirstName:{James}", "WITHCURSOR", "COUNT", "10000"));
480+
}
451481
}
452482
}

0 commit comments

Comments
 (0)