diff --git a/src/Redis.OM/Common/ExpressionParserUtilities.cs b/src/Redis.OM/Common/ExpressionParserUtilities.cs index e42cbcb..3729b73 100644 --- a/src/Redis.OM/Common/ExpressionParserUtilities.cs +++ b/src/Redis.OM/Common/ExpressionParserUtilities.cs @@ -1038,6 +1038,11 @@ private static string TranslateAnyForEmbeddedObjects(MethodCallExpression exp, L private static string ValueToString(object value) { + if (value is null) + { + return "null"; + } + Type valueType = value.GetType(); if (valueType == typeof(double) || Nullable.GetUnderlyingType(valueType) == typeof(double)) diff --git a/src/Redis.OM/Common/ExpressionTranslator.cs b/src/Redis.OM/Common/ExpressionTranslator.cs index 85015d7..8e27542 100644 --- a/src/Redis.OM/Common/ExpressionTranslator.cs +++ b/src/Redis.OM/Common/ExpressionTranslator.cs @@ -415,7 +415,12 @@ internal static string TranslateBinaryExpression(BinaryExpression binExpression, if (rightResolvesToNull) { dialectNeeded |= 1 << 1; - return $"(ismissing({leftContent}))"; + return binExpression.NodeType switch + { + ExpressionType.Equal => $"(ismissing({leftContent}))", + ExpressionType.NotEqual => $"-(ismissing({leftContent}))", + _ => throw new ArgumentException($"The expression node type {binExpression.NodeType} is not supported"), + }; } var rightContent = ExpressionParserUtilities.GetOperandStringForQueryArgs(binExpression.Right, parameters, ref dialectNeeded, treatBooleanMemberAsUnary: true); diff --git a/test/Redis.OM.Unit.Tests/RediSearchTests/SearchTests.cs b/test/Redis.OM.Unit.Tests/RediSearchTests/SearchTests.cs index da0a91b..302cbf2 100644 --- a/test/Redis.OM.Unit.Tests/RediSearchTests/SearchTests.cs +++ b/test/Redis.OM.Unit.Tests/RediSearchTests/SearchTests.cs @@ -4156,5 +4156,22 @@ await _substitute.Received().ExecuteAsync("FT.SEARCH", "0", "100"); } + + [Fact] + public async Task TestIsNotNull() + { + _substitute.ClearSubstitute(); + _substitute.ExecuteAsync(Arg.Any(), Arg.Any()).Returns(_mockReply); + var collection = new RedisCollection(_substitute); + await collection.Where(x => x.String1 != null).ToListAsync(); + await _substitute.Received().ExecuteAsync("FT.SEARCH", + $"{nameof(ObjectWithNullableStrings).ToLower()}-idx", + "-(ismissing(@String1))", + "DIALECT", + 2, + "LIMIT", + "0", + "100"); + } } } \ No newline at end of file