diff --git a/.github/dockers/cluster.redis.conf b/.github/dockers/cluster.redis.conf index d4de46fb..901d17ae 100644 --- a/.github/dockers/cluster.redis.conf +++ b/.github/dockers/cluster.redis.conf @@ -1,7 +1,7 @@ protected-mode no enable-debug-command yes loadmodule /opt/redis-stack/lib/redisearch.so -loadmodule /opt/redis-stack/lib/redisgraph.so +# loadmodule /opt/redis-stack/lib/redisgraph.so loadmodule /opt/redis-stack/lib/redistimeseries.so loadmodule /opt/redis-stack/lib/rejson.so loadmodule /opt/redis-stack/lib/redisbloom.so diff --git a/src/NRedisStack/ResponseParser.cs b/src/NRedisStack/ResponseParser.cs index 0be0b169..b6ff2632 100644 --- a/src/NRedisStack/ResponseParser.cs +++ b/src/NRedisStack/ResponseParser.cs @@ -673,7 +673,14 @@ public static Dictionary ToStringRedisResultDictionary(this foreach (var pair in res) { var arr = (RedisResult[])pair!; - dict.Add(arr[0].ToString()!, arr[1]); + if (arr.Length > 1) + { + dict.Add(arr[0].ToString()!, arr[1]); + } + else + { + dict.Add(arr[0].ToString()!, null); + } } return dict; } diff --git a/src/NRedisStack/Search/AggregationResult.cs b/src/NRedisStack/Search/AggregationResult.cs index 34ace0f3..f9497273 100644 --- a/src/NRedisStack/Search/AggregationResult.cs +++ b/src/NRedisStack/Search/AggregationResult.cs @@ -14,8 +14,9 @@ internal AggregationResult(RedisResult result, long cursorId = -1) { var arr = (RedisResult[])result!; - // the first element is always the number of results - TotalResults = (long)arr[0]; + // this statement below is not true as explained in the document https://redis.io/docs/latest/commands/ft.aggregate/#return + // // the first element is always the number of results + // TotalResults = (long)arr[0]; _results = new Dictionary[arr.Length - 1]; for (int i = 1; i < arr.Length; i++) @@ -33,7 +34,7 @@ internal AggregationResult(RedisResult result, long cursorId = -1) _results[i - 1] = cur; } - + TotalResults = _results.Length; CursorId = cursorId; } diff --git a/tests/NRedisStack.Tests/Search/SearchTests.cs b/tests/NRedisStack.Tests/Search/SearchTests.cs index 86ae7304..a269b331 100644 --- a/tests/NRedisStack.Tests/Search/SearchTests.cs +++ b/tests/NRedisStack.Tests/Search/SearchTests.cs @@ -507,7 +507,7 @@ public void TestApplyAndFilterAggregations() // actual search AggregationResult res = ft.Aggregate(index, r); - Assert.Equal(3, res.TotalResults); + Assert.Equal(2, res.TotalResults); Row r1 = res.GetRow(0); Assert.Equal("def", r1.GetString("name")); @@ -2668,7 +2668,7 @@ public async Task TestProfileSearchAsync() } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedis(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] public void TestProfile() { IDatabase db = redisFixture.Redis.GetDatabase(); @@ -2695,10 +2695,10 @@ public void TestProfile() var aggregateRes = profileAggregate.Item1; var aggregateDet = profileAggregate.Item2; Assert.Equal(5, aggregateDet.Count); - Assert.Equal(1, aggregateRes.TotalResults); + Assert.Equal(2, aggregateRes.TotalResults); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedis(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] public async Task TestProfileAsync() { IDatabase db = redisFixture.Redis.GetDatabase(); @@ -2724,7 +2724,66 @@ public async Task TestProfileAsync() var aggregateRes = profileAggregate.Item1; var aggregateDet = profileAggregate.Item2; Assert.Equal(5, aggregateDet.Count); - Assert.Equal(1, aggregateRes.TotalResults); + Assert.Equal(2, aggregateRes.TotalResults); + } + + [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.3.240")] + public void TestProfileIssue306() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + var ft = db.FT(); + + ft.Create(index, new Schema().AddTextField("t", sortable: true)); // Calling FT.CREATR without FTCreateParams + db.HashSet("1", "t", "hello"); + db.HashSet("2", "t", "world"); + + // check using Query + var q = new Query("hello|world").SetNoContent(); + var profileSearch = ft.ProfileSearch(index, q); + var searchRes = profileSearch.Item1; + var searchDet = profileSearch.Item2; + + Assert.Equal(6, searchDet.Count); + Assert.Equal(2, searchRes.Documents.Count); + + + // check using AggregationRequest + var aggReq = new AggregationRequest("*").Load(FieldName.Of("t")).Apply("startswith(@t, 'hel')", "prefix"); + var profileAggregate = ft.ProfileAggregate(index, aggReq); + var aggregateRes = profileAggregate.Item1; + var aggregateDet = profileAggregate.Item2; + Assert.True(aggregateDet.Count >= 6); + Assert.Equal(2, aggregateRes.TotalResults); + } + + [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.3.240")] + public async Task TestProfileAsyncIssue306() + { + IDatabase db = redisFixture.Redis.GetDatabase(); + db.Execute("FLUSHALL"); + var ft = db.FT(); + + await ft.CreateAsync(index, new Schema().AddTextField("t", sortable: true)); // Calling FT.CREATR without FTCreateParams + db.HashSet("1", "t", "hello"); + db.HashSet("2", "t", "world"); + + // check using Query + var q = new Query("hello|world").SetNoContent(); + var profileSearch = await ft.ProfileSearchAsync(index, q); + var searchRes = profileSearch.Item1; + var searchDet = profileSearch.Item2; + + Assert.Equal(6, searchDet.Count); + Assert.Equal(2, searchRes.Documents.Count); + + // check using AggregationRequest + var aggReq = new AggregationRequest("*").Load(FieldName.Of("t")).Apply("startswith(@t, 'hel')", "prefix"); + var profileAggregate = await ft.ProfileAggregateAsync(index, aggReq); + var aggregateRes = profileAggregate.Item1; + var aggregateDet = profileAggregate.Item2; + Assert.True(aggregateDet.Count >= 6); + Assert.Equal(2, aggregateRes.TotalResults); } [Fact]