Skip to content

Commit 8cae8fb

Browse files
authored
fixing issue with non-nullable numerics (#375)
1 parent b32280b commit 8cae8fb

File tree

3 files changed

+168
-13
lines changed

3 files changed

+168
-13
lines changed

src/Redis.OM/Common/ExpressionParserUtilities.cs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -346,19 +346,6 @@ private static string GetOperandStringForMember(MemberExpression member, bool tr
346346
return string.Join("|", ulids);
347347
}
348348

349-
if (resolved is IEnumerable<int?> ints)
350-
{
351-
var sb = new StringBuilder();
352-
sb.Append('|');
353-
foreach (var i in ints)
354-
{
355-
sb.Append($"[{i} {i}]|");
356-
}
357-
358-
sb.Remove(sb.Length - 1, 1);
359-
return sb.ToString();
360-
}
361-
362349
if (resolvedType.IsArray || resolvedType.GetInterfaces().Contains(typeof(IEnumerable)))
363350
{
364351
var asEnumerable = (IEnumerable)resolved;
@@ -368,6 +355,20 @@ private static string GetOperandStringForMember(MemberExpression member, bool tr
368355
elementType = resolvedType.GenericTypeArguments.FirstOrDefault();
369356
}
370357

358+
if (elementType != null && TypeDeterminationUtilities.IsNumeric(elementType))
359+
{
360+
var sb = new StringBuilder();
361+
sb.Append('|');
362+
363+
foreach (var item in asEnumerable)
364+
{
365+
sb.Append(FormattableString.Invariant($"[{item} {item}]|"));
366+
}
367+
368+
sb.Remove(sb.Length - 1, 1);
369+
return sb.ToString();
370+
}
371+
371372
if (elementType != null && elementType.IsEnum)
372373
{
373374
if (treatEnumsAsInt)

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

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3041,5 +3041,131 @@ public void TestSelectNestedObject()
30413041
"$.Address.ForwardingAddress"
30423042
));
30433043
}
3044+
3045+
[Fact]
3046+
public void NonNullableNumericFieldContains()
3047+
{
3048+
var ints = new int[] { 1, 2, 3 };
3049+
var bytes = new byte[] { 4, 5, 6 };
3050+
var sbytes = new sbyte[] { 7, 8, 9 };
3051+
var shorts = new short[] { 10, 11, 12 };
3052+
var uints = new uint[] { 13, 14, 15 };
3053+
var longs = new long[] { 16, 17, 18 };
3054+
var ulongs = new ulong[] { 19, 20, 21 };
3055+
var doubles = new double[] { 22.5, 23, 24 };
3056+
var floats = new float[] { 25.5F, 26, 27 };
3057+
var ushorts = new ushort[] { 28, 29, 30 };
3058+
_mock.Setup(x => x.Execute(It.IsAny<string>(), It.IsAny<string[]>()))
3059+
.Returns(_mockReply);
3060+
var collection = new RedisCollection<ObjectWithNumerics>(_mock.Object).Where(x => ints.Contains(x.Integer));
3061+
collection.ToList();
3062+
var expected = $"@{nameof(ObjectWithNumerics.Integer)}:[1 1]|@{nameof(ObjectWithNumerics.Integer)}:[2 2]|@{nameof(ObjectWithNumerics.Integer)}:[3 3]";
3063+
_mock.Verify(x => x.Execute(
3064+
"FT.SEARCH",
3065+
"objectwithnumerics-idx",
3066+
expected,
3067+
"LIMIT",
3068+
"0",
3069+
"100"));
3070+
3071+
collection = new RedisCollection<ObjectWithNumerics>(_mock.Object).Where(x => bytes.Contains(x.Byte));
3072+
collection.ToList();
3073+
expected = $"@{nameof(ObjectWithNumerics.Byte)}:[4 4]|@{nameof(ObjectWithNumerics.Byte)}:[5 5]|@{nameof(ObjectWithNumerics.Byte)}:[6 6]";
3074+
_mock.Verify(x => x.Execute(
3075+
"FT.SEARCH",
3076+
"objectwithnumerics-idx",
3077+
expected,
3078+
"LIMIT",
3079+
"0",
3080+
"100"));
3081+
3082+
collection = new RedisCollection<ObjectWithNumerics>(_mock.Object).Where(x => sbytes.Contains(x.SByte));
3083+
collection.ToList();
3084+
expected = $"@{nameof(ObjectWithNumerics.SByte)}:[7 7]|@{nameof(ObjectWithNumerics.SByte)}:[8 8]|@{nameof(ObjectWithNumerics.SByte)}:[9 9]";
3085+
_mock.Verify(x => x.Execute(
3086+
"FT.SEARCH",
3087+
"objectwithnumerics-idx",
3088+
expected,
3089+
"LIMIT",
3090+
"0",
3091+
"100"));
3092+
3093+
collection = new RedisCollection<ObjectWithNumerics>(_mock.Object).Where(x => shorts.Contains(x.Short));
3094+
collection.ToList();
3095+
expected = $"@{nameof(ObjectWithNumerics.Short)}:[10 10]|@{nameof(ObjectWithNumerics.Short)}:[11 11]|@{nameof(ObjectWithNumerics.Short)}:[12 12]";
3096+
_mock.Verify(x => x.Execute(
3097+
"FT.SEARCH",
3098+
"objectwithnumerics-idx",
3099+
expected,
3100+
"LIMIT",
3101+
"0",
3102+
"100"));
3103+
3104+
collection = new RedisCollection<ObjectWithNumerics>(_mock.Object).Where(x => ushorts.Contains(x.UShort));
3105+
collection.ToList();
3106+
expected = $"@{nameof(ObjectWithNumerics.UShort)}:[28 28]|@{nameof(ObjectWithNumerics.UShort)}:[29 29]|@{nameof(ObjectWithNumerics.UShort)}:[30 30]";
3107+
_mock.Verify(x => x.Execute(
3108+
"FT.SEARCH",
3109+
"objectwithnumerics-idx",
3110+
expected,
3111+
"LIMIT",
3112+
"0",
3113+
"100"));
3114+
3115+
collection = new RedisCollection<ObjectWithNumerics>(_mock.Object).Where(x => uints.Contains(x.UInt));
3116+
collection.ToList();
3117+
expected = $"@{nameof(ObjectWithNumerics.UInt)}:[13 13]|@{nameof(ObjectWithNumerics.UInt)}:[14 14]|@{nameof(ObjectWithNumerics.UInt)}:[15 15]";
3118+
_mock.Verify(x => x.Execute(
3119+
"FT.SEARCH",
3120+
"objectwithnumerics-idx",
3121+
expected,
3122+
"LIMIT",
3123+
"0",
3124+
"100"));
3125+
3126+
collection = new RedisCollection<ObjectWithNumerics>(_mock.Object).Where(x => longs.Contains(x.Long));
3127+
collection.ToList();
3128+
expected = $"@{nameof(ObjectWithNumerics.Long)}:[16 16]|@{nameof(ObjectWithNumerics.Long)}:[17 17]|@{nameof(ObjectWithNumerics.Long)}:[18 18]";
3129+
_mock.Verify(x => x.Execute(
3130+
"FT.SEARCH",
3131+
"objectwithnumerics-idx",
3132+
expected,
3133+
"LIMIT",
3134+
"0",
3135+
"100"));
3136+
3137+
collection = new RedisCollection<ObjectWithNumerics>(_mock.Object).Where(x => ulongs.Contains(x.ULong));
3138+
collection.ToList();
3139+
expected = $"@{nameof(ObjectWithNumerics.ULong)}:[19 19]|@{nameof(ObjectWithNumerics.ULong)}:[20 20]|@{nameof(ObjectWithNumerics.ULong)}:[21 21]";
3140+
_mock.Verify(x => x.Execute(
3141+
"FT.SEARCH",
3142+
"objectwithnumerics-idx",
3143+
expected,
3144+
"LIMIT",
3145+
"0",
3146+
"100"));
3147+
3148+
collection = new RedisCollection<ObjectWithNumerics>(_mock.Object).Where(x => doubles.Contains(x.Double));
3149+
collection.ToList();
3150+
expected = $"@{nameof(ObjectWithNumerics.Double)}:[22.5 22.5]|@{nameof(ObjectWithNumerics.Double)}:[23 23]|@{nameof(ObjectWithNumerics.Double)}:[24 24]";
3151+
_mock.Verify(x => x.Execute(
3152+
"FT.SEARCH",
3153+
"objectwithnumerics-idx",
3154+
expected,
3155+
"LIMIT",
3156+
"0",
3157+
"100"));
3158+
3159+
collection = new RedisCollection<ObjectWithNumerics>(_mock.Object).Where(x => floats.Contains(x.Float));
3160+
collection.ToList();
3161+
expected = $"@{nameof(ObjectWithNumerics.Float)}:[25.5 25.5]|@{nameof(ObjectWithNumerics.Float)}:[26 26]|@{nameof(ObjectWithNumerics.Float)}:[27 27]";
3162+
_mock.Verify(x => x.Execute(
3163+
"FT.SEARCH",
3164+
"objectwithnumerics-idx",
3165+
expected,
3166+
"LIMIT",
3167+
"0",
3168+
"100"));
3169+
}
30443170
}
30453171
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using Redis.OM.Modeling;
2+
3+
namespace Redis.OM.Unit.Tests;
4+
5+
[Document(StorageType = StorageType.Json)]
6+
public class ObjectWithNumerics
7+
{
8+
[Indexed]
9+
public int Integer { get; set; }
10+
[Indexed]
11+
public byte Byte { get; set; }
12+
[Indexed]
13+
public sbyte SByte { get; set; }
14+
[Indexed]
15+
public short Short { get; set; }
16+
[Indexed]
17+
public ushort UShort { get; set; }
18+
[Indexed]
19+
public uint UInt { get; set; }
20+
[Indexed]
21+
public long Long { get; set; }
22+
[Indexed]
23+
public ulong ULong { get; set; }
24+
[Indexed]
25+
public double Double { get; set; }
26+
[Indexed]
27+
public float Float { get; set; }
28+
}

0 commit comments

Comments
 (0)