Skip to content

fix:backward-contains-list-type-queries #263

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
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion examples/Redis.OM.FullTextSearch/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ static void ShowMovies(string type, List<Movie> movies)
connection.CreateIndex(typeof(Awards));

var redisHelper = new RedisHelper(provider);
redisHelper.InitializeCustomers();
redisHelper.InitializeMovies();

//BasicFirstOrDefaultQuery
// get first or default null value from movies redis limit set to 0 to 1
Expand Down
4 changes: 2 additions & 2 deletions examples/Redis.OM.FullTextSearch/RedisHelper/RedisHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public RedisHelper(RedisConnectionProvider provider)
movieCollection = provider.RedisCollection<Movie>();
}

public void InitializeCustomers()
public void InitializeMovies()
{
var count = movieCollection.Count();
if (count > 0)
Expand All @@ -22,7 +22,7 @@ public void InitializeCustomers()
return;
}

Console.WriteLine("Initialize Customer Data...");
Console.WriteLine("Initialize Movie Data...");

movieCollection.Insert(new Movie()
{
Expand Down
17 changes: 11 additions & 6 deletions src/Redis.OM/Common/ExpressionParserUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -588,12 +588,7 @@ private static string TranslateContainsStandardQuerySyntax(MethodCallExpression
Type type;
string memberName;
string literal;
if (exp.Object is MemberExpression)
{
expression = exp.Object as MemberExpression;
}
else if (exp.Arguments.LastOrDefault() is MemberExpression &&
exp.Arguments.FirstOrDefault() is MemberExpression)
if (exp.Arguments.LastOrDefault() is MemberExpression && exp.Arguments.FirstOrDefault() is MemberExpression)
{
var propertyExpression = (MemberExpression)exp.Arguments.Last();
var valuesExpression = (MemberExpression)exp.Arguments.First();
Expand All @@ -603,6 +598,11 @@ private static string TranslateContainsStandardQuerySyntax(MethodCallExpression
propertyExpression = (MemberExpression)exp.Arguments.First();
valuesExpression = (MemberExpression)exp.Arguments.Last();
}
else if (propertyExpression == valuesExpression)
{
propertyExpression = (MemberExpression)exp.Arguments.First();
valuesExpression = (MemberExpression)exp.Object;
}

var attribute = DetermineSearchAttribute(propertyExpression);
if (attribute == null)
Expand Down Expand Up @@ -639,6 +639,11 @@ private static string TranslateContainsStandardQuerySyntax(MethodCallExpression

return ret;
}

if (exp.Object is MemberExpression)
{
expression = exp.Object as MemberExpression;
}
else if (exp.Arguments.FirstOrDefault() is MemberExpression)
{
expression = (MemberExpression)exp.Arguments.First();
Expand Down
35 changes: 35 additions & 0 deletions test/Redis.OM.Unit.Tests/RediSearchTests/SearchFunctionalTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -966,5 +966,40 @@ public async Task BulkInsert50Records()
var countPeople = collection.Where(x => x.Age >= 17 && x.Age <= 21).ToList().Count;
Assert.Equal(people.Count, countPeople);
}

[Fact]
public async Task TestListContains()
{
var collection = new RedisCollection<Person>(_connection);
var person1 = new Person() { Name = "Ferb", Age = 14, NickNames = new[] { "Feb", "Fee" } };
var person2 = new Person() { Name = "Phineas", Age = 14, NickNames = new[] { "Phineas", "Triangle Head", "Phine" } };

await collection.InsertAsync(person1);
await collection.InsertAsync(person2);

var names = new List<string> { "Ferb", "Phineas" };
var people = await collection.Where(x => names.Contains(x.Name)).ToListAsync();

Assert.Contains(people, x => x.Id == person1.Id);
Assert.Contains(people, x => x.Id == person2.Id);
}

[Fact]
public async Task TestListMultipleContains()
{
var collection = new RedisCollection<Person>(_connection);
var person1 = new Person() { Name = "Ferb", Age = 14, NickNames = new[] { "Feb", "Fee" }, TagField = "Ferb" };
var person2 = new Person() { Name = "Phineas", Age = 14, NickNames = new[] { "Phineas", "Triangle Head", "Phine" }, TagField = "Phineas" };

await collection.InsertAsync(person1);
await collection.InsertAsync(person2);

var names = new List<string> { "Ferb", "Phineas" };
var ages = new List<int?> { 14, 50, 60 };
var people = await collection.Where(x => names.Contains(x.Name) && names.Contains(x.TagField) && ages.Contains(x.Age)).ToListAsync();

Assert.Contains(people, x => x.Id == person1.Id);
Assert.Contains(people, x => x.Id == person2.Id);
}
}
}
51 changes: 51 additions & 0 deletions test/Redis.OM.Unit.Tests/RediSearchTests/SearchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2480,5 +2480,56 @@ public async Task RangeOnDatetimeAsyncHash()
"1000"
));
}

[Fact]
public void SearchNumericFieldListContains()
{
var potentialTagFieldValues = new List<int?> { 35, 50, 60 };
_mock.Setup(x => x.Execute(It.IsAny<string>(), It.IsAny<string[]>()))
.Returns(_mockReply);
var collection = new RedisCollection<Person>(_mock.Object).Where(x => potentialTagFieldValues.Contains(x.Age));
collection.ToList();
_mock.Verify(x => x.Execute(
"FT.SEARCH",
"person-idx",
"@Age:[35 35]|@Age:[50 50]|@Age:[60 60]",
"LIMIT",
"0",
"100"));
}

[Fact]
public void SearchTagFieldAndTextListContains()
{
var potentialTagFieldValues = new List<string> { "Steve", "Alice", "Bob" };
_mock.Setup(x => x.Execute(It.IsAny<string>(), It.IsAny<string[]>()))
.Returns(_mockReply);
var collection = new RedisCollection<Person>(_mock.Object).Where(x => potentialTagFieldValues.Contains(x.TagField) || potentialTagFieldValues.Contains(x.Name));
collection.ToList();
_mock.Verify(x => x.Execute(
"FT.SEARCH",
"person-idx",
"((@TagField:{Steve|Alice|Bob}) | (@Name:Steve|Alice|Bob))",
"LIMIT",
"0",
"100"));
}

[Fact]
public void SearchTagFieldAndTextListContainsWithEscapes()
{
var potentialTagFieldValues = new List<string> { "[email protected]", "[email protected]", "[email protected]" };
_mock.Setup(x => x.Execute(It.IsAny<string>(), It.IsAny<string[]>()))
.Returns(_mockReply);
var collection = new RedisCollection<Person>(_mock.Object).Where(x => potentialTagFieldValues.Contains(x.TagField) || potentialTagFieldValues.Contains(x.Name));
collection.ToList();
_mock.Verify(x => x.Execute(
"FT.SEARCH",
"person-idx",
"((@TagField:{steve\\@example\\.com|alice\\@example\\.com|bob\\@example\\.com}) | (@Name:[email protected]|[email protected]|[email protected]))",
"LIMIT",
"0",
"100"));
}
}
}