From 570114cca7570382361450381a189e55c1ff75e8 Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Tue, 29 Jul 2025 14:43:51 +0100 Subject: [PATCH 01/10] Build cleanup: - use Directory.Build.props for common config - use Directory.Packages.props for dependencies - add package icon - enable source link, deterministic builds, etc - configure licence, package, etc in package file - add net481 as an explicit TFM (avoids some ns* package-hell scenarios) - use automatic versioning with pinned assembly version - configure build SDK --- Directory.Build.props | 48 ++++++++++ Directory.Packages.props | 28 ++++++ NRedisStack.sln | 8 ++ Redis.png | Bin 0 -> 954 bytes src/NRedisStack/NRedisStack.csproj | 34 +++---- tests/Doc/Doc.csproj | 48 ++++------ .../NRedisStack.Tests.csproj | 90 ++++++++---------- version.json | 17 ++++ 8 files changed, 177 insertions(+), 96 deletions(-) create mode 100644 Directory.Build.props create mode 100644 Directory.Packages.props create mode 100644 Redis.png create mode 100644 version.json diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 00000000..8b715f99 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,48 @@ + + + 2022- Redis, inc. + enable + latest + enable + Redis Open Source + Redis OSS + .Net Client for Redis Stack + MIT + git + https://github.com/redis/nRedisStack/ + https://github.com/redis/NRedisStack/releases + https://github.com/redis/nRedisStack/ + false + true + embedded + en-US + false + true + false + true + true + true + $(NoWarn);CS1591 + 1.0.0-beta1 + 1.0.0-beta1 + 1.0.0-beta1 + net6.0;net7.0;net8.0 + $([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::get_Windows()))) + + + + + true + true + true + + + + + + + + + + + \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 00000000..7ec4b021 --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NRedisStack.sln b/NRedisStack.sln index 5a395f10..045e7015 100644 --- a/NRedisStack.sln +++ b/NRedisStack.sln @@ -9,6 +9,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRedisStack.Tests", "tests\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Doc", "tests\Doc\Doc.csproj", "{F14F6342-14A0-4DDD-AB05-C425B1AD8001}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{84D6210F-9A65-427A-965F-57E7B76424AB}" + ProjectSection(SolutionItems) = preProject + Directory.Build.props = Directory.Build.props + Directory.Packages.props = Directory.Packages.props + global.json = global.json + version.json = version.json + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/Redis.png b/Redis.png new file mode 100644 index 0000000000000000000000000000000000000000..bafa2f6d2d2b109cda9c6198138d13b9d4e113a4 GIT binary patch literal 954 zcmV;r14aCaP)&MjZ2dozx^dAVbC&y5ZJaQ}!r_j%6Ck8_^$oU@>_oGe@= zNiQ3~TOtsjL?AwiKztH`_#^`HDadal$z%u#g+zkG12~lz^xx zNM*$Dc4KP;bF&y5hVf^?qyC@UULB4CE%Nda70uIfavbfi;KW8hw!js-R)ykH6g&Wh zf~tLXE;O-t?kSv}QqCYGsgsiNc0V2}p{4OCB@LzJ^v#6;X<`w1gYS^r&Dy^iG5aGY zntwl8TK@yBuX=k9574hi?>mtGGmg!MrWc^AM9tIeSqoMmEj<80tIOCkF}BkILmx`C z_+X_okVdW)h38dID^h z_&iCh2a8}Bfn4rypl5WPRK1W~j_OLRud$w`-_cx4{_J+Ln`KYpFDo1l-Wi1CQ0e2y zz0Y?jCl9?nD0>(;YRDtR^d~I)Oei%SbuW|B@a@+$lTfcvz81xgay%{<20vtMbr^IF zkY9uCO)UP(&`4#_7UH$Hpb8;LJvu})58Vo7W})I)Z|A#RBt^7^%;%kVqpKI=Bjkn& zRvvB!q_ySKGscgL?l6JxAxwW40fJ_0{6U}yVZJG$NIcmq=tlr+>p c9RL9T|2u~Z75d>-i2wiq07*qoM6N<$f{Qc2?f?J) literal 0 HcmV?d00001 diff --git a/src/NRedisStack/NRedisStack.csproj b/src/NRedisStack/NRedisStack.csproj index ac31fad2..efebff60 100644 --- a/src/NRedisStack/NRedisStack.csproj +++ b/src/NRedisStack/NRedisStack.csproj @@ -1,25 +1,17 @@ - - enable - netstandard2.0;net6.0;net7.0;net8.0 - true - latest - enable - Redis Open Source - Redis OSS - .Net Client for Redis Stack - README.md - 1.0.0-beta1 - 1.0.0-beta1 - 1.0.0-beta1 - - - - - - - - + + $(TargetFrameworks);netstandard2.0;net481 + true + README.md + Redis.png + + + + + + + + diff --git a/tests/Doc/Doc.csproj b/tests/Doc/Doc.csproj index 0f1f5d04..95a074e6 100644 --- a/tests/Doc/Doc.csproj +++ b/tests/Doc/Doc.csproj @@ -1,29 +1,23 @@ - - $([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::get_Windows()))) - net6.0;net7.0;net8.0;net481 - net6.0;net7.0;net8.0 - enable - enable - latest - false - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - + + $(TargetFrameworks);net481 + false + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + diff --git a/tests/NRedisStack.Tests/NRedisStack.Tests.csproj b/tests/NRedisStack.Tests/NRedisStack.Tests.csproj index 6c6585f0..86f33f2e 100644 --- a/tests/NRedisStack.Tests/NRedisStack.Tests.csproj +++ b/tests/NRedisStack.Tests/NRedisStack.Tests.csproj @@ -1,55 +1,49 @@ - - $([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::get_Windows()))) - net6.0;net7.0;net8.0;net481 - net6.0;net7.0;net8.0 - enable - enable - latest + + $(TargetFrameworks);net481 + false + - false - + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - - - - + + + - - - + + + PreserveNewest + + - - - PreserveNewest - - - - - - Always - - + + + Always + + diff --git a/version.json b/version.json new file mode 100644 index 00000000..2508286b --- /dev/null +++ b/version.json @@ -0,0 +1,17 @@ +{ + "version": "1.0", + "assemblyVersion": "1.0.0.0", + "publicReleaseRefSpec": [ + "^refs/heads/main$", + "^refs/tags/v\\d+\\.\\d+" + ], + "nugetPackageVersion": { + "semVer": 2 + }, + "cloudBuild": { + "buildNumber": { + "enabled": true, + "setVersionVariables": true + } + } +} \ No newline at end of file From 7b011d91889c95229d4b8d0cd6b93784daf93cb3 Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Tue, 29 Jul 2025 15:05:19 +0100 Subject: [PATCH 02/10] revert NBGV --- Directory.Build.props | 5 +---- src/NRedisStack/NRedisStack.csproj | 3 +++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 8b715f99..f8b71926 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -23,9 +23,6 @@ true true $(NoWarn);CS1591 - 1.0.0-beta1 - 1.0.0-beta1 - 1.0.0-beta1 net6.0;net7.0;net8.0 $([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::get_Windows()))) @@ -43,6 +40,6 @@ - + \ No newline at end of file diff --git a/src/NRedisStack/NRedisStack.csproj b/src/NRedisStack/NRedisStack.csproj index efebff60..5d9fb0ba 100644 --- a/src/NRedisStack/NRedisStack.csproj +++ b/src/NRedisStack/NRedisStack.csproj @@ -5,6 +5,9 @@ true README.md Redis.png + 1.0.0-beta1 + 1.0.0-beta1 + 1.0.0-beta1 From c7cafe7d98b20a857e5799d36b6dbd22e2046e3a Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Tue, 29 Jul 2025 15:20:58 +0100 Subject: [PATCH 03/10] Use simple TFMs to make build happy --- Directory.Build.props | 1 - src/NRedisStack/NRedisStack.csproj | 2 +- tests/Doc/Doc.csproj | 3 ++- tests/NRedisStack.Tests/NRedisStack.Tests.csproj | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index f8b71926..5d47b3ef 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -23,7 +23,6 @@ true true $(NoWarn);CS1591 - net6.0;net7.0;net8.0 $([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::get_Windows()))) diff --git a/src/NRedisStack/NRedisStack.csproj b/src/NRedisStack/NRedisStack.csproj index 5d9fb0ba..1c1d5a6c 100644 --- a/src/NRedisStack/NRedisStack.csproj +++ b/src/NRedisStack/NRedisStack.csproj @@ -1,7 +1,7 @@ - $(TargetFrameworks);netstandard2.0;net481 + net6.0;net7.0;net8.0;netstandard2.0;net481 true README.md Redis.png diff --git a/tests/Doc/Doc.csproj b/tests/Doc/Doc.csproj index 95a074e6..9cd87ea0 100644 --- a/tests/Doc/Doc.csproj +++ b/tests/Doc/Doc.csproj @@ -1,6 +1,7 @@ - $(TargetFrameworks);net481 + net6.0;net7.0;net8.0;net481 + net6.0;net7.0;net8.0 false diff --git a/tests/NRedisStack.Tests/NRedisStack.Tests.csproj b/tests/NRedisStack.Tests/NRedisStack.Tests.csproj index 86f33f2e..f8565f16 100644 --- a/tests/NRedisStack.Tests/NRedisStack.Tests.csproj +++ b/tests/NRedisStack.Tests/NRedisStack.Tests.csproj @@ -1,6 +1,7 @@ - $(TargetFrameworks);net481 + net6.0;net7.0;net8.0;net481 + net6.0;net7.0;net8.0 false From 605672e3431a06334dc9fc521b6a4dfe1193774e Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Wed, 30 Jul 2025 11:52:14 +0100 Subject: [PATCH 04/10] use redis.io as the project url --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 5d47b3ef..f47b6b64 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -11,7 +11,7 @@ git https://github.com/redis/nRedisStack/ https://github.com/redis/NRedisStack/releases - https://github.com/redis/nRedisStack/ + https://redis.io/docs/latest/develop/clients/dotnet/ false true embedded From 05abfffbc3e0dc00d447d626098d2d36fcba5555 Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Tue, 5 Aug 2025 10:11:46 +0300 Subject: [PATCH 05/10] Fixup build to clean state (#432) * fix build errors * use redis.io as the project url * enable API change tracking * upgrade packages and finish cleaning output * more cleanup * be explicit about langver * CI: install SDK 9 * Update action.yml * preserve compilation context * re-enable VSTest for net6/net7 * Enable netfx build anywhere * drop net6/net7 CI (they're EOL); add net9; net8 is preserved as LTS * dotnet format * don't ref NetTopologySuite unnecessarily --- .github/actions/run-tests/action.yml | 8 +- .github/workflows/integration.yml | 2 +- Directory.Build.props | 3 +- Directory.Packages.props | 57 +- src/NRedisStack/Auxiliary.cs | 4 +- src/NRedisStack/Bloom/BloomCommandBuilder.cs | 26 +- .../Bloom/DataTypes/BloomInformation.cs | 39 +- src/NRedisStack/Bloom/Literals/CommandArgs.cs | 19 +- src/NRedisStack/Bloom/Literals/Commands.cs | 27 +- .../CoreCommands/CoreCommandBuilder.cs | 304 ++-- src/NRedisStack/CoreCommands/CoreCommands.cs | 19 +- .../CoreCommands/CoreCommandsAsync.cs | 907 ++++++----- .../CoreCommands/Literals/CommandArgs.cs | 31 +- .../CoreCommands/Literals/Commands.cs | 39 +- .../CountMinSketch/CmsCommandBuilder.cs | 18 +- .../DataTypes/CmsInformation.cs | 31 +- .../CountMinSketch/ICmsCommands.cs | 131 +- .../CountMinSketch/ICmsCommandsAsync.cs | 131 +- .../CountMinSketch/Literals/CommandArgs.cs | 9 +- .../CountMinSketch/Literals/Commands.cs | 19 +- .../CuckooFilter/CuckooCommandBuilder.cs | 201 ++- .../CuckooFilter/CuckooCommands.cs | 136 +- .../CuckooFilter/CuckooCommandsAsync.cs | 136 +- .../DataTypes/CuckooInformation.cs | 55 +- .../CuckooFilter/ICuckooCommands.cs | 227 ++- .../CuckooFilter/ICuckooCommandsAsync.cs | 225 ++- .../CuckooFilter/Literals/CommandArgs.cs | 19 +- .../CuckooFilter/Literals/Commands.cs | 31 +- .../Json/DataTypes/KeyValuePath.cs | 17 +- src/NRedisStack/Json/JsonCommandBuilder.cs | 56 +- src/NRedisStack/Json/JsonCommands.cs | 112 +- src/NRedisStack/Json/JsonCommandsAsync.cs | 104 +- src/NRedisStack/Json/Literals/CommandArgs.cs | 13 +- src/NRedisStack/Json/Literals/Commands.cs | 59 +- src/NRedisStack/ModulePrefixes.cs | 23 +- src/NRedisStack/NRedisStack.csproj | 18 +- src/NRedisStack/Pipeline.cs | 18 +- .../PublicAPI/PublicAPI.Shipped.txt | 1352 ++++++++++++++++ .../PublicAPI/PublicAPI.Unshipped.txt | 6 + .../RedisStackCommands/SerializedCommand.cs | 11 + src/NRedisStack/ResponseParser.cs | 1432 ++++++++--------- src/NRedisStack/Search/AggregationRequest.cs | 10 +- src/NRedisStack/Search/AggregationResult.cs | 22 +- .../Search/DataTypes/InfoResult.cs | 24 +- src/NRedisStack/Search/Document.cs | 2 +- src/NRedisStack/Search/FTCreateParams.cs | 513 +++--- src/NRedisStack/Search/FTSpellCheckParams.cs | 139 +- src/NRedisStack/Search/FieldName.cs | 59 +- src/NRedisStack/Search/Group.cs | 65 +- src/NRedisStack/Search/IDialectAwareParam.cs | 20 +- src/NRedisStack/Search/ISearchCommands.cs | 620 ++++--- .../Search/ISearchCommandsAsync.cs | 620 ++++--- src/NRedisStack/Search/Limit.cs | 51 +- .../Search/Literals/Enums/IndexDataType.cs | 11 +- .../Search/ProfilingInformation.cs | 16 +- src/NRedisStack/Search/Query.cs | 1163 +++++++------ src/NRedisStack/Search/Reducer.cs | 85 +- src/NRedisStack/Search/Reducers.cs | 143 +- src/NRedisStack/Search/Row.cs | 29 +- src/NRedisStack/Search/Schema.cs | 899 ++++++----- .../Search/SearchCommandBuilder.cs | 371 +++-- src/NRedisStack/Search/SearchCommands.cs | 385 +++-- src/NRedisStack/Search/SearchCommandsAsync.cs | 424 +++-- src/NRedisStack/Search/SearchResult.cs | 129 +- src/NRedisStack/Search/SortedField.cs | 43 +- src/NRedisStack/SerializedCommand.cs | 20 - .../Tdigest/DataTypes/TdigestInformation.cs | 59 +- src/NRedisStack/Tdigest/ITdigestCommands.cs | 236 ++- .../Tdigest/ITdigestCommandsAsync.cs | 235 ++- .../Tdigest/Literals/CommandArgs.cs | 9 +- src/NRedisStack/Tdigest/Literals/Commands.cs | 37 +- .../Tdigest/TdigestCommandBuilder.cs | 190 ++- src/NRedisStack/Tdigest/TdigestCommands.cs | 158 +- .../Tdigest/TdigestCommandsAsync.cs | 152 +- .../TimeSeries/DataTypes/TSParameters.cs | 144 +- .../TimeSeries/DataTypes/TimeSeriesChunck.cs | 67 +- .../DataTypes/TimeSeriesInformation.cs | 217 ++- .../TimeSeries/DataTypes/TimeSeriesLabel.cs | 87 +- .../TimeSeries/DataTypes/TimeSeriesRule.cs | 105 +- .../TimeSeries/DataTypes/TimeSeriesTuple.cs | 89 +- .../TimeSeries/DataTypes/TimeStamp.cs | 145 +- .../Extensions/AggregationExtensions.cs | 101 +- .../Extensions/BucketTimestampsExtensions.cs | 19 +- .../Extensions/DuplicatePolicyExtensions.cs | 47 +- .../TimeSeries/Extensions/ReduceExtensions.cs | 35 +- .../TimeSeries/ITimeSeriesCommands.cs | 605 ++++--- .../TimeSeries/ITimeSeriesCommandsAsync.cs | 601 ++++--- .../TimeSeries/Literals/CommandArgs.cs | 55 +- .../TimeSeries/Literals/Commands.cs | 43 +- .../TimeSeries/Literals/Enums/Aggregation.cs | 125 +- .../Literals/Enums/BucketTimestamps.cs | 33 +- .../Literals/Enums/DuplicatePolicy.cs | 64 +- .../TimeSeries/Literals/Enums/Reduce.cs | 111 +- src/NRedisStack/TimeSeries/TimeSeriesAux.cs | 353 ++-- .../TimeSeries/TimeSeriesCommands.cs | 315 ++-- .../TimeSeries/TimeSeriesCommandsAsync.cs | 343 ++-- .../TimeSeries/TimeSeriesCommandsBuilder.cs | 315 ++-- .../TimeSeries/TimeSeriesParamsBuilder.cs | 373 +++-- .../TopK/DataTypes/TopKInformation.cs | 35 +- src/NRedisStack/TopK/ITopKCommands.cs | 143 +- src/NRedisStack/TopK/ITopKCommandsAsync.cs | 143 +- src/NRedisStack/TopK/Literals/CommandArgs.cs | 9 +- src/NRedisStack/TopK/Literals/Commands.cs | 21 +- src/NRedisStack/TopK/TopKCommandBuilder.cs | 95 +- src/NRedisStack/TopK/TopKCommands.cs | 114 +- src/NRedisStack/TopK/TopKCommandsAsync.cs | 110 +- src/NRedisStack/Transactions.cs | 45 +- tests/Doc/Bf_tutorial.cs | 10 +- tests/Doc/Bitmap_tutorial.cs | 6 +- tests/Doc/CmdsGenericExample.cs | 10 +- tests/Doc/CmdsHashExample.cs | 26 +- tests/Doc/CmdsListExample.cs | 8 +- tests/Doc/CmdsSetExample.cs | 4 +- tests/Doc/CmdsSortedSetExamples.cs | 40 +- tests/Doc/CmdsStringExample.cs | 2 +- tests/Doc/Cms_tutorial.cs | 14 +- tests/Doc/Cuckoo_tutorial.cs | 6 +- tests/Doc/Doc.csproj | 13 +- tests/Doc/Geo_tutorial.cs | 6 +- tests/Doc/HashExample.cs | 19 +- tests/Doc/Hll_tutorial.cs | 12 +- tests/Doc/HomeJsonExample.cs | 20 +- tests/Doc/HomeProbExample.cs | 34 +- tests/Doc/Json_tutorial.cs | 6 +- tests/Doc/ListTutorial.cs | 28 +- tests/Doc/PipeTransExample.cs | 30 +- tests/Doc/QueryAggExample.cs | 2 +- tests/Doc/QueryEmExample.cs | 8 +- tests/Doc/QueryFtExample.cs | 12 +- tests/Doc/QueryRangeExample.cs | 4 +- tests/Doc/SearchQuickstartExample.cs | 2 +- tests/Doc/SetGetExample.cs | 2 +- tests/Doc/SetsTutorial.cs | 50 +- tests/Doc/SortedSetExample.cs | 32 +- tests/Doc/StreamTutorial.cs | 97 +- tests/Doc/StringSnippets.cs | 11 +- tests/Doc/Tdigest_tutorial.cs | 6 +- tests/Doc/TimeSeriesTutorial.cs | 44 +- tests/Doc/Topk_tutorial.cs | 7 +- .../AbstractNRedisStackTest.cs | 18 +- tests/NRedisStack.Tests/Bloom/BloomTests.cs | 22 +- .../CommunityEditionUpdatesTests.cs | 8 +- .../Core Commands/CoreTests.cs | 604 ++++--- .../CountMinSketch/CmsTests.cs | 82 +- .../CuckooFilter/CuckooTests.cs | 32 +- tests/NRedisStack.Tests/EndpointsFixture.cs | 12 +- .../Examples/ExampleTests.cs | 198 ++- tests/NRedisStack.Tests/Json/JsonTests.cs | 96 +- .../NRedisStack.Tests.csproj | 14 +- tests/NRedisStack.Tests/PipelineTests.cs | 8 +- .../Search/IndexCreationTests.cs | 75 +- tests/NRedisStack.Tests/Search/SearchTests.cs | 756 ++++----- ...ibute.cs => SkipIfRedisTheoryAttribute.cs} | 56 +- .../SkippableTheoryDiscoverer.cs | 10 +- .../NRedisStack.Tests/Tdigest/TdigestTests.cs | 28 +- .../TimeSeries/TestAPI/TestAdd.cs | 460 +++--- .../TimeSeries/TestAPI/TestAddAsync.cs | 464 +++--- .../TimeSeries/TestAPI/TestAlter.cs | 131 +- .../TimeSeries/TestAPI/TestAlterAsync.cs | 105 +- .../TimeSeries/TestAPI/TestCreate.cs | 297 ++-- .../TimeSeries/TestAPI/TestCreateAsync.cs | 194 ++- .../TimeSeries/TestAPI/TestDecrBy.cs | 200 ++- .../TimeSeries/TestAPI/TestDecrByAsync.cs | 209 ++- .../TimeSeries/TestAPI/TestDel.cs | 73 +- .../TimeSeries/TestAPI/TestDelAsync.cs | 72 +- .../TimeSeries/TestAPI/TestGet.cs | 70 +- .../TimeSeries/TestAPI/TestGetAsync.cs | 72 +- .../TimeSeries/TestAPI/TestIncrBy.cs | 200 ++- .../TimeSeries/TestAPI/TestIncrByAsync.cs | 209 ++- .../TimeSeries/TestAPI/TestMADD.cs | 188 ++- .../TimeSeries/TestAPI/TestMAddAsync.cs | 199 ++- .../TimeSeries/TestAPI/TestMGet.cs | 154 +- .../TimeSeries/TestAPI/TestMGetAsync.cs | 156 +- .../TimeSeries/TestAPI/TestMRange.cs | 866 +++++----- .../TimeSeries/TestAPI/TestMRangeAsync.cs | 542 ++++--- .../TimeSeries/TestAPI/TestMRevRange.cs | 516 +++--- .../TimeSeries/TestAPI/TestMRevRangeAsync.cs | 528 +++--- .../TimeSeries/TestAPI/TestQueryIndex.cs | 44 +- .../TimeSeries/TestAPI/TestQueryIndexAsync.cs | 42 +- .../TimeSeries/TestAPI/TestRange.cs | 488 +++--- .../TimeSeries/TestAPI/TestRangeAsync.cs | 498 +++--- .../TimeSeries/TestAPI/TestRevRange.cs | 210 ++- .../TimeSeries/TestAPI/TestRevRangeAsync.cs | 209 ++- .../TimeSeries/TestAPI/TestRules.cs | 191 ++- .../TimeSeries/TestAPI/TestRulesAsync.cs | 186 ++- .../TimeSeries/TestAPI/TimeSeriesHelper.cs | 29 +- .../TestTimeSeriesInformation.cs | 211 ++- .../TestDataTypes/TestTimeSeriesLabel.cs | 87 +- .../TestDataTypes/TestTimeSeriesRule.cs | 103 +- .../TestDataTypes/TestTimeSeriesTuple.cs | 67 +- .../TimeSeries/TestDataTypes/TestTimeStamp.cs | 41 +- .../TimeSeries/TimeSeriesTests.cs | 6 +- .../AuthenticationTests.cs | 76 +- .../FaultInjectorClient.cs | 8 +- tests/NRedisStack.Tests/TopK/TopKTests.cs | 8 +- tests/NRedisStack.Tests/TransactionsTests.cs | 8 +- 196 files changed, 15145 insertions(+), 13983 deletions(-) create mode 100644 src/NRedisStack/PublicAPI/PublicAPI.Shipped.txt create mode 100644 src/NRedisStack/PublicAPI/PublicAPI.Unshipped.txt create mode 100644 src/NRedisStack/RedisStackCommands/SerializedCommand.cs delete mode 100644 src/NRedisStack/SerializedCommand.cs rename tests/NRedisStack.Tests/{SkipIfRedisAttribute.cs => SkipIfRedisTheoryAttribute.cs} (59%) diff --git a/.github/actions/run-tests/action.yml b/.github/actions/run-tests/action.yml index 2fa1dd30..2c6d0465 100644 --- a/.github/actions/run-tests/action.yml +++ b/.github/actions/run-tests/action.yml @@ -24,11 +24,13 @@ runs: using: "composite" steps: - uses: actions/checkout@v4 - - - name: Install .NET Core + + - name: Install .NET Core uses: actions/setup-dotnet@v4 with: - dotnet-version: ${{inputs.dotnet-version}} + dotnet-version: | + 9.0.x + ${{inputs.dotnet-version}} dotnet-quality: 'ga' - name: Setup Environment variables and run Redis diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 437be795..ea98417b 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -38,7 +38,7 @@ jobs: fail-fast: false matrix: redis-version: [ '8.0-RC2-pre', '${{ needs.redis_version.outputs.CURRENT }}', '7.2.6', '6.2.16'] - dotnet-version: ['6.0', '7.0', '8.0'] + dotnet-version: [ '8.0', '9.0'] env: ACTIONS_ALLOW_UNSECURE_COMMANDS: true name: Redis ${{ matrix.redis-version }}; .NET ${{ matrix.dotnet-version }}; diff --git a/Directory.Build.props b/Directory.Build.props index f47b6b64..80453fb9 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,7 @@ 2022- Redis, inc. enable - latest + 13 enable Redis Open Source Redis OSS @@ -21,6 +21,7 @@ false true true + true true $(NoWarn);CS1591 $([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::get_Windows()))) diff --git a/Directory.Packages.props b/Directory.Packages.props index 7ec4b021..aa207a94 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,28 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + \ No newline at end of file diff --git a/src/NRedisStack/Auxiliary.cs b/src/NRedisStack/Auxiliary.cs index c336431d..33b7857b 100644 --- a/src/NRedisStack/Auxiliary.cs +++ b/src/NRedisStack/Auxiliary.cs @@ -54,8 +54,8 @@ internal static void SetInfoInPipeline(this IDatabase db) { _setInfo = false; if (_libraryName == null) return; - Pipeline pipeline = new Pipeline(db); - _ = pipeline.Db.ClientSetInfoAsync(SetInfoAttr.LibraryName, _libraryName!); + Pipeline pipeline = new(db); + _ = pipeline.Db.ClientSetInfoAsync(SetInfoAttr.LibraryName, _libraryName); _ = pipeline.Db.ClientSetInfoAsync(SetInfoAttr.LibraryVersion, GetNRedisStackVersion()); pipeline.Execute(); } diff --git a/src/NRedisStack/Bloom/BloomCommandBuilder.cs b/src/NRedisStack/Bloom/BloomCommandBuilder.cs index 49544b7c..ffb4d162 100644 --- a/src/NRedisStack/Bloom/BloomCommandBuilder.cs +++ b/src/NRedisStack/Bloom/BloomCommandBuilder.cs @@ -7,22 +7,22 @@ public static class BloomCommandBuilder { public static SerializedCommand Add(RedisKey key, RedisValue item) { - return new SerializedCommand(BF.ADD, key, item); + return new(BF.ADD, key, item); } public static SerializedCommand Card(RedisKey key) { - return new SerializedCommand(BF.CARD, key); + return new(BF.CARD, key); } public static SerializedCommand Exists(RedisKey key, RedisValue item) { - return new SerializedCommand(BF.EXISTS, key, item); + return new(BF.EXISTS, key, item); } public static SerializedCommand Info(RedisKey key) { - return new SerializedCommand(BF.INFO, key); + return new(BF.INFO, key); } public static SerializedCommand Insert(RedisKey key, RedisValue[] items, int? capacity = null, @@ -34,12 +34,12 @@ public static SerializedCommand Insert(RedisKey key, RedisValue[] items, int? ca var args = BloomAux.BuildInsertArgs(key, items, capacity, error, expansion, nocreate, nonscaling); - return new SerializedCommand(BF.INSERT, args); + return new(BF.INSERT, args); } public static SerializedCommand LoadChunk(RedisKey key, long iterator, Byte[] data) { - return new SerializedCommand(BF.LOADCHUNK, key, iterator, data); + return new(BF.LOADCHUNK, key, iterator, data); } public static SerializedCommand MAdd(RedisKey key, params RedisValue[] items) @@ -47,10 +47,10 @@ public static SerializedCommand MAdd(RedisKey key, params RedisValue[] items) if (items.Length < 1) throw new ArgumentOutOfRangeException(nameof(items)); - List args = new List { key }; + List args = [key]; args.AddRange(items.Cast()); - return new SerializedCommand(BF.MADD, args); + return new(BF.MADD, args); } public static SerializedCommand MExists(RedisKey key, RedisValue[] items) @@ -58,17 +58,17 @@ public static SerializedCommand MExists(RedisKey key, RedisValue[] items) if (items.Length < 1) throw new ArgumentOutOfRangeException(nameof(items)); - List args = new List { key }; + List args = [key]; args.AddRange(items.Cast()); - return new SerializedCommand(BF.MEXISTS, args); + return new(BF.MEXISTS, args); } public static SerializedCommand Reserve(RedisKey key, double errorRate, long capacity, int? expansion = null, bool nonscaling = false) { - List args = new List { key, errorRate, capacity }; + List args = [key, errorRate, capacity]; if (expansion != null) { @@ -80,11 +80,11 @@ public static SerializedCommand Reserve(RedisKey key, double errorRate, long cap args.Add(BloomArgs.NONSCALING); } - return new SerializedCommand(BF.RESERVE, args); + return new(BF.RESERVE, args); } public static SerializedCommand ScanDump(RedisKey key, long iterator) { - return new SerializedCommand(BF.SCANDUMP, key, iterator); + return new(BF.SCANDUMP, key, iterator); } } \ No newline at end of file diff --git a/src/NRedisStack/Bloom/DataTypes/BloomInformation.cs b/src/NRedisStack/Bloom/DataTypes/BloomInformation.cs index 082efc21..e3b75802 100644 --- a/src/NRedisStack/Bloom/DataTypes/BloomInformation.cs +++ b/src/NRedisStack/Bloom/DataTypes/BloomInformation.cs @@ -1,24 +1,23 @@ -namespace NRedisStack.Bloom.DataTypes +namespace NRedisStack.Bloom.DataTypes; + +/// +/// This class represents the response for BF.INFO command. +/// This object has Read-only properties and cannot be generated outside a BF.INFO response. +/// +public class BloomInformation { - /// - /// This class represents the response for BF.INFO command. - /// This object has Read-only properties and cannot be generated outside a BF.INFO response. - /// - public class BloomInformation - { - public long Capacity { get; private set; } - public long Size { get; private set; } - public long NumberOfFilters { get; private set; } - public long NumberOfItemsInserted { get; private set; } - public long ExpansionRate { get; private set; } + public long Capacity { get; private set; } + public long Size { get; private set; } + public long NumberOfFilters { get; private set; } + public long NumberOfItemsInserted { get; private set; } + public long ExpansionRate { get; private set; } - internal BloomInformation(long capacity, long size, long numberOfFilters, long numberOfItemsInserted, long expansionRate) - { - Capacity = capacity; - Size = size; - NumberOfFilters = numberOfFilters; - NumberOfItemsInserted = numberOfItemsInserted; - ExpansionRate = expansionRate; - } + internal BloomInformation(long capacity, long size, long numberOfFilters, long numberOfItemsInserted, long expansionRate) + { + Capacity = capacity; + Size = size; + NumberOfFilters = numberOfFilters; + NumberOfItemsInserted = numberOfItemsInserted; + ExpansionRate = expansionRate; } } \ No newline at end of file diff --git a/src/NRedisStack/Bloom/Literals/CommandArgs.cs b/src/NRedisStack/Bloom/Literals/CommandArgs.cs index a796e643..2a30ab70 100644 --- a/src/NRedisStack/Bloom/Literals/CommandArgs.cs +++ b/src/NRedisStack/Bloom/Literals/CommandArgs.cs @@ -1,12 +1,11 @@ -namespace NRedisStack.Bloom.Literals +namespace NRedisStack.Bloom.Literals; + +internal class BloomArgs { - internal class BloomArgs - { - public const string CAPACITY = "CAPACITY"; - public const string ERROR = "ERROR"; - public const string EXPANSION = "EXPANSION"; - public const string NOCREATE = "NOCREATE"; - public const string NONSCALING = "NONSCALING"; - public const string ITEMS = "ITEMS"; - } + public const string CAPACITY = "CAPACITY"; + public const string ERROR = "ERROR"; + public const string EXPANSION = "EXPANSION"; + public const string NOCREATE = "NOCREATE"; + public const string NONSCALING = "NONSCALING"; + public const string ITEMS = "ITEMS"; } \ No newline at end of file diff --git a/src/NRedisStack/Bloom/Literals/Commands.cs b/src/NRedisStack/Bloom/Literals/Commands.cs index 3d9dfcba..5ea469b5 100644 --- a/src/NRedisStack/Bloom/Literals/Commands.cs +++ b/src/NRedisStack/Bloom/Literals/Commands.cs @@ -1,16 +1,15 @@ -namespace NRedisStack.Bloom.Literals +namespace NRedisStack.Bloom.Literals; + +internal class BF { - internal class BF - { - public const string ADD = "BF.ADD"; - public const string CARD = "BF.CARD"; - public const string EXISTS = "BF.EXISTS"; - public const string INFO = "BF.INFO"; - public const string INSERT = "BF.INSERT"; - public const string LOADCHUNK = "BF.LOADCHUNK"; - public const string MADD = "BF.MADD"; - public const string MEXISTS = "BF.MEXISTS"; - public const string RESERVE = "BF.RESERVE"; - public const string SCANDUMP = "BF.SCANDUMP"; - } + public const string ADD = "BF.ADD"; + public const string CARD = "BF.CARD"; + public const string EXISTS = "BF.EXISTS"; + public const string INFO = "BF.INFO"; + public const string INSERT = "BF.INSERT"; + public const string LOADCHUNK = "BF.LOADCHUNK"; + public const string MADD = "BF.MADD"; + public const string MEXISTS = "BF.MEXISTS"; + public const string RESERVE = "BF.RESERVE"; + public const string SCANDUMP = "BF.SCANDUMP"; } \ No newline at end of file diff --git a/src/NRedisStack/CoreCommands/CoreCommandBuilder.cs b/src/NRedisStack/CoreCommands/CoreCommandBuilder.cs index b4189185..5a557c8f 100644 --- a/src/NRedisStack/CoreCommands/CoreCommandBuilder.cs +++ b/src/NRedisStack/CoreCommands/CoreCommandBuilder.cs @@ -4,200 +4,206 @@ using NRedisStack.Core.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public static class CoreCommandBuilder { + public static SerializedCommand ClientSetInfo(SetInfoAttr attr, string value) + { + string attrValue = attr switch + { + SetInfoAttr.LibraryName => CoreArgs.lib_name, + SetInfoAttr.LibraryVersion => CoreArgs.lib_ver, + _ => throw new ArgumentOutOfRangeException(nameof(attr)), + }; - public static class CoreCommandBuilder + return new(RedisCoreCommands.CLIENT, RedisCoreCommands.SETINFO, attrValue, value); + } + + public static SerializedCommand BZMPop(double timeout, RedisKey[] keys, MinMaxModifier minMaxModifier, long? count) { - public static SerializedCommand ClientSetInfo(SetInfoAttr attr, string value) + if (keys.Length == 0) { - string attrValue = attr switch - { - SetInfoAttr.LibraryName => CoreArgs.lib_name, - SetInfoAttr.LibraryVersion => CoreArgs.lib_ver, - _ => throw new System.NotImplementedException(), - }; - - return new SerializedCommand(RedisCoreCommands.CLIENT, RedisCoreCommands.SETINFO, attrValue, value); + throw new ArgumentException("At least one key must be provided."); } - public static SerializedCommand BZMPop(double timeout, RedisKey[] keys, MinMaxModifier minMaxModifier, long? count) - { - if (keys.Length == 0) - { - throw new ArgumentException("At least one key must be provided."); - } + List args = + [ + timeout, + keys.Length + ]; - List args = new List { - timeout, - keys.Length - }; + args.AddRange(keys.Cast()); - args.AddRange(keys.Cast()); + args.Add(minMaxModifier == MinMaxModifier.Min ? CoreArgs.MIN : CoreArgs.MAX); - args.Add(minMaxModifier == MinMaxModifier.Min ? CoreArgs.MIN : CoreArgs.MAX); + if (count != null) + { + args.Add(CoreArgs.COUNT); + args.Add(count); + } - if (count != null) - { - args.Add(CoreArgs.COUNT); - args.Add(count); - } + return new(RedisCoreCommands.BZMPOP, args); + } - return new SerializedCommand(RedisCoreCommands.BZMPOP, args); - } + public static SerializedCommand BZPopMin(RedisKey[] keys, double timeout) + { + return BlockingCommandWithKeysAndTimeout(RedisCoreCommands.BZPOPMIN, keys, timeout); + } - public static SerializedCommand BZPopMin(RedisKey[] keys, double timeout) + public static SerializedCommand BZPopMax(RedisKey[] keys, double timeout) + { + return BlockingCommandWithKeysAndTimeout(RedisCoreCommands.BZPOPMAX, keys, timeout); + } + + public static SerializedCommand BLMPop(double timeout, RedisKey[] keys, ListSide listSide, long? count) + { + if (keys.Length == 0) { - return BlockingCommandWithKeysAndTimeout(RedisCoreCommands.BZPOPMIN, keys, timeout); + throw new ArgumentException("At least one key must be provided."); } - public static SerializedCommand BZPopMax(RedisKey[] keys, double timeout) + List args = + [ + timeout, + keys.Length + ]; + + args.AddRange(keys.Cast()); + args.Add(listSide == ListSide.Left ? CoreArgs.LEFT : CoreArgs.RIGHT); + + if (count != null) { - return BlockingCommandWithKeysAndTimeout(RedisCoreCommands.BZPOPMAX, keys, timeout); + args.Add(CoreArgs.COUNT); + args.Add(count); } - public static SerializedCommand BLMPop(double timeout, RedisKey[] keys, ListSide listSide, long? count) - { - if (keys.Length == 0) - { - throw new ArgumentException("At least one key must be provided."); - } + return new(RedisCoreCommands.BLMPOP, args); + } + + public static SerializedCommand BLPop(RedisKey[] keys, double timeout) + { + return BlockingCommandWithKeysAndTimeout(RedisCoreCommands.BLPOP, keys, timeout); + } - List args = new List(); + public static SerializedCommand BRPop(RedisKey[] keys, double timeout) + { + return BlockingCommandWithKeysAndTimeout(RedisCoreCommands.BRPOP, keys, timeout); + } - args.Add(timeout); - args.Add(keys.Length); - args.AddRange(keys.Cast()); - args.Add(listSide == ListSide.Left ? CoreArgs.LEFT : CoreArgs.RIGHT); + public static SerializedCommand BLMove(RedisKey source, RedisKey destination, ListSide sourceSide, ListSide destinationSide, double timeout) + { + List args = + [ + source, + destination, + sourceSide == ListSide.Left ? CoreArgs.LEFT : CoreArgs.RIGHT, + destinationSide == ListSide.Left ? CoreArgs.LEFT : CoreArgs.RIGHT, + timeout + ]; + + return new(RedisCoreCommands.BLMOVE, args); + } - if (count != null) - { - args.Add(CoreArgs.COUNT); - args.Add(count); - } + public static SerializedCommand BRPopLPush(RedisKey source, RedisKey destination, double timeout) + { + List args = + [ + source, + destination, + timeout + ]; + + return new(RedisCoreCommands.BRPOPLPUSH, args); + } - return new SerializedCommand(RedisCoreCommands.BLMPOP, args); + public static SerializedCommand XRead(RedisKey[] keys, RedisValue[] positions, int? count, int? timeoutMilliseconds) + { + if (keys.Length == 0) + { + throw new ArgumentException("At least one key must be provided."); } - public static SerializedCommand BLPop(RedisKey[] keys, double timeout) + if (keys.Length != positions.Length) { - return BlockingCommandWithKeysAndTimeout(RedisCoreCommands.BLPOP, keys, timeout); + throw new ArgumentException("The number of keys and positions must be the same."); } - public static SerializedCommand BRPop(RedisKey[] keys, double timeout) + List args = []; + + if (count != null) { - return BlockingCommandWithKeysAndTimeout(RedisCoreCommands.BRPOP, keys, timeout); + args.Add(CoreArgs.COUNT); + args.Add(count); } - public static SerializedCommand BLMove(RedisKey source, RedisKey destination, ListSide sourceSide, ListSide destinationSide, double timeout) + if (timeoutMilliseconds != null) { - List args = new List(); - args.Add(source); - args.Add(destination); - args.Add(sourceSide == ListSide.Left ? CoreArgs.LEFT : CoreArgs.RIGHT); - args.Add(destinationSide == ListSide.Left ? CoreArgs.LEFT : CoreArgs.RIGHT); - args.Add(timeout); - - return new SerializedCommand(RedisCoreCommands.BLMOVE, args); + args.Add(CoreArgs.BLOCK); + args.Add(timeoutMilliseconds); } - public static SerializedCommand BRPopLPush(RedisKey source, RedisKey destination, double timeout) + args.Add(CoreArgs.STREAMS); + args.AddRange(keys.Cast()); + args.AddRange(positions.Cast()); + + return new(RedisCoreCommands.XREAD, args); + } + + public static SerializedCommand XReadGroup(RedisValue groupName, RedisValue consumerName, RedisKey[] keys, RedisValue[] positions, int? count, int? timeoutMilliseconds, bool? noAcknowledge) + { + if (keys.Length == 0) { - List args = new List(); - args.Add(source); - args.Add(destination); - args.Add(timeout); + throw new ArgumentException("At least one key must be provided."); + } - return new SerializedCommand(RedisCoreCommands.BRPOPLPUSH, args); + if (keys.Length != positions.Length) + { + throw new ArgumentException("The number of keys and positions must be the same."); } - public static SerializedCommand XRead(RedisKey[] keys, RedisValue[] positions, int? count, int? timeoutMilliseconds) + List args = + [ + CoreArgs.GROUP, + groupName, + consumerName + ]; + + if (count != null) { - if (keys.Length == 0) - { - throw new ArgumentException("At least one key must be provided."); - } - - if (keys.Length != positions.Length) - { - throw new ArgumentException("The number of keys and positions must be the same."); - } - - List args = new List(); - - if (count != null) - { - args.Add(CoreArgs.COUNT); - args.Add(count); - } - - if (timeoutMilliseconds != null) - { - args.Add(CoreArgs.BLOCK); - args.Add(timeoutMilliseconds); - } - - args.Add(CoreArgs.STREAMS); - args.AddRange(keys.Cast()); - args.AddRange(positions.Cast()); - - return new SerializedCommand(RedisCoreCommands.XREAD, args); + args.Add(CoreArgs.COUNT); + args.Add(count); } - public static SerializedCommand XReadGroup(RedisValue groupName, RedisValue consumerName, RedisKey[] keys, RedisValue[] positions, int? count, int? timeoutMilliseconds, bool? noAcknowledge) + if (timeoutMilliseconds != null) { - if (keys.Length == 0) - { - throw new ArgumentException("At least one key must be provided."); - } - - if (keys.Length != positions.Length) - { - throw new ArgumentException("The number of keys and positions must be the same."); - } - - List args = new List(); - - args.Add(CoreArgs.GROUP); - args.Add(groupName); - args.Add(consumerName); - - if (count != null) - { - args.Add(CoreArgs.COUNT); - args.Add(count); - } - - if (timeoutMilliseconds != null) - { - args.Add(CoreArgs.BLOCK); - args.Add(timeoutMilliseconds); - } - - if (noAcknowledge != null && noAcknowledge.Value) - { - args.Add(CoreArgs.NOACK); - } - - args.Add(CoreArgs.STREAMS); - args.AddRange(keys.Cast()); - args.AddRange(positions.Cast()); - - return new SerializedCommand(RedisCoreCommands.XREADGROUP, args); + args.Add(CoreArgs.BLOCK); + args.Add(timeoutMilliseconds); } - private static SerializedCommand BlockingCommandWithKeysAndTimeout(String command, RedisKey[] keys, double timeout) + if (noAcknowledge != null && noAcknowledge.Value) { - if (keys.Length == 0) - { - throw new ArgumentException("At least one key must be provided."); - } + args.Add(CoreArgs.NOACK); + } - List args = new List(); - args.AddRange(keys.Cast()); - args.Add(timeout); + args.Add(CoreArgs.STREAMS); + args.AddRange(keys.Cast()); + args.AddRange(positions.Cast()); - return new SerializedCommand(command, args); + return new(RedisCoreCommands.XREADGROUP, args); + } + + private static SerializedCommand BlockingCommandWithKeysAndTimeout(String command, RedisKey[] keys, double timeout) + { + if (keys.Length == 0) + { + throw new ArgumentException("At least one key must be provided."); } + + List args = []; + args.AddRange(keys.Cast()); + args.Add(timeout); + + return new(command, args); } -} +} \ No newline at end of file diff --git a/src/NRedisStack/CoreCommands/CoreCommands.cs b/src/NRedisStack/CoreCommands/CoreCommands.cs index 9af50645..fd65c6bb 100644 --- a/src/NRedisStack/CoreCommands/CoreCommands.cs +++ b/src/NRedisStack/CoreCommands/CoreCommands.cs @@ -9,13 +9,14 @@ public static class CoreCommands /// /// Sets information specific to the client or connection. /// + /// the database to query /// which attribute to set /// the attribute value /// if the attribute name was successfully set, Error otherwise. /// public static bool ClientSetInfo(this IDatabase db, SetInfoAttr attr, string value) { - var compareVersions = db.Multiplexer.GetServer(db.Multiplexer.GetEndPoints()[0]).Version.CompareTo(new Version(7, 1, 242)); + var compareVersions = db.Multiplexer.GetServer(db.Multiplexer.GetEndPoints()[0]).Version.CompareTo(new(7, 1, 242)); if (compareVersions < 0) // the server does not support the CLIENT SETNAME command return false; return db.Execute(CoreCommandBuilder.ClientSetInfo(attr, value)).OKtoBoolean(); @@ -75,7 +76,7 @@ public static bool ClientSetInfo(this IDatabase db, SetInfoAttr attr, string val /// public static Tuple>? BZMPop(this IDatabase db, double timeout, RedisKey key, MinMaxModifier minMaxModifier, long? count = null) { - return BZMPop(db, timeout, new[] { key }, minMaxModifier, count); + return BZMPop(db, timeout, [key], minMaxModifier, count); } /// @@ -123,7 +124,7 @@ public static bool ClientSetInfo(this IDatabase db, SetInfoAttr attr, string val /// public static Tuple? BZPopMin(this IDatabase db, RedisKey key, double timeout) { - return BZPopMin(db, new[] { key }, timeout); + return BZPopMin(db, [key], timeout); } @@ -172,7 +173,7 @@ public static bool ClientSetInfo(this IDatabase db, SetInfoAttr attr, string val /// public static Tuple? BZPopMax(this IDatabase db, RedisKey key, double timeout) { - return BZPopMax(db, new[] { key }, timeout); + return BZPopMax(db, [key], timeout); } /// @@ -227,7 +228,7 @@ public static bool ClientSetInfo(this IDatabase db, SetInfoAttr attr, string val /// public static Tuple>? BLMPop(this IDatabase db, double timeout, RedisKey key, ListSide listSide, long? count = null) { - return BLMPop(db, timeout, new[] { key }, listSide, count); + return BLMPop(db, timeout, [key], listSide, count); } /// @@ -275,7 +276,7 @@ public static bool ClientSetInfo(this IDatabase db, SetInfoAttr attr, string val /// public static Tuple? BLPop(this IDatabase db, RedisKey key, double timeout) { - return BLPop(db, new[] { key }, timeout); + return BLPop(db, [key], timeout); } /// @@ -323,7 +324,7 @@ public static bool ClientSetInfo(this IDatabase db, SetInfoAttr attr, string val /// public static Tuple? BRPop(this IDatabase db, RedisKey key, double timeout) { - return BRPop(db, new[] { key }, timeout); + return BRPop(db, [key], timeout); } /// @@ -413,7 +414,7 @@ public static bool ClientSetInfo(this IDatabase db, SetInfoAttr attr, string val /// public static StreamEntry[]? XRead(this IDatabase db, RedisKey key, RedisValue position, int? count = null, int? timeoutMilliseconds = null) { - var result = XRead(db, new[] { key }, new[] { position }, count, timeoutMilliseconds); + var result = XRead(db, [key], [position], count, timeoutMilliseconds); if (result == null || result.Length == 0) { return null; @@ -472,7 +473,7 @@ public static bool ClientSetInfo(this IDatabase db, SetInfoAttr attr, string val /// public static StreamEntry[]? XReadGroup(this IDatabase db, RedisValue groupName, RedisValue consumerName, RedisKey key, RedisValue position, int? count = null, int? timeoutMilliseconds = null, bool? noAck = null) { - var result = XReadGroup(db, groupName, consumerName, new[] { key }, new[] { position }, count, timeoutMilliseconds, noAck); + var result = XReadGroup(db, groupName, consumerName, [key], [position], count, timeoutMilliseconds, noAck); if (result == null || result.Length == 0) { return null; diff --git a/src/NRedisStack/CoreCommands/CoreCommandsAsync.cs b/src/NRedisStack/CoreCommands/CoreCommandsAsync.cs index 8ab5eb99..668be400 100644 --- a/src/NRedisStack/CoreCommands/CoreCommandsAsync.cs +++ b/src/NRedisStack/CoreCommands/CoreCommandsAsync.cs @@ -1,485 +1,484 @@ using NRedisStack.Core; using NRedisStack.Core.DataTypes; using StackExchange.Redis; -namespace NRedisStack -{ +namespace NRedisStack; - public static class CoreCommandsAsync //: ICoreCommandsAsync +public static class CoreCommandsAsync //: ICoreCommandsAsync +{ + /// + /// Sets information specific to the client or connection. + /// + /// the database to query + /// which attribute to set + /// the attribute value + /// if the attribute name was successfully set, Error otherwise. + /// + public static async Task ClientSetInfoAsync(this IDatabaseAsync db, SetInfoAttr attr, string value) { - /// - /// Sets information specific to the client or connection. - /// - /// which attribute to set - /// the attribute value - /// if the attribute name was successfully set, Error otherwise. - /// - public static async Task ClientSetInfoAsync(this IDatabaseAsync db, SetInfoAttr attr, string value) + var compareVersions = db.Multiplexer.GetServer(db.Multiplexer.GetEndPoints()[0]).Version.CompareTo(new(7, 1, 242)); + if (compareVersions < 0) // the server does not support the CLIENT SETNAME command { - var compareVersions = db.Multiplexer.GetServer(db.Multiplexer.GetEndPoints()[0]).Version.CompareTo(new Version(7, 1, 242)); - if (compareVersions < 0) // the server does not support the CLIENT SETNAME command - { - return false; - } - return (await db.ExecuteAsync(CoreCommandBuilder.ClientSetInfo(attr, value))).OKtoBoolean(); + return false; } + return (await db.ExecuteAsync(CoreCommandBuilder.ClientSetInfo(attr, value))).OKtoBoolean(); + } - /// - /// The BZMPOP command. - ///

- /// Removes and returns up to entries from the first non-empty sorted set in - /// . If none of the sets contain elements, the call blocks on the server until elements - /// become available, or the given expires. A of 0 - /// means to wait indefinitely server-side. Returns null if the server timeout expires. - ///

- /// When using this, pay attention to the timeout configured in the client, on the - /// , which by default can be too small: - /// - /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); - /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here - /// configurationOptions.EndPoints.Add("localhost"); - /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); - /// - /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException - /// is thrown. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// The keys to check. - /// Specify from which end of the sorted set to pop values. If set to MinMaxModifier.Min - /// then the minimum elements will be popped, otherwise the maximum values. - /// The maximum number of records to pop out. If set to null then the server default - /// will be used. - /// A collection of sorted set entries paired with their scores, together with the key they were popped - /// from, or null if the server timeout expires. - /// - public static async Task>?> BZMPopAsync(this IDatabase db, double timeout, RedisKey[] keys, MinMaxModifier minMaxModifier, long? count = null) - { - var command = CoreCommandBuilder.BZMPop(timeout, keys, minMaxModifier, count); - return (await db.ExecuteAsync(command)).ToSortedSetPopResults(); - } + /// + /// The BZMPOP command. + ///

+ /// Removes and returns up to entries from the first non-empty sorted set in + /// . If none of the sets contain elements, the call blocks on the server until elements + /// become available, or the given expires. A of 0 + /// means to wait indefinitely server-side. Returns null if the server timeout expires. + ///

+ /// When using this, pay attention to the timeout configured in the client, on the + /// , which by default can be too small: + /// + /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); + /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here + /// configurationOptions.EndPoints.Add("localhost"); + /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); + /// + /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException + /// is thrown. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// The keys to check. + /// Specify from which end of the sorted set to pop values. If set to MinMaxModifier.Min + /// then the minimum elements will be popped, otherwise the maximum values. + /// The maximum number of records to pop out. If set to null then the server default + /// will be used. + /// A collection of sorted set entries paired with their scores, together with the key they were popped + /// from, or null if the server timeout expires. + /// + public static async Task>?> BZMPopAsync(this IDatabase db, double timeout, RedisKey[] keys, MinMaxModifier minMaxModifier, long? count = null) + { + var command = CoreCommandBuilder.BZMPop(timeout, keys, minMaxModifier, count); + return (await db.ExecuteAsync(command)).ToSortedSetPopResults(); + } - /// - /// Syntactic sugar for - /// , - /// where only one key is used. - /// - /// The class where this extension method is applied. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// The key to check. - /// Specify from which end of the sorted set to pop values. If set to MinMaxModifier.Min - /// then the minimum elements will be popped, otherwise the maximum values. - /// The maximum number of records to pop out. If set to null then the server default - /// will be used. - /// A collection of sorted set entries paired with their scores, together with the key they were popped - /// from, or null if the server timeout expires. - /// - public static async Task>?> BZMPopAsync(this IDatabase db, double timeout, RedisKey key, MinMaxModifier minMaxModifier, long? count = null) - { - return await BZMPopAsync(db, timeout, new[] { key }, minMaxModifier, count); - } + /// + /// Syntactic sugar for + /// , + /// where only one key is used. + /// + /// The class where this extension method is applied. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// The key to check. + /// Specify from which end of the sorted set to pop values. If set to MinMaxModifier.Min + /// then the minimum elements will be popped, otherwise the maximum values. + /// The maximum number of records to pop out. If set to null then the server default + /// will be used. + /// A collection of sorted set entries paired with their scores, together with the key they were popped + /// from, or null if the server timeout expires. + /// + public static async Task>?> BZMPopAsync(this IDatabase db, double timeout, RedisKey key, MinMaxModifier minMaxModifier, long? count = null) + { + return await BZMPopAsync(db, timeout, [key], minMaxModifier, count); + } - /// - /// The BZPOPMIN command. - ///

- /// Removes and returns the entry with the smallest score from the first non-empty sorted set in - /// . If none of the sets contain elements, the call blocks on the server until elements - /// become available, or the given expires. A of 0 - /// means to wait indefinitely server-side. Returns null if the server timeout expires. - ///

- /// When using this, pay attention to the timeout configured in the client, on the - /// , which by default can be too small: - /// - /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); - /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here - /// configurationOptions.EndPoints.Add("localhost"); - /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); - /// - /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException - /// is thrown. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// The keys to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A sorted set entry paired with its score, together with the key it was popped from, or null - /// if the server timeout expires. - /// - public static async Task?> BZPopMinAsync(this IDatabase db, RedisKey[] keys, double timeout) - { - var command = CoreCommandBuilder.BZPopMin(keys, timeout); - return (await db.ExecuteAsync(command)).ToSortedSetPopResult(); - } + /// + /// The BZPOPMIN command. + ///

+ /// Removes and returns the entry with the smallest score from the first non-empty sorted set in + /// . If none of the sets contain elements, the call blocks on the server until elements + /// become available, or the given expires. A of 0 + /// means to wait indefinitely server-side. Returns null if the server timeout expires. + ///

+ /// When using this, pay attention to the timeout configured in the client, on the + /// , which by default can be too small: + /// + /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); + /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here + /// configurationOptions.EndPoints.Add("localhost"); + /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); + /// + /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException + /// is thrown. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// The keys to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A sorted set entry paired with its score, together with the key it was popped from, or null + /// if the server timeout expires. + /// + public static async Task?> BZPopMinAsync(this IDatabase db, RedisKey[] keys, double timeout) + { + var command = CoreCommandBuilder.BZPopMin(keys, timeout); + return (await db.ExecuteAsync(command)).ToSortedSetPopResult(); + } - /// - /// Syntactic sugar for , - /// where only one key is used. - /// - /// The class where this extension method is applied. - /// The key to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A sorted set entry paired with its score, together with the key it was popped from, or null - /// if the server timeout expires. - /// - public static async Task?> BZPopMinAsync(this IDatabase db, RedisKey key, double timeout) - { - return await BZPopMinAsync(db, new[] { key }, timeout); - } + /// + /// Syntactic sugar for , + /// where only one key is used. + /// + /// The class where this extension method is applied. + /// The key to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A sorted set entry paired with its score, together with the key it was popped from, or null + /// if the server timeout expires. + /// + public static async Task?> BZPopMinAsync(this IDatabase db, RedisKey key, double timeout) + { + return await BZPopMinAsync(db, [key], timeout); + } - /// - /// The BZPOPMAX command. - ///

- /// Removes and returns the entry with the highest score from the first non-empty sorted set in - /// . If none of the sets contain elements, the call blocks on the server until elements - /// become available, or the given expires. A of 0 - /// means to wait indefinitely server-side. Returns null if the server timeout expires. - ///

- /// When using this, pay attention to the timeout configured in the client, on the - /// , which by default can be too small: - /// - /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); - /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here - /// configurationOptions.EndPoints.Add("localhost"); - /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); - /// - /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException - /// is thrown. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// The keys to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A sorted set entry paired with its score, together with the key it was popped from, or null - /// if the server timeout expires. - /// - public static async Task?> BZPopMaxAsync(this IDatabase db, RedisKey[] keys, double timeout) - { - var command = CoreCommandBuilder.BZPopMax(keys, timeout); - return (await db.ExecuteAsync(command)).ToSortedSetPopResult(); - } + /// + /// The BZPOPMAX command. + ///

+ /// Removes and returns the entry with the highest score from the first non-empty sorted set in + /// . If none of the sets contain elements, the call blocks on the server until elements + /// become available, or the given expires. A of 0 + /// means to wait indefinitely server-side. Returns null if the server timeout expires. + ///

+ /// When using this, pay attention to the timeout configured in the client, on the + /// , which by default can be too small: + /// + /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); + /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here + /// configurationOptions.EndPoints.Add("localhost"); + /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); + /// + /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException + /// is thrown. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// The keys to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A sorted set entry paired with its score, together with the key it was popped from, or null + /// if the server timeout expires. + /// + public static async Task?> BZPopMaxAsync(this IDatabase db, RedisKey[] keys, double timeout) + { + var command = CoreCommandBuilder.BZPopMax(keys, timeout); + return (await db.ExecuteAsync(command)).ToSortedSetPopResult(); + } - /// - /// Syntactic sugar for , - /// where only one key is used. - /// - /// The class where this extension method is applied. - /// The key to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A sorted set entry paired with its score, together with the key it was popped from, or null - /// if the server timeout expires. - /// - public static async Task?> BZPopMaxAsync(this IDatabase db, RedisKey key, double timeout) - { - return await BZPopMaxAsync(db, new[] { key }, timeout); - } + /// + /// Syntactic sugar for , + /// where only one key is used. + /// + /// The class where this extension method is applied. + /// The key to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A sorted set entry paired with its score, together with the key it was popped from, or null + /// if the server timeout expires. + /// + public static async Task?> BZPopMaxAsync(this IDatabase db, RedisKey key, double timeout) + { + return await BZPopMaxAsync(db, [key], timeout); + } - /// - /// The BLMPOP command. - ///

- /// Removes and returns up to entries from the first non-empty list in - /// . If none of the lists contain elements, the call blocks on the server until elements - /// become available, or the given expires. A of 0 - /// means to wait indefinitely server-side. Returns null if the server timeout expires. - ///

- /// When using this, pay attention to the timeout configured in the client, on the - /// , which by default can be too small: - /// - /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); - /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here - /// configurationOptions.EndPoints.Add("localhost"); - /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); - /// - /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException - /// is thrown. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// The keys to check. - /// Specify from which end of the list to pop values: left or right. - /// The maximum number of records to pop. If set to null then the server default - /// will be used. - /// A collection of values, together with the key they were popped from, or null if the - /// server timeout expires. - /// - public static async Task>?> BLMPopAsync(this IDatabase db, double timeout, RedisKey[] keys, ListSide listSide, long? count = null) - { - var command = CoreCommandBuilder.BLMPop(timeout, keys, listSide, count); - return (await db.ExecuteAsync(command)).ToListPopResults(); - } + /// + /// The BLMPOP command. + ///

+ /// Removes and returns up to entries from the first non-empty list in + /// . If none of the lists contain elements, the call blocks on the server until elements + /// become available, or the given expires. A of 0 + /// means to wait indefinitely server-side. Returns null if the server timeout expires. + ///

+ /// When using this, pay attention to the timeout configured in the client, on the + /// , which by default can be too small: + /// + /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); + /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here + /// configurationOptions.EndPoints.Add("localhost"); + /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); + /// + /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException + /// is thrown. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// The keys to check. + /// Specify from which end of the list to pop values: left or right. + /// The maximum number of records to pop. If set to null then the server default + /// will be used. + /// A collection of values, together with the key they were popped from, or null if the + /// server timeout expires. + /// + public static async Task>?> BLMPopAsync(this IDatabase db, double timeout, RedisKey[] keys, ListSide listSide, long? count = null) + { + var command = CoreCommandBuilder.BLMPop(timeout, keys, listSide, count); + return (await db.ExecuteAsync(command)).ToListPopResults(); + } - /// - /// Syntactic sugar for - /// , - /// where only one key is used. - /// - /// The class where this extension method is applied. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// The key to check. - /// Specify from which end of the list to pop values: left or right. - /// The maximum number of records to pop. If set to null then the server default - /// will be used. - /// A collection of values, together with the key they were popped from, or null if the - /// server timeout expires. - /// - public static async Task>?> BLMPopAsync(this IDatabase db, double timeout, RedisKey key, ListSide listSide, long? count = null) - { - return await BLMPopAsync(db, timeout, new[] { key }, listSide, count); - } + /// + /// Syntactic sugar for + /// , + /// where only one key is used. + /// + /// The class where this extension method is applied. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// The key to check. + /// Specify from which end of the list to pop values: left or right. + /// The maximum number of records to pop. If set to null then the server default + /// will be used. + /// A collection of values, together with the key they were popped from, or null if the + /// server timeout expires. + /// + public static async Task>?> BLMPopAsync(this IDatabase db, double timeout, RedisKey key, ListSide listSide, long? count = null) + { + return await BLMPopAsync(db, timeout, [key], listSide, count); + } - /// - /// The BLPOP command. - ///

- /// Removes and returns an entry from the head (left side) of the first non-empty list in . - /// If none of the lists contain elements, the call blocks on the server until elements - /// become available, or the given expires. A of 0 - /// means to wait indefinitely server-side. Returns null if the server timeout expires. - ///

- /// When using this, pay attention to the timeout configured in the client, on the - /// , which by default can be too small: - /// - /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); - /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here - /// configurationOptions.EndPoints.Add("localhost"); - /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); - /// - /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException - /// is thrown. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// The keys to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A value, together with the key it was popped from, or null if the server timeout - /// expires. - /// - public static async Task?> BLPopAsync(this IDatabase db, RedisKey[] keys, double timeout) - { - var command = CoreCommandBuilder.BLPop(keys, timeout); - return (await db.ExecuteAsync(command)).ToListPopResult(); - } + /// + /// The BLPOP command. + ///

+ /// Removes and returns an entry from the head (left side) of the first non-empty list in . + /// If none of the lists contain elements, the call blocks on the server until elements + /// become available, or the given expires. A of 0 + /// means to wait indefinitely server-side. Returns null if the server timeout expires. + ///

+ /// When using this, pay attention to the timeout configured in the client, on the + /// , which by default can be too small: + /// + /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); + /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here + /// configurationOptions.EndPoints.Add("localhost"); + /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); + /// + /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException + /// is thrown. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// The keys to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A value, together with the key it was popped from, or null if the server timeout + /// expires. + /// + public static async Task?> BLPopAsync(this IDatabase db, RedisKey[] keys, double timeout) + { + var command = CoreCommandBuilder.BLPop(keys, timeout); + return (await db.ExecuteAsync(command)).ToListPopResult(); + } - /// - /// Syntactic sugar for , - /// where only one key is used. - /// - /// The class where this extension method is applied. - /// The key to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A value, together with the key it was popped from, or null if the server timeout - /// expires. - /// - public static async Task?> BLPopAsync(this IDatabase db, RedisKey key, double timeout) - { - return await BLPopAsync(db, new[] { key }, timeout); - } + /// + /// Syntactic sugar for , + /// where only one key is used. + /// + /// The class where this extension method is applied. + /// The key to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A value, together with the key it was popped from, or null if the server timeout + /// expires. + /// + public static async Task?> BLPopAsync(this IDatabase db, RedisKey key, double timeout) + { + return await BLPopAsync(db, [key], timeout); + } - /// - /// The BRPOP command. - ///

- /// Removes and returns an entry from the tail (right side) of the first non-empty list in . - /// If none of the lists contain elements, the call blocks on the server until elements - /// become available, or the given expires. A of 0 - /// means to wait indefinitely server-side. Returns null if the server timeout expires. - ///

- /// When using this, pay attention to the timeout configured in the client, on the - /// , which by default can be too small: - /// - /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); - /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here - /// configurationOptions.EndPoints.Add("localhost"); - /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); - /// - /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException - /// is thrown. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// The keys to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A value, together with the key it was popped from, or null if the server timeout - /// expires. - /// - public static async Task?> BRPopAsync(this IDatabase db, RedisKey[] keys, double timeout) - { - var command = CoreCommandBuilder.BRPop(keys, timeout); - return (await db.ExecuteAsync(command)).ToListPopResult(); - } + /// + /// The BRPOP command. + ///

+ /// Removes and returns an entry from the tail (right side) of the first non-empty list in . + /// If none of the lists contain elements, the call blocks on the server until elements + /// become available, or the given expires. A of 0 + /// means to wait indefinitely server-side. Returns null if the server timeout expires. + ///

+ /// When using this, pay attention to the timeout configured in the client, on the + /// , which by default can be too small: + /// + /// ConfigurationOptions configurationOptions = new ConfigurationOptions(); + /// configurationOptions.SyncTimeout = 120000; // set a meaningful value here + /// configurationOptions.EndPoints.Add("localhost"); + /// ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configurationOptions); + /// + /// If the connection multiplexer timeout expires in the client, a StackExchange.Redis.RedisTimeoutException + /// is thrown. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// The keys to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A value, together with the key it was popped from, or null if the server timeout + /// expires. + /// + public static async Task?> BRPopAsync(this IDatabase db, RedisKey[] keys, double timeout) + { + var command = CoreCommandBuilder.BRPop(keys, timeout); + return (await db.ExecuteAsync(command)).ToListPopResult(); + } - /// - /// Syntactic sugar for , - /// where only one key is used. - /// - /// The class where this extension method is applied. - /// The key to check. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// A value, together with the key it was popped from, or null if the server timeout - /// expires. - /// - public static async Task?> BRPopAsync(this IDatabase db, RedisKey key, double timeout) - { - return await BRPopAsync(db, new[] { key }, timeout); - } + /// + /// Syntactic sugar for , + /// where only one key is used. + /// + /// The class where this extension method is applied. + /// The key to check. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// A value, together with the key it was popped from, or null if the server timeout + /// expires. + /// + public static async Task?> BRPopAsync(this IDatabase db, RedisKey key, double timeout) + { + return await BRPopAsync(db, [key], timeout); + } - /// - /// The BLMOVE command. - ///

- /// Atomically returns and removes the first or last element of the list stored at - /// (depending on the value of ), and pushes the element as the first or last - /// element of the list stored at (depending on the value of - /// ). - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// The key of the source list. - /// The key of the destination list. - /// What side of the list to remove from. - /// What side of the list to move to. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// The element being popped and pushed, or null if the server timeout expires. - /// - public static async Task BLMoveAsync(this IDatabase db, RedisKey source, RedisKey destination, ListSide sourceSide, ListSide destinationSide, double timeout) - { - var command = CoreCommandBuilder.BLMove(source, destination, sourceSide, destinationSide, timeout); - return (await db.ExecuteAsync(command)).ToRedisValue(); - } + /// + /// The BLMOVE command. + ///

+ /// Atomically returns and removes the first or last element of the list stored at + /// (depending on the value of ), and pushes the element as the first or last + /// element of the list stored at (depending on the value of + /// ). + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// The key of the source list. + /// The key of the destination list. + /// What side of the list to remove from. + /// What side of the list to move to. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// The element being popped and pushed, or null if the server timeout expires. + /// + public static async Task BLMoveAsync(this IDatabase db, RedisKey source, RedisKey destination, ListSide sourceSide, ListSide destinationSide, double timeout) + { + var command = CoreCommandBuilder.BLMove(source, destination, sourceSide, destinationSide, timeout); + return (await db.ExecuteAsync(command)).ToRedisValue(); + } - /// - /// The BRPOPLPUSH command. - ///

- /// Atomically returns and removes the last element (tail) of the list stored at source, and pushes the element - /// at the first element (head) of the list stored at destination. - ///

- /// This is an extension method added to the class, for convenience. - ///

- /// The class where this extension method is applied. - /// The key of the source list. - /// The key of the destination list. - /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. - /// The element being popped and pushed, or null if the server timeout expires. - /// - public static async Task BRPopLPushAsync(this IDatabase db, RedisKey source, RedisKey destination, double timeout) - { - var command = CoreCommandBuilder.BRPopLPush(source, destination, timeout); - return (await db.ExecuteAsync(command)).ToRedisValue(); - } + /// + /// The BRPOPLPUSH command. + ///

+ /// Atomically returns and removes the last element (tail) of the list stored at source, and pushes the element + /// at the first element (head) of the list stored at destination. + ///

+ /// This is an extension method added to the class, for convenience. + ///

+ /// The class where this extension method is applied. + /// The key of the source list. + /// The key of the destination list. + /// Server-side timeout for the wait. A value of 0 means to wait indefinitely. + /// The element being popped and pushed, or null if the server timeout expires. + /// + public static async Task BRPopLPushAsync(this IDatabase db, RedisKey source, RedisKey destination, double timeout) + { + var command = CoreCommandBuilder.BRPopLPush(source, destination, timeout); + return (await db.ExecuteAsync(command)).ToRedisValue(); + } - /// - /// The XREAD command. - /// - /// Read data from one or multiple streams, only returning entries with an ID greater than an ID provided by the caller. - /// - /// The class where this extension method is applied. - /// Keys of the streams where to read from. - /// The positions from which to begin reading for each stream. See - /// for special Ids that can be used. - /// The maximum number of messages to return from each stream. - /// Amount of time in milliseconds to block in case all the streams are empty. - /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. - /// A value of for each stream, or null if the command times out - /// on the server. - /// - /// This is the blocking alternative for . - /// - /// - public static async Task XReadAsync(this IDatabase db, RedisKey[] keys, RedisValue[] positions, int? count = null, int? timeoutMilliseconds = null) - { - var command = CoreCommandBuilder.XRead(keys, positions, count, timeoutMilliseconds); - return (await db.ExecuteAsync(command)).ToRedisStreamEntries(); - } + /// + /// The XREAD command. + /// + /// Read data from one or multiple streams, only returning entries with an ID greater than an ID provided by the caller. + /// + /// The class where this extension method is applied. + /// Keys of the streams where to read from. + /// The positions from which to begin reading for each stream. See + /// for special Ids that can be used. + /// The maximum number of messages to return from each stream. + /// Amount of time in milliseconds to block in case all the streams are empty. + /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. + /// A value of for each stream, or null if the command times out + /// on the server. + /// + /// This is the blocking alternative for . + /// + /// + public static async Task XReadAsync(this IDatabase db, RedisKey[] keys, RedisValue[] positions, int? count = null, int? timeoutMilliseconds = null) + { + var command = CoreCommandBuilder.XRead(keys, positions, count, timeoutMilliseconds); + return (await db.ExecuteAsync(command)).ToRedisStreamEntries(); + } - /// - /// Syntactic sugar for , - /// where only one stream is being read from. - /// - /// The class where this extension method is applied. - /// Key of the stream where to read from. - /// The position from which to begin reading. See - /// for special Ids that can be used. - /// The maximum number of messages to return from each stream. - /// Amount of time in milliseconds to block in case all the streams are empty. - /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. - /// A list with the data read from the stream, of null if the command - /// times out on the server. - /// - /// This is the blocking alternative for . - /// - /// - public static async Task XReadAsync(this IDatabase db, RedisKey key, RedisValue position, int? count = null, int? timeoutMilliseconds = null) + /// + /// Syntactic sugar for , + /// where only one stream is being read from. + /// + /// The class where this extension method is applied. + /// Key of the stream where to read from. + /// The position from which to begin reading. See + /// for special Ids that can be used. + /// The maximum number of messages to return from each stream. + /// Amount of time in milliseconds to block in case all the streams are empty. + /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. + /// A list with the data read from the stream, of null if the command + /// times out on the server. + /// + /// This is the blocking alternative for . + /// + /// + public static async Task XReadAsync(this IDatabase db, RedisKey key, RedisValue position, int? count = null, int? timeoutMilliseconds = null) + { + var result = await XReadAsync(db, [key], [position], count, timeoutMilliseconds); + if (result == null || result.Length == 0) { - var result = await XReadAsync(db, new[] { key }, new[] { position }, count, timeoutMilliseconds); - if (result == null || result.Length == 0) - { - return null; - } - return result[0].Entries; + return null; } + return result[0].Entries; + } - /// - /// The XREADGROUP command. - /// - /// Read new or historical messages in one or several streams, for a consumer in a consumer group. - /// - /// The class where this extension method is applied. - /// The consumer group name. - /// The name of the consumer in the consumer group. - /// Keys of the streams where to read from. - /// The positions from which to begin reading for each stream. See - /// for special Ids that can be used. - /// The maximum number of messages to return from each stream. - /// Amount of time in milliseconds to block in case all the streams are empty. - /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. - /// If set to true then inform the server that it should not wait for ACK for the - /// messages it sends to this read call. - /// A value of for each stream, or null if the command times out - /// on the server. - /// - /// This is the blocking alternative for . - /// - /// - public static async Task XReadGroupAsync(this IDatabase db, RedisValue groupName, RedisValue consumerName, RedisKey[] keys, RedisValue[] positions, int? count = null, int? timeoutMilliseconds = null, bool? noAck = null) - { - var command = CoreCommandBuilder.XReadGroup(groupName, consumerName, keys, positions, count, timeoutMilliseconds, noAck); - return (await db.ExecuteAsync(command)).ToRedisStreamEntries(); - } + /// + /// The XREADGROUP command. + /// + /// Read new or historical messages in one or several streams, for a consumer in a consumer group. + /// + /// The class where this extension method is applied. + /// The consumer group name. + /// The name of the consumer in the consumer group. + /// Keys of the streams where to read from. + /// The positions from which to begin reading for each stream. See + /// for special Ids that can be used. + /// The maximum number of messages to return from each stream. + /// Amount of time in milliseconds to block in case all the streams are empty. + /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. + /// If set to true then inform the server that it should not wait for ACK for the + /// messages it sends to this read call. + /// A value of for each stream, or null if the command times out + /// on the server. + /// + /// This is the blocking alternative for . + /// + /// + public static async Task XReadGroupAsync(this IDatabase db, RedisValue groupName, RedisValue consumerName, RedisKey[] keys, RedisValue[] positions, int? count = null, int? timeoutMilliseconds = null, bool? noAck = null) + { + var command = CoreCommandBuilder.XReadGroup(groupName, consumerName, keys, positions, count, timeoutMilliseconds, noAck); + return (await db.ExecuteAsync(command)).ToRedisStreamEntries(); + } - /// - /// Syntactic sugar for , - /// where only one stream is being read from. - /// - /// The class where this extension method is applied. - /// The consumer group name. - /// The name of the consumer in the consumer group. - /// Key of the stream where to read from. - /// The position from which to begin reading. See - /// for special Ids that can be used. - /// The maximum number of messages to return from each stream. - /// Amount of time in milliseconds to block in case all the streams are empty. - /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. - /// If set to true then inform the server that it should not wait for ACK for the - /// messages it sends to this read call. - /// A list with the data read from the stream, of null if the command - /// times out on the server. - /// - /// This is the blocking alternative for . - /// - /// - public static async Task XReadGroupAsync(this IDatabase db, RedisValue groupName, RedisValue consumerName, RedisKey key, RedisValue position, int? count = null, int? timeoutMilliseconds = null, bool? noAck = null) + /// + /// Syntactic sugar for , + /// where only one stream is being read from. + /// + /// The class where this extension method is applied. + /// The consumer group name. + /// The name of the consumer in the consumer group. + /// Key of the stream where to read from. + /// The position from which to begin reading. See + /// for special Ids that can be used. + /// The maximum number of messages to return from each stream. + /// Amount of time in milliseconds to block in case all the streams are empty. + /// If not provided, or set to null then the read does not block. If set to 0 then it blocks indefinitely. + /// If set to true then inform the server that it should not wait for ACK for the + /// messages it sends to this read call. + /// A list with the data read from the stream, of null if the command + /// times out on the server. + /// + /// This is the blocking alternative for . + /// + /// + public static async Task XReadGroupAsync(this IDatabase db, RedisValue groupName, RedisValue consumerName, RedisKey key, RedisValue position, int? count = null, int? timeoutMilliseconds = null, bool? noAck = null) + { + var result = await XReadGroupAsync(db, groupName, consumerName, [key], [position], count, timeoutMilliseconds, noAck); + if (result == null || result.Length == 0) { - var result = await XReadGroupAsync(db, groupName, consumerName, new[] { key }, new[] { position }, count, timeoutMilliseconds, noAck); - if (result == null || result.Length == 0) - { - return null; - } - return result[0].Entries; + return null; } + return result[0].Entries; } -} +} \ No newline at end of file diff --git a/src/NRedisStack/CoreCommands/Literals/CommandArgs.cs b/src/NRedisStack/CoreCommands/Literals/CommandArgs.cs index edb8142f..a726b67a 100644 --- a/src/NRedisStack/CoreCommands/Literals/CommandArgs.cs +++ b/src/NRedisStack/CoreCommands/Literals/CommandArgs.cs @@ -1,17 +1,16 @@ -namespace NRedisStack.Core.Literals +namespace NRedisStack.Core.Literals; + +internal static class CoreArgs { - internal static class CoreArgs - { - public const string BLOCK = "BLOCK"; - public const string COUNT = "COUNT"; - public const string GROUP = "GROUP"; - public const string LEFT = "LEFT"; - public const string MAX = "MAX"; - public const string MIN = "MIN"; - public const string NOACK = "NOACK"; - public const string RIGHT = "RIGHT"; - public const string STREAMS = "STREAMS"; - public const string lib_name = "LIB-NAME"; - public const string lib_ver = "LIB-VER"; - } -} + public const string BLOCK = "BLOCK"; + public const string COUNT = "COUNT"; + public const string GROUP = "GROUP"; + public const string LEFT = "LEFT"; + public const string MAX = "MAX"; + public const string MIN = "MIN"; + public const string NOACK = "NOACK"; + public const string RIGHT = "RIGHT"; + public const string STREAMS = "STREAMS"; + public const string lib_name = "LIB-NAME"; + public const string lib_ver = "LIB-VER"; +} \ No newline at end of file diff --git a/src/NRedisStack/CoreCommands/Literals/Commands.cs b/src/NRedisStack/CoreCommands/Literals/Commands.cs index 2b312449..c4962025 100644 --- a/src/NRedisStack/CoreCommands/Literals/Commands.cs +++ b/src/NRedisStack/CoreCommands/Literals/Commands.cs @@ -1,21 +1,20 @@ -namespace NRedisStack.Core.Literals +namespace NRedisStack.Core.Literals; + +/// +/// Redis Core command literals +/// +internal static class RedisCoreCommands { - /// - /// Redis Core command literals - /// - internal static class RedisCoreCommands - { - public const string BLMOVE = "BLMOVE"; - public const string BLMPOP = "BLMPOP"; - public const string BLPOP = "BLPOP"; - public const string BRPOP = "BRPOP"; - public const string BRPOPLPUSH = "BRPOPLPUSH"; - public const string BZMPOP = "BZMPOP"; - public const string BZPOPMAX = "BZPOPMAX"; - public const string BZPOPMIN = "BZPOPMIN"; - public const string CLIENT = "CLIENT"; - public const string SETINFO = "SETINFO"; - public const string XREAD = "XREAD"; - public const string XREADGROUP = "XREADGROUP"; - } -} + public const string BLMOVE = "BLMOVE"; + public const string BLMPOP = "BLMPOP"; + public const string BLPOP = "BLPOP"; + public const string BRPOP = "BRPOP"; + public const string BRPOPLPUSH = "BRPOPLPUSH"; + public const string BZMPOP = "BZMPOP"; + public const string BZPOPMAX = "BZPOPMAX"; + public const string BZPOPMIN = "BZPOPMIN"; + public const string CLIENT = "CLIENT"; + public const string SETINFO = "SETINFO"; + public const string XREAD = "XREAD"; + public const string XREADGROUP = "XREADGROUP"; +} \ No newline at end of file diff --git a/src/NRedisStack/CountMinSketch/CmsCommandBuilder.cs b/src/NRedisStack/CountMinSketch/CmsCommandBuilder.cs index 7e6299ab..33ceb99b 100644 --- a/src/NRedisStack/CountMinSketch/CmsCommandBuilder.cs +++ b/src/NRedisStack/CountMinSketch/CmsCommandBuilder.cs @@ -8,7 +8,7 @@ public static class CmsCommandBuilder { public static SerializedCommand IncrBy(RedisKey key, RedisValue item, long increment) { - return new SerializedCommand(CMS.INCRBY, key, item, increment); + return new(CMS.INCRBY, key, item, increment); } public static SerializedCommand IncrBy(RedisKey key, Tuple[] itemIncrements) @@ -16,14 +16,14 @@ public static SerializedCommand IncrBy(RedisKey key, Tuple[] i if (itemIncrements.Length < 1) throw new ArgumentOutOfRangeException(nameof(itemIncrements)); - List args = new List { key }; + List args = [key]; foreach (var pair in itemIncrements) { args.Add(pair.Item1); args.Add(pair.Item2); } - return new SerializedCommand(CMS.INCRBY, args); + return new(CMS.INCRBY, args); } public static SerializedCommand Info(RedisKey key) @@ -34,12 +34,12 @@ public static SerializedCommand Info(RedisKey key) public static SerializedCommand InitByDim(RedisKey key, long width, long depth) { - return new SerializedCommand(CMS.INITBYDIM, key, width, depth); + return new(CMS.INITBYDIM, key, width, depth); } public static SerializedCommand InitByProb(RedisKey key, double error, double probability) { - return new SerializedCommand(CMS.INITBYPROB, key, error, probability); + return new(CMS.INITBYPROB, key, error, probability); } public static SerializedCommand Merge(RedisValue destination, long numKeys, RedisValue[] source, @@ -48,7 +48,7 @@ public static SerializedCommand Merge(RedisValue destination, long numKeys, Redi if (source.Length < 1) throw new ArgumentOutOfRangeException(nameof(source)); - List args = new List { destination, numKeys }; + List args = [destination, numKeys]; foreach (var s in source) args.Add(s); @@ -58,7 +58,7 @@ public static SerializedCommand Merge(RedisValue destination, long numKeys, Redi foreach (var w in weight) args.Add(w); } - return new SerializedCommand(CMS.MERGE, args); + return new(CMS.MERGE, args); } public static SerializedCommand Query(RedisKey key, params RedisValue[] items) @@ -66,9 +66,9 @@ public static SerializedCommand Query(RedisKey key, params RedisValue[] items) if (items.Length < 1) throw new ArgumentOutOfRangeException(nameof(items)); - List args = new List { key }; + List args = [key]; foreach (var item in items) args.Add(item); - return new SerializedCommand(CMS.QUERY, args); + return new(CMS.QUERY, args); } } \ No newline at end of file diff --git a/src/NRedisStack/CountMinSketch/DataTypes/CmsInformation.cs b/src/NRedisStack/CountMinSketch/DataTypes/CmsInformation.cs index cb97b5e4..9f5ac260 100644 --- a/src/NRedisStack/CountMinSketch/DataTypes/CmsInformation.cs +++ b/src/NRedisStack/CountMinSketch/DataTypes/CmsInformation.cs @@ -1,21 +1,20 @@ -namespace NRedisStack.CountMinSketch.DataTypes +namespace NRedisStack.CountMinSketch.DataTypes; + +/// +/// This class represents the response for CMS.INFO command. +/// This object has Read-only properties and cannot be generated outside a CMS.INFO response. +/// +public class CmsInformation { - /// - /// This class represents the response for CMS.INFO command. - /// This object has Read-only properties and cannot be generated outside a CMS.INFO response. - /// - public class CmsInformation - { - public long Width { get; private set; } - public long Depth { get; private set; } - public long Count { get; private set; } + public long Width { get; private set; } + public long Depth { get; private set; } + public long Count { get; private set; } - internal CmsInformation(long width, long depth, long count) - { - Width = width; - Depth = depth; - Count = count; - } + internal CmsInformation(long width, long depth, long count) + { + Width = width; + Depth = depth; + Count = count; } } \ No newline at end of file diff --git a/src/NRedisStack/CountMinSketch/ICmsCommands.cs b/src/NRedisStack/CountMinSketch/ICmsCommands.cs index ca98a1db..178d9cfa 100644 --- a/src/NRedisStack/CountMinSketch/ICmsCommands.cs +++ b/src/NRedisStack/CountMinSketch/ICmsCommands.cs @@ -1,77 +1,76 @@ using NRedisStack.CountMinSketch.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public interface ICmsCommands { - public interface ICmsCommands - { - /// - /// Increases the count of item by increment. - /// - /// The name of the sketch. - /// The item which counter is to be increased. - /// Amount by which the item counter is to be increased. - /// Count of each item after increment. - /// - long IncrBy(RedisKey key, RedisValue item, long increment); + /// + /// Increases the count of item by increment. + /// + /// The name of the sketch. + /// The item which counter is to be increased. + /// Amount by which the item counter is to be increased. + /// Count of each item after increment. + /// + long IncrBy(RedisKey key, RedisValue item, long increment); - /// - /// Increases the count of item by increment. - /// - /// The name of the sketch. - /// Tuple of The items which counter is to be increased - /// and the Amount by which the item counter is to be increased. - /// Count of each item after increment. - /// - long[] IncrBy(RedisKey key, Tuple[] itemIncrements); + /// + /// Increases the count of item by increment. + /// + /// The name of the sketch. + /// Tuple of The items which counter is to be increased + /// and the Amount by which the item counter is to be increased. + /// Count of each item after increment. + /// + long[] IncrBy(RedisKey key, Tuple[] itemIncrements); - /// - /// Return information about a sketch. - /// - /// Name of the key to return information about. - /// Information of the sketch. - /// - CmsInformation Info(RedisKey key); + /// + /// Return information about a sketch. + /// + /// Name of the key to return information about. + /// Information of the sketch. + /// + CmsInformation Info(RedisKey key); - /// - /// Initializes a Count-Min Sketch to dimensions specified by user. - /// - /// TThe name of the sketch. - /// Number of counters in each array. Reduces the error size. - /// Number of counter-arrays. Reduces the probability for an error - /// of a certain size (percentage of total count). - /// if if executed correctly, Error otherwise. - /// - bool InitByDim(RedisKey key, long width, long depth); + /// + /// Initializes a Count-Min Sketch to dimensions specified by user. + /// + /// TThe name of the sketch. + /// Number of counters in each array. Reduces the error size. + /// Number of counter-arrays. Reduces the probability for an error + /// of a certain size (percentage of total count). + /// if if executed correctly, Error otherwise. + /// + bool InitByDim(RedisKey key, long width, long depth); - /// - /// Initializes a Count-Min Sketch to accommodate requested tolerances. - /// - /// The name of the sketch. - /// Estimate size of error. - /// The desired probability for inflated count. - /// if if executed correctly, Error otherwise. - /// - bool InitByProb(RedisKey key, double error, double probability); + /// + /// Initializes a Count-Min Sketch to accommodate requested tolerances. + /// + /// The name of the sketch. + /// Estimate size of error. + /// The desired probability for inflated count. + /// if if executed correctly, Error otherwise. + /// + bool InitByProb(RedisKey key, double error, double probability); - /// - /// Merges several sketches into one sketch. - /// - /// The name of destination sketch. Must be initialized - /// Number of sketches to be merged. - /// Names of source sketches to be merged. - /// Multiple of each sketch. Default = 1. - /// if if executed correctly, Error otherwise. - /// - bool Merge(RedisValue destination, long numKeys, RedisValue[] source, long[]? weight = null); + /// + /// Merges several sketches into one sketch. + /// + /// The name of destination sketch. Must be initialized + /// Number of sketches to be merged. + /// Names of source sketches to be merged. + /// Multiple of each sketch. Default = 1. + /// if if executed correctly, Error otherwise. + /// + bool Merge(RedisValue destination, long numKeys, RedisValue[] source, long[]? weight = null); - /// - /// Returns the count for one or more items in a sketch. - /// - /// The name of the sketch - /// One or more items for which to return the count. - /// Array with a min-count of each of the items in the sketch - /// - long[] Query(RedisKey key, params RedisValue[] items); - } + /// + /// Returns the count for one or more items in a sketch. + /// + /// The name of the sketch + /// One or more items for which to return the count. + /// Array with a min-count of each of the items in the sketch + /// + long[] Query(RedisKey key, params RedisValue[] items); } \ No newline at end of file diff --git a/src/NRedisStack/CountMinSketch/ICmsCommandsAsync.cs b/src/NRedisStack/CountMinSketch/ICmsCommandsAsync.cs index fb483a5d..1562d70f 100644 --- a/src/NRedisStack/CountMinSketch/ICmsCommandsAsync.cs +++ b/src/NRedisStack/CountMinSketch/ICmsCommandsAsync.cs @@ -1,77 +1,76 @@ using NRedisStack.CountMinSketch.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public interface ICmsCommandsAsync { - public interface ICmsCommandsAsync - { - /// - /// Increases the count of item by increment. - /// - /// The name of the sketch. - /// The item which counter is to be increased. - /// Amount by which the item counter is to be increased. - /// Count of each item after increment. - /// - Task IncrByAsync(RedisKey key, RedisValue item, long increment); + /// + /// Increases the count of item by increment. + /// + /// The name of the sketch. + /// The item which counter is to be increased. + /// Amount by which the item counter is to be increased. + /// Count of each item after increment. + /// + Task IncrByAsync(RedisKey key, RedisValue item, long increment); - /// - /// Increases the count of item by increment. - /// - /// The name of the sketch. - /// Tuple of The items which counter is to be increased - /// and the Amount by which the item counter is to be increased. - /// Count of each item after increment. - /// - Task IncrByAsync(RedisKey key, Tuple[] itemIncrements); + /// + /// Increases the count of item by increment. + /// + /// The name of the sketch. + /// Tuple of The items which counter is to be increased + /// and the Amount by which the item counter is to be increased. + /// Count of each item after increment. + /// + Task IncrByAsync(RedisKey key, Tuple[] itemIncrements); - /// - /// Return information about a sketch. - /// - /// Name of the key to return information about. - /// Information of the sketch. - /// - Task InfoAsync(RedisKey key); + /// + /// Return information about a sketch. + /// + /// Name of the key to return information about. + /// Information of the sketch. + /// + Task InfoAsync(RedisKey key); - /// - /// Initializes a Count-Min Sketch to dimensions specified by user. - /// - /// TThe name of the sketch. - /// Number of counters in each array. Reduces the error size. - /// Number of counter-arrays. Reduces the probability for an error - /// of a certain size (percentage of total count). - /// if if executed correctly, Error otherwise. - /// - Task InitByDimAsync(RedisKey key, long width, long depth); + /// + /// Initializes a Count-Min Sketch to dimensions specified by user. + /// + /// TThe name of the sketch. + /// Number of counters in each array. Reduces the error size. + /// Number of counter-arrays. Reduces the probability for an error + /// of a certain size (percentage of total count). + /// if if executed correctly, Error otherwise. + /// + Task InitByDimAsync(RedisKey key, long width, long depth); - /// - /// Initializes a Count-Min Sketch to accommodate requested tolerances. - /// - /// The name of the sketch. - /// Estimate size of error. - /// The desired probability for inflated count. - /// if if executed correctly, Error otherwise. - /// - Task InitByProbAsync(RedisKey key, double error, double probability); + /// + /// Initializes a Count-Min Sketch to accommodate requested tolerances. + /// + /// The name of the sketch. + /// Estimate size of error. + /// The desired probability for inflated count. + /// if if executed correctly, Error otherwise. + /// + Task InitByProbAsync(RedisKey key, double error, double probability); - /// - /// Merges several sketches into one sketch. - /// - /// The name of destination sketch. Must be initialized - /// Number of sketches to be merged. - /// Names of source sketches to be merged. - /// Multiple of each sketch. Default = 1. - /// if if executed correctly, Error otherwise. - /// - Task MergeAsync(RedisValue destination, long numKeys, RedisValue[] source, long[]? weight = null); + /// + /// Merges several sketches into one sketch. + /// + /// The name of destination sketch. Must be initialized + /// Number of sketches to be merged. + /// Names of source sketches to be merged. + /// Multiple of each sketch. Default = 1. + /// if if executed correctly, Error otherwise. + /// + Task MergeAsync(RedisValue destination, long numKeys, RedisValue[] source, long[]? weight = null); - /// - /// Returns the count for one or more items in a sketch. - /// - /// The name of the sketch - /// One or more items for which to return the count. - /// Array with a min-count of each of the items in the sketch - /// - Task QueryAsync(RedisKey key, params RedisValue[] items); - } + /// + /// Returns the count for one or more items in a sketch. + /// + /// The name of the sketch + /// One or more items for which to return the count. + /// Array with a min-count of each of the items in the sketch + /// + Task QueryAsync(RedisKey key, params RedisValue[] items); } \ No newline at end of file diff --git a/src/NRedisStack/CountMinSketch/Literals/CommandArgs.cs b/src/NRedisStack/CountMinSketch/Literals/CommandArgs.cs index 0890cb31..9f9817eb 100644 --- a/src/NRedisStack/CountMinSketch/Literals/CommandArgs.cs +++ b/src/NRedisStack/CountMinSketch/Literals/CommandArgs.cs @@ -1,7 +1,6 @@ -namespace NRedisStack.CountMinSketch.Literals +namespace NRedisStack.CountMinSketch.Literals; + +internal class CmsArgs { - internal class CmsArgs - { - public const string WEIGHTS = "WEIGHTS"; - } + public const string WEIGHTS = "WEIGHTS"; } \ No newline at end of file diff --git a/src/NRedisStack/CountMinSketch/Literals/Commands.cs b/src/NRedisStack/CountMinSketch/Literals/Commands.cs index b0a7060f..5f38139a 100644 --- a/src/NRedisStack/CountMinSketch/Literals/Commands.cs +++ b/src/NRedisStack/CountMinSketch/Literals/Commands.cs @@ -1,12 +1,11 @@ -namespace NRedisStack.CountMinSketch.Literals +namespace NRedisStack.CountMinSketch.Literals; + +internal class CMS { - internal class CMS - { - public const string INITBYDIM = "CMS.INITBYDIM"; - public const string INITBYPROB = "CMS.INITBYPROB"; - public const string INCRBY = "CMS.INCRBY"; - public const string QUERY = "CMS.QUERY"; - public const string MERGE = "CMS.MERGE"; - public const string INFO = "CMS.INFO"; - } + public const string INITBYDIM = "CMS.INITBYDIM"; + public const string INITBYPROB = "CMS.INITBYPROB"; + public const string INCRBY = "CMS.INCRBY"; + public const string QUERY = "CMS.QUERY"; + public const string MERGE = "CMS.MERGE"; + public const string INFO = "CMS.INFO"; } \ No newline at end of file diff --git a/src/NRedisStack/CuckooFilter/CuckooCommandBuilder.cs b/src/NRedisStack/CuckooFilter/CuckooCommandBuilder.cs index bb8fb957..0560509a 100644 --- a/src/NRedisStack/CuckooFilter/CuckooCommandBuilder.cs +++ b/src/NRedisStack/CuckooFilter/CuckooCommandBuilder.cs @@ -1,145 +1,144 @@ using NRedisStack.CuckooFilter.Literals; using NRedisStack.RedisStackCommands; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public static class CuckooCommandBuilder { - public static class CuckooCommandBuilder + + public static SerializedCommand Add(RedisKey key, RedisValue item) { + return new(CF.ADD, key, item); + } - public static SerializedCommand Add(RedisKey key, RedisValue item) - { - return new SerializedCommand(CF.ADD, key, item); - } + public static SerializedCommand AddNX(RedisKey key, RedisValue item) + { + return new(CF.ADDNX, key, item); + } - public static SerializedCommand AddNX(RedisKey key, RedisValue item) - { - return new SerializedCommand(CF.ADDNX, key, item); - } + public static SerializedCommand Count(RedisKey key, RedisValue item) + { + return new(CF.COUNT, key, item); + } - public static SerializedCommand Count(RedisKey key, RedisValue item) - { - return new SerializedCommand(CF.COUNT, key, item); - } + public static SerializedCommand Del(RedisKey key, RedisValue item) + { + return new(CF.DEL, key, item); + } - public static SerializedCommand Del(RedisKey key, RedisValue item) - { - return new SerializedCommand(CF.DEL, key, item); - } + public static SerializedCommand Exists(RedisKey key, RedisValue item) + { + return new(CF.EXISTS, key, item); + } + + public static SerializedCommand Info(RedisKey key) + { + var info = new SerializedCommand(CF.INFO, key); + return info; + } + + public static SerializedCommand Insert(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) + { + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); - public static SerializedCommand Exists(RedisKey key, RedisValue item) + List args = [key]; + + if (capacity != null) { - return new SerializedCommand(CF.EXISTS, key, item); + args.Add(CuckooArgs.CAPACITY); + args.Add(capacity); } - public static SerializedCommand Info(RedisKey key) + if (nocreate) { - var info = new SerializedCommand(CF.INFO, key); - return info; + args.Add(CuckooArgs.NOCREATE); } - public static SerializedCommand Insert(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) + args.Add(CuckooArgs.ITEMS); + foreach (var item in items) { - if (items.Length < 1) - throw new ArgumentOutOfRangeException(nameof(items)); - - List args = new List { key }; + args.Add(item); + } - if (capacity != null) - { - args.Add(CuckooArgs.CAPACITY); - args.Add(capacity); - } + return new(CF.INSERT, args); + } - if (nocreate) - { - args.Add(CuckooArgs.NOCREATE); - } + public static SerializedCommand InsertNX(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) + { + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); - args.Add(CuckooArgs.ITEMS); - foreach (var item in items) - { - args.Add(item); - } + List args = [key]; - return new SerializedCommand(CF.INSERT, args); + if (capacity != null) + { + args.Add(CuckooArgs.CAPACITY); + args.Add(capacity); } - public static SerializedCommand InsertNX(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) + if (nocreate) { - if (items.Length < 1) - throw new ArgumentOutOfRangeException(nameof(items)); + args.Add(CuckooArgs.NOCREATE); + } - List args = new List { key }; + args.Add(CuckooArgs.ITEMS); + foreach (var item in items) + { + args.Add(item); + } - if (capacity != null) - { - args.Add(CuckooArgs.CAPACITY); - args.Add(capacity); - } + return new(CF.INSERTNX, args); + } - if (nocreate) - { - args.Add(CuckooArgs.NOCREATE); - } + public static SerializedCommand LoadChunk(RedisKey key, long iterator, Byte[] data) + { + return new(CF.LOADCHUNK, key, iterator, data); + } - args.Add(CuckooArgs.ITEMS); - foreach (var item in items) - { - args.Add(item); - } + public static SerializedCommand MExists(RedisKey key, params RedisValue[] items) + { + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); - return new SerializedCommand(CF.INSERTNX, args); - } + List args = [key]; - public static SerializedCommand LoadChunk(RedisKey key, long iterator, Byte[] data) + foreach (var item in items) { - return new SerializedCommand(CF.LOADCHUNK, key, iterator, data); + args.Add(item); } - public static SerializedCommand MExists(RedisKey key, params RedisValue[] items) - { - if (items.Length < 1) - throw new ArgumentOutOfRangeException(nameof(items)); - - List args = new List { key }; + return new(CF.MEXISTS, args); + } - foreach (var item in items) - { - args.Add(item); - } + public static SerializedCommand Reserve(RedisKey key, long capacity, + long? bucketSize = null, int? maxIterations = null, int? expansion = null) + { + List args = [key, capacity]; - return new SerializedCommand(CF.MEXISTS, args); + if (bucketSize != null) + { + args.Add(CuckooArgs.BUCKETSIZE); + args.Add(bucketSize); } - public static SerializedCommand Reserve(RedisKey key, long capacity, - long? bucketSize = null, int? maxIterations = null, int? expansion = null) + if (maxIterations != null) { - List args = new List { key, capacity }; - - if (bucketSize != null) - { - args.Add(CuckooArgs.BUCKETSIZE); - args.Add(bucketSize); - } - - if (maxIterations != null) - { - args.Add(CuckooArgs.MAXITERATIONS); - args.Add(maxIterations); - } - - if (expansion != null) - { - args.Add(CuckooArgs.EXPANSION); - args.Add(expansion); - } - - return new SerializedCommand(CF.RESERVE, args); + args.Add(CuckooArgs.MAXITERATIONS); + args.Add(maxIterations); } - public static SerializedCommand ScanDump(RedisKey key, long iterator) + if (expansion != null) { - return new SerializedCommand(CF.SCANDUMP, key, iterator); + args.Add(CuckooArgs.EXPANSION); + args.Add(expansion); } + + return new(CF.RESERVE, args); + } + + public static SerializedCommand ScanDump(RedisKey key, long iterator) + { + return new(CF.SCANDUMP, key, iterator); } } \ No newline at end of file diff --git a/src/NRedisStack/CuckooFilter/CuckooCommands.cs b/src/NRedisStack/CuckooFilter/CuckooCommands.cs index c894b877..903b9db3 100644 --- a/src/NRedisStack/CuckooFilter/CuckooCommands.cs +++ b/src/NRedisStack/CuckooFilter/CuckooCommands.cs @@ -1,87 +1,85 @@ using NRedisStack.CuckooFilter.DataTypes; using StackExchange.Redis; -namespace NRedisStack -{ +namespace NRedisStack; - public class CuckooCommands : CuckooCommandsAsync, ICuckooCommands +public class CuckooCommands : CuckooCommandsAsync, ICuckooCommands +{ + readonly IDatabase _db; + public CuckooCommands(IDatabase db) : base(db) { - IDatabase _db; - public CuckooCommands(IDatabase db) : base(db) - { - _db = db; - } + _db = db; + } - /// - public bool Add(RedisKey key, RedisValue item) - { - return _db.Execute(CuckooCommandBuilder.Add(key, item)).ToString() == "1"; - } + /// + public bool Add(RedisKey key, RedisValue item) + { + return _db.Execute(CuckooCommandBuilder.Add(key, item)).ToString() == "1"; + } - /// - public bool AddNX(RedisKey key, RedisValue item) - { - return _db.Execute(CuckooCommandBuilder.AddNX(key, item)).ToString() == "1"; - } + /// + public bool AddNX(RedisKey key, RedisValue item) + { + return _db.Execute(CuckooCommandBuilder.AddNX(key, item)).ToString() == "1"; + } - /// - public long Count(RedisKey key, RedisValue item) - { - return _db.Execute(CuckooCommandBuilder.Count(key, item)).ToLong(); - } + /// + public long Count(RedisKey key, RedisValue item) + { + return _db.Execute(CuckooCommandBuilder.Count(key, item)).ToLong(); + } - /// - public bool Del(RedisKey key, RedisValue item) - { - return _db.Execute(CuckooCommandBuilder.Del(key, item)).ToString() == "1"; - } + /// + public bool Del(RedisKey key, RedisValue item) + { + return _db.Execute(CuckooCommandBuilder.Del(key, item)).ToString() == "1"; + } - /// - public bool Exists(RedisKey key, RedisValue item) - { - return _db.Execute(CuckooCommandBuilder.Exists(key, item)).ToString() == "1"; - } + /// + public bool Exists(RedisKey key, RedisValue item) + { + return _db.Execute(CuckooCommandBuilder.Exists(key, item)).ToString() == "1"; + } - /// - public CuckooInformation Info(RedisKey key) - { - return _db.Execute(CuckooCommandBuilder.Info(key)).ToCuckooInfo(); - } + /// + public CuckooInformation Info(RedisKey key) + { + return _db.Execute(CuckooCommandBuilder.Info(key)).ToCuckooInfo(); + } - /// - public bool[] Insert(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) - { - return _db.Execute(CuckooCommandBuilder.Insert(key, items, capacity, nocreate)).ToBooleanArray(); - } + /// + public bool[] Insert(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) + { + return _db.Execute(CuckooCommandBuilder.Insert(key, items, capacity, nocreate)).ToBooleanArray(); + } - /// - public bool[] InsertNX(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) - { - return _db.Execute(CuckooCommandBuilder.InsertNX(key, items, capacity, nocreate)).ToBooleanArray(); - } + /// + public bool[] InsertNX(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) + { + return _db.Execute(CuckooCommandBuilder.InsertNX(key, items, capacity, nocreate)).ToBooleanArray(); + } - /// - public bool LoadChunk(RedisKey key, long iterator, Byte[] data) - { - return _db.Execute(CuckooCommandBuilder.LoadChunk(key, iterator, data)).OKtoBoolean(); - } + /// + public bool LoadChunk(RedisKey key, long iterator, Byte[] data) + { + return _db.Execute(CuckooCommandBuilder.LoadChunk(key, iterator, data)).OKtoBoolean(); + } - /// - public bool[] MExists(RedisKey key, params RedisValue[] items) - { - return _db.Execute(CuckooCommandBuilder.MExists(key, items)).ToBooleanArray(); - } + /// + public bool[] MExists(RedisKey key, params RedisValue[] items) + { + return _db.Execute(CuckooCommandBuilder.MExists(key, items)).ToBooleanArray(); + } - /// - public bool Reserve(RedisKey key, long capacity, - long? bucketSize = null, int? maxIterations = null, int? expansion = null) - { - return _db.Execute(CuckooCommandBuilder.Reserve(key, capacity, bucketSize, maxIterations, expansion)).OKtoBoolean(); - } + /// + public bool Reserve(RedisKey key, long capacity, + long? bucketSize = null, int? maxIterations = null, int? expansion = null) + { + return _db.Execute(CuckooCommandBuilder.Reserve(key, capacity, bucketSize, maxIterations, expansion)).OKtoBoolean(); + } - /// - public Tuple ScanDump(RedisKey key, long iterator) - { - return _db.Execute(CuckooCommandBuilder.ScanDump(key, iterator)).ToScanDumpTuple(); - } + /// + public Tuple ScanDump(RedisKey key, long iterator) + { + return _db.Execute(CuckooCommandBuilder.ScanDump(key, iterator)).ToScanDumpTuple(); } } \ No newline at end of file diff --git a/src/NRedisStack/CuckooFilter/CuckooCommandsAsync.cs b/src/NRedisStack/CuckooFilter/CuckooCommandsAsync.cs index 81ca3b9e..e247ec1c 100644 --- a/src/NRedisStack/CuckooFilter/CuckooCommandsAsync.cs +++ b/src/NRedisStack/CuckooFilter/CuckooCommandsAsync.cs @@ -1,87 +1,85 @@ using NRedisStack.CuckooFilter.DataTypes; using StackExchange.Redis; -namespace NRedisStack -{ +namespace NRedisStack; - public class CuckooCommandsAsync : ICuckooCommandsAsync +public class CuckooCommandsAsync : ICuckooCommandsAsync +{ + readonly IDatabaseAsync _db; + public CuckooCommandsAsync(IDatabaseAsync db) { - IDatabaseAsync _db; - public CuckooCommandsAsync(IDatabaseAsync db) - { - _db = db; - } + _db = db; + } - /// - public async Task AddAsync(RedisKey key, RedisValue item) - { - return (await _db.ExecuteAsync(CuckooCommandBuilder.Add(key, item))).ToString() == "1"; - } + /// + public async Task AddAsync(RedisKey key, RedisValue item) + { + return (await _db.ExecuteAsync(CuckooCommandBuilder.Add(key, item))).ToString() == "1"; + } - /// - public async Task AddNXAsync(RedisKey key, RedisValue item) - { - return (await _db.ExecuteAsync(CuckooCommandBuilder.AddNX(key, item))).ToString() == "1"; - } + /// + public async Task AddNXAsync(RedisKey key, RedisValue item) + { + return (await _db.ExecuteAsync(CuckooCommandBuilder.AddNX(key, item))).ToString() == "1"; + } - /// - public async Task CountAsync(RedisKey key, RedisValue item) - { - return (await _db.ExecuteAsync(CuckooCommandBuilder.Count(key, item))).ToLong(); - } + /// + public async Task CountAsync(RedisKey key, RedisValue item) + { + return (await _db.ExecuteAsync(CuckooCommandBuilder.Count(key, item))).ToLong(); + } - /// - public async Task DelAsync(RedisKey key, RedisValue item) - { - return (await _db.ExecuteAsync(CuckooCommandBuilder.Del(key, item))).ToString() == "1"; - } + /// + public async Task DelAsync(RedisKey key, RedisValue item) + { + return (await _db.ExecuteAsync(CuckooCommandBuilder.Del(key, item))).ToString() == "1"; + } - /// - public async Task ExistsAsync(RedisKey key, RedisValue item) - { - return (await _db.ExecuteAsync(CuckooCommandBuilder.Exists(key, item))).ToString() == "1"; - } + /// + public async Task ExistsAsync(RedisKey key, RedisValue item) + { + return (await _db.ExecuteAsync(CuckooCommandBuilder.Exists(key, item))).ToString() == "1"; + } - /// - public async Task InfoAsync(RedisKey key) - { - return (await _db.ExecuteAsync(CuckooCommandBuilder.Info(key))).ToCuckooInfo(); - } + /// + public async Task InfoAsync(RedisKey key) + { + return (await _db.ExecuteAsync(CuckooCommandBuilder.Info(key))).ToCuckooInfo(); + } - /// - public async Task InsertAsync(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) - { - return (await _db.ExecuteAsync(CuckooCommandBuilder.Insert(key, items, capacity, nocreate))).ToBooleanArray(); - } + /// + public async Task InsertAsync(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) + { + return (await _db.ExecuteAsync(CuckooCommandBuilder.Insert(key, items, capacity, nocreate))).ToBooleanArray(); + } - /// - public async Task InsertNXAsync(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) - { - return (await _db.ExecuteAsync(CuckooCommandBuilder.InsertNX(key, items, capacity, nocreate))).ToBooleanArray(); - } + /// + public async Task InsertNXAsync(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false) + { + return (await _db.ExecuteAsync(CuckooCommandBuilder.InsertNX(key, items, capacity, nocreate))).ToBooleanArray(); + } - /// - public async Task LoadChunkAsync(RedisKey key, long iterator, Byte[] data) - { - return (await _db.ExecuteAsync(CuckooCommandBuilder.LoadChunk(key, iterator, data))).OKtoBoolean(); - } + /// + public async Task LoadChunkAsync(RedisKey key, long iterator, Byte[] data) + { + return (await _db.ExecuteAsync(CuckooCommandBuilder.LoadChunk(key, iterator, data))).OKtoBoolean(); + } - /// - public async Task MExistsAsync(RedisKey key, params RedisValue[] items) - { - return (await _db.ExecuteAsync(CuckooCommandBuilder.MExists(key, items))).ToBooleanArray(); - } + /// + public async Task MExistsAsync(RedisKey key, params RedisValue[] items) + { + return (await _db.ExecuteAsync(CuckooCommandBuilder.MExists(key, items))).ToBooleanArray(); + } - /// - public async Task ReserveAsync(RedisKey key, long capacity, - long? bucketSize = null, int? maxIterations = null, int? expansion = null) - { - return (await _db.ExecuteAsync(CuckooCommandBuilder.Reserve(key, capacity, bucketSize, maxIterations, expansion))).OKtoBoolean(); - } + /// + public async Task ReserveAsync(RedisKey key, long capacity, + long? bucketSize = null, int? maxIterations = null, int? expansion = null) + { + return (await _db.ExecuteAsync(CuckooCommandBuilder.Reserve(key, capacity, bucketSize, maxIterations, expansion))).OKtoBoolean(); + } - /// - public async Task> ScanDumpAsync(RedisKey key, long iterator) - { - return (await _db.ExecuteAsync(CuckooCommandBuilder.ScanDump(key, iterator))).ToScanDumpTuple(); - } + /// + public async Task> ScanDumpAsync(RedisKey key, long iterator) + { + return (await _db.ExecuteAsync(CuckooCommandBuilder.ScanDump(key, iterator))).ToScanDumpTuple(); } } \ No newline at end of file diff --git a/src/NRedisStack/CuckooFilter/DataTypes/CuckooInformation.cs b/src/NRedisStack/CuckooFilter/DataTypes/CuckooInformation.cs index bcbbac76..659516e0 100644 --- a/src/NRedisStack/CuckooFilter/DataTypes/CuckooInformation.cs +++ b/src/NRedisStack/CuckooFilter/DataTypes/CuckooInformation.cs @@ -1,32 +1,31 @@ -namespace NRedisStack.CuckooFilter.DataTypes +namespace NRedisStack.CuckooFilter.DataTypes; + +/// +/// This class represents the response for CF.INFO command. +/// This object has Read-only properties and cannot be generated outside a CF.INFO response. +/// +public class CuckooInformation { - /// - /// This class represents the response for CF.INFO command. - /// This object has Read-only properties and cannot be generated outside a CF.INFO response. - /// - public class CuckooInformation - { - public long Size { get; private set; } - public long NumberOfBuckets { get; private set; } - public long NumberOfFilters { get; private set; } - public long NumberOfItemsInserted { get; private set; } - public long NumberOfItemsDeleted { get; private set; } - public long BucketSize { get; private set; } - public long ExpansionRate { get; private set; } - public long MaxIterations { get; private set; } + public long Size { get; private set; } + public long NumberOfBuckets { get; private set; } + public long NumberOfFilters { get; private set; } + public long NumberOfItemsInserted { get; private set; } + public long NumberOfItemsDeleted { get; private set; } + public long BucketSize { get; private set; } + public long ExpansionRate { get; private set; } + public long MaxIterations { get; private set; } - internal CuckooInformation(long size, long numberOfBuckets, long numberOfFilter, - long numberOfItemsInserted, long numberOfItemsDeleted, - long bucketSize, long expansionRate, long maxIteration) - { - Size = size; - NumberOfBuckets = numberOfBuckets; - NumberOfFilters = numberOfFilter; - NumberOfItemsInserted = numberOfItemsInserted; - NumberOfItemsDeleted = numberOfItemsDeleted; - BucketSize = bucketSize; - ExpansionRate = expansionRate; - MaxIterations = maxIteration; - } + internal CuckooInformation(long size, long numberOfBuckets, long numberOfFilter, + long numberOfItemsInserted, long numberOfItemsDeleted, + long bucketSize, long expansionRate, long maxIteration) + { + Size = size; + NumberOfBuckets = numberOfBuckets; + NumberOfFilters = numberOfFilter; + NumberOfItemsInserted = numberOfItemsInserted; + NumberOfItemsDeleted = numberOfItemsDeleted; + BucketSize = bucketSize; + ExpansionRate = expansionRate; + MaxIterations = maxIteration; } } \ No newline at end of file diff --git a/src/NRedisStack/CuckooFilter/ICuckooCommands.cs b/src/NRedisStack/CuckooFilter/ICuckooCommands.cs index 1ec87b63..deb32bf3 100644 --- a/src/NRedisStack/CuckooFilter/ICuckooCommands.cs +++ b/src/NRedisStack/CuckooFilter/ICuckooCommands.cs @@ -1,129 +1,128 @@ using NRedisStack.CuckooFilter.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public interface ICuckooCommands { - public interface ICuckooCommands - { - /// - /// Adds an item to a Cuckoo Filter. - /// - /// The key under which the filter is found. - /// The item to add. - /// if the item did not exist in the filter, otherwise. - /// - bool Add(RedisKey key, RedisValue item); + /// + /// Adds an item to a Cuckoo Filter. + /// + /// The key under which the filter is found. + /// The item to add. + /// if the item did not exist in the filter, otherwise. + /// + bool Add(RedisKey key, RedisValue item); - /// - /// Adds an item to a Cuckoo Filter if the item did not exist previously. - /// - /// The key under which the filter is found. - /// The item to add. - /// if the item did not exist in the filter, otherwise. - /// - bool AddNX(RedisKey key, RedisValue item); + /// + /// Adds an item to a Cuckoo Filter if the item did not exist previously. + /// + /// The key under which the filter is found. + /// The item to add. + /// if the item did not exist in the filter, otherwise. + /// + bool AddNX(RedisKey key, RedisValue item); - /// - /// Returns the number of times an item may be in the filter. - /// - /// The name of the filter - /// The item to count. - /// the count of possible matching copies of the item in the filter. - /// - long Count(RedisKey key, RedisValue item); + /// + /// Returns the number of times an item may be in the filter. + /// + /// The name of the filter + /// The item to count. + /// the count of possible matching copies of the item in the filter. + /// + long Count(RedisKey key, RedisValue item); - /// - /// Deletes an item from the Cuckoo Filter. - /// - /// The name of the filter - /// The item to delete from the filter. - /// see langword="true"/> if the item has been deleted from the filter, otherwise. - /// - bool Del(RedisKey key, RedisValue item); + /// + /// Deletes an item from the Cuckoo Filter. + /// + /// The name of the filter + /// The item to delete from the filter. + /// see langword="true"/> if the item has been deleted from the filter, otherwise. + /// + bool Del(RedisKey key, RedisValue item); - /// - /// Checks whether an item exist in the Cuckoo Filter or not. - /// - /// The name of the filter. - /// The item to check for. - /// means the item may exist in the filter, - /// and means it does not exist in the filter. - /// - bool Exists(RedisKey key, RedisValue item); + /// + /// Checks whether an item exist in the Cuckoo Filter or not. + /// + /// The name of the filter. + /// The item to check for. + /// means the item may exist in the filter, + /// and means it does not exist in the filter. + /// + bool Exists(RedisKey key, RedisValue item); - /// - /// Return information about a Cuckoo filter. - /// - /// Name of the key to return information about. - /// Information of the filter. - /// - CuckooInformation Info(RedisKey key); + /// + /// Return information about a Cuckoo filter. + /// + /// Name of the key to return information about. + /// Information of the filter. + /// + CuckooInformation Info(RedisKey key); - /// - /// Adds one or more items to a Cuckoo Filter. A filter will be created if it does not exist. - /// - /// The name of the filter. - /// One or more items to add. - /// (Optional) Specifies the desired capacity for the filter to be created. - /// (Optional) to indicates that the filter should not be created if it does not already exist. - /// An array of booleans. - /// - bool[] Insert(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false); + /// + /// Adds one or more items to a Cuckoo Filter. A filter will be created if it does not exist. + /// + /// The name of the filter. + /// One or more items to add. + /// (Optional) Specifies the desired capacity for the filter to be created. + /// (Optional) to indicates that the filter should not be created if it does not already exist. + /// An array of booleans. + /// + bool[] Insert(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false); - /// - /// Adds one or more items to a Cuckoo Filter if the items did not exist previously. - /// A filter will be created if it does not exist. - /// - /// The name of the filter. - /// One or more items to add. - /// (Optional) Specifies the desired capacity for the filter to be created. - /// (Optional) to indicates that the filter should not be created if it does not already exist. - /// An array of booleans.where means the item has been added to the filter, - /// and mean, the item already existed - /// - bool[] InsertNX(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false); + /// + /// Adds one or more items to a Cuckoo Filter if the items did not exist previously. + /// A filter will be created if it does not exist. + /// + /// The name of the filter. + /// One or more items to add. + /// (Optional) Specifies the desired capacity for the filter to be created. + /// (Optional) to indicates that the filter should not be created if it does not already exist. + /// An array of booleans.where means the item has been added to the filter, + /// and mean, the item already existed + /// + bool[] InsertNX(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false); - /// - /// Restores a filter previosly saved using SCANDUMP. - /// - /// Name of the key to restore. - /// Iterator value associated with data (returned by SCANDUMP). - /// Current data chunk (returned by SCANDUMP). - /// Array with information of the filter. - /// - bool LoadChunk(RedisKey key, long iterator, Byte[] data); + /// + /// Restores a filter previosly saved using SCANDUMP. + /// + /// Name of the key to restore. + /// Iterator value associated with data (returned by SCANDUMP). + /// Current data chunk (returned by SCANDUMP). + /// Array with information of the filter. + /// + bool LoadChunk(RedisKey key, long iterator, Byte[] data); - /// - /// Checks whether one or more items may exist in the a Cuckoo Filter. - /// - /// The name of the filter. - /// One or more items to check. - /// An array of booleans, for each item means the item may exist in the filter, - /// and means the item may exist in the filter. - /// - bool[] MExists(RedisKey key, params RedisValue[] items); + /// + /// Checks whether one or more items may exist in the a Cuckoo Filter. + /// + /// The name of the filter. + /// One or more items to check. + /// An array of booleans, for each item means the item may exist in the filter, + /// and means the item may exist in the filter. + /// + bool[] MExists(RedisKey key, params RedisValue[] items); - /// - /// Creates a new Cuckoo Filter. - /// - /// The key under which the filter is found. - /// The number of entries intended to be added to the filter. - /// Number of items in each bucket. - /// Number of attempts to swap items between buckets before - /// declaring filter as full and creating an additional filter. - /// (Optional) When capacity is reached, an additional sub-filter is - /// created in size of the last sub-filter multiplied by expansion. - /// if executed correctly, Error otherwise. - /// - bool Reserve(RedisKey key, long capacity, - long? bucketSize = null, int? maxIterations = null, int? expansion = null); + /// + /// Creates a new Cuckoo Filter. + /// + /// The key under which the filter is found. + /// The number of entries intended to be added to the filter. + /// Number of items in each bucket. + /// Number of attempts to swap items between buckets before + /// declaring filter as full and creating an additional filter. + /// (Optional) When capacity is reached, an additional sub-filter is + /// created in size of the last sub-filter multiplied by expansion. + /// if executed correctly, Error otherwise. + /// + bool Reserve(RedisKey key, long capacity, + long? bucketSize = null, int? maxIterations = null, int? expansion = null); - /// - /// Begins an incremental save of the Cuckoo Filter. - /// - /// Name of the filter. - /// Iterator value; either 0 or the iterator from a previous invocation of this command. - /// Tuple of iterator and data. - /// - Tuple ScanDump(RedisKey key, long iterator); - } + /// + /// Begins an incremental save of the Cuckoo Filter. + /// + /// Name of the filter. + /// Iterator value; either 0 or the iterator from a previous invocation of this command. + /// Tuple of iterator and data. + /// + Tuple ScanDump(RedisKey key, long iterator); } \ No newline at end of file diff --git a/src/NRedisStack/CuckooFilter/ICuckooCommandsAsync.cs b/src/NRedisStack/CuckooFilter/ICuckooCommandsAsync.cs index 85225cd9..1eb36c90 100644 --- a/src/NRedisStack/CuckooFilter/ICuckooCommandsAsync.cs +++ b/src/NRedisStack/CuckooFilter/ICuckooCommandsAsync.cs @@ -1,128 +1,127 @@ using NRedisStack.CuckooFilter.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public interface ICuckooCommandsAsync { - public interface ICuckooCommandsAsync - { - /// - /// Adds an item to a Cuckoo Filter. - /// - /// The key under which the filter is found. - /// The item to add. - /// if the item did not exist in the filter, otherwise. - /// - Task AddAsync(RedisKey key, RedisValue item); + /// + /// Adds an item to a Cuckoo Filter. + /// + /// The key under which the filter is found. + /// The item to add. + /// if the item did not exist in the filter, otherwise. + /// + Task AddAsync(RedisKey key, RedisValue item); - /// - /// Adds an item to a Cuckoo Filter if the item did not exist previously. - /// - /// The key under which the filter is found. - /// The item to add. - /// if the item did not exist in the filter, otherwise. - /// - Task AddNXAsync(RedisKey key, RedisValue item); + /// + /// Adds an item to a Cuckoo Filter if the item did not exist previously. + /// + /// The key under which the filter is found. + /// The item to add. + /// if the item did not exist in the filter, otherwise. + /// + Task AddNXAsync(RedisKey key, RedisValue item); - /// - /// Returns the number of times an item may be in the filter. - /// - /// The name of the filter - /// The item to count. - /// the count of possible matching copies of the item in the filter. - /// - Task CountAsync(RedisKey key, RedisValue item); + /// + /// Returns the number of times an item may be in the filter. + /// + /// The name of the filter + /// The item to count. + /// the count of possible matching copies of the item in the filter. + /// + Task CountAsync(RedisKey key, RedisValue item); - /// - /// Deletes an item from the Cuckoo Filter. - /// - /// The name of the filter - /// The item to delete from the filter. - /// see langword="true"/> if the item has been deleted from the filter, otherwise. - /// - Task DelAsync(RedisKey key, RedisValue item); + /// + /// Deletes an item from the Cuckoo Filter. + /// + /// The name of the filter + /// The item to delete from the filter. + /// see langword="true"/> if the item has been deleted from the filter, otherwise. + /// + Task DelAsync(RedisKey key, RedisValue item); - /// - /// Checks whether an item exist in the Cuckoo Filter or not. - /// - /// The name of the filter. - /// The item to check for. - /// means the item may exist in the filter, - /// and means it does not exist in the filter. - /// - Task ExistsAsync(RedisKey key, RedisValue item); + /// + /// Checks whether an item exist in the Cuckoo Filter or not. + /// + /// The name of the filter. + /// The item to check for. + /// means the item may exist in the filter, + /// and means it does not exist in the filter. + /// + Task ExistsAsync(RedisKey key, RedisValue item); - /// - /// Return information about a Cuckoo filter. - /// - /// Name of the key to return information about. - /// Information of the filter. - /// - Task InfoAsync(RedisKey key); + /// + /// Return information about a Cuckoo filter. + /// + /// Name of the key to return information about. + /// Information of the filter. + /// + Task InfoAsync(RedisKey key); - /// - /// Adds one or more items to a Cuckoo Filter. A filter will be created if it does not exist. - /// - /// The name of the filter. - /// One or more items to add. - /// (Optional) Specifies the desired capacity for the filter to be created. - /// (Optional) to indicates that the filter should not be created if it does not already exist. - /// An array of booleans. - /// - Task InsertAsync(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false); + /// + /// Adds one or more items to a Cuckoo Filter. A filter will be created if it does not exist. + /// + /// The name of the filter. + /// One or more items to add. + /// (Optional) Specifies the desired capacity for the filter to be created. + /// (Optional) to indicates that the filter should not be created if it does not already exist. + /// An array of booleans. + /// + Task InsertAsync(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false); - /// - /// Adds one or more items to a Cuckoo Filter if the items did not exist previously. - /// A filter will be created if it does not exist. - /// - /// The name of the filter. - /// One or more items to add. - /// (Optional) Specifies the desired capacity for the filter to be created. - /// (Optional) to indicates that the filter should not be created if it does not already exist. - /// An array of booleans.where means the item has been added to the filter, and mean, the item already existed - /// - Task InsertNXAsync(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false); + /// + /// Adds one or more items to a Cuckoo Filter if the items did not exist previously. + /// A filter will be created if it does not exist. + /// + /// The name of the filter. + /// One or more items to add. + /// (Optional) Specifies the desired capacity for the filter to be created. + /// (Optional) to indicates that the filter should not be created if it does not already exist. + /// An array of booleans.where means the item has been added to the filter, and mean, the item already existed + /// + Task InsertNXAsync(RedisKey key, RedisValue[] items, int? capacity = null, bool nocreate = false); - /// - /// Restores a filter previosly saved using SCANDUMP. - /// - /// Name of the key to restore. - /// Iterator value associated with data (returned by SCANDUMP). - /// Current data chunk (returned by SCANDUMP). - /// Array with information of the filter. - /// - Task LoadChunkAsync(RedisKey key, long iterator, Byte[] data); + /// + /// Restores a filter previosly saved using SCANDUMP. + /// + /// Name of the key to restore. + /// Iterator value associated with data (returned by SCANDUMP). + /// Current data chunk (returned by SCANDUMP). + /// Array with information of the filter. + /// + Task LoadChunkAsync(RedisKey key, long iterator, Byte[] data); - /// - /// Checks whether one or more items may exist in the a Cuckoo Filter. - /// - /// The name of the filter. - /// One or more items to check. - /// An array of booleans, for each item means the item may exist in the filter, - /// and means the item may exist in the filter. - /// - Task MExistsAsync(RedisKey key, params RedisValue[] items); + /// + /// Checks whether one or more items may exist in the a Cuckoo Filter. + /// + /// The name of the filter. + /// One or more items to check. + /// An array of booleans, for each item means the item may exist in the filter, + /// and means the item may exist in the filter. + /// + Task MExistsAsync(RedisKey key, params RedisValue[] items); - /// - /// Creates a new Cuckoo Filter. - /// - /// The key under which the filter is found. - /// The number of entries intended to be added to the filter. - /// Number of items in each bucket. - /// Number of attempts to swap items between buckets before - /// declaring filter as full and creating an additional filter. - /// (Optional) When capacity is reached, an additional sub-filter is - /// created in size of the last sub-filter multiplied by expansion. - /// if executed correctly, Error otherwise. - /// - Task ReserveAsync(RedisKey key, long capacity, - long? bucketSize = null, int? maxIterations = null, int? expansion = null); + /// + /// Creates a new Cuckoo Filter. + /// + /// The key under which the filter is found. + /// The number of entries intended to be added to the filter. + /// Number of items in each bucket. + /// Number of attempts to swap items between buckets before + /// declaring filter as full and creating an additional filter. + /// (Optional) When capacity is reached, an additional sub-filter is + /// created in size of the last sub-filter multiplied by expansion. + /// if executed correctly, Error otherwise. + /// + Task ReserveAsync(RedisKey key, long capacity, + long? bucketSize = null, int? maxIterations = null, int? expansion = null); - /// - /// Begins an incremental save of the Cuckoo Filter. - /// - /// Name of the filter. - /// Iterator value; either 0 or the iterator from a previous invocation of this command. - /// Tuple of iterator and data. - /// - Task> ScanDumpAsync(RedisKey key, long iterator); - } + /// + /// Begins an incremental save of the Cuckoo Filter. + /// + /// Name of the filter. + /// Iterator value; either 0 or the iterator from a previous invocation of this command. + /// Tuple of iterator and data. + /// + Task> ScanDumpAsync(RedisKey key, long iterator); } \ No newline at end of file diff --git a/src/NRedisStack/CuckooFilter/Literals/CommandArgs.cs b/src/NRedisStack/CuckooFilter/Literals/CommandArgs.cs index b480700b..11989f0d 100644 --- a/src/NRedisStack/CuckooFilter/Literals/CommandArgs.cs +++ b/src/NRedisStack/CuckooFilter/Literals/CommandArgs.cs @@ -1,12 +1,11 @@ -namespace NRedisStack.CuckooFilter.Literals +namespace NRedisStack.CuckooFilter.Literals; + +internal class CuckooArgs { - internal class CuckooArgs - { - public const string CAPACITY = "CAPACITY"; - public const string EXPANSION = "EXPANSION"; - public const string NOCREATE = "NOCREATE"; - public const string ITEMS = "ITEMS"; - public const string BUCKETSIZE = "BUCKETSIZE"; - public const string MAXITERATIONS = "MAXITERATIONS"; - } + public const string CAPACITY = "CAPACITY"; + public const string EXPANSION = "EXPANSION"; + public const string NOCREATE = "NOCREATE"; + public const string ITEMS = "ITEMS"; + public const string BUCKETSIZE = "BUCKETSIZE"; + public const string MAXITERATIONS = "MAXITERATIONS"; } \ No newline at end of file diff --git a/src/NRedisStack/CuckooFilter/Literals/Commands.cs b/src/NRedisStack/CuckooFilter/Literals/Commands.cs index 19aaa94e..ac8e8f0a 100644 --- a/src/NRedisStack/CuckooFilter/Literals/Commands.cs +++ b/src/NRedisStack/CuckooFilter/Literals/Commands.cs @@ -1,18 +1,17 @@ -namespace NRedisStack.CuckooFilter.Literals +namespace NRedisStack.CuckooFilter.Literals; + +internal class CF { - internal class CF - { - public const string RESERVE = "CF.RESERVE"; - public const string ADD = "CF.ADD"; - public const string ADDNX = "CF.ADDNX"; - public const string INSERT = "CF.INSERT"; - public const string INSERTNX = "CF.INSERTNX"; - public const string EXISTS = "CF.EXISTS"; - public const string MEXISTS = "CF.MEXISTS"; - public const string DEL = "CF.DEL"; - public const string COUNT = "CF.COUNT"; - public const string SCANDUMP = "CF.SCANDUMP"; - public const string LOADCHUNK = "CF.LOADCHUNK"; - public const string INFO = "CF.INFO"; - } + public const string RESERVE = "CF.RESERVE"; + public const string ADD = "CF.ADD"; + public const string ADDNX = "CF.ADDNX"; + public const string INSERT = "CF.INSERT"; + public const string INSERTNX = "CF.INSERTNX"; + public const string EXISTS = "CF.EXISTS"; + public const string MEXISTS = "CF.MEXISTS"; + public const string DEL = "CF.DEL"; + public const string COUNT = "CF.COUNT"; + public const string SCANDUMP = "CF.SCANDUMP"; + public const string LOADCHUNK = "CF.LOADCHUNK"; + public const string INFO = "CF.INFO"; } \ No newline at end of file diff --git a/src/NRedisStack/Json/DataTypes/KeyValuePath.cs b/src/NRedisStack/Json/DataTypes/KeyValuePath.cs index 302485bb..54fcf79e 100644 --- a/src/NRedisStack/Json/DataTypes/KeyValuePath.cs +++ b/src/NRedisStack/Json/DataTypes/KeyValuePath.cs @@ -2,21 +2,14 @@ namespace NRedisStack.Json.DataTypes; -public struct KeyPathValue +public struct KeyPathValue(string key, string path, object value) { - public KeyPathValue(string key, string path, object value) - { - Key = key; - Path = path; - Value = value; - } - - private string Key { get; set; } - private string Path { get; set; } - private object Value { get; set; } + private string Key { get; set; } = key; + private string Path { get; set; } = path; + private object Value { get; set; } = value; public IEnumerable ToArray() { - return Value is string ? new string[] { Key, Path, Value.ToString()! } : new string[] { Key, Path, JsonSerializer.Serialize(Value) }; + return Value is string ? new[] { Key, Path, Value!.ToString()! } : new[] { Key, Path, JsonSerializer.Serialize(Value) }; } } \ No newline at end of file diff --git a/src/NRedisStack/Json/JsonCommandBuilder.cs b/src/NRedisStack/Json/JsonCommandBuilder.cs index c62c4570..1f6e684b 100644 --- a/src/NRedisStack/Json/JsonCommandBuilder.cs +++ b/src/NRedisStack/Json/JsonCommandBuilder.cs @@ -12,7 +12,7 @@ public static class JsonCommandBuilder public static SerializedCommand Resp(RedisKey key, string? path = null) { return string.IsNullOrEmpty(path) - ? new SerializedCommand(JSON.RESP, key) + ? new(JSON.RESP, key) : new SerializedCommand(JSON.RESP, key, path!); } @@ -20,9 +20,9 @@ public static SerializedCommand Set(RedisKey key, RedisValue path, RedisValue js { return when switch { - When.Exists => new SerializedCommand(JSON.SET, key, path, json, "XX"), - When.NotExists => new SerializedCommand(JSON.SET, key, path, json, "NX"), - _ => new SerializedCommand(JSON.SET, key, path, json) + When.Exists => new(JSON.SET, key, path, json, "XX"), + When.NotExists => new(JSON.SET, key, path, json, "NX"), + _ => new(JSON.SET, key, path, json) }; } @@ -32,46 +32,46 @@ public static SerializedCommand MSet(KeyPathValue[] KeyPathValueList) throw new ArgumentOutOfRangeException(nameof(KeyPathValueList)); var args = KeyPathValueList.SelectMany(x => x.ToArray()).ToArray(); - return new SerializedCommand(JSON.MSET, args); + return new(JSON.MSET, args); } public static SerializedCommand Merge(RedisKey key, RedisValue path, RedisValue json) { - return new SerializedCommand(JSON.MERGE, key, path, json); + return new(JSON.MERGE, key, path, json); } public static SerializedCommand StrAppend(RedisKey key, string value, string? path = null) { return path == null - ? new SerializedCommand(JSON.STRAPPEND, key, JsonSerializer.Serialize(value)) + ? new(JSON.STRAPPEND, key, JsonSerializer.Serialize(value)) : new SerializedCommand(JSON.STRAPPEND, key, path, JsonSerializer.Serialize(value)); } public static SerializedCommand StrLen(RedisKey key, string? path = null) { return path != null - ? new SerializedCommand(JSON.STRLEN, key, path) + ? new(JSON.STRLEN, key, path) : new SerializedCommand(JSON.STRLEN, key); } public static SerializedCommand Toggle(RedisKey key, string? path = null) { return path != null - ? new SerializedCommand(JSON.TOGGLE, key, path) + ? new(JSON.TOGGLE, key, path) : new SerializedCommand(JSON.TOGGLE, key, "$"); } public static SerializedCommand Type(RedisKey key, string? path = null) { return (path != null) - ? new SerializedCommand(JSON.TYPE, key, path) + ? new(JSON.TYPE, key, path) : new SerializedCommand(JSON.TYPE, key); } public static SerializedCommand DebugMemory(string key, string? path = null) { return (path != null) - ? new SerializedCommand(JSON.DEBUG, JSON.MEMORY, key, path) + ? new(JSON.DEBUG, JSON.MEMORY, key, path) : new SerializedCommand(JSON.DEBUG, JSON.MEMORY, key); } @@ -88,7 +88,7 @@ public static SerializedCommand ArrAppend(RedisKey key, string? path = null, par args.AddRange(values.Select(x => JsonSerializer.Serialize(x))); - return new SerializedCommand(JSON.ARRAPPEND, args.ToArray()); + return new(JSON.ARRAPPEND, args.ToArray()); } public static SerializedCommand ArrIndex(RedisKey key, string path, object value, long? start = null, @@ -98,7 +98,7 @@ public static SerializedCommand ArrIndex(RedisKey key, string path, object value throw new ArgumentException("stop cannot be defined without start"); var args = AssembleNonNullArguments(key, path, JsonSerializer.Serialize(value), start, stop); - return new SerializedCommand(JSON.ARRINDEX, args); + return new(JSON.ARRINDEX, args); } public static SerializedCommand ArrInsert(RedisKey key, string path, long index, params object[] values) @@ -108,13 +108,13 @@ public static SerializedCommand ArrInsert(RedisKey key, string path, long index, var args = new List { key, path, index }; args.AddRange(values.Select(val => JsonSerializer.Serialize(val))); - return new SerializedCommand(JSON.ARRINSERT, args); + return new(JSON.ARRINSERT, args); } public static SerializedCommand ArrLen(RedisKey key, string? path = null) { var args = AssembleNonNullArguments(key, path); - return new SerializedCommand(JSON.ARRLEN, args); + return new(JSON.ARRLEN, args); } public static SerializedCommand ArrPop(RedisKey key, string? path = null, long? index = null) @@ -123,28 +123,28 @@ public static SerializedCommand ArrPop(RedisKey key, string? path = null, long? throw new ArgumentException("index cannot be defined without path"); var args = AssembleNonNullArguments(key, path, index); - return new SerializedCommand(JSON.ARRPOP, args)!; + return new(JSON.ARRPOP, args); } public static SerializedCommand ArrTrim(RedisKey key, string path, long start, long stop) => - new SerializedCommand(JSON.ARRTRIM, key, path, start, stop); + new(JSON.ARRTRIM, key, path, start, stop); public static SerializedCommand Clear(RedisKey key, string? path = null) { var args = AssembleNonNullArguments(key, path); - return new SerializedCommand(JSON.CLEAR, args); + return new(JSON.CLEAR, args); } public static SerializedCommand Del(RedisKey key, string? path = null) { var args = AssembleNonNullArguments(key, path); - return new SerializedCommand(JSON.DEL, args); + return new(JSON.DEL, args); } public static SerializedCommand Get(RedisKey key, RedisValue? indent = null, RedisValue? newLine = null, RedisValue? space = null, RedisValue? path = null) { - List args = new List { key }; + List args = [key]; if (indent != null) { @@ -169,13 +169,13 @@ public static SerializedCommand Get(RedisKey key, RedisValue? indent = null, Red args.Add(path); } - return new SerializedCommand(JSON.GET, args); + return new(JSON.GET, args); } public static SerializedCommand Get(RedisKey key, string[] paths, RedisValue? indent = null, RedisValue? newLine = null, RedisValue? space = null) { - List args = new List() { key }; + List args = [key]; if (indent != null) { @@ -197,12 +197,12 @@ public static SerializedCommand Get(RedisKey key, string[] paths, RedisValue? in args.AddRange(paths); - return new SerializedCommand(JSON.GET, args); + return new(JSON.GET, args); } public static SerializedCommand Get(RedisKey key, string path = "$") { - return new SerializedCommand(JSON.GET, key, path); + return new(JSON.GET, key, path); } public static SerializedCommand MGet(RedisKey[] keys, string path) @@ -210,23 +210,23 @@ public static SerializedCommand MGet(RedisKey[] keys, string path) var args = keys.Cast().ToList(); args.Add(path); - return new SerializedCommand(JSON.MGET, args); + return new(JSON.MGET, args); } public static SerializedCommand NumIncrby(RedisKey key, string path, double value) { - return new SerializedCommand(JSON.NUMINCRBY, key, path, value); + return new(JSON.NUMINCRBY, key, path, value); } public static SerializedCommand ObjKeys(RedisKey key, string? path = null) { var args = AssembleNonNullArguments(key, path); - return new SerializedCommand(JSON.OBJKEYS, args); + return new(JSON.OBJKEYS, args); } public static SerializedCommand ObjLen(RedisKey key, string? path = null) { var args = AssembleNonNullArguments(key, path); - return new SerializedCommand(JSON.OBJLEN, args); + return new(JSON.OBJLEN, args); } } \ No newline at end of file diff --git a/src/NRedisStack/Json/JsonCommands.cs b/src/NRedisStack/Json/JsonCommands.cs index fd783737..c4ec254e 100644 --- a/src/NRedisStack/Json/JsonCommands.cs +++ b/src/NRedisStack/Json/JsonCommands.cs @@ -5,23 +5,16 @@ namespace NRedisStack; -public class JsonCommands : JsonCommandsAsync, IJsonCommands +public class JsonCommands(IDatabase db) : JsonCommandsAsync(db), IJsonCommands { - private readonly IDatabase _db; - - public JsonCommands(IDatabase db) : base(db) - { - _db = db; - } - /// public RedisResult[] Resp(RedisKey key, string? path = null) { - RedisResult result = _db.Execute(JsonCommandBuilder.Resp(key, path)); + RedisResult result = db.Execute(JsonCommandBuilder.Resp(key, path)); if (result.IsNull) { - return Array.Empty(); + return []; } return (RedisResult[])result!; @@ -38,26 +31,26 @@ public bool Set(RedisKey key, RedisValue path, object obj, When when = When.Alwa /// public bool Set(RedisKey key, RedisValue path, RedisValue json, When when = When.Always) { - return _db.Execute(JsonCommandBuilder.Set(key, path, json, when)).OKtoBoolean(); + return db.Execute(JsonCommandBuilder.Set(key, path, json, when)).OKtoBoolean(); } /// public bool MSet(KeyPathValue[] KeyPathValueList) { - return _db.Execute(JsonCommandBuilder.MSet(KeyPathValueList)).OKtoBoolean(); + return db.Execute(JsonCommandBuilder.MSet(KeyPathValueList)).OKtoBoolean(); } /// public bool Merge(RedisKey key, RedisValue path, RedisValue json) { - return _db.Execute(JsonCommandBuilder.Merge(key, path, json)).OKtoBoolean(); + return db.Execute(JsonCommandBuilder.Merge(key, path, json)).OKtoBoolean(); } /// public bool Merge(RedisKey key, RedisValue path, object obj, JsonSerializerOptions? serializerOptions = default) { string json = JsonSerializer.Serialize(obj, options: serializerOptions); - return _db.Execute(JsonCommandBuilder.Merge(key, path, json)).OKtoBoolean(); + return db.Execute(JsonCommandBuilder.Merge(key, path, json)).OKtoBoolean(); } /// @@ -97,28 +90,28 @@ public int SetFromDirectory(RedisValue path, string filesPath, When when = When. /// public long?[] StrAppend(RedisKey key, string value, string? path = null) { - return _db.Execute(JsonCommandBuilder.StrAppend(key, value, path)).ToNullableLongArray(); + return db.Execute(JsonCommandBuilder.StrAppend(key, value, path)).ToNullableLongArray(); } /// public long?[] StrLen(RedisKey key, string? path = null) { - return _db.Execute(JsonCommandBuilder.StrLen(key, path)).ToNullableLongArray(); + return db.Execute(JsonCommandBuilder.StrLen(key, path)).ToNullableLongArray(); } /// public bool?[] Toggle(RedisKey key, string? path = null) { - RedisResult result = _db.Execute(JsonCommandBuilder.Toggle(key, path)); + RedisResult result = db.Execute(JsonCommandBuilder.Toggle(key, path)); if (result.IsNull) { - return Array.Empty(); + return []; } - if (result.Type == ResultType.Integer) + if (result.Resp2Type == ResultType.Integer) { - return new bool?[] { (long)result == 1 }; + return [(long)result == 1]; } return ((RedisResult[])result!).Select(x => (bool?)((long)x == 1)).ToArray(); @@ -127,83 +120,74 @@ public int SetFromDirectory(RedisValue path, string filesPath, When when = When. /// public JsonType[] Type(RedisKey key, string? path = null) { - RedisResult result = _db.Execute(JsonCommandBuilder.Type(key, path)); + RedisResult result = db.Execute(JsonCommandBuilder.Type(key, path)); - if (result.Type == ResultType.MultiBulk) + return result.Resp2Type switch { - return ((RedisResult[])result!).Select(x => (JsonType)Enum.Parse(typeof(JsonType), x.ToString()!.ToUpper())).ToArray(); - } - - if (result.Type == ResultType.BulkString) - { - return new[] { (JsonType)Enum.Parse(typeof(JsonType), result.ToString()!.ToUpper()) }; - } - - return Array.Empty(); - + ResultType.Array => ((RedisResult[])result!) + .Select(x => (JsonType)Enum.Parse(typeof(JsonType), x.ToString().ToUpper())) + .ToArray(), + ResultType.BulkString => [(JsonType)Enum.Parse(typeof(JsonType), result.ToString().ToUpper())], + _ => [] + }; } public long DebugMemory(string key, string? path = null) { - return _db.Execute(JsonCommandBuilder.DebugMemory(key, path)).ToLong(); + return db.Execute(JsonCommandBuilder.DebugMemory(key, path)).ToLong(); } /// public long?[] ArrAppend(RedisKey key, string? path = null, params object[] values) { - return _db.Execute(JsonCommandBuilder.ArrAppend(key, path, values)).ToNullableLongArray(); + return db.Execute(JsonCommandBuilder.ArrAppend(key, path, values)).ToNullableLongArray(); } /// public long?[] ArrIndex(RedisKey key, string path, object value, long? start = null, long? stop = null) { - return _db.Execute(JsonCommandBuilder.ArrIndex(key, path, value, start, stop)).ToNullableLongArray(); + return db.Execute(JsonCommandBuilder.ArrIndex(key, path, value, start, stop)).ToNullableLongArray(); } /// public long?[] ArrInsert(RedisKey key, string path, long index, params object[] values) { - return _db.Execute(JsonCommandBuilder.ArrInsert(key, path, index, values)).ToNullableLongArray(); + return db.Execute(JsonCommandBuilder.ArrInsert(key, path, index, values)).ToNullableLongArray(); } /// public long?[] ArrLen(RedisKey key, string? path = null) { - return _db.Execute(JsonCommandBuilder.ArrLen(key, path)).ToNullableLongArray(); + return db.Execute(JsonCommandBuilder.ArrLen(key, path)).ToNullableLongArray(); } /// public RedisResult[] ArrPop(RedisKey key, string? path = null, long? index = null) { - RedisResult result = _db.Execute(JsonCommandBuilder.ArrPop(key, path, index)); + RedisResult result = db.Execute(JsonCommandBuilder.ArrPop(key, path, index)); - if (result.Type == ResultType.MultiBulk) + return result.Resp2Type switch { - return (RedisResult[])result!; - } - - if (result.Type == ResultType.BulkString) - { - return new[] { result }; - } - - return Array.Empty(); + ResultType.Array => (RedisResult[])result!, + ResultType.BulkString => [result], + _ => [] + }; } /// public long?[] ArrTrim(RedisKey key, string path, long start, long stop) => - _db.Execute(JsonCommandBuilder.ArrTrim(key, path, start, stop)).ToNullableLongArray(); + db.Execute(JsonCommandBuilder.ArrTrim(key, path, start, stop)).ToNullableLongArray(); /// public long Clear(RedisKey key, string? path = null) { - return _db.Execute(JsonCommandBuilder.Clear(key, path)).ToLong(); + return db.Execute(JsonCommandBuilder.Clear(key, path)).ToLong(); } /// public long Del(RedisKey key, string? path = null) { - return _db.Execute(JsonCommandBuilder.Del(key, path)).ToLong(); + return db.Execute(JsonCommandBuilder.Del(key, path)).ToLong(); } /// @@ -213,23 +197,23 @@ public long Del(RedisKey key, string? path = null) public RedisResult Get(RedisKey key, RedisValue? indent = null, RedisValue? newLine = null, RedisValue? space = null, RedisValue? path = null) { - return _db.Execute(JsonCommandBuilder.Get(key, indent, newLine, space, path)); + return db.Execute(JsonCommandBuilder.Get(key, indent, newLine, space, path)); } /// public RedisResult Get(RedisKey key, string[] paths, RedisValue? indent = null, RedisValue? newLine = null, RedisValue? space = null) { - return _db.Execute(JsonCommandBuilder.Get(key, paths, indent, newLine, space)); + return db.Execute(JsonCommandBuilder.Get(key, paths, indent, newLine, space)); } /// - public T? Get(RedisKey key, string path = "$", JsonSerializerOptions? serializerOptions = default) + public T? Get(RedisKey key, string path = "$", JsonSerializerOptions? serializerOptions = null) { - var res = _db.Execute(JsonCommandBuilder.Get(key, path)); - if (res.Type == ResultType.BulkString && !res.IsNull) + var res = db.Execute(JsonCommandBuilder.Get(key, path)); + if (res.Resp2Type == ResultType.BulkString && !res.IsNull) { - var arr = JsonSerializer.Deserialize(res.ToString()!); + var arr = JsonSerializer.Deserialize(res.ToString()); if (arr?.Count > 0) { return JsonSerializer.Deserialize(JsonSerializer.Serialize(arr[0]), serializerOptions); @@ -242,32 +226,32 @@ public RedisResult Get(RedisKey key, string[] paths, RedisValue? indent = null, /// public IEnumerable GetEnumerable(RedisKey key, string path = "$") { - RedisResult res = _db.Execute(JsonCommandBuilder.Get(key, path)); - return JsonSerializer.Deserialize>(res.ToString()!)!; + RedisResult res = db.Execute(JsonCommandBuilder.Get(key, path)); + return JsonSerializer.Deserialize>(res.ToString())!; } /// public RedisResult[] MGet(RedisKey[] keys, string path) { - return _db.Execute(JsonCommandBuilder.MGet(keys, path)).ToArray(); + return db.Execute(JsonCommandBuilder.MGet(keys, path)).ToArray(); } /// public double?[] NumIncrby(RedisKey key, string path, double value) { - var res = _db.Execute(JsonCommandBuilder.NumIncrby(key, path, value)); - return JsonSerializer.Deserialize(res.ToString()!)!; + var res = db.Execute(JsonCommandBuilder.NumIncrby(key, path, value)); + return JsonSerializer.Deserialize(res.ToString())!; } /// public IEnumerable> ObjKeys(RedisKey key, string? path = null) { - return _db.Execute(JsonCommandBuilder.ObjKeys(key, path)).ToHashSets(); + return db.Execute(JsonCommandBuilder.ObjKeys(key, path)).ToHashSets(); } /// public long?[] ObjLen(RedisKey key, string? path = null) { - return _db.Execute(JsonCommandBuilder.ObjLen(key, path)).ToNullableLongArray(); + return db.Execute(JsonCommandBuilder.ObjLen(key, path)).ToNullableLongArray(); } } \ No newline at end of file diff --git a/src/NRedisStack/Json/JsonCommandsAsync.cs b/src/NRedisStack/Json/JsonCommandsAsync.cs index ce24f73a..9ebcfebc 100644 --- a/src/NRedisStack/Json/JsonCommandsAsync.cs +++ b/src/NRedisStack/Json/JsonCommandsAsync.cs @@ -5,65 +5,53 @@ namespace NRedisStack; -public class JsonCommandsAsync : IJsonCommandsAsync +public class JsonCommandsAsync(IDatabaseAsync db) : IJsonCommandsAsync { - private readonly IDatabaseAsync _db; - - public JsonCommandsAsync(IDatabaseAsync db) - { - _db = db; - } - public async Task ArrAppendAsync(RedisKey key, string? path = null, params object[] values) { - return (await _db.ExecuteAsync(JsonCommandBuilder.ArrAppend(key, path, values))).ToNullableLongArray(); + return (await db.ExecuteAsync(JsonCommandBuilder.ArrAppend(key, path, values))).ToNullableLongArray(); } public async Task ArrIndexAsync(RedisKey key, string path, object value, long? start = null, long? stop = null) { - return (await _db.ExecuteAsync(JsonCommandBuilder.ArrIndex(key, path, value, start, stop))) + return (await db.ExecuteAsync(JsonCommandBuilder.ArrIndex(key, path, value, start, stop))) .ToNullableLongArray(); } public async Task ArrInsertAsync(RedisKey key, string path, long index, params object[] values) { - return (await _db.ExecuteAsync(JsonCommandBuilder.ArrInsert(key, path, index, values))).ToNullableLongArray(); + return (await db.ExecuteAsync(JsonCommandBuilder.ArrInsert(key, path, index, values))).ToNullableLongArray(); } public async Task ArrLenAsync(RedisKey key, string? path = null) { - return (await _db.ExecuteAsync(JsonCommandBuilder.ArrLen(key, path))).ToNullableLongArray(); + return (await db.ExecuteAsync(JsonCommandBuilder.ArrLen(key, path))).ToNullableLongArray(); } public async Task ArrPopAsync(RedisKey key, string? path = null, long? index = null) { - RedisResult result = await _db.ExecuteAsync(JsonCommandBuilder.ArrPop(key, path, index)); + RedisResult result = await db.ExecuteAsync(JsonCommandBuilder.ArrPop(key, path, index)); - if (result.Type == ResultType.MultiBulk) + return result.Resp2Type switch { - return (RedisResult[])result!; - } - - if (result.Type == ResultType.BulkString) - { - return new[] { result }; - } - - return Array.Empty(); + ResultType.Array => (RedisResult[])result!, + ResultType.BulkString => [result], + _ => [] + }; } public async Task ArrTrimAsync(RedisKey key, string path, long start, long stop) => - (await _db.ExecuteAsync(JsonCommandBuilder.ArrTrim(key, path, start, stop))).ToNullableLongArray(); + (await db.ExecuteAsync(JsonCommandBuilder.ArrTrim(key, path, start, stop))).ToNullableLongArray(); public async Task ClearAsync(RedisKey key, string? path = null) { - return (await _db.ExecuteAsync(JsonCommandBuilder.Clear(key, path))).ToLong(); + return (await db.ExecuteAsync(JsonCommandBuilder.Clear(key, path))).ToLong(); } public async Task DelAsync(RedisKey key, string? path = null) { - return (await _db.ExecuteAsync(JsonCommandBuilder.Del(key, path))).ToLong(); + return (await db.ExecuteAsync(JsonCommandBuilder.Del(key, path))).ToLong(); } public Task ForgetAsync(RedisKey key, string? path = null) => DelAsync(key, path); @@ -72,22 +60,22 @@ public async Task GetAsync(RedisKey key, RedisValue? indent = null, RedisValue? space = null, RedisValue? path = null) { - return await _db.ExecuteAsync(JsonCommandBuilder.Get(key, indent, newLine, space, path)); + return await db.ExecuteAsync(JsonCommandBuilder.Get(key, indent, newLine, space, path)); } public async Task GetAsync(RedisKey key, string[] paths, RedisValue? indent = null, RedisValue? newLine = null, RedisValue? space = null) { - return await _db.ExecuteAsync(JsonCommandBuilder.Get(key, paths, indent, newLine, space)); + return await db.ExecuteAsync(JsonCommandBuilder.Get(key, paths, indent, newLine, space)); } - public async Task GetAsync(RedisKey key, string path = "$", JsonSerializerOptions? serializerOptions = default) + public async Task GetAsync(RedisKey key, string path = "$", JsonSerializerOptions? serializerOptions = null) { - var res = await _db.ExecuteAsync(JsonCommandBuilder.Get(key, path)); - if (res.Type == ResultType.BulkString && !res.IsNull) + var res = await db.ExecuteAsync(JsonCommandBuilder.Get(key, path)); + if (res.Resp2Type == ResultType.BulkString && !res.IsNull) { - var arr = JsonSerializer.Deserialize(res.ToString()!); + var arr = JsonSerializer.Deserialize(res.ToString()); if (arr?.Count > 0) { return JsonSerializer.Deserialize(JsonSerializer.Serialize(arr[0]), serializerOptions); @@ -100,38 +88,38 @@ public async Task GetAsync(RedisKey key, string[] paths, RedisValue /// public async Task> GetEnumerableAsync(RedisKey key, string path = "$") { - RedisResult res = await _db.ExecuteAsync(JsonCommandBuilder.Get(key, path)); - return JsonSerializer.Deserialize>(res.ToString()!)!; + RedisResult res = await db.ExecuteAsync(JsonCommandBuilder.Get(key, path)); + return JsonSerializer.Deserialize>(res.ToString())!; } public async Task MGetAsync(RedisKey[] keys, string path) { - return (await _db.ExecuteAsync(JsonCommandBuilder.MGet(keys, path))).ToArray(); + return (await db.ExecuteAsync(JsonCommandBuilder.MGet(keys, path))).ToArray(); } public async Task NumIncrbyAsync(RedisKey key, string path, double value) { - var res = await _db.ExecuteAsync(JsonCommandBuilder.NumIncrby(key, path, value)); - return JsonSerializer.Deserialize(res.ToString()!)!; + var res = await db.ExecuteAsync(JsonCommandBuilder.NumIncrby(key, path, value)); + return JsonSerializer.Deserialize(res.ToString())!; } public async Task>> ObjKeysAsync(RedisKey key, string? path = null) { - return (await _db.ExecuteAsync(JsonCommandBuilder.ObjKeys(key, path))).ToHashSets(); + return (await db.ExecuteAsync(JsonCommandBuilder.ObjKeys(key, path))).ToHashSets(); } public async Task ObjLenAsync(RedisKey key, string? path = null) { - return (await _db.ExecuteAsync(JsonCommandBuilder.ObjLen(key, path))).ToNullableLongArray(); + return (await db.ExecuteAsync(JsonCommandBuilder.ObjLen(key, path))).ToNullableLongArray(); } public async Task RespAsync(RedisKey key, string? path = null) { - RedisResult result = await _db.ExecuteAsync(JsonCommandBuilder.Resp(key, path)); + RedisResult result = await db.ExecuteAsync(JsonCommandBuilder.Resp(key, path)); if (result.IsNull) { - return Array.Empty(); + return []; } return (RedisResult[])result!; @@ -147,18 +135,18 @@ public Task SetAsync(RedisKey key, RedisValue path, object obj, When when public async Task SetAsync(RedisKey key, RedisValue path, RedisValue json, When when = When.Always) { - return (await _db.ExecuteAsync(JsonCommandBuilder.Set(key, path, json, when))).OKtoBoolean(); + return (await db.ExecuteAsync(JsonCommandBuilder.Set(key, path, json, when))).OKtoBoolean(); } public async Task MSetAsync(KeyPathValue[] KeyPathValueList) { - return (await _db.ExecuteAsync(JsonCommandBuilder.MSet(KeyPathValueList))).OKtoBoolean(); + return (await db.ExecuteAsync(JsonCommandBuilder.MSet(KeyPathValueList))).OKtoBoolean(); } /// public async Task MergeAsync(RedisKey key, RedisValue path, RedisValue json) { - return (await _db.ExecuteAsync(JsonCommandBuilder.Merge(key, path, json))).OKtoBoolean(); + return (await db.ExecuteAsync(JsonCommandBuilder.Merge(key, path, json))).OKtoBoolean(); } /// @@ -166,7 +154,7 @@ public async Task MergeAsync(RedisKey key, RedisValue path, object obj, JsonSerializerOptions? serializerOptions = default) { string json = JsonSerializer.Serialize(obj, options: serializerOptions); - return (await _db.ExecuteAsync(JsonCommandBuilder.Merge(key, path, json))).OKtoBoolean(); + return (await db.ExecuteAsync(JsonCommandBuilder.Merge(key, path, json))).OKtoBoolean(); } public async Task SetFromFileAsync(RedisKey key, RedisValue path, string filePath, When when = When.Always) @@ -204,26 +192,26 @@ public async Task SetFromDirectoryAsync(RedisValue path, string filesPath, public async Task StrAppendAsync(RedisKey key, string value, string? path = null) { - return (await _db.ExecuteAsync(JsonCommandBuilder.StrAppend(key, value, path))).ToNullableLongArray(); + return (await db.ExecuteAsync(JsonCommandBuilder.StrAppend(key, value, path))).ToNullableLongArray(); } public async Task StrLenAsync(RedisKey key, string? path = null) { - return (await _db.ExecuteAsync(JsonCommandBuilder.StrLen(key, path))).ToNullableLongArray(); + return (await db.ExecuteAsync(JsonCommandBuilder.StrLen(key, path))).ToNullableLongArray(); } public async Task ToggleAsync(RedisKey key, string? path = null) { - RedisResult result = await _db.ExecuteAsync(JsonCommandBuilder.Toggle(key, path)); + RedisResult result = await db.ExecuteAsync(JsonCommandBuilder.Toggle(key, path)); if (result.IsNull) { - return Array.Empty(); + return []; } - if (result.Type == ResultType.Integer) + if (result.Resp2Type == ResultType.Integer) { - return new bool?[] { (long)result == 1 }; + return [(long)result == 1]; } return ((RedisResult[])result!).Select(x => (bool?)((long)x == 1)).ToArray(); @@ -231,23 +219,23 @@ public async Task SetFromDirectoryAsync(RedisValue path, string filesPath, public async Task TypeAsync(RedisKey key, string? path = null) { - RedisResult result = await _db.ExecuteAsync(JsonCommandBuilder.Type(key, path)); + RedisResult result = await db.ExecuteAsync(JsonCommandBuilder.Type(key, path)); - if (result.Type == ResultType.MultiBulk) + if (result.Resp2Type == ResultType.Array) { - return ((RedisResult[])result!).Select(x => (JsonType)Enum.Parse(typeof(JsonType), x.ToString()!.ToUpper())).ToArray(); + return ((RedisResult[])result!).Select(x => (JsonType)Enum.Parse(typeof(JsonType), x.ToString().ToUpper())).ToArray(); } - if (result.Type == ResultType.BulkString) + if (result.Resp2Type == ResultType.BulkString) { - return new[] { (JsonType)Enum.Parse(typeof(JsonType), result.ToString()!.ToUpper()) }; + return [(JsonType)Enum.Parse(typeof(JsonType), result.ToString().ToUpper())]; } - return Array.Empty(); + return []; } public async Task DebugMemoryAsync(string key, string? path = null) { - return (await _db.ExecuteAsync(JsonCommandBuilder.DebugMemory(key, path))).ToLong(); + return (await db.ExecuteAsync(JsonCommandBuilder.DebugMemory(key, path))).ToLong(); } } \ No newline at end of file diff --git a/src/NRedisStack/Json/Literals/CommandArgs.cs b/src/NRedisStack/Json/Literals/CommandArgs.cs index 3b2a2e33..09610d26 100644 --- a/src/NRedisStack/Json/Literals/CommandArgs.cs +++ b/src/NRedisStack/Json/Literals/CommandArgs.cs @@ -1,9 +1,8 @@ -namespace NRedisStack.Json.Literals +namespace NRedisStack.Json.Literals; + +internal class JsonArgs { - internal class JsonArgs - { - public const string INDENT = "INDENT"; - public const string NEWLINE = "NEWLINE"; - public const string SPACE = "SPACE"; - } + public const string INDENT = "INDENT"; + public const string NEWLINE = "NEWLINE"; + public const string SPACE = "SPACE"; } \ No newline at end of file diff --git a/src/NRedisStack/Json/Literals/Commands.cs b/src/NRedisStack/Json/Literals/Commands.cs index 8ddbafe0..27ae9b54 100644 --- a/src/NRedisStack/Json/Literals/Commands.cs +++ b/src/NRedisStack/Json/Literals/Commands.cs @@ -1,32 +1,31 @@ -namespace NRedisStack.Json.Literals +namespace NRedisStack.Json.Literals; + +internal class JSON { - internal class JSON - { - public const string ARRAPPEND = "JSON.ARRAPPEND"; - public const string ARRINDEX = "JSON.ARRINDEX"; - public const string ARRINSERT = "JSON.ARRINSERT"; - public const string ARRLEN = "JSON.ARRLEN"; - public const string ARRPOP = "JSON.ARRPOP"; - public const string ARRTRIM = "JSON.ARRTRIM"; - public const string CLEAR = "JSON.CLEAR"; - public const string DEBUG = "JSON.DEBUG"; - public const string DEBUG_HELP = "JSON.DEBUG HELP"; - public const string DEL = "JSON.DEL"; - public const string FORGET = "JSON.FORGET"; - public const string GET = "JSON.GET"; - public const string MEMORY = "MEMORY"; - public const string MERGE = "JSON.MERGE"; - public const string MSET = "JSON.MSET"; - public const string MGET = "JSON.MGET"; - public const string NUMINCRBY = "JSON.NUMINCRBY"; - public const string NUMMULTBY = "JSON.NUMMULTBY"; - public const string OBJKEYS = "JSON.OBJKEYS"; - public const string OBJLEN = "JSON.OBJLEN"; - public const string RESP = "JSON.RESP"; - public const string SET = "JSON.SET"; - public const string STRAPPEND = "JSON.STRAPPEND"; - public const string STRLEN = "JSON.STRLEN"; - public const string TOGGLE = "JSON.TOGGLE"; - public const string TYPE = "JSON.TYPE"; - } + public const string ARRAPPEND = "JSON.ARRAPPEND"; + public const string ARRINDEX = "JSON.ARRINDEX"; + public const string ARRINSERT = "JSON.ARRINSERT"; + public const string ARRLEN = "JSON.ARRLEN"; + public const string ARRPOP = "JSON.ARRPOP"; + public const string ARRTRIM = "JSON.ARRTRIM"; + public const string CLEAR = "JSON.CLEAR"; + public const string DEBUG = "JSON.DEBUG"; + public const string DEBUG_HELP = "JSON.DEBUG HELP"; + public const string DEL = "JSON.DEL"; + public const string FORGET = "JSON.FORGET"; + public const string GET = "JSON.GET"; + public const string MEMORY = "MEMORY"; + public const string MERGE = "JSON.MERGE"; + public const string MSET = "JSON.MSET"; + public const string MGET = "JSON.MGET"; + public const string NUMINCRBY = "JSON.NUMINCRBY"; + public const string NUMMULTBY = "JSON.NUMMULTBY"; + public const string OBJKEYS = "JSON.OBJKEYS"; + public const string OBJLEN = "JSON.OBJLEN"; + public const string RESP = "JSON.RESP"; + public const string SET = "JSON.SET"; + public const string STRAPPEND = "JSON.STRAPPEND"; + public const string STRLEN = "JSON.STRLEN"; + public const string TOGGLE = "JSON.TOGGLE"; + public const string TYPE = "JSON.TYPE"; } \ No newline at end of file diff --git a/src/NRedisStack/ModulePrefixes.cs b/src/NRedisStack/ModulePrefixes.cs index 3627a588..b8de91a8 100644 --- a/src/NRedisStack/ModulePrefixes.cs +++ b/src/NRedisStack/ModulePrefixes.cs @@ -1,23 +1,22 @@ using StackExchange.Redis; -namespace NRedisStack.RedisStackCommands +namespace NRedisStack.RedisStackCommands; + +public static class ModulePrefixes { - public static class ModulePrefixes - { - public static BloomCommands BF(this IDatabase db) => new BloomCommands(db); + public static BloomCommands BF(this IDatabase db) => new(db); - public static CuckooCommands CF(this IDatabase db) => new CuckooCommands(db); + public static CuckooCommands CF(this IDatabase db) => new(db); - public static CmsCommands CMS(this IDatabase db) => new CmsCommands(db); + public static CmsCommands CMS(this IDatabase db) => new(db); - public static TopKCommands TOPK(this IDatabase db) => new TopKCommands(db); + public static TopKCommands TOPK(this IDatabase db) => new(db); - public static TdigestCommands TDIGEST(this IDatabase db) => new TdigestCommands(db); + public static TdigestCommands TDIGEST(this IDatabase db) => new(db); - public static SearchCommands FT(this IDatabase db, int? searchDialect = 2) => new SearchCommands(db, searchDialect); + public static SearchCommands FT(this IDatabase db, int? searchDialect = 2) => new(db, searchDialect); - public static JsonCommands JSON(this IDatabase db) => new JsonCommands(db); + public static JsonCommands JSON(this IDatabase db) => new(db); - public static TimeSeriesCommands TS(this IDatabase db) => new TimeSeriesCommands(db); - } + public static TimeSeriesCommands TS(this IDatabase db) => new(db); } \ No newline at end of file diff --git a/src/NRedisStack/NRedisStack.csproj b/src/NRedisStack/NRedisStack.csproj index 1c1d5a6c..15da0637 100644 --- a/src/NRedisStack/NRedisStack.csproj +++ b/src/NRedisStack/NRedisStack.csproj @@ -5,16 +5,32 @@ true README.md Redis.png + + + $(Nowarn);RS0026 + 1.0.0-beta1 1.0.0-beta1 1.0.0-beta1 - + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + diff --git a/src/NRedisStack/Pipeline.cs b/src/NRedisStack/Pipeline.cs index c858413f..8490c247 100644 --- a/src/NRedisStack/Pipeline.cs +++ b/src/NRedisStack/Pipeline.cs @@ -10,20 +10,20 @@ public Pipeline(IDatabase db) _batch = db.CreateBatch(); } - private IBatch _batch; + private readonly IBatch _batch; public void Execute() => _batch.Execute(); - public BloomCommandsAsync Bf => new BloomCommandsAsync(_batch); - public CmsCommandsAsync Cms => new CmsCommandsAsync(_batch); - public CuckooCommandsAsync Cf => new CuckooCommandsAsync(_batch); + public BloomCommandsAsync Bf => new(_batch); + public CmsCommandsAsync Cms => new(_batch); + public CuckooCommandsAsync Cf => new(_batch); - public JsonCommandsAsync Json => new JsonCommandsAsync(_batch); - public SearchCommandsAsync Ft => new SearchCommandsAsync(_batch); - public TdigestCommandsAsync Tdigest => new TdigestCommandsAsync(_batch); - public TimeSeriesCommandsAsync Ts => new TimeSeriesCommandsAsync(_batch); - public TopKCommandsAsync TopK => new TopKCommandsAsync(_batch); + public JsonCommandsAsync Json => new(_batch); + public SearchCommandsAsync Ft => new(_batch); + public TdigestCommandsAsync Tdigest => new(_batch); + public TimeSeriesCommandsAsync Ts => new(_batch); + public TopKCommandsAsync TopK => new(_batch); public IDatabaseAsync Db => _batch; } \ No newline at end of file diff --git a/src/NRedisStack/PublicAPI/PublicAPI.Shipped.txt b/src/NRedisStack/PublicAPI/PublicAPI.Shipped.txt new file mode 100644 index 00000000..12d7f4c3 --- /dev/null +++ b/src/NRedisStack/PublicAPI/PublicAPI.Shipped.txt @@ -0,0 +1,1352 @@ +#nullable enable +abstract NRedisStack.Search.Aggregation.Reducer.Name.get -> string! +const NRedisStack.Core.DataTypes.StreamSpecialIds.AllMessagesId = "0" -> string! +const NRedisStack.Core.DataTypes.StreamSpecialIds.NewMessagesId = "$" -> string! +const NRedisStack.Core.DataTypes.StreamSpecialIds.UndeliveredMessagesId = ">" -> string! +NRedisStack.Auxiliary +NRedisStack.Bloom.DataTypes.BloomInformation +NRedisStack.Bloom.DataTypes.BloomInformation.Capacity.get -> long +NRedisStack.Bloom.DataTypes.BloomInformation.ExpansionRate.get -> long +NRedisStack.Bloom.DataTypes.BloomInformation.NumberOfFilters.get -> long +NRedisStack.Bloom.DataTypes.BloomInformation.NumberOfItemsInserted.get -> long +NRedisStack.Bloom.DataTypes.BloomInformation.Size.get -> long +NRedisStack.BloomAux +NRedisStack.BloomCommandBuilder +NRedisStack.BloomCommands +NRedisStack.BloomCommands.Add(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.BloomCommands.BloomCommands(StackExchange.Redis.IDatabase! db) -> void +NRedisStack.BloomCommands.Card(StackExchange.Redis.RedisKey key) -> long +NRedisStack.BloomCommands.Exists(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.BloomCommands.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.Bloom.DataTypes.BloomInformation! +NRedisStack.BloomCommands.Insert(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, double? error = null, int? expansion = null, bool nocreate = false, bool nonscaling = false) -> bool[]! +NRedisStack.BloomCommands.LoadChunk(StackExchange.Redis.RedisKey key, long iterator, byte[]! data) -> bool +NRedisStack.BloomCommands.MAdd(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> bool[]! +NRedisStack.BloomCommands.MExists(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items) -> bool[]! +NRedisStack.BloomCommands.Reserve(StackExchange.Redis.RedisKey key, double errorRate, long capacity, int? expansion = null, bool nonscaling = false) -> bool +NRedisStack.BloomCommands.ScanDump(StackExchange.Redis.RedisKey key, long iterator) -> System.Tuple! +NRedisStack.BloomCommandsAsync +NRedisStack.BloomCommandsAsync.AddAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.BloomCommandsAsync.BloomCommandsAsync(StackExchange.Redis.IDatabaseAsync! db) -> void +NRedisStack.BloomCommandsAsync.CardAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.BloomCommandsAsync.ExistsAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.BloomCommandsAsync.InfoAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.BloomCommandsAsync.InsertAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, double? error = null, int? expansion = null, bool nocreate = false, bool nonscaling = false) -> System.Threading.Tasks.Task! +NRedisStack.BloomCommandsAsync.LoadChunkAsync(StackExchange.Redis.RedisKey key, long iterator, byte[]! data) -> System.Threading.Tasks.Task! +NRedisStack.BloomCommandsAsync.MAddAsync(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.BloomCommandsAsync.MExistsAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.BloomCommandsAsync.ReserveAsync(StackExchange.Redis.RedisKey key, double errorRate, long capacity, int? expansion = null, bool nonscaling = false) -> System.Threading.Tasks.Task! +NRedisStack.BloomCommandsAsync.ScanDumpAsync(StackExchange.Redis.RedisKey key, long iterator) -> System.Threading.Tasks.Task!>! +NRedisStack.CmsCommandBuilder +NRedisStack.CmsCommands +NRedisStack.CmsCommands.CmsCommands(StackExchange.Redis.IDatabase! db) -> void +NRedisStack.CmsCommands.IncrBy(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item, long increment) -> long +NRedisStack.CmsCommands.IncrBy(StackExchange.Redis.RedisKey key, System.Tuple![]! itemIncrements) -> long[]! +NRedisStack.CmsCommands.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.CountMinSketch.DataTypes.CmsInformation! +NRedisStack.CmsCommands.InitByDim(StackExchange.Redis.RedisKey key, long width, long depth) -> bool +NRedisStack.CmsCommands.InitByProb(StackExchange.Redis.RedisKey key, double error, double probability) -> bool +NRedisStack.CmsCommands.Merge(StackExchange.Redis.RedisValue destination, long numKeys, StackExchange.Redis.RedisValue[]! source, long[]? weight = null) -> bool +NRedisStack.CmsCommands.Query(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> long[]! +NRedisStack.CmsCommandsAsync +NRedisStack.CmsCommandsAsync.CmsCommandsAsync(StackExchange.Redis.IDatabaseAsync! db) -> void +NRedisStack.CmsCommandsAsync.IncrByAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item, long increment) -> System.Threading.Tasks.Task! +NRedisStack.CmsCommandsAsync.IncrByAsync(StackExchange.Redis.RedisKey key, System.Tuple![]! itemIncrements) -> System.Threading.Tasks.Task! +NRedisStack.CmsCommandsAsync.InfoAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.CmsCommandsAsync.InitByDimAsync(StackExchange.Redis.RedisKey key, long width, long depth) -> System.Threading.Tasks.Task! +NRedisStack.CmsCommandsAsync.InitByProbAsync(StackExchange.Redis.RedisKey key, double error, double probability) -> System.Threading.Tasks.Task! +NRedisStack.CmsCommandsAsync.MergeAsync(StackExchange.Redis.RedisValue destination, long numKeys, StackExchange.Redis.RedisValue[]! source, long[]? weight = null) -> System.Threading.Tasks.Task! +NRedisStack.CmsCommandsAsync.QueryAsync(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.Core.DataTypes.MinMaxModifier +NRedisStack.Core.DataTypes.MinMaxModifier.Max = 1 -> NRedisStack.Core.DataTypes.MinMaxModifier +NRedisStack.Core.DataTypes.MinMaxModifier.Min = 0 -> NRedisStack.Core.DataTypes.MinMaxModifier +NRedisStack.Core.DataTypes.MinMaxModifierExtensions +NRedisStack.Core.DataTypes.RedisStreamEntries +NRedisStack.Core.DataTypes.RedisStreamEntries.Entries.get -> StackExchange.Redis.StreamEntry[]! +NRedisStack.Core.DataTypes.RedisStreamEntries.Key.get -> StackExchange.Redis.RedisKey +NRedisStack.Core.DataTypes.RedisStreamEntries.RedisStreamEntries() -> void +NRedisStack.Core.DataTypes.RedisValueWithScore +NRedisStack.Core.DataTypes.RedisValueWithScore.RedisValueWithScore() -> void +NRedisStack.Core.DataTypes.RedisValueWithScore.RedisValueWithScore(StackExchange.Redis.RedisValue value, double score) -> void +NRedisStack.Core.DataTypes.RedisValueWithScore.Score.get -> double +NRedisStack.Core.DataTypes.RedisValueWithScore.Value.get -> StackExchange.Redis.RedisValue +NRedisStack.Core.DataTypes.StreamSpecialIds +NRedisStack.Core.DataTypes.StreamSpecialIds.StreamSpecialIds() -> void +NRedisStack.Core.SetInfoAttr +NRedisStack.Core.SetInfoAttr.LibraryName = 0 -> NRedisStack.Core.SetInfoAttr +NRedisStack.Core.SetInfoAttr.LibraryVersion = 1 -> NRedisStack.Core.SetInfoAttr +NRedisStack.CoreCommandBuilder +NRedisStack.CoreCommands +NRedisStack.CoreCommandsAsync +NRedisStack.CountMinSketch.DataTypes.CmsInformation +NRedisStack.CountMinSketch.DataTypes.CmsInformation.Count.get -> long +NRedisStack.CountMinSketch.DataTypes.CmsInformation.Depth.get -> long +NRedisStack.CountMinSketch.DataTypes.CmsInformation.Width.get -> long +NRedisStack.CuckooCommandBuilder +NRedisStack.CuckooCommands +NRedisStack.CuckooCommands.Add(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.CuckooCommands.AddNX(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.CuckooCommands.Count(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> long +NRedisStack.CuckooCommands.CuckooCommands(StackExchange.Redis.IDatabase! db) -> void +NRedisStack.CuckooCommands.Del(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.CuckooCommands.Exists(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.CuckooCommands.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.CuckooFilter.DataTypes.CuckooInformation! +NRedisStack.CuckooCommands.Insert(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, bool nocreate = false) -> bool[]! +NRedisStack.CuckooCommands.InsertNX(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, bool nocreate = false) -> bool[]! +NRedisStack.CuckooCommands.LoadChunk(StackExchange.Redis.RedisKey key, long iterator, byte[]! data) -> bool +NRedisStack.CuckooCommands.MExists(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> bool[]! +NRedisStack.CuckooCommands.Reserve(StackExchange.Redis.RedisKey key, long capacity, long? bucketSize = null, int? maxIterations = null, int? expansion = null) -> bool +NRedisStack.CuckooCommands.ScanDump(StackExchange.Redis.RedisKey key, long iterator) -> System.Tuple! +NRedisStack.CuckooCommandsAsync +NRedisStack.CuckooCommandsAsync.AddAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.CuckooCommandsAsync.AddNXAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.CuckooCommandsAsync.CountAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.CuckooCommandsAsync.CuckooCommandsAsync(StackExchange.Redis.IDatabaseAsync! db) -> void +NRedisStack.CuckooCommandsAsync.DelAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.CuckooCommandsAsync.ExistsAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.CuckooCommandsAsync.InfoAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.CuckooCommandsAsync.InsertAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, bool nocreate = false) -> System.Threading.Tasks.Task! +NRedisStack.CuckooCommandsAsync.InsertNXAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, bool nocreate = false) -> System.Threading.Tasks.Task! +NRedisStack.CuckooCommandsAsync.LoadChunkAsync(StackExchange.Redis.RedisKey key, long iterator, byte[]! data) -> System.Threading.Tasks.Task! +NRedisStack.CuckooCommandsAsync.MExistsAsync(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.CuckooCommandsAsync.ReserveAsync(StackExchange.Redis.RedisKey key, long capacity, long? bucketSize = null, int? maxIterations = null, int? expansion = null) -> System.Threading.Tasks.Task! +NRedisStack.CuckooCommandsAsync.ScanDumpAsync(StackExchange.Redis.RedisKey key, long iterator) -> System.Threading.Tasks.Task!>! +NRedisStack.CuckooFilter.DataTypes.CuckooInformation +NRedisStack.CuckooFilter.DataTypes.CuckooInformation.BucketSize.get -> long +NRedisStack.CuckooFilter.DataTypes.CuckooInformation.ExpansionRate.get -> long +NRedisStack.CuckooFilter.DataTypes.CuckooInformation.MaxIterations.get -> long +NRedisStack.CuckooFilter.DataTypes.CuckooInformation.NumberOfBuckets.get -> long +NRedisStack.CuckooFilter.DataTypes.CuckooInformation.NumberOfFilters.get -> long +NRedisStack.CuckooFilter.DataTypes.CuckooInformation.NumberOfItemsDeleted.get -> long +NRedisStack.CuckooFilter.DataTypes.CuckooInformation.NumberOfItemsInserted.get -> long +NRedisStack.CuckooFilter.DataTypes.CuckooInformation.Size.get -> long +NRedisStack.DataTypes.TimeSeriesChunck +NRedisStack.DataTypes.TimeSeriesChunck.BytesPerSample.get -> string! +NRedisStack.DataTypes.TimeSeriesChunck.EndTimestamp.get -> long +NRedisStack.DataTypes.TimeSeriesChunck.Samples.get -> long +NRedisStack.DataTypes.TimeSeriesChunck.Size.get -> long +NRedisStack.DataTypes.TimeSeriesChunck.StartTimestamp.get -> long +NRedisStack.DataTypes.TimeSeriesChunck.TimeSeriesChunck(long startTimestamp, long endTimestamp, long samples, long size, string! bytesPerSample) -> void +NRedisStack.DataTypes.TimeSeriesInformation +NRedisStack.DataTypes.TimeSeriesInformation.ChunkCount.get -> long +NRedisStack.DataTypes.TimeSeriesInformation.Chunks.get -> System.Collections.Generic.IReadOnlyList? +NRedisStack.DataTypes.TimeSeriesInformation.ChunkSize.get -> long +NRedisStack.DataTypes.TimeSeriesInformation.DuplicatePolicy.get -> NRedisStack.Literals.Enums.TsDuplicatePolicy? +NRedisStack.DataTypes.TimeSeriesInformation.FirstTimeStamp.get -> NRedisStack.DataTypes.TimeStamp? +NRedisStack.DataTypes.TimeSeriesInformation.KeySelfName.get -> string? +NRedisStack.DataTypes.TimeSeriesInformation.Labels.get -> System.Collections.Generic.IReadOnlyList? +NRedisStack.DataTypes.TimeSeriesInformation.LastTimeStamp.get -> NRedisStack.DataTypes.TimeStamp? +NRedisStack.DataTypes.TimeSeriesInformation.MaxSamplesPerChunk.get -> long +NRedisStack.DataTypes.TimeSeriesInformation.MemoryUsage.get -> long +NRedisStack.DataTypes.TimeSeriesInformation.RetentionTime.get -> long +NRedisStack.DataTypes.TimeSeriesInformation.Rules.get -> System.Collections.Generic.IReadOnlyList? +NRedisStack.DataTypes.TimeSeriesInformation.SourceKey.get -> string? +NRedisStack.DataTypes.TimeSeriesInformation.TotalSamples.get -> long +NRedisStack.DataTypes.TimeSeriesLabel +NRedisStack.DataTypes.TimeSeriesLabel.Key.get -> string! +NRedisStack.DataTypes.TimeSeriesLabel.TimeSeriesLabel(string! key, string! value) -> void +NRedisStack.DataTypes.TimeSeriesLabel.Value.get -> string! +NRedisStack.DataTypes.TimeSeriesRule +NRedisStack.DataTypes.TimeSeriesRule.Aggregation.get -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.DataTypes.TimeSeriesRule.DestKey.get -> string! +NRedisStack.DataTypes.TimeSeriesRule.TimeBucket.get -> long +NRedisStack.DataTypes.TimeSeriesRule.TimeSeriesRule(string! destKey, long timeBucket, NRedisStack.Literals.Enums.TsAggregation aggregation) -> void +NRedisStack.DataTypes.TimeSeriesTuple +NRedisStack.DataTypes.TimeSeriesTuple.Time.get -> NRedisStack.DataTypes.TimeStamp +NRedisStack.DataTypes.TimeSeriesTuple.TimeSeriesTuple(NRedisStack.DataTypes.TimeStamp time, double val) -> void +NRedisStack.DataTypes.TimeSeriesTuple.Val.get -> double +NRedisStack.DataTypes.TimeStamp +NRedisStack.DataTypes.TimeStamp.TimeStamp() -> void +NRedisStack.DataTypes.TimeStamp.TimeStamp(long timestamp) -> void +NRedisStack.DataTypes.TimeStamp.TimeStamp(string! timestamp) -> void +NRedisStack.DataTypes.TimeStamp.TimeStamp(System.DateTime dateTime) -> void +NRedisStack.DataTypes.TimeStamp.Value.get -> object! +NRedisStack.IBloomCommands +NRedisStack.IBloomCommands.Add(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.IBloomCommands.Card(StackExchange.Redis.RedisKey key) -> long +NRedisStack.IBloomCommands.Exists(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.IBloomCommands.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.Bloom.DataTypes.BloomInformation! +NRedisStack.IBloomCommands.Insert(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, double? error = null, int? expansion = null, bool nocreate = false, bool nonscaling = false) -> bool[]! +NRedisStack.IBloomCommands.LoadChunk(StackExchange.Redis.RedisKey key, long iterator, byte[]! data) -> bool +NRedisStack.IBloomCommands.MAdd(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> bool[]! +NRedisStack.IBloomCommands.MExists(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items) -> bool[]! +NRedisStack.IBloomCommands.Reserve(StackExchange.Redis.RedisKey key, double errorRate, long capacity, int? expansion = null, bool nonscaling = false) -> bool +NRedisStack.IBloomCommands.ScanDump(StackExchange.Redis.RedisKey key, long iterator) -> System.Tuple! +NRedisStack.IBloomCommandsAsync +NRedisStack.IBloomCommandsAsync.AddAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.IBloomCommandsAsync.CardAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.IBloomCommandsAsync.ExistsAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.IBloomCommandsAsync.InfoAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.IBloomCommandsAsync.InsertAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, double? error = null, int? expansion = null, bool nocreate = false, bool nonscaling = false) -> System.Threading.Tasks.Task! +NRedisStack.IBloomCommandsAsync.LoadChunkAsync(StackExchange.Redis.RedisKey key, long iterator, byte[]! data) -> System.Threading.Tasks.Task! +NRedisStack.IBloomCommandsAsync.MAddAsync(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.IBloomCommandsAsync.MExistsAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.IBloomCommandsAsync.ReserveAsync(StackExchange.Redis.RedisKey key, double errorRate, long capacity, int? expansion = null, bool nonscaling = false) -> System.Threading.Tasks.Task! +NRedisStack.IBloomCommandsAsync.ScanDumpAsync(StackExchange.Redis.RedisKey key, long iterator) -> System.Threading.Tasks.Task!>! +NRedisStack.ICmsCommands +NRedisStack.ICmsCommands.IncrBy(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item, long increment) -> long +NRedisStack.ICmsCommands.IncrBy(StackExchange.Redis.RedisKey key, System.Tuple![]! itemIncrements) -> long[]! +NRedisStack.ICmsCommands.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.CountMinSketch.DataTypes.CmsInformation! +NRedisStack.ICmsCommands.InitByDim(StackExchange.Redis.RedisKey key, long width, long depth) -> bool +NRedisStack.ICmsCommands.InitByProb(StackExchange.Redis.RedisKey key, double error, double probability) -> bool +NRedisStack.ICmsCommands.Merge(StackExchange.Redis.RedisValue destination, long numKeys, StackExchange.Redis.RedisValue[]! source, long[]? weight = null) -> bool +NRedisStack.ICmsCommands.Query(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> long[]! +NRedisStack.ICmsCommandsAsync +NRedisStack.ICmsCommandsAsync.IncrByAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item, long increment) -> System.Threading.Tasks.Task! +NRedisStack.ICmsCommandsAsync.IncrByAsync(StackExchange.Redis.RedisKey key, System.Tuple![]! itemIncrements) -> System.Threading.Tasks.Task! +NRedisStack.ICmsCommandsAsync.InfoAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.ICmsCommandsAsync.InitByDimAsync(StackExchange.Redis.RedisKey key, long width, long depth) -> System.Threading.Tasks.Task! +NRedisStack.ICmsCommandsAsync.InitByProbAsync(StackExchange.Redis.RedisKey key, double error, double probability) -> System.Threading.Tasks.Task! +NRedisStack.ICmsCommandsAsync.MergeAsync(StackExchange.Redis.RedisValue destination, long numKeys, StackExchange.Redis.RedisValue[]! source, long[]? weight = null) -> System.Threading.Tasks.Task! +NRedisStack.ICmsCommandsAsync.QueryAsync(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.ICuckooCommands +NRedisStack.ICuckooCommands.Add(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.ICuckooCommands.AddNX(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.ICuckooCommands.Count(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> long +NRedisStack.ICuckooCommands.Del(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.ICuckooCommands.Exists(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.ICuckooCommands.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.CuckooFilter.DataTypes.CuckooInformation! +NRedisStack.ICuckooCommands.Insert(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, bool nocreate = false) -> bool[]! +NRedisStack.ICuckooCommands.InsertNX(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, bool nocreate = false) -> bool[]! +NRedisStack.ICuckooCommands.LoadChunk(StackExchange.Redis.RedisKey key, long iterator, byte[]! data) -> bool +NRedisStack.ICuckooCommands.MExists(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> bool[]! +NRedisStack.ICuckooCommands.Reserve(StackExchange.Redis.RedisKey key, long capacity, long? bucketSize = null, int? maxIterations = null, int? expansion = null) -> bool +NRedisStack.ICuckooCommands.ScanDump(StackExchange.Redis.RedisKey key, long iterator) -> System.Tuple! +NRedisStack.ICuckooCommandsAsync +NRedisStack.ICuckooCommandsAsync.AddAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.ICuckooCommandsAsync.AddNXAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.ICuckooCommandsAsync.CountAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.ICuckooCommandsAsync.DelAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.ICuckooCommandsAsync.ExistsAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.ICuckooCommandsAsync.InfoAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.ICuckooCommandsAsync.InsertAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, bool nocreate = false) -> System.Threading.Tasks.Task! +NRedisStack.ICuckooCommandsAsync.InsertNXAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, bool nocreate = false) -> System.Threading.Tasks.Task! +NRedisStack.ICuckooCommandsAsync.LoadChunkAsync(StackExchange.Redis.RedisKey key, long iterator, byte[]! data) -> System.Threading.Tasks.Task! +NRedisStack.ICuckooCommandsAsync.MExistsAsync(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.ICuckooCommandsAsync.ReserveAsync(StackExchange.Redis.RedisKey key, long capacity, long? bucketSize = null, int? maxIterations = null, int? expansion = null) -> System.Threading.Tasks.Task! +NRedisStack.ICuckooCommandsAsync.ScanDumpAsync(StackExchange.Redis.RedisKey key, long iterator) -> System.Threading.Tasks.Task!>! +NRedisStack.IJsonCommands +NRedisStack.IJsonCommands.ArrAppend(StackExchange.Redis.RedisKey key, string? path = null, params object![]! values) -> long?[]! +NRedisStack.IJsonCommands.ArrIndex(StackExchange.Redis.RedisKey key, string! path, object! value, long? start = null, long? stop = null) -> long?[]! +NRedisStack.IJsonCommands.ArrInsert(StackExchange.Redis.RedisKey key, string! path, long index, params object![]! values) -> long?[]! +NRedisStack.IJsonCommands.ArrLen(StackExchange.Redis.RedisKey key, string? path = null) -> long?[]! +NRedisStack.IJsonCommands.ArrPop(StackExchange.Redis.RedisKey key, string? path = null, long? index = null) -> StackExchange.Redis.RedisResult![]! +NRedisStack.IJsonCommands.ArrTrim(StackExchange.Redis.RedisKey key, string! path, long start, long stop) -> long?[]! +NRedisStack.IJsonCommands.Clear(StackExchange.Redis.RedisKey key, string? path = null) -> long +NRedisStack.IJsonCommands.DebugMemory(string! key, string? path = null) -> long +NRedisStack.IJsonCommands.Del(StackExchange.Redis.RedisKey key, string? path = null) -> long +NRedisStack.IJsonCommands.Forget(StackExchange.Redis.RedisKey key, string? path = null) -> long +NRedisStack.IJsonCommands.Get(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue? indent = null, StackExchange.Redis.RedisValue? newLine = null, StackExchange.Redis.RedisValue? space = null, StackExchange.Redis.RedisValue? path = null) -> StackExchange.Redis.RedisResult! +NRedisStack.IJsonCommands.Get(StackExchange.Redis.RedisKey key, string![]! paths, StackExchange.Redis.RedisValue? indent = null, StackExchange.Redis.RedisValue? newLine = null, StackExchange.Redis.RedisValue? space = null) -> StackExchange.Redis.RedisResult! +NRedisStack.IJsonCommands.Get(StackExchange.Redis.RedisKey key, string! path = "$", System.Text.Json.JsonSerializerOptions? serializerOptions = null) -> T? +NRedisStack.IJsonCommands.GetEnumerable(StackExchange.Redis.RedisKey key, string! path = "$") -> System.Collections.Generic.IEnumerable! +NRedisStack.IJsonCommands.Merge(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, object! obj, System.Text.Json.JsonSerializerOptions? serializerOptions = null) -> bool +NRedisStack.IJsonCommands.Merge(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, StackExchange.Redis.RedisValue json) -> bool +NRedisStack.IJsonCommands.MGet(StackExchange.Redis.RedisKey[]! keys, string! path) -> StackExchange.Redis.RedisResult![]! +NRedisStack.IJsonCommands.MSet(NRedisStack.Json.DataTypes.KeyPathValue[]! KeyPathValueList) -> bool +NRedisStack.IJsonCommands.NumIncrby(StackExchange.Redis.RedisKey key, string! path, double value) -> double?[]! +NRedisStack.IJsonCommands.ObjKeys(StackExchange.Redis.RedisKey key, string? path = null) -> System.Collections.Generic.IEnumerable!>! +NRedisStack.IJsonCommands.ObjLen(StackExchange.Redis.RedisKey key, string? path = null) -> long?[]! +NRedisStack.IJsonCommands.Resp(StackExchange.Redis.RedisKey key, string? path = null) -> StackExchange.Redis.RedisResult![]! +NRedisStack.IJsonCommands.Set(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, object! obj, StackExchange.Redis.When when = StackExchange.Redis.When.Always, System.Text.Json.JsonSerializerOptions? serializerOptions = null) -> bool +NRedisStack.IJsonCommands.Set(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, StackExchange.Redis.RedisValue json, StackExchange.Redis.When when = StackExchange.Redis.When.Always) -> bool +NRedisStack.IJsonCommands.SetFromDirectory(StackExchange.Redis.RedisValue path, string! filesPath, StackExchange.Redis.When when = StackExchange.Redis.When.Always) -> int +NRedisStack.IJsonCommands.SetFromFile(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, string! filePath, StackExchange.Redis.When when = StackExchange.Redis.When.Always) -> bool +NRedisStack.IJsonCommands.StrAppend(StackExchange.Redis.RedisKey key, string! value, string? path = null) -> long?[]! +NRedisStack.IJsonCommands.StrLen(StackExchange.Redis.RedisKey key, string? path = null) -> long?[]! +NRedisStack.IJsonCommands.Toggle(StackExchange.Redis.RedisKey key, string? path = null) -> bool?[]! +NRedisStack.IJsonCommands.Type(StackExchange.Redis.RedisKey key, string? path = null) -> NRedisStack.JsonType[]! +NRedisStack.IJsonCommandsAsync +NRedisStack.IJsonCommandsAsync.ArrAppendAsync(StackExchange.Redis.RedisKey key, string? path = null, params object![]! values) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.ArrIndexAsync(StackExchange.Redis.RedisKey key, string! path, object! value, long? start = null, long? stop = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.ArrInsertAsync(StackExchange.Redis.RedisKey key, string! path, long index, params object![]! values) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.ArrLenAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.ArrPopAsync(StackExchange.Redis.RedisKey key, string? path = null, long? index = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.ArrTrimAsync(StackExchange.Redis.RedisKey key, string! path, long start, long stop) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.ClearAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.DebugMemoryAsync(string! key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.DelAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.ForgetAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.GetAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue? indent = null, StackExchange.Redis.RedisValue? newLine = null, StackExchange.Redis.RedisValue? space = null, StackExchange.Redis.RedisValue? path = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.GetAsync(StackExchange.Redis.RedisKey key, string![]! paths, StackExchange.Redis.RedisValue? indent = null, StackExchange.Redis.RedisValue? newLine = null, StackExchange.Redis.RedisValue? space = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.GetAsync(StackExchange.Redis.RedisKey key, string! path = "$", System.Text.Json.JsonSerializerOptions? serializerOptions = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.GetEnumerableAsync(StackExchange.Redis.RedisKey key, string! path = "$") -> System.Threading.Tasks.Task!>! +NRedisStack.IJsonCommandsAsync.MergeAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, object! obj, System.Text.Json.JsonSerializerOptions? serializerOptions = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.MergeAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, StackExchange.Redis.RedisValue json) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.MGetAsync(StackExchange.Redis.RedisKey[]! keys, string! path) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.MSetAsync(NRedisStack.Json.DataTypes.KeyPathValue[]! KeyPathValueList) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.NumIncrbyAsync(StackExchange.Redis.RedisKey key, string! path, double value) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.ObjKeysAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task!>!>! +NRedisStack.IJsonCommandsAsync.ObjLenAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.RespAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.SetAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, object! obj, StackExchange.Redis.When when = StackExchange.Redis.When.Always, System.Text.Json.JsonSerializerOptions? serializerOptions = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.SetAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, StackExchange.Redis.RedisValue json, StackExchange.Redis.When when = StackExchange.Redis.When.Always) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.SetFromDirectoryAsync(StackExchange.Redis.RedisValue path, string! filesPath, StackExchange.Redis.When when = StackExchange.Redis.When.Always) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.SetFromFileAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, string! filePath, StackExchange.Redis.When when = StackExchange.Redis.When.Always) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.StrAppendAsync(StackExchange.Redis.RedisKey key, string! value, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.StrLenAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.ToggleAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.IJsonCommandsAsync.TypeAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommands +NRedisStack.ISearchCommands.Aggregate(string! index, NRedisStack.Search.AggregationRequest! query) -> NRedisStack.Search.AggregationResult! +NRedisStack.ISearchCommands.AliasAdd(string! alias, string! index) -> bool +NRedisStack.ISearchCommands.AliasDel(string! alias) -> bool +NRedisStack.ISearchCommands.AliasUpdate(string! alias, string! index) -> bool +NRedisStack.ISearchCommands.Alter(string! index, NRedisStack.Search.Schema! schema, bool skipInitialScan = false) -> bool +NRedisStack.ISearchCommands.ConfigGet(string! option) -> System.Collections.Generic.Dictionary! +NRedisStack.ISearchCommands.ConfigSet(string! option, string! value) -> bool +NRedisStack.ISearchCommands.Create(string! indexName, NRedisStack.Search.FTCreateParams! parameters, NRedisStack.Search.Schema! schema) -> bool +NRedisStack.ISearchCommands.CursorDel(string! indexName, long cursorId) -> bool +NRedisStack.ISearchCommands.CursorRead(string! indexName, long cursorId, int? count = null) -> NRedisStack.Search.AggregationResult! +NRedisStack.ISearchCommands.DictAdd(string! dict, params string![]! terms) -> long +NRedisStack.ISearchCommands.DictDel(string! dict, params string![]! terms) -> long +NRedisStack.ISearchCommands.DictDump(string! dict) -> StackExchange.Redis.RedisResult![]! +NRedisStack.ISearchCommands.DropIndex(string! indexName, bool dd = false) -> bool +NRedisStack.ISearchCommands.Explain(string! indexName, string! query, int? dialect = null) -> string! +NRedisStack.ISearchCommands.ExplainCli(string! indexName, string! query, int? dialect = null) -> StackExchange.Redis.RedisResult![]! +NRedisStack.ISearchCommands.Info(StackExchange.Redis.RedisValue index) -> NRedisStack.Search.DataTypes.InfoResult! +NRedisStack.ISearchCommands.ProfileAggregate(string! indexName, NRedisStack.Search.AggregationRequest! query, bool limited = false) -> System.Tuple!>! +NRedisStack.ISearchCommands.ProfileOnAggregate(string! indexName, NRedisStack.Search.AggregationRequest! query, bool limited = false) -> System.Tuple! +NRedisStack.ISearchCommands.ProfileOnSearch(string! indexName, NRedisStack.Search.Query! q, bool limited = false) -> System.Tuple! +NRedisStack.ISearchCommands.ProfileSearch(string! indexName, NRedisStack.Search.Query! q, bool limited = false) -> System.Tuple!>! +NRedisStack.ISearchCommands.Search(string! indexName, NRedisStack.Search.Query! q) -> NRedisStack.Search.SearchResult! +NRedisStack.ISearchCommands.SpellCheck(string! indexName, string! query, NRedisStack.Search.FTSpellCheckParams? spellCheckParams = null) -> System.Collections.Generic.Dictionary!>! +NRedisStack.ISearchCommands.SugAdd(string! key, string! str, double score, bool increment = false, string? payload = null) -> long +NRedisStack.ISearchCommands.SugDel(string! key, string! str) -> bool +NRedisStack.ISearchCommands.SugGet(string! key, string! prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) -> System.Collections.Generic.List! +NRedisStack.ISearchCommands.SugGetWithScores(string! key, string! prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) -> System.Collections.Generic.List!>! +NRedisStack.ISearchCommands.SugLen(string! key) -> long +NRedisStack.ISearchCommands.SynDump(string! indexName) -> System.Collections.Generic.Dictionary!>! +NRedisStack.ISearchCommands.SynUpdate(string! indexName, string! synonymGroupId, bool skipInitialScan = false, params string![]! terms) -> bool +NRedisStack.ISearchCommands.TagVals(string! indexName, string! fieldName) -> StackExchange.Redis.RedisResult![]! +NRedisStack.ISearchCommands._List() -> StackExchange.Redis.RedisResult![]! +NRedisStack.ISearchCommandsAsync +NRedisStack.ISearchCommandsAsync.AggregateAsync(string! index, NRedisStack.Search.AggregationRequest! query) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.AliasAddAsync(string! alias, string! index) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.AliasDelAsync(string! alias) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.AliasUpdateAsync(string! alias, string! index) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.AlterAsync(string! index, NRedisStack.Search.Schema! schema, bool skipInitialScan = false) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.ConfigGetAsync(string! option) -> System.Threading.Tasks.Task!>! +NRedisStack.ISearchCommandsAsync.ConfigSetAsync(string! option, string! value) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.CreateAsync(string! indexName, NRedisStack.Search.FTCreateParams! parameters, NRedisStack.Search.Schema! schema) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.CursorDelAsync(string! indexName, long cursorId) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.CursorReadAsync(string! indexName, long cursorId, int? count = null) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.DictAddAsync(string! dict, params string![]! terms) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.DictDelAsync(string! dict, params string![]! terms) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.DictDumpAsync(string! dict) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.DropIndexAsync(string! indexName, bool dd = false) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.ExplainAsync(string! indexName, string! query, int? dialect = null) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.ExplainCliAsync(string! indexName, string! query, int? dialect = null) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.InfoAsync(StackExchange.Redis.RedisValue index) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.ProfileAggregateAsync(string! indexName, NRedisStack.Search.AggregationRequest! query, bool limited = false) -> System.Threading.Tasks.Task!>!>! +NRedisStack.ISearchCommandsAsync.ProfileOnAggregateAsync(string! indexName, NRedisStack.Search.AggregationRequest! query, bool limited = false) -> System.Threading.Tasks.Task!>! +NRedisStack.ISearchCommandsAsync.ProfileOnSearchAsync(string! indexName, NRedisStack.Search.Query! q, bool limited = false) -> System.Threading.Tasks.Task!>! +NRedisStack.ISearchCommandsAsync.ProfileSearchAsync(string! indexName, NRedisStack.Search.Query! q, bool limited = false) -> System.Threading.Tasks.Task!>!>! +NRedisStack.ISearchCommandsAsync.SearchAsync(string! indexName, NRedisStack.Search.Query! q) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.SpellCheckAsync(string! indexName, string! query, NRedisStack.Search.FTSpellCheckParams? spellCheckParams = null) -> System.Threading.Tasks.Task!>!>! +NRedisStack.ISearchCommandsAsync.SugAddAsync(string! key, string! str, double score, bool increment = false, string? payload = null) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.SugDelAsync(string! key, string! str) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.SugGetAsync(string! key, string! prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) -> System.Threading.Tasks.Task!>! +NRedisStack.ISearchCommandsAsync.SugGetWithScoresAsync(string! key, string! prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) -> System.Threading.Tasks.Task!>!>! +NRedisStack.ISearchCommandsAsync.SugLenAsync(string! key) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.SynDumpAsync(string! indexName) -> System.Threading.Tasks.Task!>!>! +NRedisStack.ISearchCommandsAsync.SynUpdateAsync(string! indexName, string! synonymGroupId, bool skipInitialScan = false, params string![]! terms) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync.TagValsAsync(string! indexName, string! fieldName) -> System.Threading.Tasks.Task! +NRedisStack.ISearchCommandsAsync._ListAsync() -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommands +NRedisStack.ITdigestCommands.Add(StackExchange.Redis.RedisKey key, params double[]! values) -> bool +NRedisStack.ITdigestCommands.ByRank(StackExchange.Redis.RedisKey key, params long[]! ranks) -> double[]! +NRedisStack.ITdigestCommands.ByRevRank(StackExchange.Redis.RedisKey key, params long[]! ranks) -> double[]! +NRedisStack.ITdigestCommands.CDF(StackExchange.Redis.RedisKey key, params double[]! values) -> double[]! +NRedisStack.ITdigestCommands.Create(StackExchange.Redis.RedisKey key, long compression = 100) -> bool +NRedisStack.ITdigestCommands.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.Tdigest.DataTypes.TdigestInformation! +NRedisStack.ITdigestCommands.Max(StackExchange.Redis.RedisKey key) -> double +NRedisStack.ITdigestCommands.Merge(StackExchange.Redis.RedisKey destinationKey, long compression = 0, bool overide = false, params StackExchange.Redis.RedisKey[]! sourceKeys) -> bool +NRedisStack.ITdigestCommands.Min(StackExchange.Redis.RedisKey key) -> double +NRedisStack.ITdigestCommands.Quantile(StackExchange.Redis.RedisKey key, params double[]! quantile) -> double[]! +NRedisStack.ITdigestCommands.Rank(StackExchange.Redis.RedisKey key, params long[]! values) -> long[]! +NRedisStack.ITdigestCommands.Reset(StackExchange.Redis.RedisKey key) -> bool +NRedisStack.ITdigestCommands.RevRank(StackExchange.Redis.RedisKey key, params long[]! values) -> long[]! +NRedisStack.ITdigestCommands.TrimmedMean(StackExchange.Redis.RedisKey key, double lowCutQuantile, double highCutQuantile) -> double +NRedisStack.ITdigestCommandsAsync +NRedisStack.ITdigestCommandsAsync.AddAsync(StackExchange.Redis.RedisKey key, params double[]! values) -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommandsAsync.ByRankAsync(StackExchange.Redis.RedisKey key, params long[]! ranks) -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommandsAsync.ByRevRankAsync(StackExchange.Redis.RedisKey key, params long[]! ranks) -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommandsAsync.CDFAsync(StackExchange.Redis.RedisKey key, params double[]! values) -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommandsAsync.CreateAsync(StackExchange.Redis.RedisKey key, long compression = 100) -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommandsAsync.InfoAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommandsAsync.MaxAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommandsAsync.MergeAsync(StackExchange.Redis.RedisKey destinationKey, long compression = 0, bool overide = false, params StackExchange.Redis.RedisKey[]! sourceKeys) -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommandsAsync.MinAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommandsAsync.QuantileAsync(StackExchange.Redis.RedisKey key, params double[]! quantile) -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommandsAsync.RankAsync(StackExchange.Redis.RedisKey key, params long[]! values) -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommandsAsync.ResetAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommandsAsync.RevRankAsync(StackExchange.Redis.RedisKey key, params long[]! values) -> System.Threading.Tasks.Task! +NRedisStack.ITdigestCommandsAsync.TrimmedMeanAsync(StackExchange.Redis.RedisKey key, double lowCutQuantile, double highCutQuantile) -> System.Threading.Tasks.Task! +NRedisStack.ITimeSeriesCommands +NRedisStack.ITimeSeriesCommands.Add(string! key, NRedisStack.DataTypes.TimeStamp timestamp, double value, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null) -> NRedisStack.DataTypes.TimeStamp +NRedisStack.ITimeSeriesCommands.Alter(string! key, long? retentionTime = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null, System.Collections.Generic.IReadOnlyCollection? labels = null) -> bool +NRedisStack.ITimeSeriesCommands.Create(string! key, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null) -> bool +NRedisStack.ITimeSeriesCommands.CreateRule(string! sourceKey, NRedisStack.DataTypes.TimeSeriesRule! rule, long alignTimestamp = 0) -> bool +NRedisStack.ITimeSeriesCommands.DecrBy(string! key, double value, NRedisStack.DataTypes.TimeStamp? timestamp = null, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) -> NRedisStack.DataTypes.TimeStamp +NRedisStack.ITimeSeriesCommands.Del(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp) -> long +NRedisStack.ITimeSeriesCommands.DeleteRule(string! sourceKey, string! destKey) -> bool +NRedisStack.ITimeSeriesCommands.Get(string! key, bool latest = false) -> NRedisStack.DataTypes.TimeSeriesTuple? +NRedisStack.ITimeSeriesCommands.IncrBy(string! key, double value, NRedisStack.DataTypes.TimeStamp? timestamp = null, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) -> NRedisStack.DataTypes.TimeStamp +NRedisStack.ITimeSeriesCommands.Info(string! key, bool debug = false) -> NRedisStack.DataTypes.TimeSeriesInformation! +NRedisStack.ITimeSeriesCommands.MAdd(System.Collections.Generic.IReadOnlyCollection<(string! key, NRedisStack.DataTypes.TimeStamp timestamp, double value)>! sequence) -> System.Collections.Generic.IReadOnlyList! +NRedisStack.ITimeSeriesCommands.MGet(System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectedLabels = null) -> System.Collections.Generic.IReadOnlyList<(string! key, System.Collections.Generic.IReadOnlyList! labels, NRedisStack.DataTypes.TimeSeriesTuple! value)>! +NRedisStack.ITimeSeriesCommands.MRange(NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectLabels = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false, (string!, NRedisStack.Literals.Enums.TsReduce)? groupbyTuple = null) -> System.Collections.Generic.IReadOnlyList<(string! key, System.Collections.Generic.IReadOnlyList! labels, System.Collections.Generic.IReadOnlyList! values)>! +NRedisStack.ITimeSeriesCommands.MRevRange(NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectLabels = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false, (string!, NRedisStack.Literals.Enums.TsReduce)? groupbyTuple = null) -> System.Collections.Generic.IReadOnlyList<(string! key, System.Collections.Generic.IReadOnlyList! labels, System.Collections.Generic.IReadOnlyList! values)>! +NRedisStack.ITimeSeriesCommands.QueryIndex(System.Collections.Generic.IReadOnlyCollection! filter) -> System.Collections.Generic.IReadOnlyList! +NRedisStack.ITimeSeriesCommands.Range(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false) -> System.Collections.Generic.IReadOnlyList! +NRedisStack.ITimeSeriesCommands.RevRange(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false) -> System.Collections.Generic.IReadOnlyList! +NRedisStack.ITimeSeriesCommandsAsync +NRedisStack.ITimeSeriesCommandsAsync.AddAsync(string! key, NRedisStack.DataTypes.TimeStamp timestamp, double value, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null) -> System.Threading.Tasks.Task! +NRedisStack.ITimeSeriesCommandsAsync.AlterAsync(string! key, long? retentionTime = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null, System.Collections.Generic.IReadOnlyCollection? labels = null) -> System.Threading.Tasks.Task! +NRedisStack.ITimeSeriesCommandsAsync.CreateAsync(string! key, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null) -> System.Threading.Tasks.Task! +NRedisStack.ITimeSeriesCommandsAsync.CreateRuleAsync(string! sourceKey, NRedisStack.DataTypes.TimeSeriesRule! rule, long alignTimestamp = 0) -> System.Threading.Tasks.Task! +NRedisStack.ITimeSeriesCommandsAsync.DecrByAsync(string! key, double value, NRedisStack.DataTypes.TimeStamp? timestamp = null, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) -> System.Threading.Tasks.Task! +NRedisStack.ITimeSeriesCommandsAsync.DelAsync(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp) -> System.Threading.Tasks.Task! +NRedisStack.ITimeSeriesCommandsAsync.DeleteRuleAsync(string! sourceKey, string! destKey) -> System.Threading.Tasks.Task! +NRedisStack.ITimeSeriesCommandsAsync.GetAsync(string! key, bool latest = false) -> System.Threading.Tasks.Task! +NRedisStack.ITimeSeriesCommandsAsync.IncrByAsync(string! key, double value, NRedisStack.DataTypes.TimeStamp? timestamp = null, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) -> System.Threading.Tasks.Task! +NRedisStack.ITimeSeriesCommandsAsync.InfoAsync(string! key, bool debug = false) -> System.Threading.Tasks.Task! +NRedisStack.ITimeSeriesCommandsAsync.MAddAsync(System.Collections.Generic.IReadOnlyCollection<(string! key, NRedisStack.DataTypes.TimeStamp timestamp, double value)>! sequence) -> System.Threading.Tasks.Task!>! +NRedisStack.ITimeSeriesCommandsAsync.MGetAsync(System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectedLabels = null) -> System.Threading.Tasks.Task! labels, NRedisStack.DataTypes.TimeSeriesTuple! value)>!>! +NRedisStack.ITimeSeriesCommandsAsync.MRangeAsync(NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectLabels = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false, (string!, NRedisStack.Literals.Enums.TsReduce)? groupbyTuple = null) -> System.Threading.Tasks.Task! labels, System.Collections.Generic.IReadOnlyList! values)>!>! +NRedisStack.ITimeSeriesCommandsAsync.MRevRangeAsync(NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectLabels = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false, (string!, NRedisStack.Literals.Enums.TsReduce)? groupbyTuple = null) -> System.Threading.Tasks.Task! labels, System.Collections.Generic.IReadOnlyList! values)>!>! +NRedisStack.ITimeSeriesCommandsAsync.QueryIndexAsync(System.Collections.Generic.IReadOnlyCollection! filter) -> System.Threading.Tasks.Task!>! +NRedisStack.ITimeSeriesCommandsAsync.RangeAsync(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false) -> System.Threading.Tasks.Task!>! +NRedisStack.ITimeSeriesCommandsAsync.RevRangeAsync(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false) -> System.Threading.Tasks.Task!>! +NRedisStack.ITopKCommands +NRedisStack.ITopKCommands.Add(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> StackExchange.Redis.RedisResult![]? +NRedisStack.ITopKCommands.Count(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> long[]! +NRedisStack.ITopKCommands.IncrBy(StackExchange.Redis.RedisKey key, params System.Tuple![]! itemIncrements) -> StackExchange.Redis.RedisResult![]! +NRedisStack.ITopKCommands.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.TopK.DataTypes.TopKInformation! +NRedisStack.ITopKCommands.List(StackExchange.Redis.RedisKey key, bool withcount = false) -> StackExchange.Redis.RedisResult![]! +NRedisStack.ITopKCommands.Query(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> bool[]! +NRedisStack.ITopKCommands.Query(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.ITopKCommands.Reserve(StackExchange.Redis.RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) -> bool +NRedisStack.ITopKCommandsAsync +NRedisStack.ITopKCommandsAsync.AddAsync(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.ITopKCommandsAsync.CountAsync(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.ITopKCommandsAsync.IncrByAsync(StackExchange.Redis.RedisKey key, params System.Tuple![]! itemIncrements) -> System.Threading.Tasks.Task! +NRedisStack.ITopKCommandsAsync.InfoAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.ITopKCommandsAsync.ListAsync(StackExchange.Redis.RedisKey key, bool withcount = false) -> System.Threading.Tasks.Task! +NRedisStack.ITopKCommandsAsync.QueryAsync(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.ITopKCommandsAsync.QueryAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.ITopKCommandsAsync.ReserveAsync(StackExchange.Redis.RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) -> System.Threading.Tasks.Task! +NRedisStack.Json.DataTypes.KeyPathValue +NRedisStack.Json.DataTypes.KeyPathValue.KeyPathValue() -> void +NRedisStack.Json.DataTypes.KeyPathValue.KeyPathValue(string! key, string! path, object! value) -> void +NRedisStack.Json.DataTypes.KeyPathValue.ToArray() -> System.Collections.Generic.IEnumerable! +NRedisStack.JsonCommandBuilder +NRedisStack.JsonCommands +NRedisStack.JsonCommands.ArrAppend(StackExchange.Redis.RedisKey key, string? path = null, params object![]! values) -> long?[]! +NRedisStack.JsonCommands.ArrIndex(StackExchange.Redis.RedisKey key, string! path, object! value, long? start = null, long? stop = null) -> long?[]! +NRedisStack.JsonCommands.ArrInsert(StackExchange.Redis.RedisKey key, string! path, long index, params object![]! values) -> long?[]! +NRedisStack.JsonCommands.ArrLen(StackExchange.Redis.RedisKey key, string? path = null) -> long?[]! +NRedisStack.JsonCommands.ArrPop(StackExchange.Redis.RedisKey key, string? path = null, long? index = null) -> StackExchange.Redis.RedisResult![]! +NRedisStack.JsonCommands.ArrTrim(StackExchange.Redis.RedisKey key, string! path, long start, long stop) -> long?[]! +NRedisStack.JsonCommands.Clear(StackExchange.Redis.RedisKey key, string? path = null) -> long +NRedisStack.JsonCommands.DebugMemory(string! key, string? path = null) -> long +NRedisStack.JsonCommands.Del(StackExchange.Redis.RedisKey key, string? path = null) -> long +NRedisStack.JsonCommands.Forget(StackExchange.Redis.RedisKey key, string? path = null) -> long +NRedisStack.JsonCommands.Get(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue? indent = null, StackExchange.Redis.RedisValue? newLine = null, StackExchange.Redis.RedisValue? space = null, StackExchange.Redis.RedisValue? path = null) -> StackExchange.Redis.RedisResult! +NRedisStack.JsonCommands.Get(StackExchange.Redis.RedisKey key, string![]! paths, StackExchange.Redis.RedisValue? indent = null, StackExchange.Redis.RedisValue? newLine = null, StackExchange.Redis.RedisValue? space = null) -> StackExchange.Redis.RedisResult! +NRedisStack.JsonCommands.Get(StackExchange.Redis.RedisKey key, string! path = "$", System.Text.Json.JsonSerializerOptions? serializerOptions = null) -> T? +NRedisStack.JsonCommands.GetEnumerable(StackExchange.Redis.RedisKey key, string! path = "$") -> System.Collections.Generic.IEnumerable! +NRedisStack.JsonCommands.JsonCommands(StackExchange.Redis.IDatabase! db) -> void +NRedisStack.JsonCommands.Merge(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, object! obj, System.Text.Json.JsonSerializerOptions? serializerOptions = null) -> bool +NRedisStack.JsonCommands.Merge(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, StackExchange.Redis.RedisValue json) -> bool +NRedisStack.JsonCommands.MGet(StackExchange.Redis.RedisKey[]! keys, string! path) -> StackExchange.Redis.RedisResult![]! +NRedisStack.JsonCommands.MSet(NRedisStack.Json.DataTypes.KeyPathValue[]! KeyPathValueList) -> bool +NRedisStack.JsonCommands.NumIncrby(StackExchange.Redis.RedisKey key, string! path, double value) -> double?[]! +NRedisStack.JsonCommands.ObjKeys(StackExchange.Redis.RedisKey key, string? path = null) -> System.Collections.Generic.IEnumerable!>! +NRedisStack.JsonCommands.ObjLen(StackExchange.Redis.RedisKey key, string? path = null) -> long?[]! +NRedisStack.JsonCommands.Resp(StackExchange.Redis.RedisKey key, string? path = null) -> StackExchange.Redis.RedisResult![]! +NRedisStack.JsonCommands.Set(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, object! obj, StackExchange.Redis.When when = StackExchange.Redis.When.Always, System.Text.Json.JsonSerializerOptions? serializerOptions = null) -> bool +NRedisStack.JsonCommands.Set(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, StackExchange.Redis.RedisValue json, StackExchange.Redis.When when = StackExchange.Redis.When.Always) -> bool +NRedisStack.JsonCommands.SetFromDirectory(StackExchange.Redis.RedisValue path, string! filesPath, StackExchange.Redis.When when = StackExchange.Redis.When.Always) -> int +NRedisStack.JsonCommands.SetFromFile(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, string! filePath, StackExchange.Redis.When when = StackExchange.Redis.When.Always) -> bool +NRedisStack.JsonCommands.StrAppend(StackExchange.Redis.RedisKey key, string! value, string? path = null) -> long?[]! +NRedisStack.JsonCommands.StrLen(StackExchange.Redis.RedisKey key, string? path = null) -> long?[]! +NRedisStack.JsonCommands.Toggle(StackExchange.Redis.RedisKey key, string? path = null) -> bool?[]! +NRedisStack.JsonCommands.Type(StackExchange.Redis.RedisKey key, string? path = null) -> NRedisStack.JsonType[]! +NRedisStack.JsonCommandsAsync +NRedisStack.JsonCommandsAsync.ArrAppendAsync(StackExchange.Redis.RedisKey key, string? path = null, params object![]! values) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.ArrIndexAsync(StackExchange.Redis.RedisKey key, string! path, object! value, long? start = null, long? stop = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.ArrInsertAsync(StackExchange.Redis.RedisKey key, string! path, long index, params object![]! values) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.ArrLenAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.ArrPopAsync(StackExchange.Redis.RedisKey key, string? path = null, long? index = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.ArrTrimAsync(StackExchange.Redis.RedisKey key, string! path, long start, long stop) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.ClearAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.DebugMemoryAsync(string! key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.DelAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.ForgetAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.GetAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue? indent = null, StackExchange.Redis.RedisValue? newLine = null, StackExchange.Redis.RedisValue? space = null, StackExchange.Redis.RedisValue? path = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.GetAsync(StackExchange.Redis.RedisKey key, string![]! paths, StackExchange.Redis.RedisValue? indent = null, StackExchange.Redis.RedisValue? newLine = null, StackExchange.Redis.RedisValue? space = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.GetAsync(StackExchange.Redis.RedisKey key, string! path = "$", System.Text.Json.JsonSerializerOptions? serializerOptions = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.GetEnumerableAsync(StackExchange.Redis.RedisKey key, string! path = "$") -> System.Threading.Tasks.Task!>! +NRedisStack.JsonCommandsAsync.JsonCommandsAsync(StackExchange.Redis.IDatabaseAsync! db) -> void +NRedisStack.JsonCommandsAsync.MergeAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, object! obj, System.Text.Json.JsonSerializerOptions? serializerOptions = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.MergeAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, StackExchange.Redis.RedisValue json) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.MGetAsync(StackExchange.Redis.RedisKey[]! keys, string! path) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.MSetAsync(NRedisStack.Json.DataTypes.KeyPathValue[]! KeyPathValueList) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.NumIncrbyAsync(StackExchange.Redis.RedisKey key, string! path, double value) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.ObjKeysAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task!>!>! +NRedisStack.JsonCommandsAsync.ObjLenAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.RespAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.SetAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, object! obj, StackExchange.Redis.When when = StackExchange.Redis.When.Always, System.Text.Json.JsonSerializerOptions? serializerOptions = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.SetAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, StackExchange.Redis.RedisValue json, StackExchange.Redis.When when = StackExchange.Redis.When.Always) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.SetFromDirectoryAsync(StackExchange.Redis.RedisValue path, string! filesPath, StackExchange.Redis.When when = StackExchange.Redis.When.Always) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.SetFromFileAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, string! filePath, StackExchange.Redis.When when = StackExchange.Redis.When.Always) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.StrAppendAsync(StackExchange.Redis.RedisKey key, string! value, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.StrLenAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.ToggleAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonCommandsAsync.TypeAsync(StackExchange.Redis.RedisKey key, string? path = null) -> System.Threading.Tasks.Task! +NRedisStack.JsonType +NRedisStack.JsonType.ARRAY = 6 -> NRedisStack.JsonType +NRedisStack.JsonType.BOOLEAN = 2 -> NRedisStack.JsonType +NRedisStack.JsonType.INTEGER = 3 -> NRedisStack.JsonType +NRedisStack.JsonType.NULL = 1 -> NRedisStack.JsonType +NRedisStack.JsonType.NUMBER = 4 -> NRedisStack.JsonType +NRedisStack.JsonType.OBJECT = 7 -> NRedisStack.JsonType +NRedisStack.JsonType.STRING = 5 -> NRedisStack.JsonType +NRedisStack.JsonType.UNKNOWN = 0 -> NRedisStack.JsonType +NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsAggregation.Avg = 0 -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsAggregation.Count = 5 -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsAggregation.First = 6 -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsAggregation.Last = 7 -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsAggregation.Max = 3 -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsAggregation.Min = 2 -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsAggregation.Range = 4 -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsAggregation.StdP = 8 -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsAggregation.StdS = 9 -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsAggregation.Sum = 1 -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsAggregation.Twa = 12 -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsAggregation.VarP = 10 -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsAggregation.VarS = 11 -> NRedisStack.Literals.Enums.TsAggregation +NRedisStack.Literals.Enums.TsBucketTimestamps +NRedisStack.Literals.Enums.TsBucketTimestamps.high = 2 -> NRedisStack.Literals.Enums.TsBucketTimestamps +NRedisStack.Literals.Enums.TsBucketTimestamps.low = 0 -> NRedisStack.Literals.Enums.TsBucketTimestamps +NRedisStack.Literals.Enums.TsBucketTimestamps.mid = 1 -> NRedisStack.Literals.Enums.TsBucketTimestamps +NRedisStack.Literals.Enums.TsDuplicatePolicy +NRedisStack.Literals.Enums.TsDuplicatePolicy.BLOCK = 0 -> NRedisStack.Literals.Enums.TsDuplicatePolicy +NRedisStack.Literals.Enums.TsDuplicatePolicy.FIRST = 1 -> NRedisStack.Literals.Enums.TsDuplicatePolicy +NRedisStack.Literals.Enums.TsDuplicatePolicy.LAST = 2 -> NRedisStack.Literals.Enums.TsDuplicatePolicy +NRedisStack.Literals.Enums.TsDuplicatePolicy.MAX = 4 -> NRedisStack.Literals.Enums.TsDuplicatePolicy +NRedisStack.Literals.Enums.TsDuplicatePolicy.MIN = 3 -> NRedisStack.Literals.Enums.TsDuplicatePolicy +NRedisStack.Literals.Enums.TsDuplicatePolicy.SUM = 5 -> NRedisStack.Literals.Enums.TsDuplicatePolicy +NRedisStack.Literals.Enums.TsReduce +NRedisStack.Literals.Enums.TsReduce.Avg = 3 -> NRedisStack.Literals.Enums.TsReduce +NRedisStack.Literals.Enums.TsReduce.Count = 5 -> NRedisStack.Literals.Enums.TsReduce +NRedisStack.Literals.Enums.TsReduce.Max = 2 -> NRedisStack.Literals.Enums.TsReduce +NRedisStack.Literals.Enums.TsReduce.Min = 1 -> NRedisStack.Literals.Enums.TsReduce +NRedisStack.Literals.Enums.TsReduce.Range = 4 -> NRedisStack.Literals.Enums.TsReduce +NRedisStack.Literals.Enums.TsReduce.StdP = 6 -> NRedisStack.Literals.Enums.TsReduce +NRedisStack.Literals.Enums.TsReduce.StdS = 7 -> NRedisStack.Literals.Enums.TsReduce +NRedisStack.Literals.Enums.TsReduce.Sum = 0 -> NRedisStack.Literals.Enums.TsReduce +NRedisStack.Literals.Enums.TsReduce.VarP = 8 -> NRedisStack.Literals.Enums.TsReduce +NRedisStack.Literals.Enums.TsReduce.VarS = 9 -> NRedisStack.Literals.Enums.TsReduce +NRedisStack.Pipeline +NRedisStack.Pipeline.Bf.get -> NRedisStack.BloomCommandsAsync! +NRedisStack.Pipeline.Cf.get -> NRedisStack.CuckooCommandsAsync! +NRedisStack.Pipeline.Cms.get -> NRedisStack.CmsCommandsAsync! +NRedisStack.Pipeline.Db.get -> StackExchange.Redis.IDatabaseAsync! +NRedisStack.Pipeline.Execute() -> void +NRedisStack.Pipeline.Ft.get -> NRedisStack.SearchCommandsAsync! +NRedisStack.Pipeline.Json.get -> NRedisStack.JsonCommandsAsync! +NRedisStack.Pipeline.Pipeline(StackExchange.Redis.IDatabase! db) -> void +NRedisStack.Pipeline.Tdigest.get -> NRedisStack.TdigestCommandsAsync! +NRedisStack.Pipeline.TopK.get -> NRedisStack.TopKCommandsAsync! +NRedisStack.Pipeline.Ts.get -> NRedisStack.TimeSeriesCommandsAsync! +NRedisStack.RedisStackCommands.ModulePrefixes +NRedisStack.RedisStackCommands.SerializedCommand +NRedisStack.RedisStackCommands.SerializedCommand.Args.get -> object![]! +NRedisStack.RedisStackCommands.SerializedCommand.Command.get -> string! +NRedisStack.RedisStackCommands.SerializedCommand.SerializedCommand(string! command, params object![]! args) -> void +NRedisStack.RedisStackCommands.SerializedCommand.SerializedCommand(string! command, System.Collections.Generic.ICollection! args) -> void +NRedisStack.Search.Aggregation.Group +NRedisStack.Search.Aggregation.Group.Group(params string![]! fields) -> void +NRedisStack.Search.Aggregation.Group.Group(System.Collections.Generic.IList! fields) -> void +NRedisStack.Search.Aggregation.Reducer +NRedisStack.Search.Aggregation.Reducer.Alias.get -> string? +NRedisStack.Search.Aggregation.Reducer.Alias.set -> void +NRedisStack.Search.Aggregation.Reducer.As(string! alias) -> NRedisStack.Search.Aggregation.Reducer! +NRedisStack.Search.Aggregation.Reducer.Reducer(string? field) -> void +NRedisStack.Search.Aggregation.Reducers +NRedisStack.Search.Aggregation.Row +NRedisStack.Search.Aggregation.Row.ContainsKey(string! key) -> bool +NRedisStack.Search.Aggregation.Row.Get(string! key) -> object! +NRedisStack.Search.Aggregation.Row.GetDouble(string! key) -> double +NRedisStack.Search.Aggregation.Row.GetLong(string! key) -> long +NRedisStack.Search.Aggregation.Row.GetString(string! key) -> string? +NRedisStack.Search.Aggregation.Row.Row() -> void +NRedisStack.Search.Aggregation.Row.this[string! key].get -> StackExchange.Redis.RedisValue +NRedisStack.Search.Aggregation.SortedField +NRedisStack.Search.Aggregation.SortedField.FieldName.get -> string! +NRedisStack.Search.Aggregation.SortedField.Order.get -> NRedisStack.Search.Aggregation.SortedField.SortOrder +NRedisStack.Search.Aggregation.SortedField.SortedField(string! fieldName, NRedisStack.Search.Aggregation.SortedField.SortOrder order = NRedisStack.Search.Aggregation.SortedField.SortOrder.ASC) -> void +NRedisStack.Search.Aggregation.SortedField.SortOrder +NRedisStack.Search.Aggregation.SortedField.SortOrder.ASC = 0 -> NRedisStack.Search.Aggregation.SortedField.SortOrder +NRedisStack.Search.Aggregation.SortedField.SortOrder.DESC = 1 -> NRedisStack.Search.Aggregation.SortedField.SortOrder +NRedisStack.Search.AggregationRequest +NRedisStack.Search.AggregationRequest.AggregationRequest() -> void +NRedisStack.Search.AggregationRequest.AggregationRequest(string! query, int? defaultDialect = null) -> void +NRedisStack.Search.AggregationRequest.Apply(string! projection, string! alias) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.Cursor(int? count = null, long? maxIdle = null) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.Dialect(int dialect) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.dialect.get -> int? +NRedisStack.Search.AggregationRequest.Filter(string! filter) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.GetArgs() -> System.Collections.Generic.List! +NRedisStack.Search.AggregationRequest.GroupBy(NRedisStack.Search.Aggregation.Group! group) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.GroupBy(string! field, params NRedisStack.Search.Aggregation.Reducer![]! reducers) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.GroupBy(System.Collections.Generic.IList! fields, System.Collections.Generic.IList! reducers) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.IsWithCursor() -> bool +NRedisStack.Search.AggregationRequest.Limit(int count) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.Limit(int offset, int count) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.Load(params NRedisStack.Search.FieldName![]! fields) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.LoadAll() -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.Params(System.Collections.Generic.Dictionary! nameValue) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.SerializeRedisArgs() -> void +NRedisStack.Search.AggregationRequest.SortBy(int max, params NRedisStack.Search.Aggregation.SortedField![]! fields) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.SortBy(params NRedisStack.Search.Aggregation.SortedField![]! fields) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.SortBy(string! property) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.Timeout(long timeout) -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationRequest.Verbatim() -> NRedisStack.Search.AggregationRequest! +NRedisStack.Search.AggregationResult +NRedisStack.Search.AggregationResult.CursorId.get -> long +NRedisStack.Search.AggregationResult.GetResults() -> System.Collections.Generic.IReadOnlyList!>! +NRedisStack.Search.AggregationResult.GetRow(int index) -> NRedisStack.Search.Aggregation.Row +NRedisStack.Search.AggregationResult.this[int index].get -> System.Collections.Generic.Dictionary? +NRedisStack.Search.AggregationResult.TotalResults.get -> long +NRedisStack.Search.DataTypes.InfoResult +NRedisStack.Search.DataTypes.InfoResult.Attributes.get -> System.Collections.Generic.Dictionary![]! +NRedisStack.Search.DataTypes.InfoResult.BytesPerRecordAvg.get -> double +NRedisStack.Search.DataTypes.InfoResult.CursorStats.get -> System.Collections.Generic.Dictionary! +NRedisStack.Search.DataTypes.InfoResult.DocTableSizeMebibytes.get -> double +NRedisStack.Search.DataTypes.InfoResult.GcStats.get -> System.Collections.Generic.Dictionary! +NRedisStack.Search.DataTypes.InfoResult.HashIndexingFailures.get -> long +NRedisStack.Search.DataTypes.InfoResult.Indexing.get -> long +NRedisStack.Search.DataTypes.InfoResult.IndexName.get -> string! +NRedisStack.Search.DataTypes.InfoResult.IndexOption.get -> System.Collections.Generic.Dictionary! +NRedisStack.Search.DataTypes.InfoResult.InfoResult(StackExchange.Redis.RedisResult! result) -> void +NRedisStack.Search.DataTypes.InfoResult.InvertedSzMebibytes.get -> double +NRedisStack.Search.DataTypes.InfoResult.KeyTableSizeMebibytes.get -> double +NRedisStack.Search.DataTypes.InfoResult.MaxDocId.get -> string! +NRedisStack.Search.DataTypes.InfoResult.NumberOfUses.get -> long +NRedisStack.Search.DataTypes.InfoResult.NumDocs.get -> long +NRedisStack.Search.DataTypes.InfoResult.NumRecords.get -> long +NRedisStack.Search.DataTypes.InfoResult.NumTerms.get -> long +NRedisStack.Search.DataTypes.InfoResult.OffsetBitsPerRecordAvg.get -> double +NRedisStack.Search.DataTypes.InfoResult.OffsetsPerTermAvg.get -> double +NRedisStack.Search.DataTypes.InfoResult.OffsetVectorsSzMebibytes.get -> double +NRedisStack.Search.DataTypes.InfoResult.PercentIndexed.get -> double +NRedisStack.Search.DataTypes.InfoResult.RecordsPerDocAvg.get -> double +NRedisStack.Search.DataTypes.InfoResult.SortableValueSizeMebibytes.get -> double +NRedisStack.Search.DataTypes.InfoResult.TotalIndexingTime.get -> double +NRedisStack.Search.DataTypes.InfoResult.TotalInvertedIndexBlocks.get -> double +NRedisStack.Search.DataTypes.InfoResult.VectorIndexSzMebibytes.get -> double +NRedisStack.Search.Document +NRedisStack.Search.Document.Document(string! id) -> void +NRedisStack.Search.Document.Document(string! id, double score, byte[]? payload) -> void +NRedisStack.Search.Document.Document(string! id, System.Collections.Generic.Dictionary! fields, double score = 1) -> void +NRedisStack.Search.Document.Document(string! id, System.Collections.Generic.Dictionary? fields, double score, byte[]? payload) -> void +NRedisStack.Search.Document.GetProperties() -> System.Collections.Generic.IEnumerable>! +NRedisStack.Search.Document.Id.get -> string! +NRedisStack.Search.Document.Payload.get -> byte[]? +NRedisStack.Search.Document.Score.get -> double +NRedisStack.Search.Document.Score.set -> void +NRedisStack.Search.Document.ScoreExplained.get -> string![]? +NRedisStack.Search.Document.Set(string! field, StackExchange.Redis.RedisValue value) -> NRedisStack.Search.Document! +NRedisStack.Search.Document.SetScore(double score) -> NRedisStack.Search.Document! +NRedisStack.Search.Document.this[string! key].get -> StackExchange.Redis.RedisValue +NRedisStack.Search.FieldName +NRedisStack.Search.FieldName.AddCommandArguments(System.Collections.Generic.List! args) -> int +NRedisStack.Search.FieldName.Alias.get -> string? +NRedisStack.Search.FieldName.As(string! attribute) -> NRedisStack.Search.FieldName! +NRedisStack.Search.FieldName.FieldName(string! name) -> void +NRedisStack.Search.FieldName.FieldName(string! name, string? attribute) -> void +NRedisStack.Search.FieldName.Name.get -> string! +NRedisStack.Search.FTCreateParams +NRedisStack.Search.FTCreateParams.AddParams(System.Collections.Generic.List! args) -> void +NRedisStack.Search.FTCreateParams.AddPrefix(string! prefix) -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.Filter(string! filter) -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.FTCreateParams() -> void +NRedisStack.Search.FTCreateParams.Language(string! defaultLanguage) -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.LanguageField(string! languageAttribute) -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.MaxTextFields() -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.NoFields() -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.NoFreqs() -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.NoHighlights() -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.NoHL() -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.NoOffsets() -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.NoStopwords() -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.On(NRedisStack.Search.Literals.Enums.IndexDataType dataType) -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.PayloadField(string! payloadAttribute) -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.Prefix(params string![]! prefixes) -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.Score(double defaultScore) -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.ScoreField(string! scoreField) -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.SkipInitialScan() -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.Stopwords(params string![]! stopwords) -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTCreateParams.Temporary(long seconds) -> NRedisStack.Search.FTCreateParams! +NRedisStack.Search.FTSpellCheckParams +NRedisStack.Search.FTSpellCheckParams.Dialect(int dialect) -> NRedisStack.Search.FTSpellCheckParams! +NRedisStack.Search.FTSpellCheckParams.Distance(int distance) -> NRedisStack.Search.FTSpellCheckParams! +NRedisStack.Search.FTSpellCheckParams.ExcludeTerm(string! dict) -> NRedisStack.Search.FTSpellCheckParams! +NRedisStack.Search.FTSpellCheckParams.FTSpellCheckParams() -> void +NRedisStack.Search.FTSpellCheckParams.GetArgs() -> System.Collections.Generic.List! +NRedisStack.Search.FTSpellCheckParams.IncludeTerm(string! dict) -> NRedisStack.Search.FTSpellCheckParams! +NRedisStack.Search.FTSpellCheckParams.SerializeRedisArgs() -> void +NRedisStack.Search.Literals.Enums.IndexDataType +NRedisStack.Search.Literals.Enums.IndexDataType.HASH = 0 -> NRedisStack.Search.Literals.Enums.IndexDataType +NRedisStack.Search.Literals.Enums.IndexDataType.JSON = 1 -> NRedisStack.Search.Literals.Enums.IndexDataType +NRedisStack.Search.ProfilingInformation +NRedisStack.Search.ProfilingInformation.Info.get -> StackExchange.Redis.RedisResult! +NRedisStack.Search.ProfilingInformation.ProfilingInformation(StackExchange.Redis.RedisResult! info) -> void +NRedisStack.Search.Query +NRedisStack.Search.Query.AddFilter(NRedisStack.Search.Query.Filter! f) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.AddParam(string! name, object! value) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.Dialect(int dialect) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.dialect.get -> int? +NRedisStack.Search.Query.Filter +NRedisStack.Search.Query.Filter.Property.get -> string! +NRedisStack.Search.Query.GeoFilter +NRedisStack.Search.Query.GeoFilter.GeoFilter(string! property, double lon, double lat, double radius, string! unit) -> void +NRedisStack.Search.Query.HighlightFields(NRedisStack.Search.Query.HighlightTags tags, params string![]! fields) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.HighlightFields(params string![]! fields) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.HighlightTags +NRedisStack.Search.Query.HighlightTags.Close.get -> string! +NRedisStack.Search.Query.HighlightTags.HighlightTags() -> void +NRedisStack.Search.Query.HighlightTags.HighlightTags(string! open, string! close) -> void +NRedisStack.Search.Query.HighlightTags.Open.get -> string! +NRedisStack.Search.Query.Language.get -> string? +NRedisStack.Search.Query.Language.set -> void +NRedisStack.Search.Query.Limit(int offset, int count) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.LimitFields(params string![]! fields) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.LimitKeys(params string![]! keys) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.NoContent.get -> bool +NRedisStack.Search.Query.NoContent.set -> void +NRedisStack.Search.Query.NoStopwords.get -> bool +NRedisStack.Search.Query.NoStopwords.set -> void +NRedisStack.Search.Query.NumericFilter +NRedisStack.Search.Query.NumericFilter.NumericFilter(string! property, double min, bool exclusiveMin, double max, bool exclusiveMax) -> void +NRedisStack.Search.Query.NumericFilter.NumericFilter(string! property, double min, double max) -> void +NRedisStack.Search.Query.Params(System.Collections.Generic.Dictionary! nameValue) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.Payload.get -> string? +NRedisStack.Search.Query.Payload.set -> void +NRedisStack.Search.Query.Query() -> void +NRedisStack.Search.Query.Query(string! queryString) -> void +NRedisStack.Search.Query.QueryString.get -> string! +NRedisStack.Search.Query.ReturnFields(params NRedisStack.Search.FieldName![]! fields) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.ReturnFields(params string![]! fields) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.Scorer.get -> string? +NRedisStack.Search.Query.Scorer.set -> void +NRedisStack.Search.Query.SetExpander(string! field) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.SetInOrder() -> NRedisStack.Search.Query! +NRedisStack.Search.Query.SetLanguage(string! language) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.SetNoContent(bool value = true) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.SetNoStopwords(bool value = true) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.SetPayload(string! payload) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.SetScorer(string! scorer) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.SetSortBy(string! field, bool? ascending = null) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.SetVerbatim(bool value = true) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.SetWithPayloads() -> NRedisStack.Search.Query! +NRedisStack.Search.Query.SetWithScores(bool value = true) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.Slop(int slop) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.SortAscending.get -> bool? +NRedisStack.Search.Query.SortAscending.set -> void +NRedisStack.Search.Query.SortBy.get -> string? +NRedisStack.Search.Query.SortBy.set -> void +NRedisStack.Search.Query.SummarizeFields(int contextLen, int fragmentCount, string? separator, params string![]! fields) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.SummarizeFields(params string![]! fields) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.Timeout(long timeout) -> NRedisStack.Search.Query! +NRedisStack.Search.Query.Verbatim.get -> bool +NRedisStack.Search.Query.Verbatim.set -> void +NRedisStack.Search.Query.WithPayloads.get -> bool +NRedisStack.Search.Query.WithPayloads.set -> void +NRedisStack.Search.Query.WithScores.get -> bool +NRedisStack.Search.Query.WithScores.set -> void +NRedisStack.Search.Schema +NRedisStack.Search.Schema.AddField(NRedisStack.Search.Schema.Field! field) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddGeoField(NRedisStack.Search.FieldName! name, bool sortable = false, bool noIndex = false, bool missingIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddGeoField(string! name, bool sortable = false, bool noIndex = false, bool missingIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddGeoShapeField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.GeoShapeField.CoordinateSystem system, bool missingIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddGeoShapeField(string! name, NRedisStack.Search.Schema.GeoShapeField.CoordinateSystem system, bool missingIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddNumericField(NRedisStack.Search.FieldName! name, bool sortable = false, bool noIndex = false, bool missingIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddNumericField(string! name, bool sortable = false, bool noIndex = false, bool missingIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddTagField(NRedisStack.Search.FieldName! name, bool sortable = false, bool unf = false, bool noIndex = false, string! separator = ",", bool caseSensitive = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddTagField(string! name, bool sortable = false, bool unf = false, bool noIndex = false, string! separator = ",", bool caseSensitive = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddTextField(NRedisStack.Search.FieldName! name, double weight = 1, bool sortable = false, bool unf = false, bool noStem = false, string? phonetic = null, bool noIndex = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddTextField(string! name, double weight = 1, bool sortable = false, bool unf = false, bool noStem = false, string? phonetic = null, bool noIndex = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddVectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorAlgo algorithm, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddVectorField(string! name, NRedisStack.Search.Schema.VectorField.VectorAlgo algorithm, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.Field +NRedisStack.Search.Schema.Field.FieldName.get -> NRedisStack.Search.FieldName! +NRedisStack.Search.Schema.Field.Type.get -> NRedisStack.Search.Schema.FieldType +NRedisStack.Search.Schema.Fields.get -> System.Collections.Generic.List! +NRedisStack.Search.Schema.FieldType +NRedisStack.Search.Schema.FieldType.Geo = 1 -> NRedisStack.Search.Schema.FieldType +NRedisStack.Search.Schema.FieldType.GeoShape = 2 -> NRedisStack.Search.Schema.FieldType +NRedisStack.Search.Schema.FieldType.Numeric = 3 -> NRedisStack.Search.Schema.FieldType +NRedisStack.Search.Schema.FieldType.Tag = 4 -> NRedisStack.Search.Schema.FieldType +NRedisStack.Search.Schema.FieldType.Text = 0 -> NRedisStack.Search.Schema.FieldType +NRedisStack.Search.Schema.FieldType.Vector = 5 -> NRedisStack.Search.Schema.FieldType +NRedisStack.Search.Schema.GeoField +NRedisStack.Search.Schema.GeoField.MissingIndex.get -> bool +NRedisStack.Search.Schema.GeoField.NoIndex.get -> bool +NRedisStack.Search.Schema.GeoField.Sortable.get -> bool +NRedisStack.Search.Schema.GeoShapeField +NRedisStack.Search.Schema.GeoShapeField.CoordinateSystem +NRedisStack.Search.Schema.GeoShapeField.CoordinateSystem.FLAT = 0 -> NRedisStack.Search.Schema.GeoShapeField.CoordinateSystem +NRedisStack.Search.Schema.GeoShapeField.CoordinateSystem.SPHERICAL = 1 -> NRedisStack.Search.Schema.GeoShapeField.CoordinateSystem +NRedisStack.Search.Schema.GeoShapeField.MissingIndex.get -> bool +NRedisStack.Search.Schema.NumericField +NRedisStack.Search.Schema.NumericField.MissingIndex.get -> bool +NRedisStack.Search.Schema.NumericField.NoIndex.get -> bool +NRedisStack.Search.Schema.NumericField.Sortable.get -> bool +NRedisStack.Search.Schema.Schema() -> void +NRedisStack.Search.Schema.TagField +NRedisStack.Search.Schema.TagField.CaseSensitive.get -> bool +NRedisStack.Search.Schema.TagField.EmptyIndex.get -> bool +NRedisStack.Search.Schema.TagField.MissingIndex.get -> bool +NRedisStack.Search.Schema.TagField.NoIndex.get -> bool +NRedisStack.Search.Schema.TagField.Separator.get -> string! +NRedisStack.Search.Schema.TagField.Sortable.get -> bool +NRedisStack.Search.Schema.TagField.Unf.get -> bool +NRedisStack.Search.Schema.TagField.WithSuffixTrie.get -> bool +NRedisStack.Search.Schema.TextField +NRedisStack.Search.Schema.TextField.EmptyIndex.get -> bool +NRedisStack.Search.Schema.TextField.MissingIndex.get -> bool +NRedisStack.Search.Schema.TextField.NoIndex.get -> bool +NRedisStack.Search.Schema.TextField.NoStem.get -> bool +NRedisStack.Search.Schema.TextField.Phonetic.get -> string? +NRedisStack.Search.Schema.TextField.Sortable.get -> bool +NRedisStack.Search.Schema.TextField.TextField(NRedisStack.Search.FieldName! name, double weight = 1, bool noStem = false, string? phonetic = null, bool sortable = false, bool unf = false, bool noIndex = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) -> void +NRedisStack.Search.Schema.TextField.TextField(string! name, double weight = 1, bool noStem = false, string? phonetic = null, bool sortable = false, bool unf = false, bool noIndex = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) -> void +NRedisStack.Search.Schema.TextField.Unf.get -> bool +NRedisStack.Search.Schema.TextField.Weight.get -> double +NRedisStack.Search.Schema.TextField.WithSuffixTrie.get -> bool +NRedisStack.Search.Schema.VectorField +NRedisStack.Search.Schema.VectorField.Algorithm.get -> NRedisStack.Search.Schema.VectorField.VectorAlgo +NRedisStack.Search.Schema.VectorField.Attributes.get -> System.Collections.Generic.Dictionary? +NRedisStack.Search.Schema.VectorField.MissingIndex.get -> bool +NRedisStack.Search.Schema.VectorField.VectorAlgo +NRedisStack.Search.Schema.VectorField.VectorAlgo.FLAT = 0 -> NRedisStack.Search.Schema.VectorField.VectorAlgo +NRedisStack.Search.Schema.VectorField.VectorAlgo.HNSW = 1 -> NRedisStack.Search.Schema.VectorField.VectorAlgo +NRedisStack.Search.Schema.VectorField.VectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorAlgo algorithm, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> void +NRedisStack.Search.Schema.VectorField.VectorField(string! name, NRedisStack.Search.Schema.VectorField.VectorAlgo algorithm, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> void +NRedisStack.Search.SearchResult +NRedisStack.Search.SearchResult.Documents.get -> System.Collections.Generic.List! +NRedisStack.Search.SearchResult.ToJson() -> System.Collections.Generic.List! +NRedisStack.Search.SearchResult.TotalResults.get -> long +NRedisStack.SearchCommandBuilder +NRedisStack.SearchCommands +NRedisStack.SearchCommands.Aggregate(string! index, NRedisStack.Search.AggregationRequest! query) -> NRedisStack.Search.AggregationResult! +NRedisStack.SearchCommands.AliasAdd(string! alias, string! index) -> bool +NRedisStack.SearchCommands.AliasDel(string! alias) -> bool +NRedisStack.SearchCommands.AliasUpdate(string! alias, string! index) -> bool +NRedisStack.SearchCommands.Alter(string! index, NRedisStack.Search.Schema! schema, bool skipInitialScan = false) -> bool +NRedisStack.SearchCommands.ConfigGet(string! option) -> System.Collections.Generic.Dictionary! +NRedisStack.SearchCommands.ConfigSet(string! option, string! value) -> bool +NRedisStack.SearchCommands.Create(string! indexName, NRedisStack.Search.FTCreateParams! parameters, NRedisStack.Search.Schema! schema) -> bool +NRedisStack.SearchCommands.Create(string! indexName, NRedisStack.Search.Schema! schema) -> bool +NRedisStack.SearchCommands.CursorDel(string! indexName, long cursorId) -> bool +NRedisStack.SearchCommands.CursorRead(string! indexName, long cursorId, int? count = null) -> NRedisStack.Search.AggregationResult! +NRedisStack.SearchCommands.DictAdd(string! dict, params string![]! terms) -> long +NRedisStack.SearchCommands.DictDel(string! dict, params string![]! terms) -> long +NRedisStack.SearchCommands.DictDump(string! dict) -> StackExchange.Redis.RedisResult![]! +NRedisStack.SearchCommands.DropIndex(string! indexName, bool dd = false) -> bool +NRedisStack.SearchCommands.Explain(string! indexName, string! query, int? dialect = null) -> string! +NRedisStack.SearchCommands.ExplainCli(string! indexName, string! query, int? dialect = null) -> StackExchange.Redis.RedisResult![]! +NRedisStack.SearchCommands.Info(StackExchange.Redis.RedisValue index) -> NRedisStack.Search.DataTypes.InfoResult! +NRedisStack.SearchCommands.ProfileAggregate(string! indexName, NRedisStack.Search.AggregationRequest! query, bool limited = false) -> System.Tuple!>! +NRedisStack.SearchCommands.ProfileOnAggregate(string! indexName, NRedisStack.Search.AggregationRequest! query, bool limited = false) -> System.Tuple! +NRedisStack.SearchCommands.ProfileOnSearch(string! indexName, NRedisStack.Search.Query! q, bool limited = false) -> System.Tuple! +NRedisStack.SearchCommands.ProfileSearch(string! indexName, NRedisStack.Search.Query! q, bool limited = false) -> System.Tuple!>! +NRedisStack.SearchCommands.Search(string! indexName, NRedisStack.Search.Query! q) -> NRedisStack.Search.SearchResult! +NRedisStack.SearchCommands.SearchCommands(StackExchange.Redis.IDatabase! db, int? defaultDialect = 2) -> void +NRedisStack.SearchCommands.SpellCheck(string! indexName, string! query, NRedisStack.Search.FTSpellCheckParams? spellCheckParams = null) -> System.Collections.Generic.Dictionary!>! +NRedisStack.SearchCommands.SugAdd(string! key, string! str, double score, bool increment = false, string? payload = null) -> long +NRedisStack.SearchCommands.SugDel(string! key, string! str) -> bool +NRedisStack.SearchCommands.SugGet(string! key, string! prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) -> System.Collections.Generic.List! +NRedisStack.SearchCommands.SugGetWithScores(string! key, string! prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) -> System.Collections.Generic.List!>! +NRedisStack.SearchCommands.SugLen(string! key) -> long +NRedisStack.SearchCommands.SynDump(string! indexName) -> System.Collections.Generic.Dictionary!>! +NRedisStack.SearchCommands.SynUpdate(string! indexName, string! synonymGroupId, bool skipInitialScan = false, params string![]! terms) -> bool +NRedisStack.SearchCommands.TagVals(string! indexName, string! fieldName) -> StackExchange.Redis.RedisResult![]! +NRedisStack.SearchCommands._List() -> StackExchange.Redis.RedisResult![]! +NRedisStack.SearchCommandsAsync +NRedisStack.SearchCommandsAsync.AggregateAsync(string! index, NRedisStack.Search.AggregationRequest! query) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.AliasAddAsync(string! alias, string! index) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.AliasDelAsync(string! alias) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.AliasUpdateAsync(string! alias, string! index) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.AlterAsync(string! index, NRedisStack.Search.Schema! schema, bool skipInitialScan = false) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.ConfigGetAsync(string! option) -> System.Threading.Tasks.Task!>! +NRedisStack.SearchCommandsAsync.ConfigSetAsync(string! option, string! value) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.CreateAsync(string! indexName, NRedisStack.Search.FTCreateParams! parameters, NRedisStack.Search.Schema! schema) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.CreateAsync(string! indexName, NRedisStack.Search.Schema! schema) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.CursorDelAsync(string! indexName, long cursorId) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.CursorReadAsync(string! indexName, long cursorId, int? count = null) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.defaultDialect -> int? +NRedisStack.SearchCommandsAsync.DictAddAsync(string! dict, params string![]! terms) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.DictDelAsync(string! dict, params string![]! terms) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.DictDumpAsync(string! dict) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.DropIndexAsync(string! indexName, bool dd = false) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.ExplainAsync(string! indexName, string! query, int? dialect = null) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.ExplainCliAsync(string! indexName, string! query, int? dialect = null) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.InfoAsync(StackExchange.Redis.RedisValue index) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.ProfileAggregateAsync(string! indexName, NRedisStack.Search.AggregationRequest! query, bool limited = false) -> System.Threading.Tasks.Task!>!>! +NRedisStack.SearchCommandsAsync.ProfileOnAggregateAsync(string! indexName, NRedisStack.Search.AggregationRequest! query, bool limited = false) -> System.Threading.Tasks.Task!>! +NRedisStack.SearchCommandsAsync.ProfileOnSearchAsync(string! indexName, NRedisStack.Search.Query! q, bool limited = false) -> System.Threading.Tasks.Task!>! +NRedisStack.SearchCommandsAsync.ProfileSearchAsync(string! indexName, NRedisStack.Search.Query! q, bool limited = false) -> System.Threading.Tasks.Task!>!>! +NRedisStack.SearchCommandsAsync.SearchAsync(string! indexName, NRedisStack.Search.Query! q) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.SearchCommandsAsync(StackExchange.Redis.IDatabaseAsync! db, int? defaultDialect = 2) -> void +NRedisStack.SearchCommandsAsync.SetDefaultDialect(int? defaultDialect) -> void +NRedisStack.SearchCommandsAsync.SpellCheckAsync(string! indexName, string! query, NRedisStack.Search.FTSpellCheckParams? spellCheckParams = null) -> System.Threading.Tasks.Task!>!>! +NRedisStack.SearchCommandsAsync.SugAddAsync(string! key, string! str, double score, bool increment = false, string? payload = null) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.SugDelAsync(string! key, string! str) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.SugGetAsync(string! key, string! prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) -> System.Threading.Tasks.Task!>! +NRedisStack.SearchCommandsAsync.SugGetWithScoresAsync(string! key, string! prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) -> System.Threading.Tasks.Task!>!>! +NRedisStack.SearchCommandsAsync.SugLenAsync(string! key) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.SynDumpAsync(string! indexName) -> System.Threading.Tasks.Task!>!>! +NRedisStack.SearchCommandsAsync.SynUpdateAsync(string! indexName, string! synonymGroupId, bool skipInitialScan = false, params string![]! terms) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync.TagValsAsync(string! indexName, string! fieldName) -> System.Threading.Tasks.Task! +NRedisStack.SearchCommandsAsync._ListAsync() -> System.Threading.Tasks.Task! +NRedisStack.Tdigest.DataTypes.TdigestInformation +NRedisStack.Tdigest.DataTypes.TdigestInformation.Capacity.get -> long +NRedisStack.Tdigest.DataTypes.TdigestInformation.Compression.get -> long +NRedisStack.Tdigest.DataTypes.TdigestInformation.MemoryUsage.get -> long +NRedisStack.Tdigest.DataTypes.TdigestInformation.MergedNodes.get -> long +NRedisStack.Tdigest.DataTypes.TdigestInformation.MergedWeight.get -> double +NRedisStack.Tdigest.DataTypes.TdigestInformation.Observations.get -> double +NRedisStack.Tdigest.DataTypes.TdigestInformation.TotalCompressions.get -> long +NRedisStack.Tdigest.DataTypes.TdigestInformation.UnmergedNodes.get -> long +NRedisStack.Tdigest.DataTypes.TdigestInformation.UnmergedWeight.get -> double +NRedisStack.TdigestCommandBuilder +NRedisStack.TdigestCommands +NRedisStack.TdigestCommands.Add(StackExchange.Redis.RedisKey key, params double[]! values) -> bool +NRedisStack.TdigestCommands.ByRank(StackExchange.Redis.RedisKey key, params long[]! ranks) -> double[]! +NRedisStack.TdigestCommands.ByRevRank(StackExchange.Redis.RedisKey key, params long[]! ranks) -> double[]! +NRedisStack.TdigestCommands.CDF(StackExchange.Redis.RedisKey key, params double[]! values) -> double[]! +NRedisStack.TdigestCommands.Create(StackExchange.Redis.RedisKey key, long compression = 100) -> bool +NRedisStack.TdigestCommands.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.Tdigest.DataTypes.TdigestInformation! +NRedisStack.TdigestCommands.Max(StackExchange.Redis.RedisKey key) -> double +NRedisStack.TdigestCommands.Merge(StackExchange.Redis.RedisKey destinationKey, long compression = 0, bool overide = false, params StackExchange.Redis.RedisKey[]! sourceKeys) -> bool +NRedisStack.TdigestCommands.Min(StackExchange.Redis.RedisKey key) -> double +NRedisStack.TdigestCommands.Quantile(StackExchange.Redis.RedisKey key, params double[]! quantile) -> double[]! +NRedisStack.TdigestCommands.Rank(StackExchange.Redis.RedisKey key, params long[]! values) -> long[]! +NRedisStack.TdigestCommands.Reset(StackExchange.Redis.RedisKey key) -> bool +NRedisStack.TdigestCommands.RevRank(StackExchange.Redis.RedisKey key, params long[]! values) -> long[]! +NRedisStack.TdigestCommands.TdigestCommands(StackExchange.Redis.IDatabase! db) -> void +NRedisStack.TdigestCommands.TrimmedMean(StackExchange.Redis.RedisKey key, double lowCutQuantile, double highCutQuantile) -> double +NRedisStack.TdigestCommandsAsync +NRedisStack.TdigestCommandsAsync.AddAsync(StackExchange.Redis.RedisKey key, params double[]! values) -> System.Threading.Tasks.Task! +NRedisStack.TdigestCommandsAsync.ByRankAsync(StackExchange.Redis.RedisKey key, params long[]! ranks) -> System.Threading.Tasks.Task! +NRedisStack.TdigestCommandsAsync.ByRevRankAsync(StackExchange.Redis.RedisKey key, params long[]! ranks) -> System.Threading.Tasks.Task! +NRedisStack.TdigestCommandsAsync.CDFAsync(StackExchange.Redis.RedisKey key, params double[]! values) -> System.Threading.Tasks.Task! +NRedisStack.TdigestCommandsAsync.CreateAsync(StackExchange.Redis.RedisKey key, long compression = 100) -> System.Threading.Tasks.Task! +NRedisStack.TdigestCommandsAsync.InfoAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.TdigestCommandsAsync.MaxAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.TdigestCommandsAsync.MergeAsync(StackExchange.Redis.RedisKey destinationKey, long compression = 0, bool overide = false, params StackExchange.Redis.RedisKey[]! sourceKeys) -> System.Threading.Tasks.Task! +NRedisStack.TdigestCommandsAsync.MinAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.TdigestCommandsAsync.QuantileAsync(StackExchange.Redis.RedisKey key, params double[]! quantile) -> System.Threading.Tasks.Task! +NRedisStack.TdigestCommandsAsync.RankAsync(StackExchange.Redis.RedisKey key, params long[]! values) -> System.Threading.Tasks.Task! +NRedisStack.TdigestCommandsAsync.ResetAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.TdigestCommandsAsync.RevRankAsync(StackExchange.Redis.RedisKey key, params long[]! values) -> System.Threading.Tasks.Task! +NRedisStack.TdigestCommandsAsync.TdigestCommandsAsync(StackExchange.Redis.IDatabaseAsync! db) -> void +NRedisStack.TdigestCommandsAsync.TrimmedMeanAsync(StackExchange.Redis.RedisKey key, double lowCutQuantile, double highCutQuantile) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesAux +NRedisStack.TimeSeriesCommands +NRedisStack.TimeSeriesCommands.Add(string! key, NRedisStack.DataTypes.TimeStamp timestamp, double value, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null) -> NRedisStack.DataTypes.TimeStamp +NRedisStack.TimeSeriesCommands.Add(string! key, NRedisStack.TsAddParams! parameters) -> NRedisStack.DataTypes.TimeStamp +NRedisStack.TimeSeriesCommands.Alter(string! key, long? retentionTime = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null, System.Collections.Generic.IReadOnlyCollection? labels = null) -> bool +NRedisStack.TimeSeriesCommands.Alter(string! key, NRedisStack.TsAlterParams! parameters) -> bool +NRedisStack.TimeSeriesCommands.Create(string! key, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null) -> bool +NRedisStack.TimeSeriesCommands.Create(string! key, NRedisStack.TsCreateParams! parameters) -> bool +NRedisStack.TimeSeriesCommands.CreateRule(string! sourceKey, NRedisStack.DataTypes.TimeSeriesRule! rule, long alignTimestamp = 0) -> bool +NRedisStack.TimeSeriesCommands.DecrBy(string! key, double value, NRedisStack.DataTypes.TimeStamp? timestamp = null, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) -> NRedisStack.DataTypes.TimeStamp +NRedisStack.TimeSeriesCommands.DecrBy(string! key, NRedisStack.TsDecrByParams! parameters) -> NRedisStack.DataTypes.TimeStamp +NRedisStack.TimeSeriesCommands.Del(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp) -> long +NRedisStack.TimeSeriesCommands.DeleteRule(string! sourceKey, string! destKey) -> bool +NRedisStack.TimeSeriesCommands.Get(string! key, bool latest = false) -> NRedisStack.DataTypes.TimeSeriesTuple? +NRedisStack.TimeSeriesCommands.IncrBy(string! key, double value, NRedisStack.DataTypes.TimeStamp? timestamp = null, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) -> NRedisStack.DataTypes.TimeStamp +NRedisStack.TimeSeriesCommands.IncrBy(string! key, NRedisStack.TsIncrByParams! parameters) -> NRedisStack.DataTypes.TimeStamp +NRedisStack.TimeSeriesCommands.Info(string! key, bool debug = false) -> NRedisStack.DataTypes.TimeSeriesInformation! +NRedisStack.TimeSeriesCommands.MAdd(System.Collections.Generic.IReadOnlyCollection<(string! key, NRedisStack.DataTypes.TimeStamp timestamp, double value)>! sequence) -> System.Collections.Generic.IReadOnlyList! +NRedisStack.TimeSeriesCommands.MGet(System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectedLabels = null) -> System.Collections.Generic.IReadOnlyList<(string! key, System.Collections.Generic.IReadOnlyList! labels, NRedisStack.DataTypes.TimeSeriesTuple! value)>! +NRedisStack.TimeSeriesCommands.MRange(NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectLabels = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false, (string!, NRedisStack.Literals.Enums.TsReduce)? groupbyTuple = null) -> System.Collections.Generic.IReadOnlyList<(string! key, System.Collections.Generic.IReadOnlyList! labels, System.Collections.Generic.IReadOnlyList! values)>! +NRedisStack.TimeSeriesCommands.MRevRange(NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectLabels = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false, (string!, NRedisStack.Literals.Enums.TsReduce)? groupbyTuple = null) -> System.Collections.Generic.IReadOnlyList<(string! key, System.Collections.Generic.IReadOnlyList! labels, System.Collections.Generic.IReadOnlyList! values)>! +NRedisStack.TimeSeriesCommands.QueryIndex(System.Collections.Generic.IReadOnlyCollection! filter) -> System.Collections.Generic.IReadOnlyList! +NRedisStack.TimeSeriesCommands.Range(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false) -> System.Collections.Generic.IReadOnlyList! +NRedisStack.TimeSeriesCommands.RevRange(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false) -> System.Collections.Generic.IReadOnlyList! +NRedisStack.TimeSeriesCommands.TimeSeriesCommands(StackExchange.Redis.IDatabase! db) -> void +NRedisStack.TimeSeriesCommandsAsync +NRedisStack.TimeSeriesCommandsAsync.AddAsync(string! key, NRedisStack.DataTypes.TimeStamp timestamp, double value, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.AddAsync(string! key, NRedisStack.TsAddParams! parameters) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.AlterAsync(string! key, long? retentionTime = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null, System.Collections.Generic.IReadOnlyCollection? labels = null) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.AlterAsync(string! key, NRedisStack.TsAlterParams! parameters) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.CreateAsync(string! key, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.CreateAsync(string! key, NRedisStack.TsCreateParams! parameters) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.CreateRuleAsync(string! sourceKey, NRedisStack.DataTypes.TimeSeriesRule! rule, long alignTimestamp = 0) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.DecrByAsync(string! key, double value, NRedisStack.DataTypes.TimeStamp? timestamp = null, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.DecrByAsync(string! key, NRedisStack.TsDecrByParams! parameters) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.DelAsync(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.DeleteRuleAsync(string! sourceKey, string! destKey) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.GetAsync(string! key, bool latest = false) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.IncrByAsync(string! key, double value, NRedisStack.DataTypes.TimeStamp? timestamp = null, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.IncrByAsync(string! key, NRedisStack.TsIncrByParams! parameters) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.InfoAsync(string! key, bool debug = false) -> System.Threading.Tasks.Task! +NRedisStack.TimeSeriesCommandsAsync.MAddAsync(System.Collections.Generic.IReadOnlyCollection<(string! key, NRedisStack.DataTypes.TimeStamp timestamp, double value)>! sequence) -> System.Threading.Tasks.Task!>! +NRedisStack.TimeSeriesCommandsAsync.MGetAsync(System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectedLabels = null) -> System.Threading.Tasks.Task! labels, NRedisStack.DataTypes.TimeSeriesTuple! value)>!>! +NRedisStack.TimeSeriesCommandsAsync.MRangeAsync(NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectLabels = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false, (string!, NRedisStack.Literals.Enums.TsReduce)? groupbyTuple = null) -> System.Threading.Tasks.Task! labels, System.Collections.Generic.IReadOnlyList! values)>!>! +NRedisStack.TimeSeriesCommandsAsync.MRevRangeAsync(NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectLabels = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false, (string!, NRedisStack.Literals.Enums.TsReduce)? groupbyTuple = null) -> System.Threading.Tasks.Task! labels, System.Collections.Generic.IReadOnlyList! values)>!>! +NRedisStack.TimeSeriesCommandsAsync.QueryIndexAsync(System.Collections.Generic.IReadOnlyCollection! filter) -> System.Threading.Tasks.Task!>! +NRedisStack.TimeSeriesCommandsAsync.RangeAsync(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false) -> System.Threading.Tasks.Task!>! +NRedisStack.TimeSeriesCommandsAsync.RevRangeAsync(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false) -> System.Threading.Tasks.Task!>! +NRedisStack.TimeSeriesCommandsAsync.TimeSeriesCommandsAsync(StackExchange.Redis.IDatabaseAsync! db) -> void +NRedisStack.TimeSeriesCommandsBuilder +NRedisStack.TopK.DataTypes.TopKInformation +NRedisStack.TopK.DataTypes.TopKInformation.Decay.get -> double +NRedisStack.TopK.DataTypes.TopKInformation.Depth.get -> long +NRedisStack.TopK.DataTypes.TopKInformation.K.get -> long +NRedisStack.TopK.DataTypes.TopKInformation.Width.get -> long +NRedisStack.TopKCommandBuilder +NRedisStack.TopKCommands +NRedisStack.TopKCommands.Add(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> StackExchange.Redis.RedisResult![]? +NRedisStack.TopKCommands.Count(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> long[]! +NRedisStack.TopKCommands.IncrBy(StackExchange.Redis.RedisKey key, params System.Tuple![]! itemIncrements) -> StackExchange.Redis.RedisResult![]! +NRedisStack.TopKCommands.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.TopK.DataTypes.TopKInformation! +NRedisStack.TopKCommands.List(StackExchange.Redis.RedisKey key, bool withcount = false) -> StackExchange.Redis.RedisResult![]! +NRedisStack.TopKCommands.Query(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> bool[]! +NRedisStack.TopKCommands.Query(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> bool +NRedisStack.TopKCommands.Reserve(StackExchange.Redis.RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) -> bool +NRedisStack.TopKCommands.TopKCommands(StackExchange.Redis.IDatabase! db) -> void +NRedisStack.TopKCommandsAsync +NRedisStack.TopKCommandsAsync.AddAsync(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.TopKCommandsAsync.CountAsync(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.TopKCommandsAsync.IncrByAsync(StackExchange.Redis.RedisKey key, params System.Tuple![]! itemIncrements) -> System.Threading.Tasks.Task! +NRedisStack.TopKCommandsAsync.InfoAsync(StackExchange.Redis.RedisKey key) -> System.Threading.Tasks.Task! +NRedisStack.TopKCommandsAsync.ListAsync(StackExchange.Redis.RedisKey key, bool withcount = false) -> System.Threading.Tasks.Task! +NRedisStack.TopKCommandsAsync.QueryAsync(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> System.Threading.Tasks.Task! +NRedisStack.TopKCommandsAsync.QueryAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> System.Threading.Tasks.Task! +NRedisStack.TopKCommandsAsync.ReserveAsync(StackExchange.Redis.RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) -> System.Threading.Tasks.Task! +NRedisStack.TopKCommandsAsync.TopKCommandsAsync(StackExchange.Redis.IDatabaseAsync! db) -> void +NRedisStack.Transaction +NRedisStack.Transaction.AddCondition(StackExchange.Redis.Condition! condition) -> StackExchange.Redis.ConditionResult! +NRedisStack.Transaction.Bf.get -> NRedisStack.BloomCommandsAsync! +NRedisStack.Transaction.Cf.get -> NRedisStack.CuckooCommandsAsync! +NRedisStack.Transaction.Cms.get -> NRedisStack.CmsCommandsAsync! +NRedisStack.Transaction.Db.get -> StackExchange.Redis.IDatabaseAsync! +NRedisStack.Transaction.Execute(StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> bool +NRedisStack.Transaction.ExecuteAsync(StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task! +NRedisStack.Transaction.Ft.get -> NRedisStack.SearchCommandsAsync! +NRedisStack.Transaction.Json.get -> NRedisStack.JsonCommandsAsync! +NRedisStack.Transaction.Tdigest.get -> NRedisStack.TdigestCommandsAsync! +NRedisStack.Transaction.TopK.get -> NRedisStack.TopKCommandsAsync! +NRedisStack.Transaction.Transaction(StackExchange.Redis.IDatabase! db) -> void +NRedisStack.Transaction.Ts.get -> NRedisStack.TimeSeriesCommandsAsync! +NRedisStack.TsAddParams +NRedisStack.TsAddParamsBuilder +NRedisStack.TsAddParamsBuilder.AddOnDuplicate(NRedisStack.Literals.Enums.TsDuplicatePolicy duplicatePolicy) -> NRedisStack.TsAddParamsBuilder! +NRedisStack.TsAddParamsBuilder.AddTimestamp(NRedisStack.DataTypes.TimeStamp timestamp) -> NRedisStack.TsAddParamsBuilder! +NRedisStack.TsAddParamsBuilder.AddUncompressed(bool uncompressed) -> NRedisStack.TsAddParamsBuilder! +NRedisStack.TsAddParamsBuilder.AddValue(double value) -> NRedisStack.TsAddParamsBuilder! +NRedisStack.TsAddParamsBuilder.build() -> NRedisStack.TsAddParams! +NRedisStack.TsAddParamsBuilder.TsAddParamsBuilder() -> void +NRedisStack.TsAlterParams +NRedisStack.TsAlterParamsBuilder +NRedisStack.TsAlterParamsBuilder.AddDuplicatePolicy(NRedisStack.Literals.Enums.TsDuplicatePolicy duplicatePolicy) -> NRedisStack.TsAlterParamsBuilder! +NRedisStack.TsAlterParamsBuilder.build() -> NRedisStack.TsAlterParams! +NRedisStack.TsAlterParamsBuilder.TsAlterParamsBuilder() -> void +NRedisStack.TsBaseParams +NRedisStack.TsBaseParamsBuilder +NRedisStack.TsBaseParamsBuilder.AddChunkSizeBytes(long chunkSizeBytes) -> T! +NRedisStack.TsBaseParamsBuilder.AddIgnoreValues(long ignoreMaxTimeDiff, long ignoreMaxValDiff) -> T! +NRedisStack.TsBaseParamsBuilder.AddLabels(System.Collections.Generic.IReadOnlyCollection! labels) -> T! +NRedisStack.TsBaseParamsBuilder.AddRetentionTime(long retentionTime) -> T! +NRedisStack.TsCreateParams +NRedisStack.TsCreateParamsBuilder +NRedisStack.TsCreateParamsBuilder.AddDuplicatePolicy(NRedisStack.Literals.Enums.TsDuplicatePolicy duplicatePolicy) -> NRedisStack.TsCreateParamsBuilder! +NRedisStack.TsCreateParamsBuilder.AddUncompressed(bool uncompressed) -> NRedisStack.TsCreateParamsBuilder! +NRedisStack.TsCreateParamsBuilder.build() -> NRedisStack.TsCreateParams! +NRedisStack.TsCreateParamsBuilder.TsCreateParamsBuilder() -> void +NRedisStack.TsDecrByParams +NRedisStack.TsDecrByParamsBuilder +NRedisStack.TsDecrByParamsBuilder.AddDuplicatePolicy(NRedisStack.Literals.Enums.TsDuplicatePolicy duplicatePolicy) -> NRedisStack.TsDecrByParamsBuilder! +NRedisStack.TsDecrByParamsBuilder.AddTimestamp(NRedisStack.DataTypes.TimeStamp timestamp) -> NRedisStack.TsDecrByParamsBuilder! +NRedisStack.TsDecrByParamsBuilder.AddUncompressed(bool uncompressed) -> NRedisStack.TsDecrByParamsBuilder! +NRedisStack.TsDecrByParamsBuilder.AddValue(double value) -> NRedisStack.TsDecrByParamsBuilder! +NRedisStack.TsDecrByParamsBuilder.build() -> NRedisStack.TsDecrByParams! +NRedisStack.TsDecrByParamsBuilder.TsDecrByParamsBuilder() -> void +NRedisStack.TsIncrByParams +NRedisStack.TsIncrByParamsBuilder +NRedisStack.TsIncrByParamsBuilder.AddDuplicatePolicy(NRedisStack.Literals.Enums.TsDuplicatePolicy duplicatePolicy) -> NRedisStack.TsIncrByParamsBuilder! +NRedisStack.TsIncrByParamsBuilder.AddTimestamp(NRedisStack.DataTypes.TimeStamp timestamp) -> NRedisStack.TsIncrByParamsBuilder! +NRedisStack.TsIncrByParamsBuilder.AddUncompressed(bool uncompressed) -> NRedisStack.TsIncrByParamsBuilder! +NRedisStack.TsIncrByParamsBuilder.AddValue(double value) -> NRedisStack.TsIncrByParamsBuilder! +NRedisStack.TsIncrByParamsBuilder.build() -> NRedisStack.TsIncrByParams! +NRedisStack.TsIncrByParamsBuilder.TsIncrByParamsBuilder() -> void +NRedisStack.TsParamsHelper +override NRedisStack.DataTypes.TimeSeriesLabel.Equals(object? obj) -> bool +override NRedisStack.DataTypes.TimeSeriesLabel.GetHashCode() -> int +override NRedisStack.DataTypes.TimeSeriesRule.Equals(object? obj) -> bool +override NRedisStack.DataTypes.TimeSeriesRule.GetHashCode() -> int +override NRedisStack.DataTypes.TimeSeriesTuple.Equals(object? obj) -> bool +override NRedisStack.DataTypes.TimeSeriesTuple.GetHashCode() -> int +override NRedisStack.DataTypes.TimeStamp.GetHashCode() -> int +static NRedisStack.Auxiliary.AssembleNonNullArguments(params object?[]! arguments) -> object![]! +static NRedisStack.Auxiliary.Execute(this StackExchange.Redis.IDatabase! db, NRedisStack.RedisStackCommands.SerializedCommand! command) -> StackExchange.Redis.RedisResult! +static NRedisStack.Auxiliary.ExecuteAsync(this StackExchange.Redis.IDatabaseAsync! db, NRedisStack.RedisStackCommands.SerializedCommand! command) -> System.Threading.Tasks.Task! +static NRedisStack.Auxiliary.ExecuteBroadcast(this StackExchange.Redis.IDatabase! db, NRedisStack.RedisStackCommands.SerializedCommand! command) -> System.Collections.Generic.List! +static NRedisStack.Auxiliary.ExecuteBroadcast(this StackExchange.Redis.IDatabase! db, string! command) -> System.Collections.Generic.List! +static NRedisStack.Auxiliary.ExecuteBroadcastAsync(this StackExchange.Redis.IDatabaseAsync! db, string! command) -> System.Threading.Tasks.Task!>! +static NRedisStack.Auxiliary.GetDatabase(this StackExchange.Redis.ConnectionMultiplexer! redis, string? LibraryName) -> StackExchange.Redis.IDatabase! +static NRedisStack.Auxiliary.GetNRedisStackVersion() -> string! +static NRedisStack.Auxiliary.MergeArgs(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> System.Collections.Generic.List! +static NRedisStack.Auxiliary.ResetInfoDefaults() -> void +static NRedisStack.BloomAux.BuildInsertArgs(StackExchange.Redis.RedisKey key, System.Collections.Generic.IEnumerable! items, int? capacity, double? error, int? expansion, bool nocreate, bool nonscaling) -> System.Collections.Generic.List! +static NRedisStack.BloomCommandBuilder.Add(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.BloomCommandBuilder.Card(StackExchange.Redis.RedisKey key) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.BloomCommandBuilder.Exists(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.BloomCommandBuilder.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.BloomCommandBuilder.Insert(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, double? error = null, int? expansion = null, bool nocreate = false, bool nonscaling = false) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.BloomCommandBuilder.LoadChunk(StackExchange.Redis.RedisKey key, long iterator, byte[]! data) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.BloomCommandBuilder.MAdd(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.BloomCommandBuilder.MExists(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.BloomCommandBuilder.Reserve(StackExchange.Redis.RedisKey key, double errorRate, long capacity, int? expansion = null, bool nonscaling = false) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.BloomCommandBuilder.ScanDump(StackExchange.Redis.RedisKey key, long iterator) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CmsCommandBuilder.IncrBy(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item, long increment) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CmsCommandBuilder.IncrBy(StackExchange.Redis.RedisKey key, System.Tuple![]! itemIncrements) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CmsCommandBuilder.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CmsCommandBuilder.InitByDim(StackExchange.Redis.RedisKey key, long width, long depth) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CmsCommandBuilder.InitByProb(StackExchange.Redis.RedisKey key, double error, double probability) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CmsCommandBuilder.Merge(StackExchange.Redis.RedisValue destination, long numKeys, StackExchange.Redis.RedisValue[]! source, long[]? weight = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CmsCommandBuilder.Query(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.Core.DataTypes.MinMaxModifierExtensions.ToMinMax(this StackExchange.Redis.Order order) -> NRedisStack.Core.DataTypes.MinMaxModifier +static NRedisStack.CoreCommandBuilder.BLMove(StackExchange.Redis.RedisKey source, StackExchange.Redis.RedisKey destination, StackExchange.Redis.ListSide sourceSide, StackExchange.Redis.ListSide destinationSide, double timeout) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CoreCommandBuilder.BLMPop(double timeout, StackExchange.Redis.RedisKey[]! keys, StackExchange.Redis.ListSide listSide, long? count) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CoreCommandBuilder.BLPop(StackExchange.Redis.RedisKey[]! keys, double timeout) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CoreCommandBuilder.BRPop(StackExchange.Redis.RedisKey[]! keys, double timeout) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CoreCommandBuilder.BRPopLPush(StackExchange.Redis.RedisKey source, StackExchange.Redis.RedisKey destination, double timeout) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CoreCommandBuilder.BZMPop(double timeout, StackExchange.Redis.RedisKey[]! keys, NRedisStack.Core.DataTypes.MinMaxModifier minMaxModifier, long? count) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CoreCommandBuilder.BZPopMax(StackExchange.Redis.RedisKey[]! keys, double timeout) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CoreCommandBuilder.BZPopMin(StackExchange.Redis.RedisKey[]! keys, double timeout) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CoreCommandBuilder.ClientSetInfo(NRedisStack.Core.SetInfoAttr attr, string! value) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CoreCommandBuilder.XRead(StackExchange.Redis.RedisKey[]! keys, StackExchange.Redis.RedisValue[]! positions, int? count, int? timeoutMilliseconds) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CoreCommandBuilder.XReadGroup(StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue consumerName, StackExchange.Redis.RedisKey[]! keys, StackExchange.Redis.RedisValue[]! positions, int? count, int? timeoutMilliseconds, bool? noAcknowledge) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CoreCommands.BLMove(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey source, StackExchange.Redis.RedisKey destination, StackExchange.Redis.ListSide sourceSide, StackExchange.Redis.ListSide destinationSide, double timeout) -> StackExchange.Redis.RedisValue? +static NRedisStack.CoreCommands.BLMPop(this StackExchange.Redis.IDatabase! db, double timeout, StackExchange.Redis.RedisKey key, StackExchange.Redis.ListSide listSide, long? count = null) -> System.Tuple!>? +static NRedisStack.CoreCommands.BLMPop(this StackExchange.Redis.IDatabase! db, double timeout, StackExchange.Redis.RedisKey[]! keys, StackExchange.Redis.ListSide listSide, long? count = null) -> System.Tuple!>? +static NRedisStack.CoreCommands.BLPop(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey key, double timeout) -> System.Tuple? +static NRedisStack.CoreCommands.BLPop(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey[]! keys, double timeout) -> System.Tuple? +static NRedisStack.CoreCommands.BRPop(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey key, double timeout) -> System.Tuple? +static NRedisStack.CoreCommands.BRPop(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey[]! keys, double timeout) -> System.Tuple? +static NRedisStack.CoreCommands.BRPopLPush(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey source, StackExchange.Redis.RedisKey destination, double timeout) -> StackExchange.Redis.RedisValue? +static NRedisStack.CoreCommands.BZMPop(this StackExchange.Redis.IDatabase! db, double timeout, StackExchange.Redis.RedisKey key, NRedisStack.Core.DataTypes.MinMaxModifier minMaxModifier, long? count = null) -> System.Tuple!>? +static NRedisStack.CoreCommands.BZMPop(this StackExchange.Redis.IDatabase! db, double timeout, StackExchange.Redis.RedisKey[]! keys, NRedisStack.Core.DataTypes.MinMaxModifier minMaxModifier, long? count = null) -> System.Tuple!>? +static NRedisStack.CoreCommands.BZPopMax(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey key, double timeout) -> System.Tuple? +static NRedisStack.CoreCommands.BZPopMax(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey[]! keys, double timeout) -> System.Tuple? +static NRedisStack.CoreCommands.BZPopMin(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey key, double timeout) -> System.Tuple? +static NRedisStack.CoreCommands.BZPopMin(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey[]! keys, double timeout) -> System.Tuple? +static NRedisStack.CoreCommands.ClientSetInfo(this StackExchange.Redis.IDatabase! db, NRedisStack.Core.SetInfoAttr attr, string! value) -> bool +static NRedisStack.CoreCommands.XRead(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue position, int? count = null, int? timeoutMilliseconds = null) -> StackExchange.Redis.StreamEntry[]? +static NRedisStack.CoreCommands.XRead(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey[]! keys, StackExchange.Redis.RedisValue[]! positions, int? count = null, int? timeoutMilliseconds = null) -> NRedisStack.Core.DataTypes.RedisStreamEntries[]? +static NRedisStack.CoreCommands.XReadGroup(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue consumerName, StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue position, int? count = null, int? timeoutMilliseconds = null, bool? noAck = null) -> StackExchange.Redis.StreamEntry[]? +static NRedisStack.CoreCommands.XReadGroup(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue consumerName, StackExchange.Redis.RedisKey[]! keys, StackExchange.Redis.RedisValue[]! positions, int? count = null, int? timeoutMilliseconds = null, bool? noAck = null) -> NRedisStack.Core.DataTypes.RedisStreamEntries[]? +static NRedisStack.CoreCommandsAsync.BLMoveAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey source, StackExchange.Redis.RedisKey destination, StackExchange.Redis.ListSide sourceSide, StackExchange.Redis.ListSide destinationSide, double timeout) -> System.Threading.Tasks.Task! +static NRedisStack.CoreCommandsAsync.BLMPopAsync(this StackExchange.Redis.IDatabase! db, double timeout, StackExchange.Redis.RedisKey key, StackExchange.Redis.ListSide listSide, long? count = null) -> System.Threading.Tasks.Task!>?>! +static NRedisStack.CoreCommandsAsync.BLMPopAsync(this StackExchange.Redis.IDatabase! db, double timeout, StackExchange.Redis.RedisKey[]! keys, StackExchange.Redis.ListSide listSide, long? count = null) -> System.Threading.Tasks.Task!>?>! +static NRedisStack.CoreCommandsAsync.BLPopAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey key, double timeout) -> System.Threading.Tasks.Task?>! +static NRedisStack.CoreCommandsAsync.BLPopAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey[]! keys, double timeout) -> System.Threading.Tasks.Task?>! +static NRedisStack.CoreCommandsAsync.BRPopAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey key, double timeout) -> System.Threading.Tasks.Task?>! +static NRedisStack.CoreCommandsAsync.BRPopAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey[]! keys, double timeout) -> System.Threading.Tasks.Task?>! +static NRedisStack.CoreCommandsAsync.BRPopLPushAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey source, StackExchange.Redis.RedisKey destination, double timeout) -> System.Threading.Tasks.Task! +static NRedisStack.CoreCommandsAsync.BZMPopAsync(this StackExchange.Redis.IDatabase! db, double timeout, StackExchange.Redis.RedisKey key, NRedisStack.Core.DataTypes.MinMaxModifier minMaxModifier, long? count = null) -> System.Threading.Tasks.Task!>?>! +static NRedisStack.CoreCommandsAsync.BZMPopAsync(this StackExchange.Redis.IDatabase! db, double timeout, StackExchange.Redis.RedisKey[]! keys, NRedisStack.Core.DataTypes.MinMaxModifier minMaxModifier, long? count = null) -> System.Threading.Tasks.Task!>?>! +static NRedisStack.CoreCommandsAsync.BZPopMaxAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey key, double timeout) -> System.Threading.Tasks.Task?>! +static NRedisStack.CoreCommandsAsync.BZPopMaxAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey[]! keys, double timeout) -> System.Threading.Tasks.Task?>! +static NRedisStack.CoreCommandsAsync.BZPopMinAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey key, double timeout) -> System.Threading.Tasks.Task?>! +static NRedisStack.CoreCommandsAsync.BZPopMinAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey[]! keys, double timeout) -> System.Threading.Tasks.Task?>! +static NRedisStack.CoreCommandsAsync.ClientSetInfoAsync(this StackExchange.Redis.IDatabaseAsync! db, NRedisStack.Core.SetInfoAttr attr, string! value) -> System.Threading.Tasks.Task! +static NRedisStack.CoreCommandsAsync.XReadAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue position, int? count = null, int? timeoutMilliseconds = null) -> System.Threading.Tasks.Task! +static NRedisStack.CoreCommandsAsync.XReadAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisKey[]! keys, StackExchange.Redis.RedisValue[]! positions, int? count = null, int? timeoutMilliseconds = null) -> System.Threading.Tasks.Task! +static NRedisStack.CoreCommandsAsync.XReadGroupAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue consumerName, StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue position, int? count = null, int? timeoutMilliseconds = null, bool? noAck = null) -> System.Threading.Tasks.Task! +static NRedisStack.CoreCommandsAsync.XReadGroupAsync(this StackExchange.Redis.IDatabase! db, StackExchange.Redis.RedisValue groupName, StackExchange.Redis.RedisValue consumerName, StackExchange.Redis.RedisKey[]! keys, StackExchange.Redis.RedisValue[]! positions, int? count = null, int? timeoutMilliseconds = null, bool? noAck = null) -> System.Threading.Tasks.Task! +static NRedisStack.CuckooCommandBuilder.Add(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CuckooCommandBuilder.AddNX(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CuckooCommandBuilder.Count(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CuckooCommandBuilder.Del(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CuckooCommandBuilder.Exists(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue item) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CuckooCommandBuilder.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CuckooCommandBuilder.Insert(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, bool nocreate = false) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CuckooCommandBuilder.InsertNX(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! items, int? capacity = null, bool nocreate = false) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CuckooCommandBuilder.LoadChunk(StackExchange.Redis.RedisKey key, long iterator, byte[]! data) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CuckooCommandBuilder.MExists(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CuckooCommandBuilder.Reserve(StackExchange.Redis.RedisKey key, long capacity, long? bucketSize = null, int? maxIterations = null, int? expansion = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.CuckooCommandBuilder.ScanDump(StackExchange.Redis.RedisKey key, long iterator) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.DataTypes.TimeSeriesInformation.implicit operator string!(NRedisStack.DataTypes.TimeSeriesInformation! info) -> string! +static NRedisStack.DataTypes.TimeSeriesLabel.implicit operator string!(NRedisStack.DataTypes.TimeSeriesLabel! tsl) -> string! +static NRedisStack.DataTypes.TimeSeriesRule.implicit operator string!(NRedisStack.DataTypes.TimeSeriesRule! tsr) -> string! +static NRedisStack.DataTypes.TimeSeriesTuple.implicit operator string!(NRedisStack.DataTypes.TimeSeriesTuple! tst) -> string! +static NRedisStack.DataTypes.TimeStamp.implicit operator long(NRedisStack.DataTypes.TimeStamp ts) -> long +static NRedisStack.DataTypes.TimeStamp.implicit operator NRedisStack.DataTypes.TimeStamp(long l) -> NRedisStack.DataTypes.TimeStamp +static NRedisStack.DataTypes.TimeStamp.implicit operator NRedisStack.DataTypes.TimeStamp(string! s) -> NRedisStack.DataTypes.TimeStamp +static NRedisStack.DataTypes.TimeStamp.implicit operator NRedisStack.DataTypes.TimeStamp(System.DateTime dateTime) -> NRedisStack.DataTypes.TimeStamp +static NRedisStack.DataTypes.TimeStamp.implicit operator string?(NRedisStack.DataTypes.TimeStamp ts) -> string? +static NRedisStack.DataTypes.TimeStamp.implicit operator System.DateTime(NRedisStack.DataTypes.TimeStamp timeStamp) -> System.DateTime +static NRedisStack.JsonCommandBuilder.ArrAppend(StackExchange.Redis.RedisKey key, string? path = null, params object![]! values) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.ArrIndex(StackExchange.Redis.RedisKey key, string! path, object! value, long? start = null, long? stop = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.ArrInsert(StackExchange.Redis.RedisKey key, string! path, long index, params object![]! values) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.ArrLen(StackExchange.Redis.RedisKey key, string? path = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.ArrPop(StackExchange.Redis.RedisKey key, string? path = null, long? index = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.ArrTrim(StackExchange.Redis.RedisKey key, string! path, long start, long stop) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.Clear(StackExchange.Redis.RedisKey key, string? path = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.DebugMemory(string! key, string? path = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.Del(StackExchange.Redis.RedisKey key, string? path = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.Get(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue? indent = null, StackExchange.Redis.RedisValue? newLine = null, StackExchange.Redis.RedisValue? space = null, StackExchange.Redis.RedisValue? path = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.Get(StackExchange.Redis.RedisKey key, string![]! paths, StackExchange.Redis.RedisValue? indent = null, StackExchange.Redis.RedisValue? newLine = null, StackExchange.Redis.RedisValue? space = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.Get(StackExchange.Redis.RedisKey key, string! path = "$") -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.Merge(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, StackExchange.Redis.RedisValue json) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.MGet(StackExchange.Redis.RedisKey[]! keys, string! path) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.MSet(NRedisStack.Json.DataTypes.KeyPathValue[]! KeyPathValueList) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.NumIncrby(StackExchange.Redis.RedisKey key, string! path, double value) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.ObjKeys(StackExchange.Redis.RedisKey key, string? path = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.ObjLen(StackExchange.Redis.RedisKey key, string? path = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.Resp(StackExchange.Redis.RedisKey key, string? path = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.Set(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue path, StackExchange.Redis.RedisValue json, StackExchange.Redis.When when = StackExchange.Redis.When.Always) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.StrAppend(StackExchange.Redis.RedisKey key, string! value, string? path = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.StrLen(StackExchange.Redis.RedisKey key, string? path = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.Toggle(StackExchange.Redis.RedisKey key, string? path = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.JsonCommandBuilder.Type(StackExchange.Redis.RedisKey key, string? path = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.RedisStackCommands.ModulePrefixes.BF(this StackExchange.Redis.IDatabase! db) -> NRedisStack.BloomCommands! +static NRedisStack.RedisStackCommands.ModulePrefixes.CF(this StackExchange.Redis.IDatabase! db) -> NRedisStack.CuckooCommands! +static NRedisStack.RedisStackCommands.ModulePrefixes.CMS(this StackExchange.Redis.IDatabase! db) -> NRedisStack.CmsCommands! +static NRedisStack.RedisStackCommands.ModulePrefixes.FT(this StackExchange.Redis.IDatabase! db, int? searchDialect = 2) -> NRedisStack.SearchCommands! +static NRedisStack.RedisStackCommands.ModulePrefixes.JSON(this StackExchange.Redis.IDatabase! db) -> NRedisStack.JsonCommands! +static NRedisStack.RedisStackCommands.ModulePrefixes.TDIGEST(this StackExchange.Redis.IDatabase! db) -> NRedisStack.TdigestCommands! +static NRedisStack.RedisStackCommands.ModulePrefixes.TOPK(this StackExchange.Redis.IDatabase! db) -> NRedisStack.TopKCommands! +static NRedisStack.RedisStackCommands.ModulePrefixes.TS(this StackExchange.Redis.IDatabase! db) -> NRedisStack.TimeSeriesCommands! +static NRedisStack.Search.Aggregation.Reducers.Avg(string! field) -> NRedisStack.Search.Aggregation.Reducer! +static NRedisStack.Search.Aggregation.Reducers.Count() -> NRedisStack.Search.Aggregation.Reducer! +static NRedisStack.Search.Aggregation.Reducers.CountDistinct(string! field) -> NRedisStack.Search.Aggregation.Reducer! +static NRedisStack.Search.Aggregation.Reducers.CountDistinctish(string! field) -> NRedisStack.Search.Aggregation.Reducer! +static NRedisStack.Search.Aggregation.Reducers.FirstValue(string! field) -> NRedisStack.Search.Aggregation.Reducer! +static NRedisStack.Search.Aggregation.Reducers.FirstValue(string! field, NRedisStack.Search.Aggregation.SortedField? sortBy) -> NRedisStack.Search.Aggregation.Reducer! +static NRedisStack.Search.Aggregation.Reducers.Max(string! field) -> NRedisStack.Search.Aggregation.Reducer! +static NRedisStack.Search.Aggregation.Reducers.Min(string! field) -> NRedisStack.Search.Aggregation.Reducer! +static NRedisStack.Search.Aggregation.Reducers.Quantile(string! field, double percentile) -> NRedisStack.Search.Aggregation.Reducer! +static NRedisStack.Search.Aggregation.Reducers.RandomSample(string! field, int size) -> NRedisStack.Search.Aggregation.Reducer! +static NRedisStack.Search.Aggregation.Reducers.StdDev(string! field) -> NRedisStack.Search.Aggregation.Reducer! +static NRedisStack.Search.Aggregation.Reducers.Sum(string! field) -> NRedisStack.Search.Aggregation.Reducer! +static NRedisStack.Search.Aggregation.Reducers.ToList(string! field) -> NRedisStack.Search.Aggregation.Reducer! +static NRedisStack.Search.Aggregation.SortedField.Asc(string! field) -> NRedisStack.Search.Aggregation.SortedField! +static NRedisStack.Search.Aggregation.SortedField.Desc(string! field) -> NRedisStack.Search.Aggregation.SortedField! +static NRedisStack.Search.Document.Load(string! id, double score, byte[]? payload, StackExchange.Redis.RedisValue[]? fields) -> NRedisStack.Search.Document! +static NRedisStack.Search.Document.Load(string! id, double score, byte[]? payload, StackExchange.Redis.RedisValue[]? fields, string![]? scoreExplained) -> NRedisStack.Search.Document! +static NRedisStack.Search.FieldName.Of(string! name) -> NRedisStack.Search.FieldName! +static NRedisStack.Search.FTCreateParams.CreateParams() -> NRedisStack.Search.FTCreateParams! +static NRedisStack.SearchCommandBuilder.Aggregate(string! index, NRedisStack.Search.AggregationRequest! query) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.AliasAdd(string! alias, string! index) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.AliasDel(string! alias) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.AliasUpdate(string! alias, string! index) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.Alter(string! index, NRedisStack.Search.Schema! schema, bool skipInitialScan = false) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.ConfigGet(string! option) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.ConfigSet(string! option, string! value) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.Create(string! indexName, NRedisStack.Search.FTCreateParams! parameters, NRedisStack.Search.Schema! schema) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.CursorDel(string! indexName, long cursorId) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.CursorRead(string! indexName, long cursorId, int? count = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.DictAdd(string! dict, params string![]! terms) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.DictDel(string! dict, params string![]! terms) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.DictDump(string! dict) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.DropIndex(string! indexName, bool dd = false) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.Explain(string! indexName, string! query, int? dialect) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.ExplainCli(string! indexName, string! query, int? dialect) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.Info(StackExchange.Redis.RedisValue index) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.ProfileAggregate(string! IndexName, NRedisStack.Search.AggregationRequest! query, bool limited = false) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.ProfileSearch(string! IndexName, NRedisStack.Search.Query! q, bool limited = false) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.Search(string! indexName, NRedisStack.Search.Query! q) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.SpellCheck(string! indexName, string! query, NRedisStack.Search.FTSpellCheckParams? spellCheckParams = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.SugAdd(string! key, string! str, double score, bool increment = false, string? payload = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.SugDel(string! key, string! str) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.SugGet(string! key, string! prefix, bool fuzzy = false, bool withScores = false, bool withPayloads = false, int? max = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.SugLen(string! key) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.SynDump(string! indexName) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.SynUpdate(string! indexName, string! synonymGroupId, bool skipInitialScan = false, params string![]! terms) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder.TagVals(string! indexName, string! fieldName) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.SearchCommandBuilder._List() -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.Add(StackExchange.Redis.RedisKey key, params double[]! values) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.ByRank(StackExchange.Redis.RedisKey key, params long[]! ranks) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.ByRevRank(StackExchange.Redis.RedisKey key, params long[]! ranks) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.CDF(StackExchange.Redis.RedisKey key, params double[]! values) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.Create(StackExchange.Redis.RedisKey key, long compression = 100) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.Max(StackExchange.Redis.RedisKey key) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.Merge(StackExchange.Redis.RedisKey destinationKey, long compression = 0, bool overide = false, params StackExchange.Redis.RedisKey[]! sourceKeys) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.Min(StackExchange.Redis.RedisKey key) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.Quantile(StackExchange.Redis.RedisKey key, params double[]! quantile) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.Rank(StackExchange.Redis.RedisKey key, params long[]! values) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.Reset(StackExchange.Redis.RedisKey key) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.RevRank(StackExchange.Redis.RedisKey key, params long[]! values) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TdigestCommandBuilder.TrimmedMean(StackExchange.Redis.RedisKey key, double lowCutQuantile, double highCutQuantile) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesAux.AddAggregation(this System.Collections.Generic.IList! args, NRedisStack.DataTypes.TimeStamp? align, NRedisStack.Literals.Enums.TsAggregation? aggregation, long? timeBucket, NRedisStack.Literals.Enums.TsBucketTimestamps? bt, bool empty) -> void +static NRedisStack.TimeSeriesAux.AddAggregation(this System.Collections.Generic.IList! args, NRedisStack.Literals.Enums.TsAggregation? aggregation, long? timeBucket) -> void +static NRedisStack.TimeSeriesAux.AddAlign(this System.Collections.Generic.IList! args, NRedisStack.DataTypes.TimeStamp? alignMaybe) -> void +static NRedisStack.TimeSeriesAux.AddBucketTimestamp(this System.Collections.Generic.IList! args, NRedisStack.Literals.Enums.TsBucketTimestamps? bt) -> void +static NRedisStack.TimeSeriesAux.AddCount(this System.Collections.Generic.IList! args, long? count) -> void +static NRedisStack.TimeSeriesAux.AddFilterByTs(this System.Collections.Generic.List! args, System.Collections.Generic.IReadOnlyCollection? filter) -> void +static NRedisStack.TimeSeriesAux.AddFilterByValue(this System.Collections.Generic.List! args, (long, long)? filter) -> void +static NRedisStack.TimeSeriesAux.AddFilters(this System.Collections.Generic.List! args, System.Collections.Generic.IReadOnlyCollection! filter) -> void +static NRedisStack.TimeSeriesAux.AddGroupby(this System.Collections.Generic.IList! args, (string! groupby, NRedisStack.Literals.Enums.TsReduce reduce)? groupbyTuple) -> void +static NRedisStack.TimeSeriesAux.AddLatest(this System.Collections.Generic.IList! args, bool latest) -> void +static NRedisStack.TimeSeriesAux.AddRule(this System.Collections.Generic.IList! args, NRedisStack.DataTypes.TimeSeriesRule! rule) -> void +static NRedisStack.TimeSeriesAux.AddTimeStamp(this System.Collections.Generic.IList! args, NRedisStack.DataTypes.TimeStamp timeStamp) -> void +static NRedisStack.TimeSeriesAux.AddWithLabels(this System.Collections.Generic.IList! args, bool? withLabels, System.Collections.Generic.IReadOnlyCollection? selectLabels = null) -> void +static NRedisStack.TimeSeriesAux.BuildMultiRangeArgs(NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, System.Collections.Generic.IReadOnlyCollection! filter, bool latest, System.Collections.Generic.IReadOnlyCollection? filterByTs, (long, long)? filterByValue, bool? withLabels, System.Collections.Generic.IReadOnlyCollection? selectLabels, long? count, NRedisStack.DataTypes.TimeStamp? align, NRedisStack.Literals.Enums.TsAggregation? aggregation, long? timeBucket, NRedisStack.Literals.Enums.TsBucketTimestamps? bt, bool empty, (string!, NRedisStack.Literals.Enums.TsReduce)? groupbyTuple) -> System.Collections.Generic.List! +static NRedisStack.TimeSeriesAux.BuildRangeArgs(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, bool latest, System.Collections.Generic.IReadOnlyCollection? filterByTs, (long, long)? filterByValue, long? count, NRedisStack.DataTypes.TimeStamp? align, NRedisStack.Literals.Enums.TsAggregation? aggregation, long? timeBucket, NRedisStack.Literals.Enums.TsBucketTimestamps? bt, bool empty) -> System.Collections.Generic.List! +static NRedisStack.TimeSeriesAux.BuildTsDelArgs(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp) -> System.Collections.Generic.List! +static NRedisStack.TimeSeriesAux.BuildTsMaddArgs(System.Collections.Generic.IReadOnlyCollection<(string! key, NRedisStack.DataTypes.TimeStamp timestamp, double value)>! sequence) -> System.Collections.Generic.List! +static NRedisStack.TimeSeriesAux.BuildTsMgetArgs(bool latest, System.Collections.Generic.IReadOnlyCollection! filter, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectedLabels = null) -> System.Collections.Generic.List! +static NRedisStack.TimeSeriesCommandsBuilder.Add(string! key, NRedisStack.DataTypes.TimeStamp timestamp, double value, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.Add(string! key, NRedisStack.TsAddParams! parameters) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.Alter(string! key, long? retentionTime = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null, System.Collections.Generic.IReadOnlyCollection? labels = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.Alter(string! key, NRedisStack.TsAlterParams! parameters) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.Create(string! key, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, NRedisStack.Literals.Enums.TsDuplicatePolicy? duplicatePolicy = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.Create(string! key, NRedisStack.TsCreateParams! parameters) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.CreateRule(string! sourceKey, NRedisStack.DataTypes.TimeSeriesRule! rule, long alignTimestamp = 0) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.DecrBy(string! key, double value, NRedisStack.DataTypes.TimeStamp? timestamp = null, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.DecrBy(string! key, NRedisStack.TsDecrByParams! parameters) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.Del(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.DeleteRule(string! sourceKey, string! destKey) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.Get(string! key, bool latest = false) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.IncrBy(string! key, double value, NRedisStack.DataTypes.TimeStamp? timestamp = null, long? retentionTime = null, System.Collections.Generic.IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.IncrBy(string! key, NRedisStack.TsIncrByParams! parameters) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.Info(string! key, bool debug = false) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.MAdd(System.Collections.Generic.IReadOnlyCollection<(string! key, NRedisStack.DataTypes.TimeStamp timestamp, double value)>! sequence) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.MGet(System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectedLabels = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.MRange(NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectLabels = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false, (string!, NRedisStack.Literals.Enums.TsReduce)? groupbyTuple = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.MRevRange(NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, System.Collections.Generic.IReadOnlyCollection! filter, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, bool? withLabels = null, System.Collections.Generic.IReadOnlyCollection? selectLabels = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false, (string!, NRedisStack.Literals.Enums.TsReduce)? groupbyTuple = null) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.QueryIndex(System.Collections.Generic.IReadOnlyCollection! filter) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.Range(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TimeSeriesCommandsBuilder.RevRange(string! key, NRedisStack.DataTypes.TimeStamp fromTimeStamp, NRedisStack.DataTypes.TimeStamp toTimeStamp, bool latest = false, System.Collections.Generic.IReadOnlyCollection? filterByTs = null, (long, long)? filterByValue = null, long? count = null, NRedisStack.DataTypes.TimeStamp? align = null, NRedisStack.Literals.Enums.TsAggregation? aggregation = null, long? timeBucket = null, NRedisStack.Literals.Enums.TsBucketTimestamps? bt = null, bool empty = false) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TopKCommandBuilder.Add(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TopKCommandBuilder.Count(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TopKCommandBuilder.IncrBy(StackExchange.Redis.RedisKey key, params System.Tuple![]! itemIncrements) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TopKCommandBuilder.Info(StackExchange.Redis.RedisKey key) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TopKCommandBuilder.List(StackExchange.Redis.RedisKey key, bool withcount = false) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TopKCommandBuilder.Query(StackExchange.Redis.RedisKey key, params StackExchange.Redis.RedisValue[]! items) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TopKCommandBuilder.Reserve(StackExchange.Redis.RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) -> NRedisStack.RedisStackCommands.SerializedCommand! +static NRedisStack.TsParamsHelper.AddChunkSize(this System.Collections.Generic.IList! args, long? chunkSize) -> void +static NRedisStack.TsParamsHelper.AddDuplicatePolicy(this System.Collections.Generic.IList! args, NRedisStack.Literals.Enums.TsDuplicatePolicy? policy) -> void +static NRedisStack.TsParamsHelper.AddIgnoreValues(this System.Collections.Generic.IList! args, long? ignoreMaxTimeDiff, long? ignoreMaxValDiff) -> void +static NRedisStack.TsParamsHelper.AddLabels(this System.Collections.Generic.IList! args, System.Collections.Generic.IReadOnlyCollection? labels) -> void +static NRedisStack.TsParamsHelper.AddOnDuplicate(this System.Collections.Generic.IList! args, NRedisStack.Literals.Enums.TsDuplicatePolicy? policy) -> void +static NRedisStack.TsParamsHelper.AddRetentionTime(this System.Collections.Generic.IList! args, long? retentionTime) -> void +static NRedisStack.TsParamsHelper.AddUncompressed(this System.Collections.Generic.IList! args, bool? uncompressed) -> void +static readonly NRedisStack.Search.Query.GeoFilter.FEET -> string! +static readonly NRedisStack.Search.Query.GeoFilter.KILOMETERS -> string! +static readonly NRedisStack.Search.Query.GeoFilter.METERS -> string! +static readonly NRedisStack.Search.Query.GeoFilter.MILES -> string! +virtual NRedisStack.Search.Aggregation.Reducer.AddOwnArgs(System.Collections.Generic.List! args) -> void +virtual NRedisStack.Search.Aggregation.Reducer.GetOwnArgsCount() -> int diff --git a/src/NRedisStack/PublicAPI/PublicAPI.Unshipped.txt b/src/NRedisStack/PublicAPI/PublicAPI.Unshipped.txt new file mode 100644 index 00000000..8fa5a504 --- /dev/null +++ b/src/NRedisStack/PublicAPI/PublicAPI.Unshipped.txt @@ -0,0 +1,6 @@ +#nullable enable +~override NRedisStack.DataTypes.TimeStamp.ToString() -> string +~override NRedisStack.DataTypes.TimeStamp.Equals(object obj) -> bool +NRedisStack.DataTypes.TimeStamp.Equals(NRedisStack.DataTypes.TimeStamp other) -> bool +static NRedisStack.DataTypes.TimeStamp.operator ==(NRedisStack.DataTypes.TimeStamp left, NRedisStack.DataTypes.TimeStamp right) -> bool +static NRedisStack.DataTypes.TimeStamp.operator !=(NRedisStack.DataTypes.TimeStamp left, NRedisStack.DataTypes.TimeStamp right) -> bool \ No newline at end of file diff --git a/src/NRedisStack/RedisStackCommands/SerializedCommand.cs b/src/NRedisStack/RedisStackCommands/SerializedCommand.cs new file mode 100644 index 00000000..7306d8fa --- /dev/null +++ b/src/NRedisStack/RedisStackCommands/SerializedCommand.cs @@ -0,0 +1,11 @@ +namespace NRedisStack.RedisStackCommands; + +public class SerializedCommand(string command, params object[] args) +{ + public string Command { get; } = command; + public object[] Args { get; } = args; + + public SerializedCommand(string command, ICollection args) : this(command, args.ToArray()) + { + } +} \ No newline at end of file diff --git a/src/NRedisStack/ResponseParser.cs b/src/NRedisStack/ResponseParser.cs index 46421344..8382771a 100644 --- a/src/NRedisStack/ResponseParser.cs +++ b/src/NRedisStack/ResponseParser.cs @@ -9,873 +9,871 @@ using NRedisStack.TopK.DataTypes; using NRedisStack.Tdigest.DataTypes; using NRedisStack.Search; -using NRedisStack.Search.Aggregation; -namespace NRedisStack +namespace NRedisStack; + +internal static class ResponseParser { - internal static class ResponseParser + public static bool OKtoBoolean(this RedisResult result) { - public static bool OKtoBoolean(this RedisResult result) + return result.ToString() == "OK"; + } + + public static bool[] ToBooleanArray(this RedisResult result) + { + RedisResult[] redisResults = result.ToArray(); + + bool[] boolArr = new bool[redisResults.Length]; + for (int i = 0; i < redisResults.Length; i++) { - return result.ToString() == "OK"; + boolArr[i] = redisResults[i].ToString() == "1"; } - public static bool[] ToBooleanArray(this RedisResult result) - { - RedisResult[]? redisResults = result.ToArray(); + return boolArr; + } - bool[] boolArr = new bool[redisResults.Length]; - for (int i = 0; i < redisResults.Length; i++) - { - boolArr[i] = redisResults[i].ToString() == "1"; - } + public static RedisResult[] ToArray(this RedisResult result) + { + var redisResults = (RedisResult[]?)result; + if (redisResults != null) + return redisResults; + throw new ArgumentNullException(nameof(redisResults)); + } - return boolArr; - } + public static long ToLong(this RedisResult result) + { + if ((long?)result == null) + throw new ArgumentNullException(nameof(result)); + return (long)result; + } - public static RedisResult[] ToArray(this RedisResult result) - { - var redisResults = (RedisResult[]?)result; - if (redisResults != null) - return redisResults; - throw new ArgumentNullException(nameof(redisResults)); - } + public static double ToDouble(this RedisResult result) + { + if (result.ToString() == "nan") + return double.NaN; + if ((double?)result == null) + throw new ArgumentNullException(nameof(result)); + return (double)result; + } - public static long ToLong(this RedisResult result) + public static double[] ToDoubleArray(this RedisResult result) + { + List redisResults = []; + foreach (var res in result.ToArray()) { - if ((long?)result == null) - throw new ArgumentNullException(nameof(result)); - return (long)result; + redisResults.Add(ToDouble(res)); } - public static double ToDouble(this RedisResult result) - { - if (result.ToString() == "nan") - return double.NaN; - if ((double?)result == null) - throw new ArgumentNullException(nameof(result)); - return (double)result; - } + return redisResults.ToArray(); + } - public static double[] ToDoubleArray(this RedisResult result) + public static long[] ToLongArray(this RedisResult result) + { + List redisResults = []; + foreach (var res in result.ToArray()) { - List redisResults = new List(); - foreach (var res in result.ToArray()) - { - redisResults.Add(ToDouble(res)); - } - - return redisResults.ToArray(); + redisResults.Add(ToLong(res)); } - public static long[] ToLongArray(this RedisResult result) - { - List redisResults = new List(); - foreach (var res in result.ToArray()) - { - redisResults.Add(ToLong(res)); - } + return redisResults.ToArray(); + } - return redisResults.ToArray(); - } + public static TimeStamp ToTimeStamp(this RedisResult result) + { + if (result.Resp2Type == ResultType.None) return null!; + return new((long)result); + } - public static TimeStamp ToTimeStamp(this RedisResult result) - { - if (result.Type == ResultType.None) return null!; - return new TimeStamp((long)result); - } + public static RedisKey ToRedisKey(this RedisResult result) + { + return new(result.ToString()); + } - public static RedisKey ToRedisKey(this RedisResult result) - { - return new RedisKey(result.ToString()); - } + public static RedisValue ToRedisValue(this RedisResult result) + { + return new(result.ToString()); + } - public static RedisValue ToRedisValue(this RedisResult result) - { - return new RedisValue(result.ToString()); - } + public static IReadOnlyList ToTimeStampArray(this RedisResult result) + { + RedisResult[] redisResults = (RedisResult[])result!; + var list = new List(redisResults.Length); + if (redisResults.Length == 0) return list; + Array.ForEach(redisResults, timestamp => list.Add(ToTimeStamp(timestamp))); + return list; + } - public static IReadOnlyList ToTimeStampArray(this RedisResult result) - { - RedisResult[] redisResults = (RedisResult[])result!; - var list = new List(redisResults.Length); - if (redisResults.Length == 0) return list; - Array.ForEach(redisResults, timestamp => list.Add(ToTimeStamp(timestamp))); - return list; - } + public static TimeSeriesTuple ToTimeSeriesTuple(this RedisResult result) + { + RedisResult[] redisResults = result.ToArray(); + if (redisResults.Length == 0) return null!; + return new(ToTimeStamp(redisResults[0]), (double)redisResults[1]); + } - public static TimeSeriesTuple ToTimeSeriesTuple(this RedisResult result) - { - RedisResult[] redisResults = result.ToArray(); - if (redisResults.Length == 0) return null!; - return new TimeSeriesTuple(ToTimeStamp(redisResults[0]), (double)redisResults[1]); - } + public static Tuple ToScanDumpTuple(this RedisResult result) + { + RedisResult[] redisResults = result.ToArray(); + if (redisResults == null || redisResults.Length == 0) return null!; + return new((long)redisResults[0], (byte[])redisResults[1]!); + } - public static Tuple ToScanDumpTuple(this RedisResult result) - { - RedisResult[] redisResults = result.ToArray(); - if (redisResults == null || redisResults.Length == 0) return null!; - return new Tuple((long)redisResults[0], (byte[])redisResults[1]!); - } + // TODO: check if this is needed: + // public static HashEntry ToHashEntry(this RedisResult result) + // { + // RedisResult[] redisResults = result.ToArray(); + // if (redisResults.Length < 2) + // throw new ArgumentOutOfRangeException(nameof(result)); - // TODO: check if this is needed: - // public static HashEntry ToHashEntry(this RedisResult result) - // { - // RedisResult[] redisResults = result.ToArray(); - // if (redisResults.Length < 2) - // throw new ArgumentOutOfRangeException(nameof(result)); + // return new HashEntry((RedisValue)(redisResults[0]), ((RedisValue)redisResults[1])); + // } - // return new HashEntry((RedisValue)(redisResults[0]), ((RedisValue)redisResults[1])); - // } + // public static HashEntry[] ToHashEntryArray(this RedisResult result) + // { + // RedisResult[] redisResults = result.ToArray(); - // public static HashEntry[] ToHashEntryArray(this RedisResult result) - // { - // RedisResult[] redisResults = result.ToArray(); + // var hash = new HashEntry[redisResults.Length / 2]; + // if (redisResults.Length == 0) return hash; - // var hash = new HashEntry[redisResults.Length / 2]; - // if (redisResults.Length == 0) return hash; + // for (int i = 0; i < redisResults.Length - 1; i += 2) + // hash[i / 2] = new HashEntry(((RedisValue)redisResults[i]), ((RedisValue)redisResults[i + 1])); + // return hash; + // } - // for (int i = 0; i < redisResults.Length - 1; i += 2) - // hash[i / 2] = new HashEntry(((RedisValue)redisResults[i]), ((RedisValue)redisResults[i + 1])); - // return hash; - // } + public static IReadOnlyList ToTimeSeriesTupleArray(this RedisResult result) + { + RedisResult[] redisResults = (RedisResult[])result!; + var list = new List(redisResults.Length); + if (redisResults.Length == 0) return list; + Array.ForEach(redisResults, tuple => list.Add(ToTimeSeriesTuple(tuple))); + return list; + } - public static IReadOnlyList ToTimeSeriesTupleArray(this RedisResult result) - { - RedisResult[] redisResults = (RedisResult[])result!; - var list = new List(redisResults.Length); - if (redisResults.Length == 0) return list; - Array.ForEach(redisResults, tuple => list.Add(ToTimeSeriesTuple(tuple)!)); - return list; - } + public static IReadOnlyList ToLabelArray(this RedisResult result) + { + RedisResult[] redisResults = (RedisResult[])result!; + var list = new List(redisResults.Length); + if (redisResults.Length == 0) return list; + Array.ForEach(redisResults, labelResult => + { + var labelTuple = (RedisResult[])labelResult!; + list.Add(new(labelTuple[0].ToString(), labelTuple[1].ToString())); + }); + return list; + } - public static IReadOnlyList ToLabelArray(this RedisResult result) - { - RedisResult[] redisResults = (RedisResult[])result!; - var list = new List(redisResults.Length); - if (redisResults.Length == 0) return list; - Array.ForEach(redisResults, labelResult => - { - var labelTuple = (RedisResult[])labelResult!; - list.Add(new TimeSeriesLabel(labelTuple[0].ToString()!, labelTuple[1].ToString()!)); - }); - return list; - } - - // public static IReadOnlyList ToCunckArray(this RedisResult result) - // { - // RedisResult[] redisResults = (RedisResult[])result; - // var list = new List(redisResults.Length); - // if (redisResults.Length == 0) return list; - // Array.ForEach(redisResults, chunckResult => - // { - // RedisResult[] labelTuple = (RedisResult[])labelResult; - // list.Add(new TimeSeriesCunck((string)labelTuple[0], (string)labelTuple[1])); - // }); - // return list; - // } - - public static IReadOnlyList<(string key, IReadOnlyList labels, TimeSeriesTuple value)> ParseMGetResponse(this RedisResult result) - { - var redisResults = (RedisResult[])result!; - var list = new List<(string key, IReadOnlyList labels, TimeSeriesTuple values)>(redisResults.Length); - if (redisResults.Length == 0) return list; - Array.ForEach(redisResults, MRangeValue => - { - var MRangeTuple = (RedisResult[])MRangeValue!; - string key = MRangeTuple[0].ToString()!; - IReadOnlyList labels = ToLabelArray(MRangeTuple[1]); - TimeSeriesTuple? value = ToTimeSeriesTuple(MRangeTuple[2]); - list.Add((key!, labels!, value!)); - }); - return list; - } + // public static IReadOnlyList ToCunckArray(this RedisResult result) + // { + // RedisResult[] redisResults = (RedisResult[])result; + // var list = new List(redisResults.Length); + // if (redisResults.Length == 0) return list; + // Array.ForEach(redisResults, chunckResult => + // { + // RedisResult[] labelTuple = (RedisResult[])labelResult; + // list.Add(new TimeSeriesCunck((string)labelTuple[0], (string)labelTuple[1])); + // }); + // return list; + // } + + public static IReadOnlyList<(string key, IReadOnlyList labels, TimeSeriesTuple value)> ParseMGetResponse(this RedisResult result) + { + var redisResults = (RedisResult[])result!; + var list = new List<(string key, IReadOnlyList labels, TimeSeriesTuple values)>(redisResults.Length); + if (redisResults.Length == 0) return list; + Array.ForEach(redisResults, MRangeValue => + { + var MRangeTuple = (RedisResult[])MRangeValue!; + string key = MRangeTuple[0].ToString(); + IReadOnlyList labels = ToLabelArray(MRangeTuple[1]); + TimeSeriesTuple? value = ToTimeSeriesTuple(MRangeTuple[2]); + list.Add((key, labels, value)); + }); + return list; + } - public static IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> ParseMRangeResponse(this RedisResult result) - { - var redisResults = (RedisResult[])result!; - var list = new List<(string key, IReadOnlyList labels, IReadOnlyList values)>(redisResults.Length); - if (redisResults.Length == 0) return list; - Array.ForEach(redisResults, MRangeValue => - { - var MRangeTuple = (RedisResult[])MRangeValue!; - string key = MRangeTuple[0].ToString()!; - IReadOnlyList labels = ToLabelArray(MRangeTuple[1]); - IReadOnlyList values = ToTimeSeriesTupleArray(MRangeTuple[2]); - list.Add((key, labels, values)); - }); - return list; - } + public static IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> ParseMRangeResponse(this RedisResult result) + { + var redisResults = (RedisResult[])result!; + var list = new List<(string key, IReadOnlyList labels, IReadOnlyList values)>(redisResults.Length); + if (redisResults.Length == 0) return list; + Array.ForEach(redisResults, MRangeValue => + { + var MRangeTuple = (RedisResult[])MRangeValue!; + string key = MRangeTuple[0].ToString(); + IReadOnlyList labels = ToLabelArray(MRangeTuple[1]); + IReadOnlyList values = ToTimeSeriesTupleArray(MRangeTuple[2]); + list.Add((key, labels, values)); + }); + return list; + } - public static TimeSeriesRule ToRule(this RedisResult result) - { - var redisResults = (RedisResult[])result!; - string destKey = redisResults[0].ToString()!; - long bucketTime = (long)redisResults[1]; - var aggregation = AggregationExtensions.AsAggregation(redisResults[2].ToString()!); - return new TimeSeriesRule(destKey, bucketTime, aggregation); - } + public static TimeSeriesRule ToRule(this RedisResult result) + { + var redisResults = (RedisResult[])result!; + string destKey = redisResults[0].ToString(); + long bucketTime = (long)redisResults[1]; + var aggregation = AggregationExtensions.AsAggregation(redisResults[2].ToString()); + return new(destKey, bucketTime, aggregation); + } - public static IReadOnlyList ToRuleArray(this RedisResult result) - { - var redisResults = (RedisResult[])result!; - var list = new List(); - if (redisResults.Length == 0) return list; - Array.ForEach(redisResults, rule => list.Add(ToRule(rule))); - return list; - } + public static IReadOnlyList ToRuleArray(this RedisResult result) + { + var redisResults = (RedisResult[])result!; + var list = new List(); + if (redisResults.Length == 0) return list; + Array.ForEach(redisResults, rule => list.Add(ToRule(rule))); + return list; + } - public static TsDuplicatePolicy? ToPolicy(this RedisResult result) + public static TsDuplicatePolicy? ToPolicy(this RedisResult result) + { + var policyStatus = result.ToString(); + if (String.IsNullOrEmpty(policyStatus) || policyStatus == "(nil)") { - var policyStatus = result.ToString(); - if (String.IsNullOrEmpty(policyStatus) || policyStatus == "(nil)") - { - return null; - } - - return DuplicatePolicyExtensions.AsPolicy(policyStatus.ToUpper()); + return null; } - public static BloomInformation ToBloomInfo(this RedisResult result) //TODO: Think about a different implementation, because if the output of BF.INFO changes or even just the names of the labels then the parsing will not work - { - long capacity, size, numberOfFilters, numberOfItemsInserted, expansionRate; - capacity = size = numberOfFilters = numberOfItemsInserted = expansionRate = -1; - RedisResult[] redisResults = result.ToArray(); - - for (int i = 0; i < redisResults.Length; ++i) - { - string? label = redisResults[i++].ToString(); - // string.Compare(label, "Capacity", true) - switch (label) - { - case "Capacity": - capacity = (long)redisResults[i]; - break; - case "Size": - size = (long)redisResults[i]; - break; - case "Number of filters": - numberOfFilters = (long)redisResults[i]; - break; - case "Number of items inserted": - numberOfItemsInserted = (long)redisResults[i]; - break; - case "Expansion rate": - expansionRate = (long)redisResults[i]; - break; - } - } + return DuplicatePolicyExtensions.AsPolicy(policyStatus.ToUpper()); + } - return new BloomInformation(capacity, size, numberOfFilters, numberOfItemsInserted, expansionRate); - } + public static BloomInformation ToBloomInfo(this RedisResult result) //TODO: Think about a different implementation, because if the output of BF.INFO changes or even just the names of the labels then the parsing will not work + { + long capacity, size, numberOfFilters, numberOfItemsInserted, expansionRate; + capacity = size = numberOfFilters = numberOfItemsInserted = expansionRate = -1; + RedisResult[] redisResults = result.ToArray(); + + for (int i = 0; i < redisResults.Length; ++i) + { + string? label = redisResults[i++].ToString(); + // string.Compare(label, "Capacity", true) + switch (label) + { + case "Capacity": + capacity = (long)redisResults[i]; + break; + case "Size": + size = (long)redisResults[i]; + break; + case "Number of filters": + numberOfFilters = (long)redisResults[i]; + break; + case "Number of items inserted": + numberOfItemsInserted = (long)redisResults[i]; + break; + case "Expansion rate": + expansionRate = (long)redisResults[i]; + break; + } + } + + return new(capacity, size, numberOfFilters, numberOfItemsInserted, expansionRate); + } - public static CuckooInformation ToCuckooInfo(this RedisResult result) //TODO: Think about a different implementation, because if the output of BF.INFO changes or even just the names of the labels then the parsing will not work - { - long size, numberOfBuckets, numberOfFilters, numberOfItemsInserted, - numberOfItemsDeleted, bucketSize, expansionRate, maxIterations; + public static CuckooInformation ToCuckooInfo(this RedisResult result) //TODO: Think about a different implementation, because if the output of BF.INFO changes or even just the names of the labels then the parsing will not work + { + long size, numberOfBuckets, numberOfFilters, numberOfItemsInserted, + numberOfItemsDeleted, bucketSize, expansionRate, maxIterations; - size = numberOfBuckets = numberOfFilters = + size = numberOfBuckets = numberOfFilters = numberOfItemsInserted = numberOfItemsDeleted = - bucketSize = expansionRate = maxIterations = -1; - - RedisResult[] redisResults = result.ToArray(); + bucketSize = expansionRate = maxIterations = -1; + + RedisResult[] redisResults = result.ToArray(); + + for (int i = 0; i < redisResults.Length; ++i) + { + string? label = redisResults[i++].ToString(); + + switch (label) + { + case "Size": + size = (long)redisResults[i]; + break; + case "Number of buckets": + numberOfBuckets = (long)redisResults[i]; + break; + case "Number of filters": + numberOfFilters = (long)redisResults[i]; + break; + case "Number of items inserted": + numberOfItemsInserted = (long)redisResults[i]; + break; + case "Number of items deleted": + numberOfItemsDeleted = (long)redisResults[i]; + break; + case "Bucket size": + bucketSize = (long)redisResults[i]; + break; + case "Expansion rate": + expansionRate = (long)redisResults[i]; + break; + case "Max iterations": + maxIterations = (long)redisResults[i]; + break; + } + } + + return new(size, numberOfBuckets, numberOfFilters, numberOfItemsInserted, + numberOfItemsDeleted, bucketSize, expansionRate, maxIterations); + } - for (int i = 0; i < redisResults.Length; ++i) - { - string? label = redisResults[i++].ToString(); + public static CmsInformation ToCmsInfo(this RedisResult result) //TODO: Think about a different implementation, because if the output of CMS.INFO changes or even just the names of the labels then the parsing will not work + { + long width, depth, count; - switch (label) - { - case "Size": - size = (long)redisResults[i]; - break; - case "Number of buckets": - numberOfBuckets = (long)redisResults[i]; - break; - case "Number of filters": - numberOfFilters = (long)redisResults[i]; - break; - case "Number of items inserted": - numberOfItemsInserted = (long)redisResults[i]; - break; - case "Number of items deleted": - numberOfItemsDeleted = (long)redisResults[i]; - break; - case "Bucket size": - bucketSize = (long)redisResults[i]; - break; - case "Expansion rate": - expansionRate = (long)redisResults[i]; - break; - case "Max iterations": - maxIterations = (long)redisResults[i]; - break; - } - } + width = depth = count = -1; - return new CuckooInformation(size, numberOfBuckets, numberOfFilters, numberOfItemsInserted, - numberOfItemsDeleted, bucketSize, expansionRate, maxIterations); - } + RedisResult[] redisResults = result.ToArray(); - public static CmsInformation ToCmsInfo(this RedisResult result) //TODO: Think about a different implementation, because if the output of CMS.INFO changes or even just the names of the labels then the parsing will not work + for (int i = 0; i < redisResults.Length; ++i) { - long width, depth, count; + string? label = redisResults[i++].ToString(); - width = depth = count = -1; + switch (label) + { + case "width": + width = (long)redisResults[i]; + break; + case "depth": + depth = (long)redisResults[i]; + break; + case "count": + count = (long)redisResults[i]; + break; + } + } - RedisResult[] redisResults = result.ToArray(); + return new(width, depth, count); + } - for (int i = 0; i < redisResults.Length; ++i) - { - string? label = redisResults[i++].ToString(); + public static TopKInformation ToTopKInfo(this RedisResult result) //TODO: Think about a different implementation, because if the output of CMS.INFO changes or even just the names of the labels then the parsing will not work + { + long k, width, depth; + double decay; - switch (label) - { - case "width": - width = (long)redisResults[i]; - break; - case "depth": - depth = (long)redisResults[i]; - break; - case "count": - count = (long)redisResults[i]; - break; - } - } + k = width = depth = -1; + decay = -1.0; - return new CmsInformation(width, depth, count); - } + RedisResult[] redisResults = result.ToArray(); - public static TopKInformation ToTopKInfo(this RedisResult result) //TODO: Think about a different implementation, because if the output of CMS.INFO changes or even just the names of the labels then the parsing will not work + for (int i = 0; i < redisResults.Length; ++i) { - long k, width, depth; - double decay; + string? label = redisResults[i++].ToString(); - k = width = depth = -1; - decay = -1.0; + switch (label) + { + case "k": + k = (long)redisResults[i]; + break; + case "width": + width = (long)redisResults[i]; + break; + case "depth": + depth = (long)redisResults[i]; + break; + case "decay": + decay = (double)redisResults[i]; + break; + } + } - RedisResult[] redisResults = result.ToArray(); + return new(k, width, depth, decay); + } - for (int i = 0; i < redisResults.Length; ++i) - { - string? label = redisResults[i++].ToString(); + public static TdigestInformation ToTdigestInfo(this RedisResult result) //TODO: Think about a different implementation, because if the output of CMS.INFO changes or even just the names of the labels then the parsing will not work + { + long compression, capacity, mergedNodes, unmergedNodes, totalCompressions, memoryUsage; + double mergedWeight, unmergedWeight, observations; + + compression = capacity = mergedNodes = unmergedNodes = totalCompressions = memoryUsage = -1; + mergedWeight = unmergedWeight = observations = -1.0; + + RedisResult[] redisResults = result.ToArray(); + + for (int i = 0; i < redisResults.Length; ++i) + { + string? label = redisResults[i++].ToString(); + + switch (label) + { + case "Compression": + compression = (long)redisResults[i]; + break; + case "Capacity": + capacity = (long)redisResults[i]; + break; + case "Merged nodes": + mergedNodes = (long)redisResults[i]; + break; + case "Unmerged nodes": + unmergedNodes = (long)redisResults[i]; + break; + case "Merged weight": + mergedWeight = (double)redisResults[i]; + break; + case "Unmerged weight": + unmergedWeight = (double)redisResults[i]; + break; + case "Observations": + observations = (double)redisResults[i]; + break; + case "Total compressions": + totalCompressions = (long)redisResults[i]; + break; + case "Memory usage": + memoryUsage = (long)redisResults[i]; + break; + } + } + + return new(compression, capacity, mergedNodes, unmergedNodes, + mergedWeight, unmergedWeight, observations, totalCompressions, memoryUsage); + } - switch (label) - { - case "k": - k = (long)redisResults[i]; - break; - case "width": - width = (long)redisResults[i]; - break; - case "depth": - depth = (long)redisResults[i]; - break; - case "decay": - decay = (double)redisResults[i]; - break; - } - } + [Obsolete] + public static TimeSeriesInformation ToTimeSeriesInfo(this RedisResult result) + { + long totalSamples = -1, memoryUsage = -1, retentionTime = -1, chunkSize = -1, chunkCount = -1; + TimeStamp? firstTimestamp = null, lastTimestamp = null; + IReadOnlyList? labels = null; + IReadOnlyList? rules = null; + string? sourceKey = null, keySelfName = null; + TsDuplicatePolicy? duplicatePolicy = null; + IReadOnlyList? chunks = null; + var redisResults = (RedisResult[])result!; + for (int i = 0; i < redisResults.Length; ++i) + { + string label = redisResults[i++].ToString(); + switch (label) + { + case "totalSamples": + totalSamples = (long)redisResults[i]; + break; + case "memoryUsage": + memoryUsage = (long)redisResults[i]; + break; + case "retentionTime": + retentionTime = (long)redisResults[i]; + break; + case "chunkCount": + chunkCount = (long)redisResults[i]; + break; + case "chunkSize": + chunkSize = (long)redisResults[i]; + break; + // case "maxSamplesPerChunk": + // // If the property name is maxSamplesPerChunk then this is an old + // // version of RedisTimeSeries and we used the number of samples before ( now Bytes ) + // chunkSize = chunkSize * 16; + // break; + case "firstTimestamp": + firstTimestamp = ToTimeStamp(redisResults[i]); + break; + case "lastTimestamp": + lastTimestamp = ToTimeStamp(redisResults[i]); + break; + case "labels": + labels = ToLabelArray(redisResults[i]); + break; + case "sourceKey": + sourceKey = redisResults[i].ToString(); + break; + case "rules": + rules = ToRuleArray(redisResults[i]); + break; + case "duplicatePolicy": + // Avalible for > v1.4 + duplicatePolicy = ToPolicy(redisResults[i]); + break; + case "keySelfName": + // Avalible for > v1.4 + keySelfName = redisResults[i].ToString(); + break; + case "Chunks": + // Avalible for > v1.4 + chunks = ToTimeSeriesChunkArray(redisResults[i]); + break; + } + } + + return new(totalSamples, memoryUsage, firstTimestamp, + lastTimestamp, retentionTime, chunkCount, chunkSize, labels, sourceKey, rules, duplicatePolicy, keySelfName, chunks); + } - return new TopKInformation(k, width, depth, decay); + // TODO: check if this is needed + // public static Dictionary ToFtInfoAsDictionary(this RedisResult value) + // { + // var res = (RedisResult[])value; + // var info = new Dictionary(); + // for (int i = 0; i < res.Length; i += 2) + // { + // var val = res[i + 1]; + // if (val.Type != ResultType.Array) + // { + // info.Add((string)res[i], (RedisValue)val); + // } + // } + // return info; + // } + + public static Dictionary ToConfigDictionary(this RedisResult value) + { + var res = (RedisResult[])value!; + var dict = new Dictionary(); + foreach (var pair in res) + { + var arr = (RedisResult[])pair!; + dict.Add(arr[0].ToString(), arr[1].ToString()); } + return dict; + } - public static TdigestInformation ToTdigestInfo(this RedisResult result) //TODO: Think about a different implementation, because if the output of CMS.INFO changes or even just the names of the labels then the parsing will not work - { - long compression, capacity, mergedNodes, unmergedNodes, totalCompressions, memoryUsage; - double mergedWeight, unmergedWeight, observations; + public static IReadOnlyList ToTimeSeriesChunkArray(this RedisResult result) + { + var redisResults = (RedisResult[])result!; + var list = new List(); + if (redisResults.Length == 0) return list; + Array.ForEach(redisResults, chunk => list.Add(ToTimeSeriesChunk(chunk))); + return list; + } - compression = capacity = mergedNodes = unmergedNodes = totalCompressions = memoryUsage = -1; - mergedWeight = unmergedWeight = observations = -1.0; + public static TimeSeriesChunck ToTimeSeriesChunk(this RedisResult result) + { + long startTimestamp = -1, endTimestamp = -1, samples = -1, size = -1; + string bytesPerSample = ""; + var redisResults = (RedisResult[])result!; + for (int i = 0; i < redisResults.Length; ++i) + { + string label = redisResults[i++].ToString(); + switch (label) + { + case "startTimestamp": + startTimestamp = (long)redisResults[i]; + break; + case "endTimestamp": + endTimestamp = (long)redisResults[i]; + break; + case "samples": + samples = (long)redisResults[i]; + break; + case "size": + size = (long)redisResults[i]; + break; + case "bytesPerSample": + bytesPerSample = redisResults[i].ToString(); + break; + } + } + + return new(startTimestamp, endTimestamp, + samples, size, bytesPerSample); - RedisResult[] redisResults = result.ToArray(); + } - for (int i = 0; i < redisResults.Length; ++i) - { - string? label = redisResults[i++].ToString(); + public static List ToStringList(this RedisResult result) + { + RedisResult[] redisResults = result.ToArray(); - switch (label) - { - case "Compression": - compression = (long)redisResults[i]; - break; - case "Capacity": - capacity = (long)redisResults[i]; - break; - case "Merged nodes": - mergedNodes = (long)redisResults[i]; - break; - case "Unmerged nodes": - unmergedNodes = (long)redisResults[i]; - break; - case "Merged weight": - mergedWeight = (double)redisResults[i]; - break; - case "Unmerged weight": - unmergedWeight = (double)redisResults[i]; - break; - case "Observations": - observations = (double)redisResults[i]; - break; - case "Total compressions": - totalCompressions = (long)redisResults[i]; - break; - case "Memory usage": - memoryUsage = (long)redisResults[i]; - break; - } - } + var list = new List(); + if (redisResults.Length == 0) return list; + Array.ForEach(redisResults, str => list.Add(str.ToString())); + return list; + } - return new TdigestInformation(compression, capacity, mergedNodes, unmergedNodes, - mergedWeight, unmergedWeight, observations, totalCompressions, memoryUsage); + public static long?[] ToNullableLongArray(this RedisResult result) + { + if (result.IsNull) + { + return []; } - [Obsolete] - public static TimeSeriesInformation ToTimeSeriesInfo(this RedisResult result) + if (result.Resp2Type == ResultType.Integer) { - long totalSamples = -1, memoryUsage = -1, retentionTime = -1, chunkSize = -1, chunkCount = -1; - TimeStamp? firstTimestamp = null, lastTimestamp = null; - IReadOnlyList? labels = null; - IReadOnlyList? rules = null; - string? sourceKey = null, keySelfName = null; - TsDuplicatePolicy? duplicatePolicy = null; - IReadOnlyList? chunks = null; - var redisResults = (RedisResult[])result!; - for (int i = 0; i < redisResults.Length; ++i) - { - string label = redisResults[i++].ToString()!; - switch (label) - { - case "totalSamples": - totalSamples = (long)redisResults[i]; - break; - case "memoryUsage": - memoryUsage = (long)redisResults[i]; - break; - case "retentionTime": - retentionTime = (long)redisResults[i]; - break; - case "chunkCount": - chunkCount = (long)redisResults[i]; - break; - case "chunkSize": - chunkSize = (long)redisResults[i]; - break; - // case "maxSamplesPerChunk": - // // If the property name is maxSamplesPerChunk then this is an old - // // version of RedisTimeSeries and we used the number of samples before ( now Bytes ) - // chunkSize = chunkSize * 16; - // break; - case "firstTimestamp": - firstTimestamp = ToTimeStamp(redisResults[i]); - break; - case "lastTimestamp": - lastTimestamp = ToTimeStamp(redisResults[i]); - break; - case "labels": - labels = ToLabelArray(redisResults[i]); - break; - case "sourceKey": - sourceKey = redisResults[i].ToString(); - break; - case "rules": - rules = ToRuleArray(redisResults[i]); - break; - case "duplicatePolicy": - // Avalible for > v1.4 - duplicatePolicy = ToPolicy(redisResults[i]); - break; - case "keySelfName": - // Avalible for > v1.4 - keySelfName = redisResults[i].ToString(); - break; - case "Chunks": - // Avalible for > v1.4 - chunks = ToTimeSeriesChunkArray(redisResults[i]); - break; - } - } - - return new TimeSeriesInformation(totalSamples, memoryUsage, firstTimestamp, - lastTimestamp, retentionTime, chunkCount, chunkSize, labels, sourceKey, rules, duplicatePolicy, keySelfName, chunks); + return [(long?)result]; } - // TODO: check if this is needed - // public static Dictionary ToFtInfoAsDictionary(this RedisResult value) - // { - // var res = (RedisResult[])value; - // var info = new Dictionary(); - // for (int i = 0; i < res.Length; i += 2) - // { - // var val = res[i + 1]; - // if (val.Type != ResultType.MultiBulk) - // { - // info.Add((string)res[i], (RedisValue)val); - // } - // } - // return info; - // } - - public static Dictionary ToConfigDictionary(this RedisResult value) - { - var res = (RedisResult[])value!; - var dict = new Dictionary(); - foreach (var pair in res) - { - var arr = (RedisResult[])pair!; - dict.Add(arr[0].ToString()!, arr[1].ToString()!); - } - return dict; + return ((RedisResult[])result!).Select(x => (long?)x).ToArray(); + } + + public static IEnumerable> ToHashSets(this RedisResult result) + { + if (result.IsNull) + { + return []; } - public static IReadOnlyList ToTimeSeriesChunkArray(this RedisResult result) + var res = (RedisResult[])result!; + var sets = new List>(); + if (res.All(x => x.Resp2Type != ResultType.Array)) { - var redisResults = (RedisResult[])result!; - var list = new List(); - if (redisResults.Length == 0) return list; - Array.ForEach(redisResults, chunk => list.Add(ToTimeSeriesChunk(chunk))); - return list; + var keys = res.Select(x => x.ToString()); + sets.Add([.. keys]); + return sets; } - public static TimeSeriesChunck ToTimeSeriesChunk(this RedisResult result) + foreach (var arr in res) { - long startTimestamp = -1, endTimestamp = -1, samples = -1, size = -1; - string bytesPerSample = ""; - var redisResults = (RedisResult[])result!; - for (int i = 0; i < redisResults.Length; ++i) + var set = new HashSet(); + if (arr.Resp2Type == ResultType.Array) { - string label = redisResults[i++].ToString()!; - switch (label) + var resultArr = (RedisResult[])arr!; + foreach (var item in resultArr) { - case "startTimestamp": - startTimestamp = (long)redisResults[i]; - break; - case "endTimestamp": - endTimestamp = (long)redisResults[i]; - break; - case "samples": - samples = (long)redisResults[i]; - break; - case "size": - size = (long)redisResults[i]; - break; - case "bytesPerSample": - bytesPerSample = redisResults[i].ToString()!; - break; + set.Add(item.ToString()); } } - - return new TimeSeriesChunck(startTimestamp, endTimestamp, - samples, size, bytesPerSample); - + sets.Add(set); } - public static List ToStringList(this RedisResult result) + return sets; + } + + public static Dictionary> ToFtSpellCheckResult(this RedisResult result) + { + var rawTerms = (RedisResult[])result!; + var returnTerms = new Dictionary>(rawTerms.Length); + foreach (var term in rawTerms) { - RedisResult[] redisResults = result.ToArray(); + var rawElements = (RedisResult[])term!; - var list = new List(); - if (redisResults.Length == 0) return list; - Array.ForEach(redisResults, str => list.Add(str.ToString()!)); - return list; - } + string termValue = rawElements[1].ToString(); - public static long?[] ToNullableLongArray(this RedisResult result) - { - if (result.IsNull) + var list = (RedisResult[])rawElements[2]!; + Dictionary entries = new(list.Length); + foreach (var entry in list) { - return Array.Empty(); + var entryElements = (RedisResult[])entry!; + string suggestion = entryElements[1].ToString(); + double score = (double)entryElements[0]; + entries.Add(suggestion, score); } + returnTerms.Add(termValue, entries); + } - if (result.Type == ResultType.Integer) - { - return new[] { (long?)result }; - } + return returnTerms; + } - return ((RedisResult[])result!).Select(x => (long?)x).ToArray(); + public static List> ToStringDoubleTupleList(this RedisResult result) // TODO: consider create class Suggestion instead of List> + { + var results = (RedisResult[])result!; + var list = new List>(results.Length / 2); + for (int i = 0; i < results.Length; i += 2) + { + var suggestion = results[i].ToString(); + var score = (double)results[i + 1]; + list.Add(new(suggestion, score)); } + return list; + } - public static IEnumerable> ToHashSets(this RedisResult result) + public static Dictionary ToStringRedisResultDictionary(this RedisResult value) + { + var res = (RedisResult[])value!; + var dict = new Dictionary(); + foreach (var pair in res) { - if (result.IsNull) + var arr = (RedisResult[])pair!; + if (arr.Length > 1) { - return Array.Empty>(); + dict.Add(arr[0].ToString(), arr[1]); } - - var res = (RedisResult[])result!; - var sets = new List>(); - if (res.All(x => x.Type != ResultType.MultiBulk)) + else { - var keys = res.Select(x => x.ToString()!); - sets.Add(new HashSet(keys)); - return sets; + dict.Add(arr[0].ToString(), null!); } - - foreach (var arr in res) - { - var set = new HashSet(); - if (arr.Type == ResultType.MultiBulk) - { - var resultArr = (RedisResult[])arr!; - foreach (var item in resultArr) - { - set.Add(item.ToString()!); - } - } - sets.Add(set); - } - - return sets; } + return dict; + } - public static Dictionary> ToFtSpellCheckResult(this RedisResult result) - { - var rawTerms = (RedisResult[])result!; - var returnTerms = new Dictionary>(rawTerms.Length); - foreach (var term in rawTerms) - { - var rawElements = (RedisResult[])term!; - - string termValue = rawElements[1].ToString()!; + public static Tuple> ToProfileSearchResult(this RedisResult result, Query q) + { + var results = (RedisResult[])result!; - var list = (RedisResult[])rawElements[2]!; - Dictionary entries = new Dictionary(list.Length); - foreach (var entry in list) - { - var entryElements = (RedisResult[])entry!; - string suggestion = entryElements[1].ToString()!; - double score = (double)entryElements[0]; - entries.Add(suggestion, score); - } - returnTerms.Add(termValue, entries); - } + var searchResult = results[0].ToSearchResult(q); + var profile = results[1].ToStringRedisResultDictionary(); + return new(searchResult, profile); + } - return returnTerms; - } + public static Tuple ParseProfileSearchResult(this RedisResult result, Query q) + { + var results = (RedisResult[])result!; - public static List> ToStringDoubleTupleList(this RedisResult result) // TODO: consider create class Suggestion instead of List> - { - var results = (RedisResult[])result!; - var list = new List>(results.Length / 2); - for (int i = 0; i < results.Length; i += 2) - { - var suggestion = results[i].ToString()!; - var score = (double)results[i + 1]; - list.Add(new Tuple(suggestion, score)); - } - return list; - } + var searchResult = results[0].ToSearchResult(q); + var profile = new ProfilingInformation(results[1]); + return new(searchResult, profile); + } - public static Dictionary ToStringRedisResultDictionary(this RedisResult value) - { - var res = (RedisResult[])value!; - var dict = new Dictionary(); - foreach (var pair in res) - { - var arr = (RedisResult[])pair!; - if (arr.Length > 1) - { - dict.Add(arr[0].ToString()!, arr[1]); - } - else - { - dict.Add(arr[0].ToString()!, null); - } - } - return dict; - } + public static SearchResult ToSearchResult(this RedisResult result, Query q) + { + return new((RedisResult[])result!, !q.NoContent, q.WithScores, q.WithPayloads/*, q.ExplainScore*/); + } - public static Tuple> ToProfileSearchResult(this RedisResult result, Query q) - { - var results = (RedisResult[])result!; + public static Tuple> ToProfileAggregateResult(this RedisResult result, AggregationRequest q) + { + var results = (RedisResult[])result!; + var aggregateResult = results[0].ToAggregationResult(q); + var profile = results[1].ToStringRedisResultDictionary(); + return new(aggregateResult, profile); + } - var searchResult = results[0].ToSearchResult(q); - var profile = results[1].ToStringRedisResultDictionary(); - return new Tuple>(searchResult, profile); - } + public static Tuple ParseProfileAggregateResult(this RedisResult result, AggregationRequest q) + { + var results = (RedisResult[])result!; + var aggregateResult = results[0].ToAggregationResult(q); + var profile = new ProfilingInformation(results[1]); + return new(aggregateResult, profile); + } - public static Tuple ParseProfileSearchResult(this RedisResult result, Query q) + public static AggregationResult ToAggregationResult(this RedisResult result, AggregationRequest query) + { + if (query.IsWithCursor()) { var results = (RedisResult[])result!; - var searchResult = results[0].ToSearchResult(q); - var profile = new ProfilingInformation(results[1]); - return new Tuple(searchResult, profile); + return new(results[0], (long)results[1]); } - - public static SearchResult ToSearchResult(this RedisResult result, Query q) + else { - return new SearchResult((RedisResult[])result!, !q.NoContent, q.WithScores, q.WithPayloads/*, q.ExplainScore*/); - } - - public static Tuple> ToProfileAggregateResult(this RedisResult result, AggregationRequest q) - { - var results = (RedisResult[])result!; - var aggregateResult = results[0].ToAggregationResult(q); - var profile = results[1].ToStringRedisResultDictionary(); - return new Tuple>(aggregateResult, profile); + return new(result); } + } - public static Tuple ParseProfileAggregateResult(this RedisResult result, AggregationRequest q) + public static Dictionary[] ToDictionarys(this RedisResult result) + { + var resArr = (RedisResult[])result!; + var dicts = new Dictionary[resArr.Length]; + for (int i = 0; i < resArr.Length; i++) { - var results = (RedisResult[])result!; - var aggregateResult = results[0].ToAggregationResult(q); - var profile = new ProfilingInformation(results[1]); - return new Tuple(aggregateResult, profile); + dicts[i] = resArr[i].ToDictionary(); } - public static AggregationResult ToAggregationResult(this RedisResult result, AggregationRequest query) - { - if (query.IsWithCursor()) - { - var results = (RedisResult[])result!; + return dicts; - return new AggregationResult(results[0], (long)results[1]); - } - else - { - return new AggregationResult(result); - } - } + } - public static Dictionary[] ToDictionarys(this RedisResult result) + public static Tuple? ToSortedSetPopResult(this RedisResult result) + { + if (result.IsNull) { - var resArr = (RedisResult[])result!; - var dicts = new Dictionary[resArr.Length]; - for (int i = 0; i < resArr.Length; i++) - { - dicts[i] = resArr[i].ToDictionary(); - } - - return dicts; - + return null; } - public static Tuple? ToSortedSetPopResult(this RedisResult result) - { - if (result.IsNull) - { - return null; - } + var resultArray = (RedisResult[])result!; + var resultKey = resultArray[0].ToRedisKey(); + var value = resultArray[1].ToRedisValue(); + var score = resultArray[2].ToDouble(); + var valuesWithScores = new RedisValueWithScore(value, score); - var resultArray = (RedisResult[])result!; - var resultKey = resultArray[0].ToRedisKey(); - var value = resultArray[1].ToRedisValue(); - var score = resultArray[2].ToDouble(); - var valuesWithScores = new RedisValueWithScore(value, score); + return new(resultKey, valuesWithScores); + } - return new Tuple(resultKey, valuesWithScores); + public static Tuple>? ToSortedSetPopResults(this RedisResult result) + { + if (result.IsNull) + { + return null; } - public static Tuple>? ToSortedSetPopResults(this RedisResult result) - { - if (result.IsNull) - { - return null; - } + var resultArray = (RedisResult[])result!; + var resultKey = resultArray[0].ToRedisKey(); + var resultSetItems = resultArray[1].ToArray(); - var resultArray = (RedisResult[])result!; - var resultKey = resultArray[0].ToRedisKey(); - var resultSetItems = resultArray[1].ToArray(); + List valuesWithScores = []; - List valuesWithScores = new List(); + foreach (var resultSetItem in resultSetItems) + { + var resultSetItemArray = (RedisResult[])resultSetItem!; + var value = resultSetItemArray[0].ToRedisValue(); + var score = resultSetItemArray[1].ToDouble(); + valuesWithScores.Add(new(value, score)); + } - foreach (var resultSetItem in resultSetItems) - { - var resultSetItemArray = (RedisResult[])resultSetItem!; - var value = resultSetItemArray[0].ToRedisValue(); - var score = resultSetItemArray[1].ToDouble(); - valuesWithScores.Add(new RedisValueWithScore(value, score)); - } + return new(resultKey, valuesWithScores); + } - return new Tuple>(resultKey, valuesWithScores); + public static Tuple? ToListPopResult(this RedisResult result) + { + if (result.IsNull) + { + return null; } - public static Tuple? ToListPopResult(this RedisResult result) - { - if (result.IsNull) - { - return null; - } + var resultArray = (RedisResult[])result!; + var resultKey = resultArray[0].ToRedisKey(); + var value = resultArray[1].ToRedisValue(); - var resultArray = (RedisResult[])result!; - var resultKey = resultArray[0].ToRedisKey(); - var value = resultArray[1].ToRedisValue(); + return new(resultKey, value); + } - return new Tuple(resultKey, value); + public static Tuple>? ToListPopResults(this RedisResult result) + { + if (result.IsNull) + { + return null; } - public static Tuple>? ToListPopResults(this RedisResult result) - { - if (result.IsNull) - { - return null; - } + var resultArray = (RedisResult[])result!; + var resultKey = resultArray[0].ToRedisKey(); + var resultSetItems = resultArray[1].ToArray(); - var resultArray = (RedisResult[])result!; - var resultKey = resultArray[0].ToRedisKey(); - var resultSetItems = resultArray[1].ToArray(); + List values = []; - List values = new List(); + foreach (var resultSetItem in resultSetItems) + { + var value = (RedisValue)resultSetItem!; + values.Add(value); + } - foreach (var resultSetItem in resultSetItems) - { - var value = (RedisValue)resultSetItem!; - values.Add(value); - } + return new(resultKey, values); + } - return new Tuple>(resultKey, values); + public static RedisStreamEntries[]? ToRedisStreamEntries(this RedisResult result) + { + if (result.IsNull) + { + return null; } - public static RedisStreamEntries[]? ToRedisStreamEntries(this RedisResult result) + var resultArray = (RedisResult[])result!; + RedisStreamEntries[] redisStreamEntries = new RedisStreamEntries[resultArray.Length]; + for (int i = 0; i < resultArray.Length; i++) { - if (result.IsNull) - { - return null; - } - - var resultArray = (RedisResult[])result!; - RedisStreamEntries[] redisStreamEntries = new RedisStreamEntries[resultArray.Length]; - for (int i = 0; i < resultArray.Length; i++) - { - RedisResult[] streamResultArray = (RedisResult[])resultArray[i]!; - RedisKey streamKey = streamResultArray[0].ToRedisKey(); - StreamEntry[] streamEntries = ParseStreamEntries(streamResultArray[1].ToArray()); - redisStreamEntries[i] = new RedisStreamEntries(streamKey, streamEntries); - } - - return redisStreamEntries; + RedisResult[] streamResultArray = (RedisResult[])resultArray[i]!; + RedisKey streamKey = streamResultArray[0].ToRedisKey(); + StreamEntry[] streamEntries = ParseStreamEntries(streamResultArray[1].ToArray()); + redisStreamEntries[i] = new(streamKey, streamEntries); } - private static StreamEntry[] ParseStreamEntries(IReadOnlyList results) - { - int count = results.Count; - StreamEntry[] streamEntries = new StreamEntry[count]; + return redisStreamEntries; + } - for (int i = 0; i < count; i++) - { - RedisResult[] streamEntryArray = (RedisResult[])results[i]!; - RedisValue key = streamEntryArray[0].ToRedisValue(); - NameValueEntry[] nameValueEntries = ParseNameValueEntries(streamEntryArray[1].ToArray()); - streamEntries[i] = new StreamEntry(key, nameValueEntries); - } + private static StreamEntry[] ParseStreamEntries(IReadOnlyList results) + { + int count = results.Count; + StreamEntry[] streamEntries = new StreamEntry[count]; - return streamEntries; + for (int i = 0; i < count; i++) + { + RedisResult[] streamEntryArray = (RedisResult[])results[i]!; + RedisValue key = streamEntryArray[0].ToRedisValue(); + NameValueEntry[] nameValueEntries = ParseNameValueEntries(streamEntryArray[1].ToArray()); + streamEntries[i] = new(key, nameValueEntries); } - private static NameValueEntry[] ParseNameValueEntries(IReadOnlyList redisResults) - { - int count = redisResults.Count / 2; - var nameValueEntries = new NameValueEntry[count]; + return streamEntries; + } - for (int i = 0; i < count; i++) - { - nameValueEntries[i] = new NameValueEntry( - redisResults[2 * i].ToRedisValue(), - redisResults[2 * i + 1].ToRedisValue()); - } + private static NameValueEntry[] ParseNameValueEntries(IReadOnlyList redisResults) + { + int count = redisResults.Count / 2; + var nameValueEntries = new NameValueEntry[count]; - return nameValueEntries; + for (int i = 0; i < count; i++) + { + nameValueEntries[i] = new( + redisResults[2 * i].ToRedisValue(), + redisResults[2 * i + 1].ToRedisValue()); } + + return nameValueEntries; } } \ No newline at end of file diff --git a/src/NRedisStack/Search/AggregationRequest.cs b/src/NRedisStack/Search/AggregationRequest.cs index faab2bbd..cd3bcd8a 100644 --- a/src/NRedisStack/Search/AggregationRequest.cs +++ b/src/NRedisStack/Search/AggregationRequest.cs @@ -4,14 +4,14 @@ namespace NRedisStack.Search; public class AggregationRequest : IDialectAwareParam { - private List args = new List(); // Check if Readonly + private readonly List args = []; // Check if Readonly private bool isWithCursor = false; public int? dialect { get; private set; } = null; public AggregationRequest(string query, int? defaultDialect = null) { - this.dialect = defaultDialect; + dialect = defaultDialect; args.Add(query); } @@ -52,12 +52,12 @@ public AggregationRequest Timeout(long timeout) public AggregationRequest GroupBy(string field, params Reducer[] reducers) { - return GroupBy(new[] { field }, reducers); + return GroupBy([field], reducers); } public AggregationRequest GroupBy(IList fields, IList reducers) { - Group g = new Group(fields); + Group g = new(fields); foreach (Reducer r in reducers) { g.Reduce(r); @@ -117,7 +117,7 @@ public AggregationRequest Limit(int offset, int count) public AggregationRequest Filter(string filter) { args.Add(SearchArgs.FILTER); - args.Add(filter!); + args.Add(filter); return this; } diff --git a/src/NRedisStack/Search/AggregationResult.cs b/src/NRedisStack/Search/AggregationResult.cs index 22f861a6..3eb4827d 100644 --- a/src/NRedisStack/Search/AggregationResult.cs +++ b/src/NRedisStack/Search/AggregationResult.cs @@ -7,7 +7,7 @@ public sealed class AggregationResult { public long TotalResults { get; } private readonly Dictionary[] _results; - private Dictionary[] _resultsAsRedisValues; + private Dictionary[]? _resultsAsRedisValues; public long CursorId { get; } @@ -29,7 +29,7 @@ internal AggregationResult(RedisResult result, long cursorId = -1) { var key = (string)raw[j++]!; var val = raw[j++]; - if (val.Type == ResultType.MultiBulk) + if (val.Resp2Type == ResultType.Array) { cur.Add(key, ConvertMultiBulkToObject((RedisResult[])val!)); } @@ -57,7 +57,7 @@ internal AggregationResult(RedisResult result, long cursorId = -1) /// object private object ConvertMultiBulkToObject(IEnumerable multiBulkArray) { - return multiBulkArray.Select(item => item.Type == ResultType.MultiBulk + return multiBulkArray.Select(item => item.Resp2Type == ResultType.Array ? ConvertMultiBulkToObject((RedisResult[])item!) : (RedisValue)item) .ToList(); @@ -73,7 +73,7 @@ private object ConvertMultiBulkToObject(IEnumerable multiBulkArray) [Obsolete("This method is deprecated and will be removed in future versions. Please use 'GetRow' instead.")] public IReadOnlyList> GetResults() { - return getResultsAsRedisValues(); + return GetResultsAsRedisValues(); } /// @@ -86,20 +86,18 @@ public IReadOnlyList> GetResults() /// [Obsolete("This method is deprecated and will be removed in future versions. Please use 'GetRow' instead.")] public Dictionary? this[int index] - => index >= getResultsAsRedisValues().Length ? null : getResultsAsRedisValues()[index]; + => index >= GetResultsAsRedisValues().Length ? null : GetResultsAsRedisValues()[index]; public Row GetRow(int index) { return index >= _results.Length ? default : new Row(_results[index]); } - private Dictionary[] getResultsAsRedisValues() + private Dictionary[] GetResultsAsRedisValues() { - if (_resultsAsRedisValues == null) - _resultsAsRedisValues = _results.Select(dict => dict.ToDictionary( - kvp => kvp.Key, - kvp => kvp.Value is RedisValue value ? value : RedisValue.Null - )).ToArray(); - return _resultsAsRedisValues; + return _resultsAsRedisValues ??= _results.Select(dict => dict.ToDictionary( + kvp => kvp.Key, + kvp => kvp.Value is RedisValue value ? value : RedisValue.Null + )).ToArray(); } } \ No newline at end of file diff --git a/src/NRedisStack/Search/DataTypes/InfoResult.cs b/src/NRedisStack/Search/DataTypes/InfoResult.cs index f931df92..27d00476 100644 --- a/src/NRedisStack/Search/DataTypes/InfoResult.cs +++ b/src/NRedisStack/Search/DataTypes/InfoResult.cs @@ -1,20 +1,20 @@ -using System.Reflection.Emit; -using StackExchange.Redis; +using StackExchange.Redis; namespace NRedisStack.Search.DataTypes; public class InfoResult { private readonly Dictionary _all = new(); - private Dictionary[] _attributes; - private Dictionary _indexOption; - private Dictionary _gcStats; - private Dictionary _cursorStats; + private Dictionary[]? _attributes; + private Dictionary? _indexOption; + private Dictionary? _gcStats; + private Dictionary? _cursorStats; - private static readonly string[] booleanAttributes = { "SORTABLE", "UNF", "NOSTEM", "NOINDEX", "CASESENSITIVE", "WITHSUFFIXTRIE", "INDEXEMPTY", "INDEXMISSING" }; + private static readonly string[] booleanAttributes = ["SORTABLE", "UNF", "NOSTEM", "NOINDEX", "CASESENSITIVE", "WITHSUFFIXTRIE", "INDEXEMPTY", "INDEXMISSING" + ]; public string IndexName => GetString("index_name")!; - public Dictionary IndexOption => _indexOption = _indexOption ?? GetRedisResultDictionary("index_options")!; - public Dictionary[] Attributes => _attributes = _attributes ?? GetAttributesAsDictionaryArray()!; + public Dictionary IndexOption => _indexOption ??= GetRedisResultDictionary("index_options")!; + public Dictionary[] Attributes => _attributes ??= GetAttributesAsDictionaryArray()!; public long NumDocs => GetLong("num_docs"); public string MaxDocId => GetString("max_doc_id")!; public long NumTerms => GetLong("num_terms"); @@ -54,9 +54,9 @@ public class InfoResult public long NumberOfUses => GetLong("number_of_uses"); - public Dictionary GcStats => _gcStats = _gcStats ?? GetRedisResultDictionary("gc_stats")!; + public Dictionary GcStats => _gcStats ??= GetRedisResultDictionary("gc_stats")!; - public Dictionary CursorStats => _cursorStats = _cursorStats ?? GetRedisResultDictionary("cursor_stats")!; + public Dictionary CursorStats => _cursorStats ??= GetRedisResultDictionary("cursor_stats")!; public InfoResult(RedisResult result) { @@ -113,7 +113,7 @@ private double GetDouble(string key) IEnumerator results = enumerable.GetEnumerator(); while (results.MoveNext()) { - string attribute = (string)results.Current; + string attribute = (string)results.Current!; // if its boolean attributes add itself to the dictionary and continue if (booleanAttributes.Contains(attribute)) { diff --git a/src/NRedisStack/Search/Document.cs b/src/NRedisStack/Search/Document.cs index c8f9dec5..80f6da46 100644 --- a/src/NRedisStack/Search/Document.cs +++ b/src/NRedisStack/Search/Document.cs @@ -29,7 +29,7 @@ public Document(string id, Dictionary? fields, double score, public static Document Load(string id, double score, byte[]? payload, RedisValue[]? fields) { - Document ret = new Document(id, score, payload); + Document ret = new(id, score, payload); if (fields == null) return ret; if (fields.Length == 1 && fields[0].IsNull) { diff --git a/src/NRedisStack/Search/FTCreateParams.cs b/src/NRedisStack/Search/FTCreateParams.cs index 9ae3e4f4..18ffa9dd 100644 --- a/src/NRedisStack/Search/FTCreateParams.cs +++ b/src/NRedisStack/Search/FTCreateParams.cs @@ -1,317 +1,316 @@ using NRedisStack.Search.Literals; using NRedisStack.Search.Literals.Enums; -namespace NRedisStack.Search +namespace NRedisStack.Search; + +public class FTCreateParams { - public class FTCreateParams + private IndexDataType dataType; + private List? prefixes; + private string? filter; + private string? language; + private string? languageField; + private double score; + private string? scoreField; + private string? payloadField; + private bool maxTextFields; + private bool noOffsets; + private long temporary; + private bool noHL; + private bool noFields; + private bool noFreqs; + private List? stopwords; + private bool skipInitialScan; + + public FTCreateParams() { - private IndexDataType dataType; - private List? prefixes; - private string? filter; - private string? language; - private string? languageField; - private double score; - private string? scoreField; - private string? payloadField; - private bool maxTextFields; - private bool noOffsets; - private long temporary; - private bool noHL; - private bool noFields; - private bool noFreqs; - private List? stopwords; - private bool skipInitialScan; - - public FTCreateParams() - { - } + } - public static FTCreateParams CreateParams() - { - return new FTCreateParams(); - } + public static FTCreateParams CreateParams() + { + return new(); + } - /// - /// Currently supports HASH (default) and JSON. To index JSON, you must have the RedisJSON module - /// installed. - /// - public FTCreateParams On(IndexDataType dataType) - { - this.dataType = dataType; - return this; - } + /// + /// Currently supports HASH (default) and JSON. To index JSON, you must have the RedisJSON module + /// installed. + /// + public FTCreateParams On(IndexDataType dataType) + { + this.dataType = dataType; + return this; + } - /// - /// Tells the index which keys it should index. You can add several prefixes to index. - /// - public FTCreateParams Prefix(params string[] prefixes) + /// + /// Tells the index which keys it should index. You can add several prefixes to index. + /// + public FTCreateParams Prefix(params string[] prefixes) + { + if (this.prefixes == null) { - if (this.prefixes == null) - { - this.prefixes = new List(prefixes.Length); - } - this.prefixes.AddRange(prefixes); - return this; + this.prefixes = new(prefixes.Length); } + this.prefixes.AddRange(prefixes); + return this; + } - /// - /// This method can be chained to add multiple prefixes. - /// @see FTCreateParams#prefix(java.lang.params string[]) - /// - public FTCreateParams AddPrefix(string prefix) + /// + /// This method can be chained to add multiple prefixes. + /// @see FTCreateParams#prefix(java.lang.params string[]) + /// + public FTCreateParams AddPrefix(string prefix) + { + if (prefixes == null) { - if (this.prefixes == null) - { - this.prefixes = new List(); - } - this.prefixes.Add(prefix); - return this; + prefixes = []; } + prefixes.Add(prefix); + return this; + } - /// - /// A filter expression with the full RediSearch aggregation expression language. - /// - public FTCreateParams Filter(string filter) - { - this.filter = filter; - return this; - } + /// + /// A filter expression with the full RediSearch aggregation expression language. + /// + public FTCreateParams Filter(string filter) + { + this.filter = filter; + return this; + } + + /// + /// default language for documents in the index. + /// + public FTCreateParams Language(string defaultLanguage) + { + language = defaultLanguage; + return this; + } + + /// + /// Document attribute set as the document language. + /// + public FTCreateParams LanguageField(string languageAttribute) + { + languageField = languageAttribute; + return this; + } + + /// + /// Default score for documents in the index. + /// + public FTCreateParams Score(double defaultScore) + { + score = defaultScore; + return this; + } - /// - /// default language for documents in the index. - /// - public FTCreateParams Language(string defaultLanguage) + /// + /// Document attribute that you use as the document rank based on the user ranking. + /// Ranking must be between 0.0 and 1.0. + /// + public FTCreateParams ScoreField(string scoreField) + { + this.scoreField = scoreField; + return this; + } + + /// + /// Document attribute that you use as a binary safe payload string to the document that can be + /// evaluated at query time by a custom scoring function or retrieved to the client. + /// + public FTCreateParams PayloadField(string payloadAttribute) + { + //TODO: check if this is correct + // Array.Copy(this.payloadField, payloadAttribute, payloadAttribute.Length); + payloadField = payloadAttribute; + return this; + } + + + /// + /// Forces RediSearch to encode indexes as if there were more than 32 text attributes. + /// + public FTCreateParams MaxTextFields() + { + maxTextFields = true; + return this; + } + + /// + /// Does not store term offsets for documents. It saves memory, but does not allow exact searches + /// or highlighting. + /// + public FTCreateParams NoOffsets() + { + noOffsets = true; + return this; + } + + /// + /// Creates a lightweight temporary index that expires after a specified period of inactivity. + /// + public FTCreateParams Temporary(long seconds) + { + temporary = seconds; + return this; + } + + /// + /// Conserves storage space and memory by disabling highlighting support. + /// + public FTCreateParams NoHL() + { + noHL = true; + return this; + } + + /// + /// @see FTCreateParams#noHL() + /// + public FTCreateParams NoHighlights() + { + return NoHL(); + } + + /// + /// Does not store attribute bits for each term. It saves memory, but it does not allow filtering + /// by specific attributes. + /// + public FTCreateParams NoFields() + { + noFields = true; + return this; + } + + /// + /// Avoids saving the term frequencies in the index. It saves memory, but does not allow sorting + /// based on the frequencies of a given term within the document. + /// + public FTCreateParams NoFreqs() + { + noFreqs = true; + return this; + } + + /// + /// Sets the index with a custom stopword list, to be ignored during indexing and search time. + /// + public FTCreateParams Stopwords(params string[] stopwords) + { + this.stopwords = stopwords.ToList(); + return this; + } + + /// + /// The index does not have stopwords, not even the default ones. + /// + public FTCreateParams NoStopwords() + { + stopwords = []; + return this; + } + + /// + /// Does not scan and index. + /// + public FTCreateParams SkipInitialScan() + { + skipInitialScan = true; + return this; + } + + public void AddParams(List args) + { + + if (dataType != default(IndexDataType)) { - this.language = defaultLanguage; - return this; + args.Add("ON"); + args.Add(dataType.ToString()); } - /// - /// Document attribute set as the document language. - /// - public FTCreateParams LanguageField(string languageAttribute) + if (prefixes != null) { - this.languageField = languageAttribute; - return this; + args.Add(SearchArgs.PREFIX); + args.Add(prefixes.Count); + foreach (var prefix in prefixes) + if (prefix != null) + args.Add(prefix); } - /// - /// Default score for documents in the index. - /// - public FTCreateParams Score(double defaultScore) + if (filter != null) { - this.score = defaultScore; - return this; + args.Add(SearchArgs.FILTER); + args.Add(filter); } - /// - /// Document attribute that you use as the document rank based on the user ranking. - /// Ranking must be between 0.0 and 1.0. - /// - public FTCreateParams ScoreField(string scoreField) + if (language != null) { - this.scoreField = scoreField; - return this; + args.Add(SearchArgs.LANGUAGE); + args.Add(language); } - - /// - /// Document attribute that you use as a binary safe payload string to the document that can be - /// evaluated at query time by a custom scoring function or retrieved to the client. - /// - public FTCreateParams PayloadField(string payloadAttribute) + if (languageField != null) { - //TODO: check if this is correct - // Array.Copy(this.payloadField, payloadAttribute, payloadAttribute.Length); - this.payloadField = payloadAttribute; - return this; + args.Add(SearchArgs.LANGUAGE_FIELD); + args.Add(languageField); } - - /// - /// Forces RediSearch to encode indexes as if there were more than 32 text attributes. - /// - public FTCreateParams MaxTextFields() + if (score != default(double)) { - this.maxTextFields = true; - return this; + args.Add(SearchArgs.SCORE); + args.Add(score); } - - /// - /// Does not store term offsets for documents. It saves memory, but does not allow exact searches - /// or highlighting. - /// - public FTCreateParams NoOffsets() + if (scoreField != null) { - this.noOffsets = true; - return this; + args.Add(SearchArgs.SCORE_FIELD); + args.Add(scoreField); } - /// - /// Creates a lightweight temporary index that expires after a specified period of inactivity. - /// - public FTCreateParams Temporary(long seconds) + if (payloadField != null) { - this.temporary = seconds; - return this; + args.Add(SearchArgs.PAYLOAD_FIELD); + args.Add(payloadField); } - /// - /// Conserves storage space and memory by disabling highlighting support. - /// - public FTCreateParams NoHL() + if (maxTextFields) { - this.noHL = true; - return this; + args.Add(SearchArgs.MAXTEXTFIELDS); } - - /// - /// @see FTCreateParams#noHL() - /// - public FTCreateParams NoHighlights() + //[TEMPORARY seconds] seposed to be here + if (noOffsets) { - return NoHL(); + args.Add(SearchArgs.NOOFFSETS); } - /// - /// Does not store attribute bits for each term. It saves memory, but it does not allow filtering - /// by specific attributes. - /// - public FTCreateParams NoFields() + if (temporary != default(long)) { - this.noFields = true; - return this; + args.Add(SearchArgs.TEMPORARY); + args.Add(temporary); } - /// - /// Avoids saving the term frequencies in the index. It saves memory, but does not allow sorting - /// based on the frequencies of a given term within the document. - /// - public FTCreateParams NoFreqs() + if (noHL) { - this.noFreqs = true; - return this; + args.Add(SearchArgs.NOHL); } - /// - /// Sets the index with a custom stopword list, to be ignored during indexing and search time. - /// - public FTCreateParams Stopwords(params string[] stopwords) + if (noFields) { - this.stopwords = stopwords.ToList(); - return this; + args.Add(SearchArgs.NOFIELDS); } - /// - /// The index does not have stopwords, not even the default ones. - /// - public FTCreateParams NoStopwords() + if (noFreqs) { - this.stopwords = new List { }; - return this; + args.Add(SearchArgs.NOFREQS); } - /// - /// Does not scan and index. - /// - public FTCreateParams SkipInitialScan() + if (stopwords != null) { - this.skipInitialScan = true; - return this; + args.Add(SearchArgs.STOPWORDS); + args.Add(stopwords.Count); + stopwords.ForEach(w => args.Add(w)); } - public void AddParams(List args) + if (skipInitialScan) { - - if (dataType != default(IndexDataType)) - { - args.Add("ON"); - args.Add(dataType.ToString()); - } - - if (prefixes != null) - { - args.Add(SearchArgs.PREFIX); - args.Add(prefixes.Count); - foreach (var prefix in prefixes) - if (prefix != null) - args.Add(prefix); - } - - if (filter != null) - { - args.Add(SearchArgs.FILTER); - args.Add(filter); - } - - if (language != null) - { - args.Add(SearchArgs.LANGUAGE); - args.Add(language); - } - if (languageField != null) - { - args.Add(SearchArgs.LANGUAGE_FIELD); - args.Add(languageField); - } - - if (score != default(double)) - { - args.Add(SearchArgs.SCORE); - args.Add(score); - } - if (scoreField != null) - { - args.Add(SearchArgs.SCORE_FIELD); - args.Add(scoreField); - } - - if (payloadField != null) - { - args.Add(SearchArgs.PAYLOAD_FIELD); - args.Add(payloadField); - } - - if (maxTextFields) - { - args.Add(SearchArgs.MAXTEXTFIELDS); - } - //[TEMPORARY seconds] seposed to be here - if (noOffsets) - { - args.Add(SearchArgs.NOOFFSETS); - } - - if (temporary != default(long)) - { - args.Add(SearchArgs.TEMPORARY); - args.Add(temporary); - } - - if (noHL) - { - args.Add(SearchArgs.NOHL); - } - - if (noFields) - { - args.Add(SearchArgs.NOFIELDS); - } - - if (noFreqs) - { - args.Add(SearchArgs.NOFREQS); - } - - if (stopwords != null) - { - args.Add(SearchArgs.STOPWORDS); - args.Add(stopwords.Count); - stopwords.ForEach(w => args.Add(w)); - } - - if (skipInitialScan) - { - args.Add(SearchArgs.SKIPINITIALSCAN); - } + args.Add(SearchArgs.SKIPINITIALSCAN); } } } \ No newline at end of file diff --git a/src/NRedisStack/Search/FTSpellCheckParams.cs b/src/NRedisStack/Search/FTSpellCheckParams.cs index cfc9e551..3ef6f2f7 100644 --- a/src/NRedisStack/Search/FTSpellCheckParams.cs +++ b/src/NRedisStack/Search/FTSpellCheckParams.cs @@ -1,87 +1,86 @@ using NRedisStack.Search.Literals; -namespace NRedisStack.Search +namespace NRedisStack.Search; + +public class FTSpellCheckParams : IDialectAwareParam { - public class FTSpellCheckParams : IDialectAwareParam + readonly List args = []; + private readonly List> terms = []; + private int? distance = null; + private int? dialect = null; + + public FTSpellCheckParams() { } + + /// + /// Specifies an inclusion (INCLUDE) of a custom dictionary. + /// + public FTSpellCheckParams IncludeTerm(string dict) { - List args = new List(); - private List> terms = new List>(); - private int? distance = null; - private int? dialect = null; + return AddTerm(dict, SearchArgs.INCLUDE); + } - public FTSpellCheckParams() { } + /// + /// Specifies an inclusion (EXCLUDE) of a custom dictionary. + /// + public FTSpellCheckParams ExcludeTerm(string dict) + { + return AddTerm(dict, SearchArgs.EXCLUDE); + } - /// - /// Specifies an inclusion (INCLUDE) of a custom dictionary. - /// - public FTSpellCheckParams IncludeTerm(string dict) - { - return AddTerm(dict, SearchArgs.INCLUDE); - } + /// + /// Specifies an inclusion (INCLUDE) or exclusion (EXCLUDE) of a custom dictionary. + /// + private FTSpellCheckParams AddTerm(string dict, string type) + { + terms.Add(new(dict, type)); + return this; + } - /// - /// Specifies an inclusion (EXCLUDE) of a custom dictionary. - /// - public FTSpellCheckParams ExcludeTerm(string dict) - { - return AddTerm(dict, SearchArgs.EXCLUDE); - } + /// + /// Maximum Levenshtein distance for spelling suggestions (default: 1, max: 4). + /// + public FTSpellCheckParams Distance(int distance) + { + this.distance = distance; + return this; + } - /// - /// Specifies an inclusion (INCLUDE) or exclusion (EXCLUDE) of a custom dictionary. - /// - private FTSpellCheckParams AddTerm(string dict, string type) - { - terms.Add(new KeyValuePair(dict, type)); - return this; - } + /// + /// Selects the dialect version under which to execute the query. + /// + public FTSpellCheckParams Dialect(int dialect) + { + this.dialect = dialect; + return this; + } - /// - /// Maximum Levenshtein distance for spelling suggestions (default: 1, max: 4). - /// - public FTSpellCheckParams Distance(int distance) - { - this.distance = distance; - return this; - } + public List GetArgs() + { + return args; + } - /// - /// Selects the dialect version under which to execute the query. - /// - public FTSpellCheckParams Dialect(int dialect) + public void SerializeRedisArgs() + { + if (dialect != null) { - this.dialect = dialect; - return this; + args.Add(SearchArgs.DIALECT); + args.Add(dialect); } - - public List GetArgs() + foreach (var term in terms) { - return args; + args.Add(SearchArgs.TERMS); + args.Add(term.Value); + args.Add(term.Key); } - - public void SerializeRedisArgs() + if (distance != null) { - if (dialect != null) - { - args.Add(SearchArgs.DIALECT); - args.Add(dialect); - } - foreach (var term in terms) - { - args.Add(SearchArgs.TERMS); - args.Add(term.Value); - args.Add(term.Key); - } - if (distance != null) - { - args.Add(SearchArgs.DISTANCE); - args.Add(distance); - } + args.Add(SearchArgs.DISTANCE); + args.Add(distance); } + } - int? IDialectAwareParam.Dialect - { - get { return dialect; } - set { dialect = value; } - } + int? IDialectAwareParam.Dialect + { + get { return dialect; } + set { dialect = value; } } -} +} \ No newline at end of file diff --git a/src/NRedisStack/Search/FieldName.cs b/src/NRedisStack/Search/FieldName.cs index eee3ca7e..9a269a52 100644 --- a/src/NRedisStack/Search/FieldName.cs +++ b/src/NRedisStack/Search/FieldName.cs @@ -1,40 +1,39 @@ -namespace NRedisStack.Search +namespace NRedisStack.Search; + +public class FieldName { - public class FieldName - { - public string Name { get; } - public string? Alias { get; private set; } + public string Name { get; } + public string? Alias { get; private set; } - public FieldName(string name) : this(name, null) { } + public FieldName(string name) : this(name, null) { } - public FieldName(string name, string? attribute) - { - this.Name = name; - this.Alias = attribute; - } + public FieldName(string name, string? attribute) + { + Name = name; + Alias = attribute; + } - public int AddCommandArguments(List args) + public int AddCommandArguments(List args) + { + args.Add(Name); + if (Alias is null) { - args.Add(Name); - if (Alias is null) - { - return 1; - } - - args.Add("AS"); - args.Add(Alias); - return 3; + return 1; } - public static FieldName Of(string name) - { - return new FieldName(name); - } + args.Add("AS"); + args.Add(Alias); + return 3; + } - public FieldName As(string attribute) - { - this.Alias = attribute; - return this; - } + public static FieldName Of(string name) + { + return new(name); + } + + public FieldName As(string attribute) + { + Alias = attribute; + return this; } } \ No newline at end of file diff --git a/src/NRedisStack/Search/Group.cs b/src/NRedisStack/Search/Group.cs index a45e065f..4a7ad148 100644 --- a/src/NRedisStack/Search/Group.cs +++ b/src/NRedisStack/Search/Group.cs @@ -1,45 +1,44 @@ -namespace NRedisStack.Search.Aggregation +namespace NRedisStack.Search.Aggregation; + +public class Group { - public class Group - { - private readonly IList _reducers = new List(); - private readonly IList _fields; - private Limit _limit = Aggregation.Limit.NO_LIMIT; + private readonly IList _reducers = new List(); + private readonly IList _fields; + private Limit _limit = Aggregation.Limit.NO_LIMIT; - public Group(params string[] fields) => _fields = fields; - public Group(IList fields) => _fields = fields; + public Group(params string[] fields) => _fields = fields; + public Group(IList fields) => _fields = fields; - internal Group Limit(Limit limit) - { - _limit = limit; - return this; - } + internal Group Limit(Limit limit) + { + _limit = limit; + return this; + } - internal Group Reduce(Reducer r) - { - _reducers.Add(r); - return this; - } + internal Group Reduce(Reducer r) + { + _reducers.Add(r); + return this; + } - internal void SerializeRedisArgs(List args) + internal void SerializeRedisArgs(List args) + { + args.Add(_fields.Count); + foreach (var field in _fields) + args.Add(field); + foreach (var r in _reducers) { - args.Add(_fields.Count); - foreach (var field in _fields) - args.Add(field); - foreach (var r in _reducers) + args.Add("REDUCE"); + args.Add(r.Name); + r.SerializeRedisArgs(args); + var alias = r.Alias; + if (!string.IsNullOrEmpty(alias)) { - args.Add("REDUCE"); - args.Add(r.Name); - r.SerializeRedisArgs(args); - var alias = r.Alias; - if (!string.IsNullOrEmpty(alias)) - { - args.Add("AS"); - args.Add(alias!); - } + args.Add("AS"); + args.Add(alias!); } - _limit.SerializeRedisArgs(args); } + _limit.SerializeRedisArgs(args); } } \ No newline at end of file diff --git a/src/NRedisStack/Search/IDialectAwareParam.cs b/src/NRedisStack/Search/IDialectAwareParam.cs index 42ccfd3f..2d21ce62 100644 --- a/src/NRedisStack/Search/IDialectAwareParam.cs +++ b/src/NRedisStack/Search/IDialectAwareParam.cs @@ -1,15 +1,13 @@ -namespace NRedisStack.Search +namespace NRedisStack.Search; + +/// +/// Interface for dialect-aware parameters. +/// To provide a single interface to manage default dialect version under which to execute the query. +/// +internal interface IDialectAwareParam { /// - /// Interface for dialect-aware parameters. - /// To provide a single interface to manage default dialect version under which to execute the query. + /// Selects the dialect version under which to execute the query. /// - internal interface IDialectAwareParam - { - /// - /// Selects the dialect version under which to execute the query. - /// - internal int? Dialect { get; set; } - } - + internal int? Dialect { get; set; } } \ No newline at end of file diff --git a/src/NRedisStack/Search/ISearchCommands.cs b/src/NRedisStack/Search/ISearchCommands.cs index a63f473f..86408bfe 100644 --- a/src/NRedisStack/Search/ISearchCommands.cs +++ b/src/NRedisStack/Search/ISearchCommands.cs @@ -1,317 +1,315 @@ using NRedisStack.Search; -using NRedisStack.Search.Aggregation; using NRedisStack.Search.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public interface ISearchCommands { - public interface ISearchCommands - { - - /// - /// Returns a list of all existing indexes. - /// - /// Array with index names. - /// - RedisResult[] _List(); - - /// - /// Run a search query on an index, and perform aggregate transformations on the results. - /// - /// The index name. - /// The query - /// An object - /// - AggregationResult Aggregate(string index, AggregationRequest query); - - /// - /// Add an alias to an index. - /// - /// Alias to be added to an index. - /// The index name. - /// if executed correctly, error otherwise - /// - bool AliasAdd(string alias, string index); - - /// - /// Remove an alias to an index. - /// - /// Alias to be removed. - /// if executed correctly, error otherwise - /// - bool AliasDel(string alias); - - /// - /// Add an alias to an index. If the alias is already associated with another index, - /// FT.ALIASUPDATE removes the alias association with the previous index. - /// - /// Alias to be removed. - /// The index name. - /// if executed correctly, error otherwise - /// - bool AliasUpdate(string alias, string index); - - /// - /// Add a new attribute to the index - /// - /// The index name. - /// If set, does not scan and index. - /// the schema. - /// if executed correctly, error otherwise - /// - bool Alter(string index, Schema schema, bool skipInitialScan = false); - - /// - /// Retrieve configuration options. - /// - /// is name of the configuration option, or '*' for all. - /// An array reply of the configuration name and value. - /// - [Obsolete("Starting from Redis 8.0, use db.ConfigGet instead")] - Dictionary ConfigGet(string option); - - /// - /// Describe configuration options. - /// - /// is name of the configuration option, or '*' for all. - /// is value of the configuration option. - /// if executed correctly, error otherwise. - /// - [Obsolete("Starting from Redis 8.0, use db.ConfigSet instead")] - bool ConfigSet(string option, string value); - - /// - /// Create an index with the given specification. - /// - /// The index name. - /// Command's parameters. - /// The index schema. - /// if executed correctly, error otherwise - /// - bool Create(string indexName, FTCreateParams parameters, Schema schema); - - /// - /// Delete a cursor from the index. - /// - /// The index name - /// The cursor's ID. - /// if it has been deleted, if it did not exist. - /// - bool CursorDel(string indexName, long cursorId); - - /// - /// Read next results from an existing cursor. - /// - /// The index name - /// The cursor's ID. - /// Limit the amount of returned results. - /// A AggregationResult object with the results - /// - AggregationResult CursorRead(string indexName, long cursorId, int? count = null); - - /// - /// Add terms to a dictionary. - /// - /// The dictionary name - /// Terms to add to the dictionary.. - /// The number of new terms that were added. - /// - long DictAdd(string dict, params string[] terms); - - /// - /// Delete terms from a dictionary. - /// - /// The dictionary name - /// Terms to delete to the dictionary.. - /// The number of new terms that were deleted. - /// - long DictDel(string dict, params string[] terms); - - /// - /// Dump all terms in the given dictionary. - /// - /// The dictionary name - /// An array, where each element is term. - /// - RedisResult[] DictDump(string dict); - - /// - /// Delete an index. - /// - /// The index name - /// If set, deletes the actual document hashes. - /// if executed correctly, error otherwise - /// - bool DropIndex(string indexName, bool dd = false); - - /// - /// Return the execution plan for a complex query - /// - /// The index name - /// The query to explain - /// Dialect version under which to execute the query - /// String that representing the execution plan - /// - string Explain(string indexName, string query, int? dialect = null); - - /// - /// Return the execution plan for a complex query - /// - /// The index name - /// The query to explain - /// Dialect version under which to execute the query - /// An array reply with a string representing the execution plan - /// - RedisResult[] ExplainCli(string indexName, string query, int? dialect = null); - - /// - /// Return information and statistics on the index. - /// - /// The name of the index. - /// Dictionary of key and value with information about the index - /// - InfoResult Info(RedisValue index); - - /// - /// Apply FT.SEARCH command to collect performance details. - /// - /// The index name, created using FT.CREATE. - /// The query string. - /// Removes details of reader iterator. - /// - [Obsolete("Consider using ProfileOnSearch with Redis CE 8.0 and later")] - Tuple> ProfileSearch(string indexName, Query q, bool limited = false); - - /// - /// Apply FT.SEARCH command to collect performance details. - /// - /// The index name, created using FT.CREATE. - /// The query string. - /// Removes details of reader iterator. - /// - Tuple ProfileOnSearch(string indexName, Query q, bool limited = false); - - /// - /// Apply FT.AGGREGATE command to collect performance details. - /// - /// The index name, created using FT.CREATE. - /// The query string. - /// Removes details of reader iterator. - /// - [Obsolete("Consider using ProfileOnAggregate with Redis CE 8.0 and later")] - Tuple> ProfileAggregate(string indexName, AggregationRequest query, bool limited = false); - - /// - /// Apply FT.AGGREGATE command to collect performance details. - /// - /// The index name, created using FT.CREATE. - /// The query string. - /// Removes details of reader iterator. - /// - Tuple ProfileOnAggregate(string indexName, AggregationRequest query, bool limited = false); - - /// - /// Search the index - /// - /// The index name - /// a object with the query string and optional parameters - /// a object with the results - /// - SearchResult Search(string indexName, Query q); - - /// - /// Dump the contents of a synonym group. - /// - /// The index name - /// Pairs of term and an array of synonym groups. - /// - Dictionary> SynDump(string indexName); - - /// - /// Perform spelling correction on a query, returning suggestions for misspelled terms. - /// - /// is index with the indexed terms. - /// is search query. - /// Optional Spellcheck Parameters - /// An array reply, in which each element represents a misspelled term from the query. - /// - Dictionary> SpellCheck(string indexName, string query, FTSpellCheckParams? spellCheckParams = null); - - /// - /// Add a suggestion string to an auto-complete suggestion dictionary - /// - /// is suggestion dictionary key. - /// is suggestion string to index. - /// is floating point number of the suggestion string's weight. - /// increments the existing entry of the suggestion by the given score, - /// instead of replacing the score. - /// saves an extra payload with the suggestion, that can be fetched by adding the WITHPAYLOADS argument to FT.SUGGET. - /// The current size of the suggestion dictionary. - /// - long SugAdd(string key, string str, double score, bool increment = false, string? payload = null); - - /// - /// Delete a string from a suggestion index. - /// - /// is suggestion dictionary key. - /// is suggestion string to index. - /// if the string was found and deleted, otherwise. - /// - bool SugDel(string key, string str); - - /// - /// Get completion suggestions for a prefix. - /// - /// is suggestion dictionary key. - /// is prefix to complete on. - /// performs a fuzzy prefix search, - /// including prefixes at Levenshtein distance of 1 from the prefix sent. - /// returns optional payloads saved along with the suggestions. - /// limits the results to a maximum of num (default: 5). - /// List of the top suggestions matching the prefix. - /// - List SugGet(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null); - - /// - /// Get completion suggestions for a prefix with the score of each suggestion. - /// - /// is suggestion dictionary key. - /// is prefix to complete on. - /// performs a fuzzy prefix search, - /// including prefixes at Levenshtein distance of 1 from the prefix sent. - /// returns optional payloads saved along with the suggestions. - /// limits the results to a maximum of num (default: 5). - /// List of the top suggestions matching the prefix. - /// - List> SugGetWithScores(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null); - - /// - /// Get the size of an auto-complete suggestion dictionary. - /// - /// is suggestion dictionary key. - /// The current size of the suggestion dictionary. - /// - long SugLen(string key); - - /// - /// Update a synonym group. - /// - /// The index name - /// Is synonym group to return - /// does not scan and index, and only documents - /// that are indexed after the update are affected - /// The terms - /// Pairs of term and an array of synonym groups. - /// - bool SynUpdate(string indexName, string synonymGroupId, bool skipInitialScan = false, params string[] terms); - - /// - /// Return a distinct set of values indexed in a Tag field. - /// - /// The index name - /// TAG field name - /// List of TAG field values - /// - RedisResult[] TagVals(string indexName, string fieldName); - } + + /// + /// Returns a list of all existing indexes. + /// + /// Array with index names. + /// + RedisResult[] _List(); + + /// + /// Run a search query on an index, and perform aggregate transformations on the results. + /// + /// The index name. + /// The query + /// An object + /// + AggregationResult Aggregate(string index, AggregationRequest query); + + /// + /// Add an alias to an index. + /// + /// Alias to be added to an index. + /// The index name. + /// if executed correctly, error otherwise + /// + bool AliasAdd(string alias, string index); + + /// + /// Remove an alias to an index. + /// + /// Alias to be removed. + /// if executed correctly, error otherwise + /// + bool AliasDel(string alias); + + /// + /// Add an alias to an index. If the alias is already associated with another index, + /// FT.ALIASUPDATE removes the alias association with the previous index. + /// + /// Alias to be removed. + /// The index name. + /// if executed correctly, error otherwise + /// + bool AliasUpdate(string alias, string index); + + /// + /// Add a new attribute to the index + /// + /// The index name. + /// If set, does not scan and index. + /// the schema. + /// if executed correctly, error otherwise + /// + bool Alter(string index, Schema schema, bool skipInitialScan = false); + + /// + /// Retrieve configuration options. + /// + /// is name of the configuration option, or '*' for all. + /// An array reply of the configuration name and value. + /// + [Obsolete("Starting from Redis 8.0, use db.ConfigGet instead")] + Dictionary ConfigGet(string option); + + /// + /// Describe configuration options. + /// + /// is name of the configuration option, or '*' for all. + /// is value of the configuration option. + /// if executed correctly, error otherwise. + /// + [Obsolete("Starting from Redis 8.0, use db.ConfigSet instead")] + bool ConfigSet(string option, string value); + + /// + /// Create an index with the given specification. + /// + /// The index name. + /// Command's parameters. + /// The index schema. + /// if executed correctly, error otherwise + /// + bool Create(string indexName, FTCreateParams parameters, Schema schema); + + /// + /// Delete a cursor from the index. + /// + /// The index name + /// The cursor's ID. + /// if it has been deleted, if it did not exist. + /// + bool CursorDel(string indexName, long cursorId); + + /// + /// Read next results from an existing cursor. + /// + /// The index name + /// The cursor's ID. + /// Limit the amount of returned results. + /// A AggregationResult object with the results + /// + AggregationResult CursorRead(string indexName, long cursorId, int? count = null); + + /// + /// Add terms to a dictionary. + /// + /// The dictionary name + /// Terms to add to the dictionary.. + /// The number of new terms that were added. + /// + long DictAdd(string dict, params string[] terms); + + /// + /// Delete terms from a dictionary. + /// + /// The dictionary name + /// Terms to delete to the dictionary.. + /// The number of new terms that were deleted. + /// + long DictDel(string dict, params string[] terms); + + /// + /// Dump all terms in the given dictionary. + /// + /// The dictionary name + /// An array, where each element is term. + /// + RedisResult[] DictDump(string dict); + + /// + /// Delete an index. + /// + /// The index name + /// If set, deletes the actual document hashes. + /// if executed correctly, error otherwise + /// + bool DropIndex(string indexName, bool dd = false); + + /// + /// Return the execution plan for a complex query + /// + /// The index name + /// The query to explain + /// Dialect version under which to execute the query + /// String that representing the execution plan + /// + string Explain(string indexName, string query, int? dialect = null); + + /// + /// Return the execution plan for a complex query + /// + /// The index name + /// The query to explain + /// Dialect version under which to execute the query + /// An array reply with a string representing the execution plan + /// + RedisResult[] ExplainCli(string indexName, string query, int? dialect = null); + + /// + /// Return information and statistics on the index. + /// + /// The name of the index. + /// Dictionary of key and value with information about the index + /// + InfoResult Info(RedisValue index); + + /// + /// Apply FT.SEARCH command to collect performance details. + /// + /// The index name, created using FT.CREATE. + /// The query string. + /// Removes details of reader iterator. + /// + [Obsolete("Consider using ProfileOnSearch with Redis CE 8.0 and later")] + Tuple> ProfileSearch(string indexName, Query q, bool limited = false); + + /// + /// Apply FT.SEARCH command to collect performance details. + /// + /// The index name, created using FT.CREATE. + /// The query string. + /// Removes details of reader iterator. + /// + Tuple ProfileOnSearch(string indexName, Query q, bool limited = false); + + /// + /// Apply FT.AGGREGATE command to collect performance details. + /// + /// The index name, created using FT.CREATE. + /// The query string. + /// Removes details of reader iterator. + /// + [Obsolete("Consider using ProfileOnAggregate with Redis CE 8.0 and later")] + Tuple> ProfileAggregate(string indexName, AggregationRequest query, bool limited = false); + + /// + /// Apply FT.AGGREGATE command to collect performance details. + /// + /// The index name, created using FT.CREATE. + /// The query string. + /// Removes details of reader iterator. + /// + Tuple ProfileOnAggregate(string indexName, AggregationRequest query, bool limited = false); + + /// + /// Search the index + /// + /// The index name + /// a object with the query string and optional parameters + /// a object with the results + /// + SearchResult Search(string indexName, Query q); + + /// + /// Dump the contents of a synonym group. + /// + /// The index name + /// Pairs of term and an array of synonym groups. + /// + Dictionary> SynDump(string indexName); + + /// + /// Perform spelling correction on a query, returning suggestions for misspelled terms. + /// + /// is index with the indexed terms. + /// is search query. + /// Optional Spellcheck Parameters + /// An array reply, in which each element represents a misspelled term from the query. + /// + Dictionary> SpellCheck(string indexName, string query, FTSpellCheckParams? spellCheckParams = null); + + /// + /// Add a suggestion string to an auto-complete suggestion dictionary + /// + /// is suggestion dictionary key. + /// is suggestion string to index. + /// is floating point number of the suggestion string's weight. + /// increments the existing entry of the suggestion by the given score, + /// instead of replacing the score. + /// saves an extra payload with the suggestion, that can be fetched by adding the WITHPAYLOADS argument to FT.SUGGET. + /// The current size of the suggestion dictionary. + /// + long SugAdd(string key, string str, double score, bool increment = false, string? payload = null); + + /// + /// Delete a string from a suggestion index. + /// + /// is suggestion dictionary key. + /// is suggestion string to index. + /// if the string was found and deleted, otherwise. + /// + bool SugDel(string key, string str); + + /// + /// Get completion suggestions for a prefix. + /// + /// is suggestion dictionary key. + /// is prefix to complete on. + /// performs a fuzzy prefix search, + /// including prefixes at Levenshtein distance of 1 from the prefix sent. + /// returns optional payloads saved along with the suggestions. + /// limits the results to a maximum of num (default: 5). + /// List of the top suggestions matching the prefix. + /// + List SugGet(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null); + + /// + /// Get completion suggestions for a prefix with the score of each suggestion. + /// + /// is suggestion dictionary key. + /// is prefix to complete on. + /// performs a fuzzy prefix search, + /// including prefixes at Levenshtein distance of 1 from the prefix sent. + /// returns optional payloads saved along with the suggestions. + /// limits the results to a maximum of num (default: 5). + /// List of the top suggestions matching the prefix. + /// + List> SugGetWithScores(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null); + + /// + /// Get the size of an auto-complete suggestion dictionary. + /// + /// is suggestion dictionary key. + /// The current size of the suggestion dictionary. + /// + long SugLen(string key); + + /// + /// Update a synonym group. + /// + /// The index name + /// Is synonym group to return + /// does not scan and index, and only documents + /// that are indexed after the update are affected + /// The terms + /// Pairs of term and an array of synonym groups. + /// + bool SynUpdate(string indexName, string synonymGroupId, bool skipInitialScan = false, params string[] terms); + + /// + /// Return a distinct set of values indexed in a Tag field. + /// + /// The index name + /// TAG field name + /// List of TAG field values + /// + RedisResult[] TagVals(string indexName, string fieldName); } \ No newline at end of file diff --git a/src/NRedisStack/Search/ISearchCommandsAsync.cs b/src/NRedisStack/Search/ISearchCommandsAsync.cs index b3047892..f9088dfc 100644 --- a/src/NRedisStack/Search/ISearchCommandsAsync.cs +++ b/src/NRedisStack/Search/ISearchCommandsAsync.cs @@ -1,317 +1,315 @@ using NRedisStack.Search; -using NRedisStack.Search.Aggregation; using NRedisStack.Search.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public interface ISearchCommandsAsync { - public interface ISearchCommandsAsync - { - /// - /// Returns a list of all existing indexes. - /// - /// Array with index names. - /// - Task _ListAsync(); - - /// - /// Run a search query on an index, and perform aggregate transformations on the results. - /// - /// The index name. - /// The query - /// An object - /// - Task AggregateAsync(string index, AggregationRequest query); - - /// - /// Add an alias to an index. - /// - /// Alias to be added to an index. - /// The index name. - /// if executed correctly, error otherwise - /// - Task AliasAddAsync(string alias, string index); - - /// - /// Remove an alias to an index. - /// - /// Alias to be removed. - /// if executed correctly, error otherwise - /// - Task AliasDelAsync(string alias); - - /// - /// Add an alias to an index. If the alias is already associated with another index, - /// FT.ALIASUPDATE removes the alias association with the previous index. - /// - /// Alias to be removed. - /// The index name. - /// if executed correctly, error otherwise - /// - Task AliasUpdateAsync(string alias, string index); - - /// - /// Add a new attribute to the index - /// - /// The index name. - /// If set, does not scan and index. - /// the schema. - /// if executed correctly, error otherwise - /// - Task AlterAsync(string index, Schema schema, bool skipInitialScan = false); - - /// - /// Retrieve configuration options. - /// - /// is name of the configuration option, or '*' for all. - /// An array reply of the configuration name and value. - /// - [Obsolete("Starting from Redis 8.0, use db.ConfigGetAsync instead")] - Task> ConfigGetAsync(string option); - - /// - /// Describe configuration options. - /// - /// is name of the configuration option, or '*' for all. - /// is value of the configuration option. - /// if executed correctly, error otherwise. - /// - [Obsolete("Starting from Redis 8.0, use db.ConfigSetAsync instead")] - Task ConfigSetAsync(string option, string value); - - /// - /// Create an index with the given specification. - /// - /// The index name. - /// Command's parameters. - /// The index schema. - /// if executed correctly, error otherwise - /// - Task CreateAsync(string indexName, FTCreateParams parameters, Schema schema); - - /// - /// Delete a cursor from the index. - /// - /// The index name - /// The cursor's ID. - /// if it has been deleted, if it did not exist. - /// - Task CursorDelAsync(string indexName, long cursorId); - - /// - /// Read next results from an existing cursor. - /// - /// The index name - /// The cursor's ID. - /// Limit the amount of returned results. - /// A AggregationResult object with the results - /// - Task CursorReadAsync(string indexName, long cursorId, int? count = null); - - /// - /// Add terms to a dictionary. - /// - /// The dictionary name - /// Terms to add to the dictionary.. - /// The number of new terms that were added. - /// - Task DictAddAsync(string dict, params string[] terms); - - /// - /// Delete terms from a dictionary. - /// - /// The dictionary name - /// Terms to delete to the dictionary.. - /// The number of new terms that were deleted. - /// - Task DictDelAsync(string dict, params string[] terms); - - /// - /// Dump all terms in the given dictionary. - /// - /// The dictionary name - /// An array, where each element is term. - /// - Task DictDumpAsync(string dict); - - /// - /// Delete an index. - /// - /// The index name - /// If set, deletes the actual document hashes. - /// if executed correctly, error otherwise - /// - Task DropIndexAsync(string indexName, bool dd = false); - - /// - /// Return the execution plan for a complex query - /// - /// The index name - /// The query to explain - /// Dialect version under which to execute the query - /// String that representing the execution plan - /// - Task ExplainAsync(string indexName, string query, int? dialect = null); - - /// - /// Return the execution plan for a complex query - /// - /// The index name - /// The query to explain - /// Dialect version under which to execute the query - /// An array reply with a string representing the execution plan - /// - Task ExplainCliAsync(string indexName, string query, int? dialect = null); - - /// - /// Return information and statistics on the index. - /// - /// The name of the index. - /// Dictionary of key and value with information about the index - /// - Task InfoAsync(RedisValue index); - - /// - /// Apply FT.SEARCH command to collect performance details. - /// - /// The index name, created using FT.CREATE. - /// The query string. - /// Removes details of reader iterator. - /// - [Obsolete("Consider using ProfileOnSearchAsync with Redis CE 8.0 and later")] - Task>> ProfileSearchAsync(string indexName, Query q, bool limited = false); - - /// - /// Apply FT.SEARCH command to collect performance details. - /// - /// The index name, created using FT.CREATE. - /// The query string. - /// Removes details of reader iterator. - /// - Task> ProfileOnSearchAsync(string indexName, Query q, bool limited = false); - - /// - /// Apply FT.AGGREGATE command to collect performance details. - /// - /// The index name, created using FT.CREATE. - /// The query string. - /// Removes details of reader iterator. - /// - [Obsolete("Consider using ProfileOnAggregateAsync with Redis CE 8.0 and later")] - Task>> ProfileAggregateAsync(string indexName, AggregationRequest query, bool limited = false); - - /// - /// Apply FT.AGGREGATE command to collect performance details. - /// - /// The index name, created using FT.CREATE. - /// The query string. - /// Removes details of reader iterator. - /// - Task> ProfileOnAggregateAsync(string indexName, AggregationRequest query, bool limited = false); - - /// - /// Search the index - /// - /// The index name - /// a object with the query string and optional parameters - /// a object with the results - /// - Task SearchAsync(string indexName, Query q); - - /// - /// Perform spelling correction on a query, returning suggestions for misspelled terms. - /// - /// is index with the indexed terms. - /// is search query. - /// Optional Spellcheck Parameters - /// An array reply, in which each element represents a misspelled term from the query. - /// - /// - Task>> SpellCheckAsync(string indexName, string query, FTSpellCheckParams? spellCheckParams = null); - - /// - /// Add a suggestion string to an auto-complete suggestion dictionary - /// - /// is suggestion dictionary key. - /// is suggestion string to index. - /// is floating point number of the suggestion string's weight. - /// increments the existing entry of the suggestion by the given score, - /// instead of replacing the score. - /// saves an extra payload with the suggestion, that can be fetched by adding the WITHPAYLOADS argument to FT.SUGGET. - /// The current size of the suggestion dictionary. - /// - Task SugAddAsync(string key, string str, double score, bool increment = false, string? payload = null); - - /// - /// Delete a string from a suggestion index. - /// - /// is suggestion dictionary key. - /// is suggestion string to index. - /// if the string was found and deleted, otherwise. - /// - Task SugDelAsync(string key, string str); - - /// - /// Get completion suggestions for a prefix. - /// - /// is suggestion dictionary key. - /// is prefix to complete on. - /// performs a fuzzy prefix search, - /// including prefixes at Levenshtein distance of 1 from the prefix sent. - /// returns optional payloads saved along with the suggestions. - /// limits the results to a maximum of num (default: 5). - /// List of the top suggestions matching the prefix. - /// - Task> SugGetAsync(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null); - - /// - /// Get completion suggestions for a prefix with the score of each suggestion. - /// - /// is suggestion dictionary key. - /// is prefix to complete on. - /// performs a fuzzy prefix search, - /// including prefixes at Levenshtein distance of 1 from the prefix sent. - /// returns optional payloads saved along with the suggestions. - /// limits the results to a maximum of num (default: 5). - /// List of the top suggestions matching the prefix. - /// - Task>> SugGetWithScoresAsync(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null); - - /// - /// Get the size of an auto-complete suggestion dictionary. - /// - /// is suggestion dictionary key. - /// The current size of the suggestion dictionary. - /// - Task SugLenAsync(string key); - - /// - /// Dump the contents of a synonym group. - /// - /// The index name - /// Pairs of term and an array of synonym groups. - /// - Task>> SynDumpAsync(string indexName); - - /// - /// Update a synonym group. - /// - /// The index name - /// Is synonym group to return - /// does not scan and index, and only documents - /// that are indexed after the update are affected - /// The terms - /// Pairs of term and an array of synonym groups. - /// - Task SynUpdateAsync(string indexName, string synonymGroupId, bool skipInitialScan = false, params string[] terms); - - /// - /// Return a distinct set of values indexed in a Tag field. - /// - /// The index name - /// TAG field name - /// List of TAG field values - /// - Task TagValsAsync(string indexName, string fieldName); - } + /// + /// Returns a list of all existing indexes. + /// + /// Array with index names. + /// + Task _ListAsync(); + + /// + /// Run a search query on an index, and perform aggregate transformations on the results. + /// + /// The index name. + /// The query + /// An object + /// + Task AggregateAsync(string index, AggregationRequest query); + + /// + /// Add an alias to an index. + /// + /// Alias to be added to an index. + /// The index name. + /// if executed correctly, error otherwise + /// + Task AliasAddAsync(string alias, string index); + + /// + /// Remove an alias to an index. + /// + /// Alias to be removed. + /// if executed correctly, error otherwise + /// + Task AliasDelAsync(string alias); + + /// + /// Add an alias to an index. If the alias is already associated with another index, + /// FT.ALIASUPDATE removes the alias association with the previous index. + /// + /// Alias to be removed. + /// The index name. + /// if executed correctly, error otherwise + /// + Task AliasUpdateAsync(string alias, string index); + + /// + /// Add a new attribute to the index + /// + /// The index name. + /// If set, does not scan and index. + /// the schema. + /// if executed correctly, error otherwise + /// + Task AlterAsync(string index, Schema schema, bool skipInitialScan = false); + + /// + /// Retrieve configuration options. + /// + /// is name of the configuration option, or '*' for all. + /// An array reply of the configuration name and value. + /// + [Obsolete("Starting from Redis 8.0, use db.ConfigGetAsync instead")] + Task> ConfigGetAsync(string option); + + /// + /// Describe configuration options. + /// + /// is name of the configuration option, or '*' for all. + /// is value of the configuration option. + /// if executed correctly, error otherwise. + /// + [Obsolete("Starting from Redis 8.0, use db.ConfigSetAsync instead")] + Task ConfigSetAsync(string option, string value); + + /// + /// Create an index with the given specification. + /// + /// The index name. + /// Command's parameters. + /// The index schema. + /// if executed correctly, error otherwise + /// + Task CreateAsync(string indexName, FTCreateParams parameters, Schema schema); + + /// + /// Delete a cursor from the index. + /// + /// The index name + /// The cursor's ID. + /// if it has been deleted, if it did not exist. + /// + Task CursorDelAsync(string indexName, long cursorId); + + /// + /// Read next results from an existing cursor. + /// + /// The index name + /// The cursor's ID. + /// Limit the amount of returned results. + /// A AggregationResult object with the results + /// + Task CursorReadAsync(string indexName, long cursorId, int? count = null); + + /// + /// Add terms to a dictionary. + /// + /// The dictionary name + /// Terms to add to the dictionary.. + /// The number of new terms that were added. + /// + Task DictAddAsync(string dict, params string[] terms); + + /// + /// Delete terms from a dictionary. + /// + /// The dictionary name + /// Terms to delete to the dictionary.. + /// The number of new terms that were deleted. + /// + Task DictDelAsync(string dict, params string[] terms); + + /// + /// Dump all terms in the given dictionary. + /// + /// The dictionary name + /// An array, where each element is term. + /// + Task DictDumpAsync(string dict); + + /// + /// Delete an index. + /// + /// The index name + /// If set, deletes the actual document hashes. + /// if executed correctly, error otherwise + /// + Task DropIndexAsync(string indexName, bool dd = false); + + /// + /// Return the execution plan for a complex query + /// + /// The index name + /// The query to explain + /// Dialect version under which to execute the query + /// String that representing the execution plan + /// + Task ExplainAsync(string indexName, string query, int? dialect = null); + + /// + /// Return the execution plan for a complex query + /// + /// The index name + /// The query to explain + /// Dialect version under which to execute the query + /// An array reply with a string representing the execution plan + /// + Task ExplainCliAsync(string indexName, string query, int? dialect = null); + + /// + /// Return information and statistics on the index. + /// + /// The name of the index. + /// Dictionary of key and value with information about the index + /// + Task InfoAsync(RedisValue index); + + /// + /// Apply FT.SEARCH command to collect performance details. + /// + /// The index name, created using FT.CREATE. + /// The query string. + /// Removes details of reader iterator. + /// + [Obsolete("Consider using ProfileOnSearchAsync with Redis CE 8.0 and later")] + Task>> ProfileSearchAsync(string indexName, Query q, bool limited = false); + + /// + /// Apply FT.SEARCH command to collect performance details. + /// + /// The index name, created using FT.CREATE. + /// The query string. + /// Removes details of reader iterator. + /// + Task> ProfileOnSearchAsync(string indexName, Query q, bool limited = false); + + /// + /// Apply FT.AGGREGATE command to collect performance details. + /// + /// The index name, created using FT.CREATE. + /// The query string. + /// Removes details of reader iterator. + /// + [Obsolete("Consider using ProfileOnAggregateAsync with Redis CE 8.0 and later")] + Task>> ProfileAggregateAsync(string indexName, AggregationRequest query, bool limited = false); + + /// + /// Apply FT.AGGREGATE command to collect performance details. + /// + /// The index name, created using FT.CREATE. + /// The query string. + /// Removes details of reader iterator. + /// + Task> ProfileOnAggregateAsync(string indexName, AggregationRequest query, bool limited = false); + + /// + /// Search the index + /// + /// The index name + /// a object with the query string and optional parameters + /// a object with the results + /// + Task SearchAsync(string indexName, Query q); + + /// + /// Perform spelling correction on a query, returning suggestions for misspelled terms. + /// + /// is index with the indexed terms. + /// is search query. + /// Optional Spellcheck Parameters + /// An array reply, in which each element represents a misspelled term from the query. + /// + /// + Task>> SpellCheckAsync(string indexName, string query, FTSpellCheckParams? spellCheckParams = null); + + /// + /// Add a suggestion string to an auto-complete suggestion dictionary + /// + /// is suggestion dictionary key. + /// is suggestion string to index. + /// is floating point number of the suggestion string's weight. + /// increments the existing entry of the suggestion by the given score, + /// instead of replacing the score. + /// saves an extra payload with the suggestion, that can be fetched by adding the WITHPAYLOADS argument to FT.SUGGET. + /// The current size of the suggestion dictionary. + /// + Task SugAddAsync(string key, string str, double score, bool increment = false, string? payload = null); + + /// + /// Delete a string from a suggestion index. + /// + /// is suggestion dictionary key. + /// is suggestion string to index. + /// if the string was found and deleted, otherwise. + /// + Task SugDelAsync(string key, string str); + + /// + /// Get completion suggestions for a prefix. + /// + /// is suggestion dictionary key. + /// is prefix to complete on. + /// performs a fuzzy prefix search, + /// including prefixes at Levenshtein distance of 1 from the prefix sent. + /// returns optional payloads saved along with the suggestions. + /// limits the results to a maximum of num (default: 5). + /// List of the top suggestions matching the prefix. + /// + Task> SugGetAsync(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null); + + /// + /// Get completion suggestions for a prefix with the score of each suggestion. + /// + /// is suggestion dictionary key. + /// is prefix to complete on. + /// performs a fuzzy prefix search, + /// including prefixes at Levenshtein distance of 1 from the prefix sent. + /// returns optional payloads saved along with the suggestions. + /// limits the results to a maximum of num (default: 5). + /// List of the top suggestions matching the prefix. + /// + Task>> SugGetWithScoresAsync(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null); + + /// + /// Get the size of an auto-complete suggestion dictionary. + /// + /// is suggestion dictionary key. + /// The current size of the suggestion dictionary. + /// + Task SugLenAsync(string key); + + /// + /// Dump the contents of a synonym group. + /// + /// The index name + /// Pairs of term and an array of synonym groups. + /// + Task>> SynDumpAsync(string indexName); + + /// + /// Update a synonym group. + /// + /// The index name + /// Is synonym group to return + /// does not scan and index, and only documents + /// that are indexed after the update are affected + /// The terms + /// Pairs of term and an array of synonym groups. + /// + Task SynUpdateAsync(string indexName, string synonymGroupId, bool skipInitialScan = false, params string[] terms); + + /// + /// Return a distinct set of values indexed in a Tag field. + /// + /// The index name + /// TAG field name + /// List of TAG field values + /// + Task TagValsAsync(string indexName, string fieldName); } \ No newline at end of file diff --git a/src/NRedisStack/Search/Limit.cs b/src/NRedisStack/Search/Limit.cs index e3e9e917..b5302599 100644 --- a/src/NRedisStack/Search/Limit.cs +++ b/src/NRedisStack/Search/Limit.cs @@ -1,31 +1,30 @@ -namespace NRedisStack.Search.Aggregation +namespace NRedisStack.Search.Aggregation; + +internal readonly struct Limit { - internal readonly struct Limit - { - public static Limit NO_LIMIT = new Limit(0, 0); - private readonly int _offset, _count; + public static Limit NO_LIMIT = new(0, 0); + private readonly int _offset, _count; - public Limit(int offset, int count) - { - _offset = offset; - _count = count; - } + public Limit(int offset, int count) + { + _offset = offset; + _count = count; + } - // public void addArgs(List args) { - // if (count == 0) { - // return; - // } - // args.add("LIMIT"); - // args.add(Integer.toString(offset)); - // args.add(Integer.toString(count)); - // } + // public void addArgs(List args) { + // if (count == 0) { + // return; + // } + // args.add("LIMIT"); + // args.add(Integer.toString(offset)); + // args.add(Integer.toString(count)); + // } - internal void SerializeRedisArgs(List args) - { - if (_count == 0) return; - args.Add("LIMIT"); - args.Add(_offset); - args.Add(_count); - } + internal void SerializeRedisArgs(List args) + { + if (_count == 0) return; + args.Add("LIMIT"); + args.Add(_offset); + args.Add(_count); } -} +} \ No newline at end of file diff --git a/src/NRedisStack/Search/Literals/Enums/IndexDataType.cs b/src/NRedisStack/Search/Literals/Enums/IndexDataType.cs index 36f1b84d..3187667e 100644 --- a/src/NRedisStack/Search/Literals/Enums/IndexDataType.cs +++ b/src/NRedisStack/Search/Literals/Enums/IndexDataType.cs @@ -1,9 +1,8 @@ -namespace NRedisStack.Search.Literals.Enums +namespace NRedisStack.Search.Literals.Enums; + +public enum IndexDataType { - public enum IndexDataType - { - HASH, - JSON, + HASH, + JSON, - } } \ No newline at end of file diff --git a/src/NRedisStack/Search/ProfilingInformation.cs b/src/NRedisStack/Search/ProfilingInformation.cs index 4ccc1590..a87a7454 100644 --- a/src/NRedisStack/Search/ProfilingInformation.cs +++ b/src/NRedisStack/Search/ProfilingInformation.cs @@ -1,15 +1,13 @@ using StackExchange.Redis; -namespace NRedisStack.Search -{ +namespace NRedisStack.Search; - public class ProfilingInformation +public class ProfilingInformation +{ + public RedisResult Info { get; private set; } + public ProfilingInformation(RedisResult info) { - public RedisResult Info { get; private set; } - public ProfilingInformation(RedisResult info) - { - this.Info = info; - } - + Info = info; } + } \ No newline at end of file diff --git a/src/NRedisStack/Search/Query.cs b/src/NRedisStack/Search/Query.cs index 524a191f..73480d77 100644 --- a/src/NRedisStack/Search/Query.cs +++ b/src/NRedisStack/Search/Query.cs @@ -2,701 +2,700 @@ using NRedisStack.Search.Literals; using StackExchange.Redis; -namespace NRedisStack.Search +namespace NRedisStack.Search; + +/// +/// Query represents query parameters and filters to load results from the engine +/// +public sealed class Query : IDialectAwareParam { /// - /// Query represents query parameters and filters to load results from the engine + /// Filter represents a filtering rules in a query /// - public sealed class Query : IDialectAwareParam + public abstract class Filter { - /// - /// Filter represents a filtering rules in a query - /// - public abstract class Filter - { - public string Property { get; } + public string Property { get; } - internal abstract void SerializeRedisArgs(List args); + internal abstract void SerializeRedisArgs(List args); - internal Filter(string property) - { - Property = property; - } + internal Filter(string property) + { + Property = property; } + } - /// - /// NumericFilter wraps a range filter on a numeric field. It can be inclusive or exclusive - /// - public class NumericFilter : Filter - { - private readonly double min, max; - private readonly bool exclusiveMin, exclusiveMax; + /// + /// NumericFilter wraps a range filter on a numeric field. It can be inclusive or exclusive + /// + public class NumericFilter : Filter + { + private readonly double min, max; + private readonly bool exclusiveMin, exclusiveMax; - public NumericFilter(string property, double min, bool exclusiveMin, double max, bool exclusiveMax) : base(property) - { - this.min = min; - this.max = max; - this.exclusiveMax = exclusiveMax; - this.exclusiveMin = exclusiveMin; - } + public NumericFilter(string property, double min, bool exclusiveMin, double max, bool exclusiveMax) : base(property) + { + this.min = min; + this.max = max; + this.exclusiveMax = exclusiveMax; + this.exclusiveMin = exclusiveMin; + } - public NumericFilter(string property, double min, double max) : this(property, min, false, max, false) { } + public NumericFilter(string property, double min, double max) : this(property, min, false, max, false) { } - internal override void SerializeRedisArgs(List args) + internal override void SerializeRedisArgs(List args) + { + static RedisValue FormatNum(double num, bool exclude) { - static RedisValue FormatNum(double num, bool exclude) + if (!exclude || double.IsInfinity(num)) { - if (!exclude || double.IsInfinity(num)) - { - return (RedisValue)num; // can use directly - } - // need to add leading bracket - return "(" + num.ToString("G17", NumberFormatInfo.InvariantInfo); + return (RedisValue)num; // can use directly } - args.Add(SearchArgs.FILTER); - args.Add(Property); - args.Add(FormatNum(min, exclusiveMin)); - args.Add(FormatNum(max, exclusiveMax)); + // need to add leading bracket + return "(" + num.ToString("G17", NumberFormatInfo.InvariantInfo); } + args.Add(SearchArgs.FILTER); + args.Add(Property); + args.Add(FormatNum(min, exclusiveMin)); + args.Add(FormatNum(max, exclusiveMax)); } + } - /// - /// GeoFilter encapsulates a radius filter on a geographical indexed fields - /// - public class GeoFilter : Filter - { - public static readonly string KILOMETERS = "km"; - public static readonly string METERS = "m"; - public static readonly string FEET = "ft"; - public static readonly string MILES = "mi"; - private readonly double lon, lat, radius; - private readonly string unit; // TODO: think about implementing this as an enum - - public GeoFilter(string property, double lon, double lat, double radius, string unit) : base(property) - { - this.lon = lon; - this.lat = lat; - this.radius = radius; - this.unit = unit; - } + /// + /// GeoFilter encapsulates a radius filter on a geographical indexed fields + /// + public class GeoFilter : Filter + { + public static readonly string KILOMETERS = "km"; + public static readonly string METERS = "m"; + public static readonly string FEET = "ft"; + public static readonly string MILES = "mi"; + private readonly double lon, lat, radius; + private readonly string unit; // TODO: think about implementing this as an enum - internal override void SerializeRedisArgs(List args) - { - args.Add("GEOFILTER"); - args.Add(Property); - args.Add(lon); - args.Add(lat); - args.Add(radius); - args.Add(unit); - } + public GeoFilter(string property, double lon, double lat, double radius, string unit) : base(property) + { + this.lon = lon; + this.lat = lat; + this.radius = radius; + this.unit = unit; } - internal readonly struct Paging + internal override void SerializeRedisArgs(List args) { - public int Offset { get; } - public int Count { get; } + args.Add("GEOFILTER"); + args.Add(Property); + args.Add(lon); + args.Add(lat); + args.Add(radius); + args.Add(unit); + } + } - public Paging(int offset, int count) - { - Offset = offset; - Count = count; - } + internal readonly struct Paging + { + public int Offset { get; } + public int Count { get; } + + public Paging(int offset, int count) + { + Offset = offset; + Count = count; } + } - public readonly struct HighlightTags + public readonly struct HighlightTags + { + public HighlightTags(string open, string close) { - public HighlightTags(string open, string close) - { - Open = open; - Close = close; - } - public string Open { get; } - public string Close { get; } - } - - /// - /// The query's filter list. We only support AND operation on all those filters - /// - internal readonly List _filters = new List(); - - /// - /// The textual part of the query - /// - public string QueryString { get; } - - /// - /// The sorting parameters - /// - internal Paging _paging = new Paging(0, 10); - - /// - /// Set the query to verbatim mode, disabling stemming and query expansion - /// - public bool Verbatim { get; set; } - /// - /// Set the query not to return the contents of documents, and rather just return the ids - /// - public bool NoContent { get; set; } - /// - /// Set the query not to filter for stopwords. In general this should not be used - /// - public bool NoStopwords { get; set; } - /// - /// Set the query to return a factored score for each results. This is useful to merge results from multiple queries. - /// - public bool WithScores { get; set; } - /// - /// Set the query to return object payloads, if any were given - /// - public bool WithPayloads { get; set; } - - /// - /// Set the query language, for stemming purposes; see http://redisearch.io for documentation on languages and stemming - /// - public string? Language { get; set; } - - internal string[]? _fields; - internal string[]? _keys; - internal string[]? _returnFields; - internal FieldName[]? _returnFieldsNames; - internal string[]? _highlightFields; - internal string[]? _summarizeFields; - internal HighlightTags? _highlightTags; - internal string? _summarizeSeparator; - internal int _summarizeNumFragments = -1, _summarizeFragmentLen = -1; - - /// - /// Set the query payload to be evaluated by the scoring function - /// - public string? Payload { get; set; } // TODO: should this be a byte[]? - - // TODO: Check if I need to add here WITHSORTKEYS - - /// - /// Set the query parameter to sort by - /// - public string? SortBy { get; set; } - - /// - /// Set the query parameter to sort by ASC by default - /// - public bool? SortAscending { get; set; } = null; - - // highlight and summarize - internal bool _wantsHighlight = false, _wantsSummarize = false; - - /// - /// Set the query scoring. see https://oss.redislabs.com/redisearch/Scoring.html for documentation - /// - public string? Scorer { get; set; } - // public bool ExplainScore { get; set; } // TODO: Check if this is needed because Jedis doesn't have it - - private Dictionary _params = new Dictionary(); - public int? dialect { get; private set; } = null; - private int _slop = -1; - private long _timeout = -1; - private bool _inOrder = false; - private string? _expander = null; - - public Query() : this("*") { } - - /// - /// Create a new index - /// - /// The query string to use for this query. - public Query(string queryString) - { - QueryString = queryString; - } - - internal void SerializeRedisArgs(List args) - { - args.Add(QueryString); - - if (Verbatim) - { - args.Add(SearchArgs.VERBATIM); - } - if (NoContent) - { - args.Add(SearchArgs.NOCONTENT); - } - if (NoStopwords) - { - args.Add(SearchArgs.NOSTOPWORDS); - } - if (WithScores) - { - args.Add(SearchArgs.WITHSCORES); - // if (ExplainScore) - // { - // args.Add("EXPLAINSCORE"); // TODO: Check Why Jedis doesn't have it - // } - } - if (WithPayloads) - { - args.Add(SearchArgs.WITHPAYLOADS); - } - if (Language != null) - { - args.Add(SearchArgs.LANGUAGE); - args.Add(Language); - } + Open = open; + Close = close; + } + public string Open { get; } + public string Close { get; } + } - if (Scorer != null) - { - args.Add(SearchArgs.SCORER); - args.Add(Scorer); - } + /// + /// The query's filter list. We only support AND operation on all those filters + /// + internal readonly List _filters = []; - if (_fields?.Length > 0) - { - args.Add(SearchArgs.INFIELDS); - args.Add(_fields.Length); - args.AddRange(_fields); - } + /// + /// The textual part of the query + /// + public string QueryString { get; } - if (SortBy != null) - { - args.Add(SearchArgs.SORTBY); - args.Add(SortBy); - if (SortAscending != null) - args.Add(((bool)SortAscending ? SearchArgs.ASC : SearchArgs.DESC)); - } - if (Payload != null) - { - args.Add(SearchArgs.PAYLOAD); - args.Add(Payload); - } + /// + /// The sorting parameters + /// + internal Paging _paging = new(0, 10); - if (_paging.Offset != 0 || _paging.Count != 10) - { - args.Add(SearchArgs.LIMIT); - args.Add(_paging.Offset); - args.Add(_paging.Count); - } + /// + /// Set the query to verbatim mode, disabling stemming and query expansion + /// + public bool Verbatim { get; set; } + /// + /// Set the query not to return the contents of documents, and rather just return the ids + /// + public bool NoContent { get; set; } + /// + /// Set the query not to filter for stopwords. In general this should not be used + /// + public bool NoStopwords { get; set; } + /// + /// Set the query to return a factored score for each results. This is useful to merge results from multiple queries. + /// + public bool WithScores { get; set; } + /// + /// Set the query to return object payloads, if any were given + /// + public bool WithPayloads { get; set; } - if (_filters?.Count > 0) - { - foreach (var f in _filters) - { - f.SerializeRedisArgs(args); - } - } + /// + /// Set the query language, for stemming purposes; see http://redisearch.io for documentation on languages and stemming + /// + public string? Language { get; set; } + + internal string[]? _fields; + internal string[]? _keys; + internal string[]? _returnFields; + internal FieldName[]? _returnFieldsNames; + internal string[]? _highlightFields; + internal string[]? _summarizeFields; + internal HighlightTags? _highlightTags; + internal string? _summarizeSeparator; + internal int _summarizeNumFragments = -1, _summarizeFragmentLen = -1; - if (_wantsHighlight) - { - args.Add(SearchArgs.HIGHLIGHT); - if (_highlightFields != null) - { - args.Add(SearchArgs.FIELDS); - args.Add(_highlightFields.Length); - foreach (var s in _highlightFields) - { - args.Add(s); - } - } - if (_highlightTags != null) - { - args.Add(SearchArgs.TAGS); - var tags = _highlightTags.GetValueOrDefault(); - args.Add(tags.Open); - args.Add(tags.Close); - } - } - if (_wantsSummarize) - { - args.Add(SearchArgs.SUMMARIZE); - if (_summarizeFields != null) - { - args.Add(SearchArgs.FIELDS); - args.Add(_summarizeFields.Length); - foreach (var s in _summarizeFields) - { - args.Add(s); - } - } - if (_summarizeNumFragments != -1) - { - args.Add(SearchArgs.FRAGS); - args.Add(_summarizeNumFragments); - } - if (_summarizeFragmentLen != -1) - { - args.Add(SearchArgs.LEN); - args.Add(_summarizeFragmentLen); - } - if (_summarizeSeparator != null) - { - args.Add(SearchArgs.SEPARATOR); - args.Add(_summarizeSeparator); - } - } + /// + /// Set the query payload to be evaluated by the scoring function + /// + public string? Payload { get; set; } // TODO: should this be a byte[]? - if (_keys != null && _keys.Length > 0) - { - args.Add(SearchArgs.INKEYS); - args.Add(_keys.Length); + // TODO: Check if I need to add here WITHSORTKEYS - foreach (var key in _keys) - { - args.Add(key); - } - } + /// + /// Set the query parameter to sort by + /// + public string? SortBy { get; set; } - if (_returnFields?.Length > 0) - { - args.Add(SearchArgs.RETURN); - args.Add(_returnFields.Length); - args.AddRange(_returnFields); - } + /// + /// Set the query parameter to sort by ASC by default + /// + public bool? SortAscending { get; set; } = null; - else if (_returnFieldsNames?.Length > 0) - { - args.Add(SearchArgs.RETURN); - int returnCountIndex = args.Count; - int returnCount = 0; - foreach (FieldName fn in _returnFieldsNames) - { - returnCount += fn.AddCommandArguments(args); - } + // highlight and summarize + internal bool _wantsHighlight = false, _wantsSummarize = false; - args.Insert(returnCountIndex, returnCount); - } - if (_params != null && _params.Count > 0) - { - args.Add(SearchArgs.PARAMS); - args.Add(_params.Count * 2); - foreach (var entry in _params) - { - args.Add(entry.Key); - args.Add(entry.Value); - } - } + /// + /// Set the query scoring. see https://oss.redislabs.com/redisearch/Scoring.html for documentation + /// + public string? Scorer { get; set; } + // public bool ExplainScore { get; set; } // TODO: Check if this is needed because Jedis doesn't have it - if (dialect >= 1) - { - args.Add(SearchArgs.DIALECT); - args.Add(dialect); - } + private readonly Dictionary _params = new(); + public int? dialect { get; private set; } = null; + private int _slop = -1; + private long _timeout = -1; + private bool _inOrder = false; + private string? _expander = null; - if (_slop >= 0) - { - args.Add(SearchArgs.SLOP); - args.Add(_slop); - } + public Query() : this("*") { } - if (_timeout >= 0) - { - args.Add(SearchArgs.TIMEOUT); - args.Add(_timeout); - } + /// + /// Create a new index + /// + /// The query string to use for this query. + public Query(string queryString) + { + QueryString = queryString; + } - if (_inOrder) - { - args.Add(SearchArgs.INORDER); - } + internal void SerializeRedisArgs(List args) + { + args.Add(QueryString); - if (_expander != null) - { - args.Add(SearchArgs.EXPANDER); - args.Add(_expander); - } + if (Verbatim) + { + args.Add(SearchArgs.VERBATIM); } - - // TODO: check if DelayedRawable is needed here (Jedis have it) - - /// - /// Limit the results to a certain offset and limit - /// - /// the first result to show, zero based indexing - /// how many results we want to show - /// the query itself, for builder-style syntax - public Query Limit(int offset, int count) + if (NoContent) { - _paging = new Paging(offset, count); - return this; + args.Add(SearchArgs.NOCONTENT); } - - /// - /// Add a filter to the query's filter list - /// - /// either a numeric or geo filter object - /// the query itself - public Query AddFilter(Filter f) + if (NoStopwords) { - _filters.Add(f); - return this; + args.Add(SearchArgs.NOSTOPWORDS); } - - /// - /// Set the query payload to be evaluated by the scoring function - /// - /// the payload - /// the query itself - public Query SetPayload(string payload) + if (WithScores) { - Payload = payload; - return this; + args.Add(SearchArgs.WITHSCORES); + // if (ExplainScore) + // { + // args.Add("EXPLAINSCORE"); // TODO: Check Why Jedis doesn't have it + // } } - - /// - /// Set the query to verbatim mode, disabling stemming and query expansion - /// - /// the query itself - public Query SetVerbatim(bool value = true) + if (WithPayloads) { - Verbatim = value; - return this; + args.Add(SearchArgs.WITHPAYLOADS); } - - /// - /// Set the query not to return the contents of documents, and rather just return the ids - /// - /// the query itself - public Query SetNoContent(bool value = true) + if (Language != null) { - NoContent = value; - return this; + args.Add(SearchArgs.LANGUAGE); + args.Add(Language); } - /// - /// Set the query not to filter for stopwords. In general this should not be used - /// - /// the query itself - public Query SetNoStopwords(bool value = true) + if (Scorer != null) { - NoStopwords = value; - return this; + args.Add(SearchArgs.SCORER); + args.Add(Scorer); } - /// - /// Set the query to return a factored score for each results. This is useful to merge results from - /// multiple queries. - /// - /// the query itself - public Query SetWithScores(bool value = true) + if (_fields?.Length > 0) { - WithScores = value; - return this; + args.Add(SearchArgs.INFIELDS); + args.Add(_fields.Length); + args.AddRange(_fields); } - /// - /// Set the query to return object payloads, if any were given - /// - /// the query itself - public Query SetWithPayloads() + if (SortBy != null) { - WithPayloads = true; - return this; + args.Add(SearchArgs.SORTBY); + args.Add(SortBy); + if (SortAscending != null) + args.Add(((bool)SortAscending ? SearchArgs.ASC : SearchArgs.DESC)); } - - /// - /// Set the query language, for stemming purposes - /// - /// the language - /// the query itself - public Query SetLanguage(string language) + if (Payload != null) { - Language = language; - return this; + args.Add(SearchArgs.PAYLOAD); + args.Add(Payload); } - /// - /// Set the query language, for stemming purposes - /// - /// - /// - public Query SetScorer(string scorer) + if (_paging.Offset != 0 || _paging.Count != 10) { - Scorer = scorer; - return this; + args.Add(SearchArgs.LIMIT); + args.Add(_paging.Offset); + args.Add(_paging.Count); } - // TODO: check if this is needed (Jedis doesn't have it) - // /// - // /// returns a textual description of how the scores were calculated. - // /// Using this options requires the WITHSCORES option. - // /// - // /// - // /// - // public Query SetExplainScore(bool explainScore = true) - // { - // ExplainScore = explainScore; - // return this; - // } - - /// - /// Limit the query to results that are limited to a specific set of fields - /// - /// a list of TEXT fields in the schemas - /// the query object itself - public Query LimitFields(params string[] fields) + if (_filters?.Count > 0) { - _fields = fields; - return this; + foreach (var f in _filters) + { + f.SerializeRedisArgs(args); + } } - /// - /// Limit the query to results that are limited to a specific set of keys - /// - /// a list of the TEXT fields in the schemas - /// the query object itself - public Query LimitKeys(params string[] keys) + if (_wantsHighlight) + { + args.Add(SearchArgs.HIGHLIGHT); + if (_highlightFields != null) + { + args.Add(SearchArgs.FIELDS); + args.Add(_highlightFields.Length); + foreach (var s in _highlightFields) + { + args.Add(s); + } + } + if (_highlightTags != null) + { + args.Add(SearchArgs.TAGS); + var tags = _highlightTags.GetValueOrDefault(); + args.Add(tags.Open); + args.Add(tags.Close); + } + } + if (_wantsSummarize) { - _keys = keys; - return this; + args.Add(SearchArgs.SUMMARIZE); + if (_summarizeFields != null) + { + args.Add(SearchArgs.FIELDS); + args.Add(_summarizeFields.Length); + foreach (var s in _summarizeFields) + { + args.Add(s); + } + } + if (_summarizeNumFragments != -1) + { + args.Add(SearchArgs.FRAGS); + args.Add(_summarizeNumFragments); + } + if (_summarizeFragmentLen != -1) + { + args.Add(SearchArgs.LEN); + args.Add(_summarizeFragmentLen); + } + if (_summarizeSeparator != null) + { + args.Add(SearchArgs.SEPARATOR); + args.Add(_summarizeSeparator); + } } - /// - /// Result's projection - the fields to return by the query - /// - /// fields a list of TEXT fields in the schemas - /// the query object itself - public Query ReturnFields(params string[] fields) + if (_keys != null && _keys.Length > 0) { - _returnFields = fields; - _returnFieldsNames = null; - return this; + args.Add(SearchArgs.INKEYS); + args.Add(_keys.Length); + + foreach (var key in _keys) + { + args.Add(key); + } } - /// - /// Result's projection - the fields to return by the query - /// - /// field a list of TEXT fields in the schemas - /// the query object itself - public Query ReturnFields(params FieldName[] fields) + if (_returnFields?.Length > 0) { - _returnFields = null; - _returnFieldsNames = fields; - return this; + args.Add(SearchArgs.RETURN); + args.Add(_returnFields.Length); + args.AddRange(_returnFields); } - public Query HighlightFields(HighlightTags tags, params string[] fields) => HighlightFieldsImpl(tags, fields); - public Query HighlightFields(params string[] fields) => HighlightFieldsImpl(null, fields); - private Query HighlightFieldsImpl(HighlightTags? tags, string[] fields) + else if (_returnFieldsNames?.Length > 0) { - if (fields == null || fields.Length > 0) + args.Add(SearchArgs.RETURN); + int returnCountIndex = args.Count; + int returnCount = 0; + foreach (FieldName fn in _returnFieldsNames) { - _highlightFields = fields; + returnCount += fn.AddCommandArguments(args); } - _highlightTags = tags; - _wantsHighlight = true; - return this; - } - public Query SummarizeFields(int contextLen, int fragmentCount, string? separator, params string[] fields) + args.Insert(returnCountIndex, returnCount); + } + if (_params != null && _params.Count > 0) { - if (fields == null || fields.Length > 0) + args.Add(SearchArgs.PARAMS); + args.Add(_params.Count * 2); + foreach (var entry in _params) { - _summarizeFields = fields; + args.Add(entry.Key); + args.Add(entry.Value); } - _summarizeFragmentLen = contextLen; - _summarizeNumFragments = fragmentCount; - _summarizeSeparator = separator; - _wantsSummarize = true; - return this; } - public Query SummarizeFields(params string[] fields) => SummarizeFields(-1, -1, null, fields); - - /// - /// Set the query to be sorted by a sortable field defined in the schema - /// - /// the sorting field's name - /// if set to true, the sorting order is ascending, else descending - /// the query object itself - public Query SetSortBy(string field, bool? ascending = null) + if (dialect >= 1) { - SortBy = field; - SortAscending = ascending; - return this; + args.Add(SearchArgs.DIALECT); + args.Add(dialect); } - /// - /// Parameters can be referenced in the query string by a $ , followed by the parameter name, - /// e.g., $user , and each such reference in the search query to a parameter name is substituted - /// by the corresponding parameter value. - /// Note: when calling this function with an externally supplied parameter, value should be a string. - /// - /// - /// can be String, long or float - /// The query object itself - public Query AddParam(string name, object value) + if (_slop >= 0) { - _params.Add(name, value); - return this; + args.Add(SearchArgs.SLOP); + args.Add(_slop); } - public Query Params(Dictionary nameValue) + if (_timeout >= 0) { - foreach (var entry in nameValue) - { - _params.Add(entry.Key, entry.Value); - } - return this; + args.Add(SearchArgs.TIMEOUT); + args.Add(_timeout); } - /// - /// Set the dialect version to execute the query accordingly - /// - /// - /// the query object itself - public Query Dialect(int dialect) + if (_inOrder) { - this.dialect = dialect; - return this; + args.Add(SearchArgs.INORDER); } - /// - /// Set the slop to execute the query accordingly - /// - /// - /// the query object itself - public Query Slop(int slop) + if (_expander != null) { - _slop = slop; - return this; + args.Add(SearchArgs.EXPANDER); + args.Add(_expander); } + } - /// - /// Set the timeout to execute the query accordingly - /// - /// - /// the query object itself - public Query Timeout(long timeout) + // TODO: check if DelayedRawable is needed here (Jedis have it) + + /// + /// Limit the results to a certain offset and limit + /// + /// the first result to show, zero based indexing + /// how many results we want to show + /// the query itself, for builder-style syntax + public Query Limit(int offset, int count) + { + _paging = new(offset, count); + return this; + } + + /// + /// Add a filter to the query's filter list + /// + /// either a numeric or geo filter object + /// the query itself + public Query AddFilter(Filter f) + { + _filters.Add(f); + return this; + } + + /// + /// Set the query payload to be evaluated by the scoring function + /// + /// the payload + /// the query itself + public Query SetPayload(string payload) + { + Payload = payload; + return this; + } + + /// + /// Set the query to verbatim mode, disabling stemming and query expansion + /// + /// the query itself + public Query SetVerbatim(bool value = true) + { + Verbatim = value; + return this; + } + + /// + /// Set the query not to return the contents of documents, and rather just return the ids + /// + /// the query itself + public Query SetNoContent(bool value = true) + { + NoContent = value; + return this; + } + + /// + /// Set the query not to filter for stopwords. In general this should not be used + /// + /// the query itself + public Query SetNoStopwords(bool value = true) + { + NoStopwords = value; + return this; + } + + /// + /// Set the query to return a factored score for each results. This is useful to merge results from + /// multiple queries. + /// + /// the query itself + public Query SetWithScores(bool value = true) + { + WithScores = value; + return this; + } + + /// + /// Set the query to return object payloads, if any were given + /// + /// the query itself + public Query SetWithPayloads() + { + WithPayloads = true; + return this; + } + + /// + /// Set the query language, for stemming purposes + /// + /// the language + /// the query itself + public Query SetLanguage(string language) + { + Language = language; + return this; + } + + /// + /// Set the query language, for stemming purposes + /// + /// + /// + public Query SetScorer(string scorer) + { + Scorer = scorer; + return this; + } + + // TODO: check if this is needed (Jedis doesn't have it) + // /// + // /// returns a textual description of how the scores were calculated. + // /// Using this options requires the WITHSCORES option. + // /// + // /// + // /// + // public Query SetExplainScore(bool explainScore = true) + // { + // ExplainScore = explainScore; + // return this; + // } + + /// + /// Limit the query to results that are limited to a specific set of fields + /// + /// a list of TEXT fields in the schemas + /// the query object itself + public Query LimitFields(params string[] fields) + { + _fields = fields; + return this; + } + + /// + /// Limit the query to results that are limited to a specific set of keys + /// + /// a list of the TEXT fields in the schemas + /// the query object itself + public Query LimitKeys(params string[] keys) + { + _keys = keys; + return this; + } + + /// + /// Result's projection - the fields to return by the query + /// + /// fields a list of TEXT fields in the schemas + /// the query object itself + public Query ReturnFields(params string[] fields) + { + _returnFields = fields; + _returnFieldsNames = null; + return this; + } + + /// + /// Result's projection - the fields to return by the query + /// + /// field a list of TEXT fields in the schemas + /// the query object itself + public Query ReturnFields(params FieldName[] fields) + { + _returnFields = null; + _returnFieldsNames = fields; + return this; + } + + public Query HighlightFields(HighlightTags tags, params string[] fields) => HighlightFieldsImpl(tags, fields); + public Query HighlightFields(params string[] fields) => HighlightFieldsImpl(null, fields); + private Query HighlightFieldsImpl(HighlightTags? tags, string[] fields) + { + if (fields == null || fields.Length > 0) { - _timeout = timeout; - return this; + _highlightFields = fields; } + _highlightTags = tags; + _wantsHighlight = true; + return this; + } - /// - /// Set the query terms appear in the same order in the document as in the query, regardless of the offsets between them - /// - /// the query object - public Query SetInOrder() + public Query SummarizeFields(int contextLen, int fragmentCount, string? separator, params string[] fields) + { + if (fields == null || fields.Length > 0) { - this._inOrder = true; - return this; + _summarizeFields = fields; } + _summarizeFragmentLen = contextLen; + _summarizeNumFragments = fragmentCount; + _summarizeSeparator = separator; + _wantsSummarize = true; + return this; + } - /// - /// Set the query to use a custom query expander instead of the stemmer - /// - /// - /// the query object itself + public Query SummarizeFields(params string[] fields) => SummarizeFields(-1, -1, null, fields); - public Query SetExpander(String field) - { - _expander = field; - return this; - } + /// + /// Set the query to be sorted by a sortable field defined in the schema + /// + /// the sorting field's name + /// if set to true, the sorting order is ascending, else descending + /// the query object itself + public Query SetSortBy(string field, bool? ascending = null) + { + SortBy = field; + SortAscending = ascending; + return this; + } - int? IDialectAwareParam.Dialect + /// + /// Parameters can be referenced in the query string by a $ , followed by the parameter name, + /// e.g., $user , and each such reference in the search query to a parameter name is substituted + /// by the corresponding parameter value. + /// Note: when calling this function with an externally supplied parameter, value should be a string. + /// + /// + /// can be String, long or float + /// The query object itself + public Query AddParam(string name, object value) + { + _params.Add(name, value); + return this; + } + + public Query Params(Dictionary nameValue) + { + foreach (var entry in nameValue) { - get { return dialect; } - set { dialect = value; } + _params.Add(entry.Key, entry.Value); } + return this; + } + + /// + /// Set the dialect version to execute the query accordingly + /// + /// + /// the query object itself + public Query Dialect(int dialect) + { + this.dialect = dialect; + return this; + } + + /// + /// Set the slop to execute the query accordingly + /// + /// + /// the query object itself + public Query Slop(int slop) + { + _slop = slop; + return this; + } + /// + /// Set the timeout to execute the query accordingly + /// + /// + /// the query object itself + public Query Timeout(long timeout) + { + _timeout = timeout; + return this; + } + + /// + /// Set the query terms appear in the same order in the document as in the query, regardless of the offsets between them + /// + /// the query object + public Query SetInOrder() + { + _inOrder = true; + return this; + } + + /// + /// Set the query to use a custom query expander instead of the stemmer + /// + /// the expander field's name + /// the query object itself + + public Query SetExpander(string field) + { + _expander = field; + return this; } + + int? IDialectAwareParam.Dialect + { + get { return dialect; } + set { dialect = value; } + } + } \ No newline at end of file diff --git a/src/NRedisStack/Search/Reducer.cs b/src/NRedisStack/Search/Reducer.cs index a55fcd5a..c4717b5f 100644 --- a/src/NRedisStack/Search/Reducer.cs +++ b/src/NRedisStack/Search/Reducer.cs @@ -1,47 +1,46 @@ -namespace NRedisStack.Search.Aggregation +namespace NRedisStack.Search.Aggregation; + +public abstract class Reducer { - public abstract class Reducer + // internal Reducer(string field) => _field = field; + + /// + /// The name of the reducer + /// + public abstract string Name { get; } + + public string? Alias { get; set; } + private readonly string? _field; + + + protected Reducer(string? field) + { + _field = field; + Alias = null; + } + + //protected Reducer() : this(field: null) { } + + protected virtual int GetOwnArgsCount() => _field == null ? 0 : 1; + protected virtual void AddOwnArgs(List args) + { + if (_field != null) args.Add(_field); + } + + public Reducer As(string alias) + { + Alias = alias; + return this; + } + + internal void SerializeRedisArgs(List args) { - // internal Reducer(string field) => _field = field; - - /// - /// The name of the reducer - /// - public abstract string Name { get; } - - public string? Alias { get; set; } - private readonly string? _field; - - - protected Reducer(string? field) - { - _field = field; - Alias = null; - } - - //protected Reducer() : this(field: null) { } - - protected virtual int GetOwnArgsCount() => _field == null ? 0 : 1; - protected virtual void AddOwnArgs(List args) - { - if (_field != null) args.Add(_field); - } - - public Reducer As(string alias) - { - Alias = alias; - return this; - } - - internal void SerializeRedisArgs(List args) - { - int count = GetOwnArgsCount(); - args.Add(count); - int before = args.Count; - AddOwnArgs(args); - int after = args.Count; - if (count != (after - before)) - throw new InvalidOperationException($"Reducer '{ToString()}' incorrectly reported the arg-count as {count}, but added {after - before}"); - } + int count = GetOwnArgsCount(); + args.Add(count); + int before = args.Count; + AddOwnArgs(args); + int after = args.Count; + if (count != (after - before)) + throw new InvalidOperationException($"Reducer '{ToString()}' incorrectly reported the arg-count as {count}, but added {after - before}"); } } \ No newline at end of file diff --git a/src/NRedisStack/Search/Reducers.cs b/src/NRedisStack/Search/Reducers.cs index c054388b..df5bf098 100644 --- a/src/NRedisStack/Search/Reducers.cs +++ b/src/NRedisStack/Search/Reducers.cs @@ -1,100 +1,99 @@ -namespace NRedisStack.Search.Aggregation +namespace NRedisStack.Search.Aggregation; + +public static class Reducers { - public static class Reducers + public static Reducer Count() => CountReducer.Instance; + private sealed class CountReducer : Reducer { - public static Reducer Count() => CountReducer.Instance; - private sealed class CountReducer : Reducer - { - internal static readonly Reducer Instance = new CountReducer(); - private CountReducer() : base(null) { } - public override string Name => "COUNT"; - } + internal static readonly Reducer Instance = new CountReducer(); + private CountReducer() : base(null) { } + public override string Name => "COUNT"; + } - private sealed class SingleFieldReducer : Reducer - { - public override string Name { get; } + private sealed class SingleFieldReducer : Reducer + { + public override string Name { get; } - internal SingleFieldReducer(string name, string field) : base(field) - { - Name = name; - } + internal SingleFieldReducer(string name, string field) : base(field) + { + Name = name; } + } - public static Reducer CountDistinct(string field) => new SingleFieldReducer("COUNT_DISTINCT", field); + public static Reducer CountDistinct(string field) => new SingleFieldReducer("COUNT_DISTINCT", field); - public static Reducer CountDistinctish(string field) => new SingleFieldReducer("COUNT_DISTINCTISH", field); + public static Reducer CountDistinctish(string field) => new SingleFieldReducer("COUNT_DISTINCTISH", field); - public static Reducer Sum(string field) => new SingleFieldReducer("SUM", field); + public static Reducer Sum(string field) => new SingleFieldReducer("SUM", field); - public static Reducer Min(string field) => new SingleFieldReducer("MIN", field); + public static Reducer Min(string field) => new SingleFieldReducer("MIN", field); - public static Reducer Max(string field) => new SingleFieldReducer("MAX", field); + public static Reducer Max(string field) => new SingleFieldReducer("MAX", field); - public static Reducer Avg(string field) => new SingleFieldReducer("AVG", field); + public static Reducer Avg(string field) => new SingleFieldReducer("AVG", field); - public static Reducer StdDev(string field) => new SingleFieldReducer("STDDEV", field); + public static Reducer StdDev(string field) => new SingleFieldReducer("STDDEV", field); - public static Reducer Quantile(string field, double percentile) => new QuantileReducer(field, percentile); + public static Reducer Quantile(string field, double percentile) => new QuantileReducer(field, percentile); - private sealed class QuantileReducer : Reducer + private sealed class QuantileReducer : Reducer + { + private readonly double _percentile; + public QuantileReducer(string field, double percentile) : base(field) { - private readonly double _percentile; - public QuantileReducer(string field, double percentile) : base(field) - { - _percentile = percentile; - } - protected override int GetOwnArgsCount() => base.GetOwnArgsCount() + 1; - protected override void AddOwnArgs(List args) - { - base.AddOwnArgs(args); - args.Add(_percentile); - } - public override string Name => "QUANTILE"; + _percentile = percentile; } - public static Reducer FirstValue(string field, SortedField? sortBy) => new FirstValueReducer(field, sortBy); - private sealed class FirstValueReducer : Reducer + protected override int GetOwnArgsCount() => base.GetOwnArgsCount() + 1; + protected override void AddOwnArgs(List args) { - private readonly SortedField? _sortBy; - public FirstValueReducer(string field, SortedField? sortBy) : base(field) - { - _sortBy = sortBy; - } - public override string Name => "FIRST_VALUE"; + base.AddOwnArgs(args); + args.Add(_percentile); + } + public override string Name => "QUANTILE"; + } + public static Reducer FirstValue(string field, SortedField? sortBy) => new FirstValueReducer(field, sortBy); + private sealed class FirstValueReducer : Reducer + { + private readonly SortedField? _sortBy; + public FirstValueReducer(string field, SortedField? sortBy) : base(field) + { + _sortBy = sortBy; + } + public override string Name => "FIRST_VALUE"; - // TODO: Check if needed - // protected override int GetOwnArgsCount() => base.GetOwnArgsCount() + (_sortBy.HasValue ? 3 : 0); - protected override void AddOwnArgs(List args) + // TODO: Check if needed + // protected override int GetOwnArgsCount() => base.GetOwnArgsCount() + (_sortBy.HasValue ? 3 : 0); + protected override void AddOwnArgs(List args) + { + base.AddOwnArgs(args); + if (_sortBy != null) { - base.AddOwnArgs(args); - if (_sortBy != null) - { - var sortBy = _sortBy; - args.Add("BY"); - args.Add(sortBy.FieldName); - args.Add(sortBy.Order.ToString()); - } + var sortBy = _sortBy; + args.Add("BY"); + args.Add(sortBy.FieldName); + args.Add(sortBy.Order.ToString()); } } - public static Reducer FirstValue(string field) => FirstValue(field, null); + } + public static Reducer FirstValue(string field) => FirstValue(field, null); - public static Reducer ToList(string field) => new SingleFieldReducer("TOLIST", field); + public static Reducer ToList(string field) => new SingleFieldReducer("TOLIST", field); - public static Reducer RandomSample(string field, int size) => new RandomSampleReducer(field, size); + public static Reducer RandomSample(string field, int size) => new RandomSampleReducer(field, size); - private sealed class RandomSampleReducer : Reducer + private sealed class RandomSampleReducer : Reducer + { + private readonly int _size; + public RandomSampleReducer(string field, int size) : base(field) { - private readonly int _size; - public RandomSampleReducer(string field, int size) : base(field) - { - _size = size; - } - public override string Name => "RANDOM_SAMPLE"; - protected override int GetOwnArgsCount() => base.GetOwnArgsCount() + 1; - protected override void AddOwnArgs(List args) - { - base.AddOwnArgs(args); - args.Add(_size); - } + _size = size; + } + public override string Name => "RANDOM_SAMPLE"; + protected override int GetOwnArgsCount() => base.GetOwnArgsCount() + 1; + protected override void AddOwnArgs(List args) + { + base.AddOwnArgs(args); + args.Add(_size); } } } \ No newline at end of file diff --git a/src/NRedisStack/Search/Row.cs b/src/NRedisStack/Search/Row.cs index 07153f85..3bbf451d 100644 --- a/src/NRedisStack/Search/Row.cs +++ b/src/NRedisStack/Search/Row.cs @@ -1,22 +1,21 @@ using StackExchange.Redis; -namespace NRedisStack.Search.Aggregation +namespace NRedisStack.Search.Aggregation; + +public readonly struct Row { - public readonly struct Row - { - private readonly Dictionary _fields; + private readonly Dictionary _fields; - internal Row(Dictionary fields) - { - _fields = fields; - } + internal Row(Dictionary fields) + { + _fields = fields; + } - public bool ContainsKey(string key) => _fields.ContainsKey(key); - public RedisValue this[string key] => _fields.TryGetValue(key, out var result) ? (result is RedisValue ? (RedisValue)result : RedisValue.Null) : RedisValue.Null; - public object Get(string key) => _fields.TryGetValue(key, out var result) ? result : RedisValue.Null; + public bool ContainsKey(string key) => _fields.ContainsKey(key); + public RedisValue this[string key] => _fields.TryGetValue(key, out var result) ? (result is RedisValue ? (RedisValue)result : RedisValue.Null) : RedisValue.Null; + public object Get(string key) => _fields.TryGetValue(key, out var result) ? result : RedisValue.Null; - public string? GetString(string key) => _fields.TryGetValue(key, out var result) ? result.ToString() : default; - public long GetLong(string key) => _fields.TryGetValue(key, out var result) ? (long)(RedisValue)result : default; - public double GetDouble(string key) => _fields.TryGetValue(key, out var result) ? (double)(RedisValue)result : default; - } + public string? GetString(string key) => _fields.TryGetValue(key, out var result) ? result.ToString() : default; + public long GetLong(string key) => _fields.TryGetValue(key, out var result) ? (long)(RedisValue)result : default; + public double GetDouble(string key) => _fields.TryGetValue(key, out var result) ? (double)(RedisValue)result : default; } \ No newline at end of file diff --git a/src/NRedisStack/Search/Schema.cs b/src/NRedisStack/Search/Schema.cs index 96bb920b..2c19a673 100644 --- a/src/NRedisStack/Search/Schema.cs +++ b/src/NRedisStack/Search/Schema.cs @@ -2,531 +2,530 @@ using static NRedisStack.Search.Schema.GeoShapeField; using static NRedisStack.Search.Schema.VectorField; -namespace NRedisStack.Search +namespace NRedisStack.Search; + +/// +/// Schema abstracts the schema definition when creating an index. +/// Documents can contain fields not mentioned in the schema, but the index will only index pre-defined fields +/// +public sealed class Schema { - /// - /// Schema abstracts the schema definition when creating an index. - /// Documents can contain fields not mentioned in the schema, but the index will only index pre-defined fields - /// - public sealed class Schema + public enum FieldType { - public enum FieldType - { - Text, - Geo, - GeoShape, - Numeric, - Tag, - Vector - } + Text, + Geo, + GeoShape, + Numeric, + Tag, + Vector + } - public class Field - { - public FieldName FieldName { get; } - public FieldType Type { get; } + public class Field + { + public FieldName FieldName { get; } + public FieldType Type { get; } - internal Field(string name, FieldType type) + internal Field(string name, FieldType type) : this(FieldName.Of(name), type) { } - internal Field(FieldName name, FieldType type) - { - FieldName = name; - Type = type; - } + internal Field(FieldName name, FieldType type) + { + FieldName = name; + Type = type; + } - internal void AddSchemaArgs(List args) + internal void AddSchemaArgs(List args) + { + static object GetForRedis(FieldType type) => type switch { - static object GetForRedis(FieldType type) => type switch - { - FieldType.Text => "TEXT", - FieldType.Geo => "GEO", - FieldType.GeoShape => "GEOSHAPE", - FieldType.Numeric => "NUMERIC", - FieldType.Tag => "TAG", - FieldType.Vector => "VECTOR", - _ => throw new ArgumentOutOfRangeException(nameof(type)), - }; - FieldName.AddCommandArguments(args); - args.Add(GetForRedis(Type)); - AddFieldTypeArgs(args); - } - internal virtual void AddFieldTypeArgs(List args) { } + FieldType.Text => "TEXT", + FieldType.Geo => "GEO", + FieldType.GeoShape => "GEOSHAPE", + FieldType.Numeric => "NUMERIC", + FieldType.Tag => "TAG", + FieldType.Vector => "VECTOR", + _ => throw new ArgumentOutOfRangeException(nameof(type)), + }; + FieldName.AddCommandArguments(args); + args.Add(GetForRedis(Type)); + AddFieldTypeArgs(args); } + internal virtual void AddFieldTypeArgs(List args) { } + } - public class TextField : Field - { - public double Weight { get; } - public bool NoStem { get; } - public string? Phonetic { get; } - public bool Sortable { get; } - public bool Unf { get; } - public bool NoIndex { get; } - public bool WithSuffixTrie { get; } - public bool MissingIndex { get; } - public bool EmptyIndex { get; } - - public TextField(FieldName name, double weight = 1.0, bool noStem = false, - string? phonetic = null, bool sortable = false, bool unf = false, - bool noIndex = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) + public class TextField : Field + { + public double Weight { get; } + public bool NoStem { get; } + public string? Phonetic { get; } + public bool Sortable { get; } + public bool Unf { get; } + public bool NoIndex { get; } + public bool WithSuffixTrie { get; } + public bool MissingIndex { get; } + public bool EmptyIndex { get; } + + public TextField(FieldName name, double weight = 1.0, bool noStem = false, + string? phonetic = null, bool sortable = false, bool unf = false, + bool noIndex = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) : base(name, FieldType.Text) + { + Weight = weight; + NoStem = noStem; + Phonetic = phonetic; + Sortable = sortable; + if (unf && !sortable) { - Weight = weight; - NoStem = noStem; - Phonetic = phonetic; - Sortable = sortable; - if (unf && !sortable) - { - throw new ArgumentException("UNF can't be applied on a non-sortable field."); - } - Unf = unf; - NoIndex = noIndex; - WithSuffixTrie = withSuffixTrie; - MissingIndex = missingIndex; - EmptyIndex = emptyIndex; + throw new ArgumentException("UNF can't be applied on a non-sortable field."); } + Unf = unf; + NoIndex = noIndex; + WithSuffixTrie = withSuffixTrie; + MissingIndex = missingIndex; + EmptyIndex = emptyIndex; + } - public TextField(string name, double weight = 1.0, bool noStem = false, - string? phonetic = null, bool sortable = false, bool unf = false, - bool noIndex = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) + public TextField(string name, double weight = 1.0, bool noStem = false, + string? phonetic = null, bool sortable = false, bool unf = false, + bool noIndex = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) : this(FieldName.Of(name), weight, noStem, phonetic, sortable, unf, noIndex, withSuffixTrie, missingIndex, emptyIndex) { } - internal override void AddFieldTypeArgs(List args) - { - if (NoStem) args.Add(SearchArgs.NOSTEM); - if (NoIndex) args.Add(SearchArgs.NOINDEX); - AddPhonetic(args); - AddWeight(args); - if (WithSuffixTrie) args.Add(SearchArgs.WITHSUFFIXTRIE); - if (Unf) args.Add(SearchArgs.UNF); - if (MissingIndex) args.Add(FieldOptions.INDEXMISSING); - if (EmptyIndex) args.Add(FieldOptions.INDEXEMPTY); - if (Sortable) args.Add(FieldOptions.SORTABLE); - } + internal override void AddFieldTypeArgs(List args) + { + if (NoStem) args.Add(SearchArgs.NOSTEM); + if (NoIndex) args.Add(SearchArgs.NOINDEX); + AddPhonetic(args); + AddWeight(args); + if (WithSuffixTrie) args.Add(SearchArgs.WITHSUFFIXTRIE); + if (Unf) args.Add(SearchArgs.UNF); + if (MissingIndex) args.Add(FieldOptions.INDEXMISSING); + if (EmptyIndex) args.Add(FieldOptions.INDEXEMPTY); + if (Sortable) args.Add(FieldOptions.SORTABLE); + } - private void AddWeight(List args) + private void AddWeight(List args) + { + if (Weight != 1.0) { - if (Weight != 1.0) - { - args.Add(SearchArgs.WEIGHT); - args.Add(Weight); - } + args.Add(SearchArgs.WEIGHT); + args.Add(Weight); } + } - private void AddPhonetic(List args) + private void AddPhonetic(List args) + { + if (Phonetic != null) { - if (Phonetic != null) - { - args.Add(SearchArgs.PHONETIC); - args.Add(this.Phonetic); - } + args.Add(SearchArgs.PHONETIC); + args.Add(Phonetic); } } + } - public class TagField : Field - { - public bool Sortable { get; } - public bool Unf { get; } - public bool NoIndex { get; } - public string Separator { get; } - public bool CaseSensitive { get; } - public bool WithSuffixTrie { get; } - public bool MissingIndex { get; } - public bool EmptyIndex { get; } - - internal TagField(FieldName name, bool sortable = false, bool unf = false, - bool noIndex = false, string separator = ",", - bool caseSensitive = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) + public class TagField : Field + { + public bool Sortable { get; } + public bool Unf { get; } + public bool NoIndex { get; } + public string Separator { get; } + public bool CaseSensitive { get; } + public bool WithSuffixTrie { get; } + public bool MissingIndex { get; } + public bool EmptyIndex { get; } + + internal TagField(FieldName name, bool sortable = false, bool unf = false, + bool noIndex = false, string separator = ",", + bool caseSensitive = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) : base(name, FieldType.Tag) - { - Sortable = sortable; - Unf = unf; - NoIndex = noIndex; - Separator = separator; - CaseSensitive = caseSensitive; - WithSuffixTrie = withSuffixTrie; - EmptyIndex = emptyIndex; - MissingIndex = missingIndex; - } + { + Sortable = sortable; + Unf = unf; + NoIndex = noIndex; + Separator = separator; + CaseSensitive = caseSensitive; + WithSuffixTrie = withSuffixTrie; + EmptyIndex = emptyIndex; + MissingIndex = missingIndex; + } - internal TagField(string name, bool sortable = false, bool unf = false, - bool noIndex = false, string separator = ",", - bool caseSensitive = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) + internal TagField(string name, bool sortable = false, bool unf = false, + bool noIndex = false, string separator = ",", + bool caseSensitive = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) : this(FieldName.Of(name), sortable, unf, noIndex, separator, caseSensitive, withSuffixTrie, missingIndex, emptyIndex) { } - internal override void AddFieldTypeArgs(List args) + internal override void AddFieldTypeArgs(List args) + { + if (NoIndex) args.Add(SearchArgs.NOINDEX); + if (WithSuffixTrie) args.Add(SearchArgs.WITHSUFFIXTRIE); + if (Separator != ",") { - if (NoIndex) args.Add(SearchArgs.NOINDEX); - if (WithSuffixTrie) args.Add(SearchArgs.WITHSUFFIXTRIE); - if (Separator != ",") - { - args.Add(SearchArgs.SEPARATOR); - args.Add(Separator); - } - if (CaseSensitive) args.Add(SearchArgs.CASESENSITIVE); - if (Unf) args.Add(SearchArgs.UNF); - if (MissingIndex) args.Add(FieldOptions.INDEXMISSING); - if (EmptyIndex) args.Add(FieldOptions.INDEXEMPTY); - if (Sortable) args.Add(FieldOptions.SORTABLE); + args.Add(SearchArgs.SEPARATOR); + args.Add(Separator); } + if (CaseSensitive) args.Add(SearchArgs.CASESENSITIVE); + if (Unf) args.Add(SearchArgs.UNF); + if (MissingIndex) args.Add(FieldOptions.INDEXMISSING); + if (EmptyIndex) args.Add(FieldOptions.INDEXEMPTY); + if (Sortable) args.Add(FieldOptions.SORTABLE); } + } - public class GeoField : Field - { - public bool Sortable { get; } - public bool NoIndex { get; } - public bool MissingIndex { get; } + public class GeoField : Field + { + public bool Sortable { get; } + public bool NoIndex { get; } + public bool MissingIndex { get; } - internal GeoField(FieldName name, bool sortable = false, bool noIndex = false, bool missingIndex = false) + internal GeoField(FieldName name, bool sortable = false, bool noIndex = false, bool missingIndex = false) : base(name, FieldType.Geo) - { - Sortable = sortable; - NoIndex = noIndex; - MissingIndex = missingIndex; - } + { + Sortable = sortable; + NoIndex = noIndex; + MissingIndex = missingIndex; + } - internal GeoField(string name, bool sortable = false, bool noIndex = false, bool missingIndex = false) + internal GeoField(string name, bool sortable = false, bool noIndex = false, bool missingIndex = false) : this(FieldName.Of(name), sortable, noIndex, missingIndex) { } - internal override void AddFieldTypeArgs(List args) - { - if (NoIndex) args.Add(SearchArgs.NOINDEX); - if (MissingIndex) args.Add(FieldOptions.INDEXMISSING); - if (Sortable) args.Add(FieldOptions.SORTABLE); - } + internal override void AddFieldTypeArgs(List args) + { + if (NoIndex) args.Add(SearchArgs.NOINDEX); + if (MissingIndex) args.Add(FieldOptions.INDEXMISSING); + if (Sortable) args.Add(FieldOptions.SORTABLE); } + } - public class GeoShapeField : Field + public class GeoShapeField : Field + { + public enum CoordinateSystem { - public enum CoordinateSystem - { - /// - /// For cartesian (X,Y). - /// - FLAT, - - /// - /// For geographic (lon, lat). - /// - SPHERICAL - } - private CoordinateSystem system { get; } - public bool MissingIndex { get; } + /// + /// For cartesian (X,Y). + /// + FLAT, + + /// + /// For geographic (lon, lat). + /// + SPHERICAL + } + private CoordinateSystem system { get; } + public bool MissingIndex { get; } - internal GeoShapeField(FieldName name, CoordinateSystem system, bool missingIndex = false) + internal GeoShapeField(FieldName name, CoordinateSystem system, bool missingIndex = false) : base(name, FieldType.GeoShape) - { - this.system = system; - MissingIndex = missingIndex; - } + { + this.system = system; + MissingIndex = missingIndex; + } - internal GeoShapeField(string name, CoordinateSystem system, bool missingIndex = false) + internal GeoShapeField(string name, CoordinateSystem system, bool missingIndex = false) : this(FieldName.Of(name), system, missingIndex) { } - internal override void AddFieldTypeArgs(List args) - { - args.Add(system.ToString()); - if (MissingIndex) args.Add(FieldOptions.INDEXMISSING); - } + internal override void AddFieldTypeArgs(List args) + { + args.Add(system.ToString()); + if (MissingIndex) args.Add(FieldOptions.INDEXMISSING); } + } - public class NumericField : Field - { - public bool Sortable { get; } - public bool NoIndex { get; } - public bool MissingIndex { get; } + public class NumericField : Field + { + public bool Sortable { get; } + public bool NoIndex { get; } + public bool MissingIndex { get; } - internal NumericField(FieldName name, bool sortable = false, bool noIndex = false, bool missingIndex = false) + internal NumericField(FieldName name, bool sortable = false, bool noIndex = false, bool missingIndex = false) : base(name, FieldType.Numeric) - { - Sortable = sortable; - NoIndex = noIndex; - MissingIndex = missingIndex; - } + { + Sortable = sortable; + NoIndex = noIndex; + MissingIndex = missingIndex; + } - internal NumericField(string name, bool sortable = false, bool noIndex = false, bool missingIndex = false) + internal NumericField(string name, bool sortable = false, bool noIndex = false, bool missingIndex = false) : this(FieldName.Of(name), sortable, noIndex, missingIndex) { } - internal override void AddFieldTypeArgs(List args) - { - if (NoIndex) args.Add(SearchArgs.NOINDEX); - if (MissingIndex) args.Add(FieldOptions.INDEXMISSING); - if (Sortable) args.Add(FieldOptions.SORTABLE); - } + internal override void AddFieldTypeArgs(List args) + { + if (NoIndex) args.Add(SearchArgs.NOINDEX); + if (MissingIndex) args.Add(FieldOptions.INDEXMISSING); + if (Sortable) args.Add(FieldOptions.SORTABLE); } + } - public class VectorField : Field + public class VectorField : Field + { + public enum VectorAlgo { - public enum VectorAlgo - { - FLAT, - HNSW - } + FLAT, + HNSW + } - public VectorAlgo Algorithm { get; } - public Dictionary? Attributes { get; } - public bool MissingIndex { get; } + public VectorAlgo Algorithm { get; } + public Dictionary? Attributes { get; } + public bool MissingIndex { get; } - public VectorField(FieldName name, VectorAlgo algorithm, Dictionary? attributes = null, bool missingIndex = false) - : base(name, FieldType.Vector) - { - Algorithm = algorithm; - Attributes = attributes; - MissingIndex = missingIndex; - } + public VectorField(FieldName name, VectorAlgo algorithm, Dictionary? attributes = null, bool missingIndex = false) + : base(name, FieldType.Vector) + { + Algorithm = algorithm; + Attributes = attributes; + MissingIndex = missingIndex; + } - public VectorField(string name, VectorAlgo algorithm, Dictionary? attributes = null, bool missingIndex = false) - : this(FieldName.Of(name), algorithm, attributes, missingIndex) { } + public VectorField(string name, VectorAlgo algorithm, Dictionary? attributes = null, bool missingIndex = false) + : this(FieldName.Of(name), algorithm, attributes, missingIndex) { } - internal override void AddFieldTypeArgs(List args) + internal override void AddFieldTypeArgs(List args) + { + args.Add(Algorithm.ToString()); + if (Attributes != null) { - args.Add(Algorithm.ToString()); - if (Attributes != null) - { - args.Add(Attributes.Count() * 2); + args.Add(Attributes.Count() * 2); - foreach (var attribute in Attributes) - { - args.Add(attribute.Key); - args.Add(attribute.Value); - } + foreach (var attribute in Attributes) + { + args.Add(attribute.Key); + args.Add(attribute.Value); } - if (MissingIndex) args.Add(FieldOptions.INDEXMISSING); } + if (MissingIndex) args.Add(FieldOptions.INDEXMISSING); } - public List Fields { get; } = new List(); - - /// - /// Add a field to the schema. - /// - /// The to add. - /// The object. - public Schema AddField(Field field) - { - Fields.Add(field ?? throw new ArgumentNullException(nameof(field))); - return this; - } + } + public List Fields { get; } = []; - /// - /// Add a Text field to the schema. - /// - /// The field's name. - /// Its weight, a positive floating point number. - /// If true, the text field can be sorted. - /// Disable stemming when indexing its values. - /// Declaring a text attribute as PHONETIC will perform phonetic matching on it in searches by default. - /// Attributes can have the NOINDEX option, which means they will not be indexed. - /// Set this to true to prevent the indexer from sorting on the normalized form. - /// Normalied form is the field sent to lower case with all diaretics removed - /// Keeps a suffix trie with all terms which match the suffix. - /// search for missing values, that is, documents that do not contain a specific field. - /// Note the difference between a field with an empty value and a document with a missing value. - /// By default, missing values are not indexed. - /// allows you to index and search for empty strings. By default, empty strings are not indexed. - /// The object. - public Schema AddTextField(string name, double weight = 1.0, bool sortable = false, bool unf = false, bool noStem = false, - string? phonetic = null, bool noIndex = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) - { - Fields.Add(new TextField(name, weight, noStem, phonetic, sortable, unf, noIndex, withSuffixTrie, missingIndex, emptyIndex)); - return this; - } + /// + /// Add a field to the schema. + /// + /// The to add. + /// The object. + public Schema AddField(Field field) + { + Fields.Add(field ?? throw new ArgumentNullException(nameof(field))); + return this; + } - /// - /// Add a Text field to the schema. - /// - /// The field's name. - /// Its weight, a positive floating point number. - /// If true, the text field can be sorted. - /// Disable stemming when indexing its values. - /// Declaring a text attribute as PHONETIC will perform phonetic matching on it in searches by default. - /// Attributes can have the NOINDEX option, which means they will not be indexed. - /// Set this to true to prevent the indexer from sorting on the normalized form. - /// Normalied form is the field sent to lower case with all diaretics removed - /// Keeps a suffix trie with all terms which match the suffix. - /// search for missing values, that is, documents that do not contain a specific field. - /// Note the difference between a field with an empty value and a document with a missing value. - /// By default, missing values are not indexed. - /// allows you to index and search for empty strings. By default, empty strings are not indexed. - /// The object. - public Schema AddTextField(FieldName name, double weight = 1.0, bool sortable = false, bool unf = false, bool noStem = false, - string? phonetic = null, bool noIndex = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) - { - Fields.Add(new TextField(name, weight, noStem, phonetic, sortable, unf, noIndex, withSuffixTrie, missingIndex, emptyIndex)); - return this; - } + /// + /// Add a Text field to the schema. + /// + /// The field's name. + /// Its weight, a positive floating point number. + /// If true, the text field can be sorted. + /// Disable stemming when indexing its values. + /// Declaring a text attribute as PHONETIC will perform phonetic matching on it in searches by default. + /// Attributes can have the NOINDEX option, which means they will not be indexed. + /// Set this to true to prevent the indexer from sorting on the normalized form. + /// Normalied form is the field sent to lower case with all diaretics removed + /// Keeps a suffix trie with all terms which match the suffix. + /// search for missing values, that is, documents that do not contain a specific field. + /// Note the difference between a field with an empty value and a document with a missing value. + /// By default, missing values are not indexed. + /// allows you to index and search for empty strings. By default, empty strings are not indexed. + /// The object. + public Schema AddTextField(string name, double weight = 1.0, bool sortable = false, bool unf = false, bool noStem = false, + string? phonetic = null, bool noIndex = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) + { + Fields.Add(new TextField(name, weight, noStem, phonetic, sortable, unf, noIndex, withSuffixTrie, missingIndex, emptyIndex)); + return this; + } - /// - /// Add a GeoShape field to the schema. - /// - /// The field's name. - /// The coordinate system to use. - /// search for missing values, that is, documents that do not contain a specific field. - /// Note the difference between a field with an empty value and a document with a missing value. - /// By default, missing values are not indexed. - /// The object. - public Schema AddGeoShapeField(string name, CoordinateSystem system, bool missingIndex = false) - { - Fields.Add(new GeoShapeField(name, system, missingIndex)); - return this; - } + /// + /// Add a Text field to the schema. + /// + /// The field's name. + /// Its weight, a positive floating point number. + /// If true, the text field can be sorted. + /// Disable stemming when indexing its values. + /// Declaring a text attribute as PHONETIC will perform phonetic matching on it in searches by default. + /// Attributes can have the NOINDEX option, which means they will not be indexed. + /// Set this to true to prevent the indexer from sorting on the normalized form. + /// Normalied form is the field sent to lower case with all diaretics removed + /// Keeps a suffix trie with all terms which match the suffix. + /// search for missing values, that is, documents that do not contain a specific field. + /// Note the difference between a field with an empty value and a document with a missing value. + /// By default, missing values are not indexed. + /// allows you to index and search for empty strings. By default, empty strings are not indexed. + /// The object. + public Schema AddTextField(FieldName name, double weight = 1.0, bool sortable = false, bool unf = false, bool noStem = false, + string? phonetic = null, bool noIndex = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) + { + Fields.Add(new TextField(name, weight, noStem, phonetic, sortable, unf, noIndex, withSuffixTrie, missingIndex, emptyIndex)); + return this; + } - /// - /// Add a GeoShape field to the schema. - /// - /// The field's name. - /// The coordinate system to use. - /// search for missing values, that is, documents that do not contain a specific field. - /// Note the difference between a field with an empty value and a document with a missing value. - /// By default, missing values are not indexed. - /// The object. - public Schema AddGeoShapeField(FieldName name, CoordinateSystem system, bool missingIndex = false) - { - Fields.Add(new GeoShapeField(name, system, missingIndex)); - return this; - } + /// + /// Add a GeoShape field to the schema. + /// + /// The field's name. + /// The coordinate system to use. + /// search for missing values, that is, documents that do not contain a specific field. + /// Note the difference between a field with an empty value and a document with a missing value. + /// By default, missing values are not indexed. + /// The object. + public Schema AddGeoShapeField(string name, CoordinateSystem system, bool missingIndex = false) + { + Fields.Add(new GeoShapeField(name, system, missingIndex)); + return this; + } - /// - /// Add a Geo field to the schema. - /// - /// The field's name. - /// If true, the text field can be sorted. - /// Attributes can have the NOINDEX option, which means they will not be indexed. - /// search for missing values, that is, documents that do not contain a specific field. - /// Note the difference between a field with an empty value and a document with a missing value. - /// By default, missing values are not indexed. - /// The object. - public Schema AddGeoField(FieldName name, bool sortable = false, bool noIndex = false, bool missingIndex = false) - { - Fields.Add(new GeoField(name, sortable, noIndex, missingIndex)); - return this; - } + /// + /// Add a GeoShape field to the schema. + /// + /// The field's name. + /// The coordinate system to use. + /// search for missing values, that is, documents that do not contain a specific field. + /// Note the difference between a field with an empty value and a document with a missing value. + /// By default, missing values are not indexed. + /// The object. + public Schema AddGeoShapeField(FieldName name, CoordinateSystem system, bool missingIndex = false) + { + Fields.Add(new GeoShapeField(name, system, missingIndex)); + return this; + } - /// - /// Add a Geo field to the schema. - /// - /// The field's name. - /// If true, the text field can be sorted. - /// Attributes can have the NOINDEX option, which means they will not be indexed. - /// search for missing values, that is, documents that do not contain a specific field. - /// Note the difference between a field with an empty value and a document with a missing value. - /// By default, missing values are not indexed. - /// The object. - public Schema AddGeoField(string name, bool sortable = false, bool noIndex = false, bool missingIndex = false) - { - Fields.Add(new GeoField(name, sortable, noIndex, missingIndex)); - return this; - } + /// + /// Add a Geo field to the schema. + /// + /// The field's name. + /// If true, the text field can be sorted. + /// Attributes can have the NOINDEX option, which means they will not be indexed. + /// search for missing values, that is, documents that do not contain a specific field. + /// Note the difference between a field with an empty value and a document with a missing value. + /// By default, missing values are not indexed. + /// The object. + public Schema AddGeoField(FieldName name, bool sortable = false, bool noIndex = false, bool missingIndex = false) + { + Fields.Add(new GeoField(name, sortable, noIndex, missingIndex)); + return this; + } - /// - /// Add a Numeric field to the schema. - /// - /// The field's name. - /// If true, the text field can be sorted. - /// Attributes can have the NOINDEX option, which means they will not be indexed. - /// search for missing values, that is, documents that do not contain a specific field. - /// Note the difference between a field with an empty value and a document with a missing value. - /// By default, missing values are not indexed. - /// The object. - public Schema AddNumericField(FieldName name, bool sortable = false, bool noIndex = false, bool missingIndex = false) - { - Fields.Add(new NumericField(name, sortable, noIndex, missingIndex)); - return this; - } + /// + /// Add a Geo field to the schema. + /// + /// The field's name. + /// If true, the text field can be sorted. + /// Attributes can have the NOINDEX option, which means they will not be indexed. + /// search for missing values, that is, documents that do not contain a specific field. + /// Note the difference between a field with an empty value and a document with a missing value. + /// By default, missing values are not indexed. + /// The object. + public Schema AddGeoField(string name, bool sortable = false, bool noIndex = false, bool missingIndex = false) + { + Fields.Add(new GeoField(name, sortable, noIndex, missingIndex)); + return this; + } - /// - /// Add a Numeric field to the schema. - /// - /// The field's name. - /// If true, the text field can be sorted. - /// Attributes can have the NOINDEX option, which means they will not be indexed. - /// search for missing values, that is, documents that do not contain a specific field. - /// Note the difference between a field with an empty value and a document with a missing value. - /// By default, missing values are not indexed. - /// The object. - public Schema AddNumericField(string name, bool sortable = false, bool noIndex = false, bool missingIndex = false) - { - Fields.Add(new NumericField(name, sortable, noIndex, missingIndex)); - return this; - } + /// + /// Add a Numeric field to the schema. + /// + /// The field's name. + /// If true, the text field can be sorted. + /// Attributes can have the NOINDEX option, which means they will not be indexed. + /// search for missing values, that is, documents that do not contain a specific field. + /// Note the difference between a field with an empty value and a document with a missing value. + /// By default, missing values are not indexed. + /// The object. + public Schema AddNumericField(FieldName name, bool sortable = false, bool noIndex = false, bool missingIndex = false) + { + Fields.Add(new NumericField(name, sortable, noIndex, missingIndex)); + return this; + } - /// - /// Add a Tag field to the schema. - /// - /// The field's name. - /// If true, the field can be sorted. - /// Set this to true to prevent the indexer from sorting on the normalized form. - /// Attributes can have the NOINDEX option, which means they will not be indexed. - /// The tag separator. - /// If true, Keeps the original letter cases of the tags. - /// Normalied form is the field sent to lower case with all diaretics removed - /// Keeps a suffix trie with all terms which match the suffix. - /// search for missing values, that is, documents that do not contain a specific field. - /// Note the difference between a field with an empty value and a document with a missing value. - /// By default, missing values are not indexed. - /// allows you to index and search for empty strings. By default, empty strings are not indexed. - /// The object. - public Schema AddTagField(FieldName name, bool sortable = false, bool unf = false, - bool noIndex = false, string separator = ",", - bool caseSensitive = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) - { - Fields.Add(new TagField(name, sortable, unf, noIndex, separator, caseSensitive, withSuffixTrie, missingIndex, emptyIndex)); - return this; - } + /// + /// Add a Numeric field to the schema. + /// + /// The field's name. + /// If true, the text field can be sorted. + /// Attributes can have the NOINDEX option, which means they will not be indexed. + /// search for missing values, that is, documents that do not contain a specific field. + /// Note the difference between a field with an empty value and a document with a missing value. + /// By default, missing values are not indexed. + /// The object. + public Schema AddNumericField(string name, bool sortable = false, bool noIndex = false, bool missingIndex = false) + { + Fields.Add(new NumericField(name, sortable, noIndex, missingIndex)); + return this; + } - /// - /// Add a Tag field to the schema. - /// - /// The field's name. - /// If true, the field can be sorted. - /// Set this to true to prevent the indexer from sorting on the normalized form. - /// Attributes can have the NOINDEX option, which means they will not be indexed. - /// The tag separator. - /// If true, Keeps the original letter cases of the tags. - /// Normalied form is the field sent to lower case with all diaretics removed - /// Keeps a suffix trie with all terms which match the suffix. - /// search for missing values, that is, documents that do not contain a specific field. - /// Note the difference between a field with an empty value and a document with a missing value. - /// By default, missing values are not indexed. - /// allows you to index and search for empty strings. By default, empty strings are not indexed. - /// The object. - public Schema AddTagField(string name, bool sortable = false, bool unf = false, - bool noIndex = false, string separator = ",", - bool caseSensitive = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) - { - Fields.Add(new TagField(name, sortable, unf, noIndex, separator, caseSensitive, withSuffixTrie, missingIndex, emptyIndex)); - return this; - } + /// + /// Add a Tag field to the schema. + /// + /// The field's name. + /// If true, the field can be sorted. + /// Set this to true to prevent the indexer from sorting on the normalized form. + /// Attributes can have the NOINDEX option, which means they will not be indexed. + /// The tag separator. + /// If true, Keeps the original letter cases of the tags. + /// Normalied form is the field sent to lower case with all diaretics removed + /// Keeps a suffix trie with all terms which match the suffix. + /// search for missing values, that is, documents that do not contain a specific field. + /// Note the difference between a field with an empty value and a document with a missing value. + /// By default, missing values are not indexed. + /// allows you to index and search for empty strings. By default, empty strings are not indexed. + /// The object. + public Schema AddTagField(FieldName name, bool sortable = false, bool unf = false, + bool noIndex = false, string separator = ",", + bool caseSensitive = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) + { + Fields.Add(new TagField(name, sortable, unf, noIndex, separator, caseSensitive, withSuffixTrie, missingIndex, emptyIndex)); + return this; + } - /// - /// Add a Vector field to the schema. - /// - /// The field's name. - /// The vector similarity algorithm to use. - /// The algorithm attributes for the creation of the vector index. - /// search for missing values, that is, documents that do not contain a specific field. - /// Note the difference between a field with an empty value and a document with a missing value. - /// By default, missing values are not indexed. - /// The object. - public Schema AddVectorField(FieldName name, VectorAlgo algorithm, Dictionary? attributes = null, bool missingIndex = false) - { - Fields.Add(new VectorField(name, algorithm, attributes, missingIndex)); - return this; - } + /// + /// Add a Tag field to the schema. + /// + /// The field's name. + /// If true, the field can be sorted. + /// Set this to true to prevent the indexer from sorting on the normalized form. + /// Attributes can have the NOINDEX option, which means they will not be indexed. + /// The tag separator. + /// If true, Keeps the original letter cases of the tags. + /// Normalied form is the field sent to lower case with all diaretics removed + /// Keeps a suffix trie with all terms which match the suffix. + /// search for missing values, that is, documents that do not contain a specific field. + /// Note the difference between a field with an empty value and a document with a missing value. + /// By default, missing values are not indexed. + /// allows you to index and search for empty strings. By default, empty strings are not indexed. + /// The object. + public Schema AddTagField(string name, bool sortable = false, bool unf = false, + bool noIndex = false, string separator = ",", + bool caseSensitive = false, bool withSuffixTrie = false, bool missingIndex = false, bool emptyIndex = false) + { + Fields.Add(new TagField(name, sortable, unf, noIndex, separator, caseSensitive, withSuffixTrie, missingIndex, emptyIndex)); + return this; + } - /// - /// Add a Vector field to the schema. - /// - /// The field's name. - /// The vector similarity algorithm to use. - /// The algorithm attributes for the creation of the vector index. - /// search for missing values, that is, documents that do not contain a specific field. - /// Note the difference between a field with an empty value and a document with a missing value. - /// By default, missing values are not indexed. - /// The object. - public Schema AddVectorField(string name, VectorAlgo algorithm, Dictionary? attributes = null, bool missingIndex = false) - { - Fields.Add(new VectorField(name, algorithm, attributes, missingIndex)); - return this; - } + /// + /// Add a Vector field to the schema. + /// + /// The field's name. + /// The vector similarity algorithm to use. + /// The algorithm attributes for the creation of the vector index. + /// search for missing values, that is, documents that do not contain a specific field. + /// Note the difference between a field with an empty value and a document with a missing value. + /// By default, missing values are not indexed. + /// The object. + public Schema AddVectorField(FieldName name, VectorAlgo algorithm, Dictionary? attributes = null, bool missingIndex = false) + { + Fields.Add(new VectorField(name, algorithm, attributes, missingIndex)); + return this; + } + + /// + /// Add a Vector field to the schema. + /// + /// The field's name. + /// The vector similarity algorithm to use. + /// The algorithm attributes for the creation of the vector index. + /// search for missing values, that is, documents that do not contain a specific field. + /// Note the difference between a field with an empty value and a document with a missing value. + /// By default, missing values are not indexed. + /// The object. + public Schema AddVectorField(string name, VectorAlgo algorithm, Dictionary? attributes = null, bool missingIndex = false) + { + Fields.Add(new VectorField(name, algorithm, attributes, missingIndex)); + return this; } -} +} \ No newline at end of file diff --git a/src/NRedisStack/Search/SearchCommandBuilder.cs b/src/NRedisStack/Search/SearchCommandBuilder.cs index 696983ee..b2206a07 100644 --- a/src/NRedisStack/Search/SearchCommandBuilder.cs +++ b/src/NRedisStack/Search/SearchCommandBuilder.cs @@ -1,247 +1,244 @@ using NRedisStack.Search.Literals; using NRedisStack.RedisStackCommands; using NRedisStack.Search; -using NRedisStack.Search.Aggregation; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public static class SearchCommandBuilder { - public static class SearchCommandBuilder + public static SerializedCommand _List() { - public static SerializedCommand _List() - { - return new SerializedCommand(FT._LIST); - } + return new(FT._LIST); + } - public static SerializedCommand Aggregate(string index, AggregationRequest query) - { - List args = new List { index }; - query.SerializeRedisArgs(); - args.AddRange(query.GetArgs()); - return new SerializedCommand(FT.AGGREGATE, args); - } + public static SerializedCommand Aggregate(string index, AggregationRequest query) + { + List args = [index]; + query.SerializeRedisArgs(); + args.AddRange(query.GetArgs()); + return new(FT.AGGREGATE, args); + } - public static SerializedCommand AliasAdd(string alias, string index) - { - return new SerializedCommand(FT.ALIASADD, alias, index); - } + public static SerializedCommand AliasAdd(string alias, string index) + { + return new(FT.ALIASADD, alias, index); + } - public static SerializedCommand AliasDel(string alias) - { - return new SerializedCommand(FT.ALIASDEL, alias); - } + public static SerializedCommand AliasDel(string alias) + { + return new(FT.ALIASDEL, alias); + } - public static SerializedCommand AliasUpdate(string alias, string index) - { - return new SerializedCommand(FT.ALIASUPDATE, alias, index); - } - public static SerializedCommand Alter(string index, Schema schema, bool skipInitialScan = false) + public static SerializedCommand AliasUpdate(string alias, string index) + { + return new(FT.ALIASUPDATE, alias, index); + } + public static SerializedCommand Alter(string index, Schema schema, bool skipInitialScan = false) + { + List args = [index]; + if (skipInitialScan) args.Add("SKIPINITIALSCAN"); + args.Add("SCHEMA"); + args.Add("ADD"); + foreach (var f in schema.Fields) { - List args = new List() { index }; - if (skipInitialScan) args.Add("SKIPINITIALSCAN"); - args.Add("SCHEMA"); - args.Add("ADD"); - foreach (var f in schema.Fields) - { - f.AddSchemaArgs(args); - } - return new SerializedCommand(FT.ALTER, args); + f.AddSchemaArgs(args); } + return new(FT.ALTER, args); + } - [Obsolete("Starting from Redis 8.0, use db.ConfigGet instead")] - public static SerializedCommand ConfigGet(string option) - { - return new SerializedCommand(FT.CONFIG, "GET", option); - } + [Obsolete("Starting from Redis 8.0, use db.ConfigGet instead")] + public static SerializedCommand ConfigGet(string option) + { + return new(FT.CONFIG, "GET", option); + } - [Obsolete("Starting from Redis 8.0, use db.ConfigSet instead")] - public static SerializedCommand ConfigSet(string option, string value) - { - return new SerializedCommand(FT.CONFIG, "SET", option, value); - } + [Obsolete("Starting from Redis 8.0, use db.ConfigSet instead")] + public static SerializedCommand ConfigSet(string option, string value) + { + return new(FT.CONFIG, "SET", option, value); + } - public static SerializedCommand Create(string indexName, FTCreateParams parameters, Schema schema) + public static SerializedCommand Create(string indexName, FTCreateParams parameters, Schema schema) + { + var args = new List() { indexName }; + parameters.AddParams(args); // TODO: Think of a better implementation + + args.Add("SCHEMA"); + + foreach (var f in schema.Fields) { - var args = new List() { indexName }; - parameters.AddParams(args); // TODO: Think of a better implementation + f.AddSchemaArgs(args); + } - args.Add("SCHEMA"); + return new(FT.CREATE, args); + } - foreach (var f in schema.Fields) - { - f.AddSchemaArgs(args); - } + public static SerializedCommand CursorDel(string indexName, long cursorId) + { + return new(FT.CURSOR, "DEL", indexName, cursorId); + } - return new SerializedCommand(FT.CREATE, args); - } + public static SerializedCommand CursorRead(string indexName, long cursorId, int? count = null) + { + return ((count == null) ? new(FT.CURSOR, "READ", indexName, cursorId) + : new SerializedCommand(FT.CURSOR, "READ", indexName, cursorId, "COUNT", count)); + } - public static SerializedCommand CursorDel(string indexName, long cursorId) + public static SerializedCommand DictAdd(string dict, params string[] terms) + { + if (terms.Length < 1) { - return new SerializedCommand(FT.CURSOR, "DEL", indexName, cursorId); + throw new ArgumentOutOfRangeException("At least one term must be provided"); } - public static SerializedCommand CursorRead(string indexName, long cursorId, int? count = null) + var args = new List(terms.Length + 1) { dict }; + foreach (var t in terms) { - return ((count == null) ? new SerializedCommand(FT.CURSOR, "READ", indexName, cursorId) - : new SerializedCommand(FT.CURSOR, "READ", indexName, cursorId, "COUNT", count)); + args.Add(t); } - public static SerializedCommand DictAdd(string dict, params string[] terms) - { - if (terms.Length < 1) - { - throw new ArgumentOutOfRangeException("At least one term must be provided"); - } - - var args = new List(terms.Length + 1) { dict }; - foreach (var t in terms) - { - args.Add(t); - } - - return new SerializedCommand(FT.DICTADD, args); - } + return new(FT.DICTADD, args); + } - public static SerializedCommand DictDel(string dict, params string[] terms) + public static SerializedCommand DictDel(string dict, params string[] terms) + { + if (terms.Length < 1) { - if (terms.Length < 1) - { - throw new ArgumentOutOfRangeException("At least one term must be provided"); - } - - var args = new List(terms.Length + 1) { dict }; - foreach (var t in terms) - { - args.Add(t); - } - - return new SerializedCommand(FT.DICTDEL, args); + throw new ArgumentOutOfRangeException("At least one term must be provided"); } - public static SerializedCommand DictDump(string dict) + var args = new List(terms.Length + 1) { dict }; + foreach (var t in terms) { - return new SerializedCommand(FT.DICTDUMP, dict); + args.Add(t); } - public static SerializedCommand DropIndex(string indexName, bool dd = false) - { - return ((dd) ? new SerializedCommand(FT.DROPINDEX, indexName, "DD") - : new SerializedCommand(FT.DROPINDEX, indexName)); - } + return new(FT.DICTDEL, args); + } - public static SerializedCommand Explain(string indexName, string query, int? dialect) + public static SerializedCommand DictDump(string dict) + { + return new(FT.DICTDUMP, dict); + } + + public static SerializedCommand DropIndex(string indexName, bool dd = false) + { + return ((dd) ? new(FT.DROPINDEX, indexName, "DD") + : new SerializedCommand(FT.DROPINDEX, indexName)); + } + + public static SerializedCommand Explain(string indexName, string query, int? dialect) + { + var args = new List { indexName, query }; + if (dialect != null) { - var args = new List { indexName, query }; - if (dialect != null) - { - args.Add("DIALECT"); - args.Add(dialect); - } - return new SerializedCommand(FT.EXPLAIN, args); + args.Add("DIALECT"); + args.Add(dialect); } + return new(FT.EXPLAIN, args); + } - public static SerializedCommand ExplainCli(string indexName, string query, int? dialect) + public static SerializedCommand ExplainCli(string indexName, string query, int? dialect) + { + var args = new List { indexName, query }; + if (dialect != null) { - var args = new List { indexName, query }; - if (dialect != null) - { - args.Add("DIALECT"); - args.Add(dialect); - } - return new SerializedCommand(FT.EXPLAINCLI, args); + args.Add("DIALECT"); + args.Add(dialect); } + return new(FT.EXPLAINCLI, args); + } - public static SerializedCommand Info(RedisValue index) => - new SerializedCommand(FT.INFO, index); + public static SerializedCommand Info(RedisValue index) => new(FT.INFO, index); - public static SerializedCommand Search(string indexName, Query q) - { - var args = new List { indexName }; - q.SerializeRedisArgs(args); + public static SerializedCommand Search(string indexName, Query q) + { + var args = new List { indexName }; + q.SerializeRedisArgs(args); - return new SerializedCommand(FT.SEARCH, args); - } + return new(FT.SEARCH, args); + } - public static SerializedCommand ProfileSearch(string IndexName, Query q, bool limited = false) - { - var args = - (limited) - ? new List() { IndexName, SearchArgs.SEARCH, SearchArgs.LIMITED, SearchArgs.QUERY } + public static SerializedCommand ProfileSearch(string IndexName, Query q, bool limited = false) + { + var args = + (limited) + ? new() { IndexName, SearchArgs.SEARCH, SearchArgs.LIMITED, SearchArgs.QUERY } : new List() { IndexName, SearchArgs.SEARCH, SearchArgs.QUERY }; - q.SerializeRedisArgs(args); - return new SerializedCommand(FT.PROFILE, args); - } + q.SerializeRedisArgs(args); + return new(FT.PROFILE, args); + } - public static SerializedCommand ProfileAggregate(string IndexName, AggregationRequest query, bool limited = false) - { - var args = (limited) - ? new List { IndexName, SearchArgs.AGGREGATE, SearchArgs.LIMITED, SearchArgs.QUERY } - : new List { IndexName, SearchArgs.AGGREGATE, SearchArgs.QUERY }; + public static SerializedCommand ProfileAggregate(string IndexName, AggregationRequest query, bool limited = false) + { + var args = (limited) + ? new() { IndexName, SearchArgs.AGGREGATE, SearchArgs.LIMITED, SearchArgs.QUERY } + : new List { IndexName, SearchArgs.AGGREGATE, SearchArgs.QUERY }; - query.SerializeRedisArgs(); - args.AddRange(query.GetArgs()); - return new SerializedCommand(FT.PROFILE, args); - } + query.SerializeRedisArgs(); + args.AddRange(query.GetArgs()); + return new(FT.PROFILE, args); + } - public static SerializedCommand SpellCheck(string indexName, string query, FTSpellCheckParams? spellCheckParams = null) + public static SerializedCommand SpellCheck(string indexName, string query, FTSpellCheckParams? spellCheckParams = null) + { + if (spellCheckParams != null) { - if (spellCheckParams != null) - { - spellCheckParams.SerializeRedisArgs(); - var args = new List(spellCheckParams!.GetArgs().Count + 2) { indexName, query }; // TODO: check if this improves performance (create a list with exact size) - args.AddRange(spellCheckParams.GetArgs()); - return new SerializedCommand(FT.SPELLCHECK, args); - } - - return new SerializedCommand(FT.SPELLCHECK, indexName, query); + spellCheckParams.SerializeRedisArgs(); + var args = new List(spellCheckParams.GetArgs().Count + 2) { indexName, query }; // TODO: check if this improves performance (create a list with exact size) + args.AddRange(spellCheckParams.GetArgs()); + return new(FT.SPELLCHECK, args); } - public static SerializedCommand SugAdd(string key, string str, double score, bool increment = false, string? payload = null) - { - var args = new List { key, str, score }; - if (increment) { args.Add(SearchArgs.INCR); } - if (payload != null) { args.Add(SearchArgs.PAYLOAD); args.Add(payload); } - return new SerializedCommand(FT.SUGADD, args); - } + return new(FT.SPELLCHECK, indexName, query); + } - public static SerializedCommand SugDel(string key, string str) - { - return new SerializedCommand(FT.SUGDEL, key, str); - } + public static SerializedCommand SugAdd(string key, string str, double score, bool increment = false, string? payload = null) + { + var args = new List { key, str, score }; + if (increment) { args.Add(SearchArgs.INCR); } + if (payload != null) { args.Add(SearchArgs.PAYLOAD); args.Add(payload); } + return new(FT.SUGADD, args); + } - public static SerializedCommand SugGet(string key, string prefix, bool fuzzy = false, bool withScores = false, bool withPayloads = false, int? max = null) - { - var args = new List { key, prefix }; - if (fuzzy) { args.Add(SearchArgs.FUZZY); } - if (withScores) { args.Add(SearchArgs.WITHSCORES); } - if (withPayloads) { args.Add(SearchArgs.WITHPAYLOADS); } - if (max != null) { args.Add(SearchArgs.MAX); args.Add(max); } - return new SerializedCommand(FT.SUGGET, args); - } + public static SerializedCommand SugDel(string key, string str) + { + return new(FT.SUGDEL, key, str); + } - public static SerializedCommand SugLen(string key) - { - return new SerializedCommand(FT.SUGLEN, key); - } + public static SerializedCommand SugGet(string key, string prefix, bool fuzzy = false, bool withScores = false, bool withPayloads = false, int? max = null) + { + var args = new List { key, prefix }; + if (fuzzy) { args.Add(SearchArgs.FUZZY); } + if (withScores) { args.Add(SearchArgs.WITHSCORES); } + if (withPayloads) { args.Add(SearchArgs.WITHPAYLOADS); } + if (max != null) { args.Add(SearchArgs.MAX); args.Add(max); } + return new(FT.SUGGET, args); + } - public static SerializedCommand SynDump(string indexName) - { - return new SerializedCommand(FT.SYNDUMP, indexName); - } + public static SerializedCommand SugLen(string key) + { + return new(FT.SUGLEN, key); + } - public static SerializedCommand SynUpdate(string indexName, string synonymGroupId, bool skipInitialScan = false, params string[] terms) + public static SerializedCommand SynDump(string indexName) + { + return new(FT.SYNDUMP, indexName); + } + + public static SerializedCommand SynUpdate(string indexName, string synonymGroupId, bool skipInitialScan = false, params string[] terms) + { + if (terms.Length < 1) { - if (terms.Length < 1) - { - throw new ArgumentOutOfRangeException("terms must have at least one element"); - } - var args = new List { indexName, synonymGroupId }; - if (skipInitialScan) { args.Add(SearchArgs.SKIPINITIALSCAN); } - args.AddRange(terms); - return new SerializedCommand(FT.SYNUPDATE, args); + throw new ArgumentOutOfRangeException("terms must have at least one element"); } - - public static SerializedCommand TagVals(string indexName, string fieldName) => //TODO: consider return Set - new SerializedCommand(FT.TAGVALS, indexName, fieldName); + var args = new List { indexName, synonymGroupId }; + if (skipInitialScan) { args.Add(SearchArgs.SKIPINITIALSCAN); } + args.AddRange(terms); + return new(FT.SYNUPDATE, args); } + + public static SerializedCommand TagVals(string indexName, string fieldName) => //TODO: consider return Set + new(FT.TAGVALS, indexName, fieldName); } \ No newline at end of file diff --git a/src/NRedisStack/Search/SearchCommands.cs b/src/NRedisStack/Search/SearchCommands.cs index ea42e2ee..381cb13b 100644 --- a/src/NRedisStack/Search/SearchCommands.cs +++ b/src/NRedisStack/Search/SearchCommands.cs @@ -1,241 +1,234 @@ using NRedisStack.Search; -using NRedisStack.Search.Aggregation; using NRedisStack.Search.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public class SearchCommands(IDatabase db, int? defaultDialect = 2) + : SearchCommandsAsync(db, defaultDialect), ISearchCommands { - public class SearchCommands : SearchCommandsAsync, ISearchCommands + /// + public RedisResult[] _List() { - private IDatabase _db; - public SearchCommands(IDatabase db, int? defaultDialect = 2) : base(db, defaultDialect) - { - _db = db; - } - - /// - public RedisResult[] _List() - { - return _db.Execute(SearchCommandBuilder._List()).ToArray(); - } + return db.Execute(SearchCommandBuilder._List()).ToArray(); + } - /// - public AggregationResult Aggregate(string index, AggregationRequest query) - { - setDefaultDialectIfUnset(query); - var result = _db.Execute(SearchCommandBuilder.Aggregate(index, query)); - return result.ToAggregationResult(query); - } + /// + public AggregationResult Aggregate(string index, AggregationRequest query) + { + SetDefaultDialectIfUnset(query); + var result = db.Execute(SearchCommandBuilder.Aggregate(index, query)); + return result.ToAggregationResult(query); + } - /// - public bool AliasAdd(string alias, string index) - { - return _db.Execute(SearchCommandBuilder.AliasAdd(alias, index)).OKtoBoolean(); - } + /// + public bool AliasAdd(string alias, string index) + { + return db.Execute(SearchCommandBuilder.AliasAdd(alias, index)).OKtoBoolean(); + } - /// - public bool AliasDel(string alias) - { - return _db.Execute(SearchCommandBuilder.AliasDel(alias)).OKtoBoolean(); - } + /// + public bool AliasDel(string alias) + { + return db.Execute(SearchCommandBuilder.AliasDel(alias)).OKtoBoolean(); + } - /// - public bool AliasUpdate(string alias, string index) - { - return _db.Execute(SearchCommandBuilder.AliasUpdate(alias, index)).OKtoBoolean(); - } + /// + public bool AliasUpdate(string alias, string index) + { + return db.Execute(SearchCommandBuilder.AliasUpdate(alias, index)).OKtoBoolean(); + } - /// - public bool Alter(string index, Schema schema, bool skipInitialScan = false) - { - return _db.Execute(SearchCommandBuilder.Alter(index, schema, skipInitialScan)).OKtoBoolean(); - } + /// + public bool Alter(string index, Schema schema, bool skipInitialScan = false) + { + return db.Execute(SearchCommandBuilder.Alter(index, schema, skipInitialScan)).OKtoBoolean(); + } - /// - [Obsolete("Starting from Redis 8.0, use db.ConfigGet instead")] - public Dictionary ConfigGet(string option) - { - return _db.Execute(SearchCommandBuilder.ConfigGet(option)).ToConfigDictionary(); - } + /// + [Obsolete("Starting from Redis 8.0, use db.ConfigGet instead")] + public Dictionary ConfigGet(string option) + { + return db.Execute(SearchCommandBuilder.ConfigGet(option)).ToConfigDictionary(); + } - /// - [Obsolete("Starting from Redis 8.0, use db.ConfigSet instead")] - public bool ConfigSet(string option, string value) - { - return _db.Execute(SearchCommandBuilder.ConfigSet(option, value)).OKtoBoolean(); - } + /// + [Obsolete("Starting from Redis 8.0, use db.ConfigSet instead")] + public bool ConfigSet(string option, string value) + { + return db.Execute(SearchCommandBuilder.ConfigSet(option, value)).OKtoBoolean(); + } - // TODO: Add an ability to add fildes like that: TextField.Of("name") - /// - public bool Create(string indexName, FTCreateParams parameters, Schema schema) - { - return _db.Execute(SearchCommandBuilder.Create(indexName, parameters, schema)).OKtoBoolean(); - } + // TODO: Add an ability to add fildes like that: TextField.Of("name") + /// + public bool Create(string indexName, FTCreateParams parameters, Schema schema) + { + return db.Execute(SearchCommandBuilder.Create(indexName, parameters, schema)).OKtoBoolean(); + } - /// - public bool Create(string indexName, Schema schema) - { - return Create(indexName, new FTCreateParams(), schema); - } + /// + public bool Create(string indexName, Schema schema) + { + return Create(indexName, new(), schema); + } - /// - public bool CursorDel(string indexName, long cursorId) - { - return _db.Execute(SearchCommandBuilder.CursorDel(indexName, cursorId)).OKtoBoolean(); - } + /// + public bool CursorDel(string indexName, long cursorId) + { + return db.Execute(SearchCommandBuilder.CursorDel(indexName, cursorId)).OKtoBoolean(); + } - /// - public AggregationResult CursorRead(string indexName, long cursorId, int? count = null) - { - var resp = _db.Execute(SearchCommandBuilder.CursorRead(indexName, cursorId, count)).ToArray(); - return new AggregationResult(resp[0], (long)resp[1]); - } + /// + public AggregationResult CursorRead(string indexName, long cursorId, int? count = null) + { + var resp = db.Execute(SearchCommandBuilder.CursorRead(indexName, cursorId, count)).ToArray(); + return new(resp[0], (long)resp[1]); + } - /// - public long DictAdd(string dict, params string[] terms) - { - return _db.Execute(SearchCommandBuilder.DictAdd(dict, terms)).ToLong(); - } + /// + public long DictAdd(string dict, params string[] terms) + { + return db.Execute(SearchCommandBuilder.DictAdd(dict, terms)).ToLong(); + } - /// - public long DictDel(string dict, params string[] terms) - { - return _db.Execute(SearchCommandBuilder.DictDel(dict, terms)).ToLong(); - } + /// + public long DictDel(string dict, params string[] terms) + { + return db.Execute(SearchCommandBuilder.DictDel(dict, terms)).ToLong(); + } - /// - public RedisResult[] DictDump(string dict) - { - return _db.Execute(SearchCommandBuilder.DictDump(dict)).ToArray(); - } + /// + public RedisResult[] DictDump(string dict) + { + return db.Execute(SearchCommandBuilder.DictDump(dict)).ToArray(); + } - /// - public bool DropIndex(string indexName, bool dd = false) - { - return _db.Execute(SearchCommandBuilder.DropIndex(indexName, dd)).OKtoBoolean(); - } + /// + public bool DropIndex(string indexName, bool dd = false) + { + return db.Execute(SearchCommandBuilder.DropIndex(indexName, dd)).OKtoBoolean(); + } - /// - public string Explain(string indexName, string query, int? dialect = null) - { - dialect = checkAndGetDefaultDialect(dialect); - return _db.Execute(SearchCommandBuilder.Explain(indexName, query, dialect)).ToString()!; - } + /// + public string Explain(string indexName, string query, int? dialect = null) + { + dialect = CheckAndGetDefaultDialect(dialect); + return db.Execute(SearchCommandBuilder.Explain(indexName, query, dialect)).ToString(); + } - /// - public RedisResult[] ExplainCli(string indexName, string query, int? dialect = null) - { - dialect = checkAndGetDefaultDialect(dialect); - return _db.Execute(SearchCommandBuilder.ExplainCli(indexName, query, dialect)).ToArray(); - } + /// + public RedisResult[] ExplainCli(string indexName, string query, int? dialect = null) + { + dialect = CheckAndGetDefaultDialect(dialect); + return db.Execute(SearchCommandBuilder.ExplainCli(indexName, query, dialect)).ToArray(); + } - /// - public InfoResult Info(RedisValue index) => - new InfoResult(_db.Execute(SearchCommandBuilder.Info(index))); + /// + public InfoResult Info(RedisValue index) => + new(db.Execute(SearchCommandBuilder.Info(index))); - /// - [Obsolete("Consider using ProfileOnSearch with Redis CE 8.0 and later")] - public Tuple> ProfileSearch(string indexName, Query q, bool limited = false) - { - setDefaultDialectIfUnset(q); - return _db.Execute(SearchCommandBuilder.ProfileSearch(indexName, q, limited)) - .ToProfileSearchResult(q); - } + /// + [Obsolete("Consider using ProfileOnSearch with Redis CE 8.0 and later")] + public Tuple> ProfileSearch(string indexName, Query q, bool limited = false) + { + SetDefaultDialectIfUnset(q); + return db.Execute(SearchCommandBuilder.ProfileSearch(indexName, q, limited)) + .ToProfileSearchResult(q); + } - /// - public Tuple ProfileOnSearch(string indexName, Query q, bool limited = false) - { - return _db.Execute(SearchCommandBuilder.ProfileSearch(indexName, q, limited)) - .ParseProfileSearchResult(q); - } + /// + public Tuple ProfileOnSearch(string indexName, Query q, bool limited = false) + { + return db.Execute(SearchCommandBuilder.ProfileSearch(indexName, q, limited)) + .ParseProfileSearchResult(q); + } - /// - [Obsolete("Consider using ProfileOnAggregate with Redis CE 8.0 and later")] - public Tuple> ProfileAggregate(string indexName, AggregationRequest query, bool limited = false) - { - setDefaultDialectIfUnset(query); - return _db.Execute(SearchCommandBuilder.ProfileAggregate(indexName, query, limited)) - .ToProfileAggregateResult(query); - } + /// + [Obsolete("Consider using ProfileOnAggregate with Redis CE 8.0 and later")] + public Tuple> ProfileAggregate(string indexName, AggregationRequest query, bool limited = false) + { + SetDefaultDialectIfUnset(query); + return db.Execute(SearchCommandBuilder.ProfileAggregate(indexName, query, limited)) + .ToProfileAggregateResult(query); + } - /// - public Tuple ProfileOnAggregate(string indexName, AggregationRequest query, bool limited = false) - { - setDefaultDialectIfUnset(query); - return _db.Execute(SearchCommandBuilder.ProfileAggregate(indexName, query, limited)) - .ParseProfileAggregateResult(query); - } + /// + public Tuple ProfileOnAggregate(string indexName, AggregationRequest query, bool limited = false) + { + SetDefaultDialectIfUnset(query); + return db.Execute(SearchCommandBuilder.ProfileAggregate(indexName, query, limited)) + .ParseProfileAggregateResult(query); + } - /// - public SearchResult Search(string indexName, Query q) - { - setDefaultDialectIfUnset(q); - return _db.Execute(SearchCommandBuilder.Search(indexName, q)).ToSearchResult(q); - } + /// + public SearchResult Search(string indexName, Query q) + { + SetDefaultDialectIfUnset(q); + return db.Execute(SearchCommandBuilder.Search(indexName, q)).ToSearchResult(q); + } - /// - public Dictionary> SpellCheck(string indexName, string query, FTSpellCheckParams? spellCheckParams = null) - { - setDefaultDialectIfUnset(spellCheckParams); - return _db.Execute(SearchCommandBuilder.SpellCheck(indexName, query, spellCheckParams)).ToFtSpellCheckResult(); - } + /// + public Dictionary> SpellCheck(string indexName, string query, FTSpellCheckParams? spellCheckParams = null) + { + SetDefaultDialectIfUnset(spellCheckParams); + return db.Execute(SearchCommandBuilder.SpellCheck(indexName, query, spellCheckParams)).ToFtSpellCheckResult(); + } - /// - public long SugAdd(string key, string str, double score, bool increment = false, string? payload = null) - { - return _db.Execute(SearchCommandBuilder.SugAdd(key, str, score, increment, payload)).ToLong(); - } + /// + public long SugAdd(string key, string str, double score, bool increment = false, string? payload = null) + { + return db.Execute(SearchCommandBuilder.SugAdd(key, str, score, increment, payload)).ToLong(); + } - /// - public bool SugDel(string key, string str) - { - return _db.Execute(SearchCommandBuilder.SugDel(key, str)).ToString() == "1"; - } + /// + public bool SugDel(string key, string str) + { + return db.Execute(SearchCommandBuilder.SugDel(key, str)).ToString() == "1"; + } - /// - public List SugGet(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) - { - return _db.Execute(SearchCommandBuilder.SugGet(key, prefix, fuzzy, false, withPayloads, max)).ToStringList(); - } + /// + public List SugGet(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) + { + return db.Execute(SearchCommandBuilder.SugGet(key, prefix, fuzzy, false, withPayloads, max)).ToStringList(); + } - /// - public List> SugGetWithScores(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) - { - return _db.Execute(SearchCommandBuilder.SugGet(key, prefix, fuzzy, true, withPayloads, max)).ToStringDoubleTupleList(); - } + /// + public List> SugGetWithScores(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) + { + return db.Execute(SearchCommandBuilder.SugGet(key, prefix, fuzzy, true, withPayloads, max)).ToStringDoubleTupleList(); + } - /// - public long SugLen(string key) - { - return _db.Execute(SearchCommandBuilder.SugLen(key)).ToLong(); - } + /// + public long SugLen(string key) + { + return db.Execute(SearchCommandBuilder.SugLen(key)).ToLong(); + } - /// - public Dictionary> SynDump(string indexName) + /// + public Dictionary> SynDump(string indexName) + { + var resp = db.Execute(SearchCommandBuilder.SynDump(indexName)).ToArray(); + var result = new Dictionary>(); + for (int i = 0; i < resp.Length; i += 2) { - var resp = _db.Execute(SearchCommandBuilder.SynDump(indexName)).ToArray(); - var result = new Dictionary>(); - for (int i = 0; i < resp.Length; i += 2) - { - var term = resp[i].ToString(); - var synonyms = (resp[i + 1]).ToArray().Select(x => x.ToString()).ToList(); // TODO: consider leave synonyms as RedisValue[] - result.Add(term!, synonyms!); - } - return result; + var term = resp[i].ToString(); + var synonyms = (resp[i + 1]).ToArray().Select(x => x.ToString()).ToList(); // TODO: consider leave synonyms as RedisValue[] + result.Add(term, synonyms); } + return result; + } - /// - public bool SynUpdate(string indexName, string synonymGroupId, bool skipInitialScan = false, params string[] terms) - { - return _db.Execute(SearchCommandBuilder.SynUpdate(indexName, synonymGroupId, skipInitialScan, terms)).OKtoBoolean(); - } - - /// - public RedisResult[] TagVals(string indexName, string fieldName) => //TODO: consider return Set - _db.Execute(SearchCommandBuilder.TagVals(indexName, fieldName)).ToArray(); + /// + public bool SynUpdate(string indexName, string synonymGroupId, bool skipInitialScan = false, params string[] terms) + { + return db.Execute(SearchCommandBuilder.SynUpdate(indexName, synonymGroupId, skipInitialScan, terms)).OKtoBoolean(); } + + /// + public RedisResult[] TagVals(string indexName, string fieldName) => //TODO: consider return Set + db.Execute(SearchCommandBuilder.TagVals(indexName, fieldName)).ToArray(); } \ No newline at end of file diff --git a/src/NRedisStack/Search/SearchCommandsAsync.cs b/src/NRedisStack/Search/SearchCommandsAsync.cs index 7dcd25b7..f4757af3 100644 --- a/src/NRedisStack/Search/SearchCommandsAsync.cs +++ b/src/NRedisStack/Search/SearchCommandsAsync.cs @@ -1,270 +1,268 @@ using NRedisStack.Search; -using NRedisStack.Search.Aggregation; using NRedisStack.Search.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public class SearchCommandsAsync : ISearchCommandsAsync { - public class SearchCommandsAsync : ISearchCommandsAsync + private readonly IDatabaseAsync _db; + protected int? defaultDialect; + + public SearchCommandsAsync(IDatabaseAsync db, int? defaultDialect = 2) { - private IDatabaseAsync _db; - protected int? defaultDialect; + _db = db; + SetDefaultDialect(defaultDialect); + } - public SearchCommandsAsync(IDatabaseAsync db, int? defaultDialect = 2) + internal void SetDefaultDialectIfUnset(IDialectAwareParam? param) + { + if (param != null && param.Dialect == null && defaultDialect != null) { - _db = db; - SetDefaultDialect(defaultDialect); + param.Dialect = defaultDialect; } + } - internal void setDefaultDialectIfUnset(IDialectAwareParam param) + internal int? CheckAndGetDefaultDialect(int? dialect) => + (dialect == null && defaultDialect != null) ? defaultDialect : dialect; + + public void SetDefaultDialect(int? defaultDialect) + { + if (defaultDialect == 0) { - if (param != null && param.Dialect == null && defaultDialect != null) - { - param.Dialect = defaultDialect; - } + throw new ArgumentOutOfRangeException("DIALECT=0 cannot be set."); } + this.defaultDialect = defaultDialect; + } - internal int? checkAndGetDefaultDialect(int? dialect) => - (dialect == null && defaultDialect != null) ? defaultDialect : dialect; + /// + public async Task _ListAsync() + { + return (await _db.ExecuteAsync(SearchCommandBuilder._List())).ToArray(); + } - public void SetDefaultDialect(int? defaultDialect) + /// + public async Task AggregateAsync(string index, AggregationRequest query) + { + SetDefaultDialectIfUnset(query); + var result = await _db.ExecuteAsync(SearchCommandBuilder.Aggregate(index, query)); + if (query.IsWithCursor()) { - if (defaultDialect == 0) - { - throw new System.ArgumentOutOfRangeException("DIALECT=0 cannot be set."); - } - this.defaultDialect = defaultDialect; - } + var results = (RedisResult[])result!; - /// - public async Task _ListAsync() - { - return (await _db.ExecuteAsync(SearchCommandBuilder._List())).ToArray(); + return new(results[0], (long)results[1]); } - - /// - public async Task AggregateAsync(string index, AggregationRequest query) + else { - setDefaultDialectIfUnset(query); - var result = await _db.ExecuteAsync(SearchCommandBuilder.Aggregate(index, query)); - if (query.IsWithCursor()) - { - var results = (RedisResult[])result!; - - return new AggregationResult(results[0], (long)results[1]); - } - else - { - return new AggregationResult(result); - } + return new(result); } + } - /// - public async Task AliasAddAsync(string alias, string index) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.AliasAdd(alias, index))).OKtoBoolean(); - } + /// + public async Task AliasAddAsync(string alias, string index) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.AliasAdd(alias, index))).OKtoBoolean(); + } - /// - public async Task AliasDelAsync(string alias) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.AliasDel(alias))).OKtoBoolean(); - } + /// + public async Task AliasDelAsync(string alias) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.AliasDel(alias))).OKtoBoolean(); + } - /// - public async Task AliasUpdateAsync(string alias, string index) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.AliasUpdate(alias, index))).OKtoBoolean(); - } + /// + public async Task AliasUpdateAsync(string alias, string index) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.AliasUpdate(alias, index))).OKtoBoolean(); + } - /// - public async Task AlterAsync(string index, Schema schema, bool skipInitialScan = false) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.Alter(index, schema, skipInitialScan))).OKtoBoolean(); - } + /// + public async Task AlterAsync(string index, Schema schema, bool skipInitialScan = false) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.Alter(index, schema, skipInitialScan))).OKtoBoolean(); + } - /// - [Obsolete("Starting from Redis 8.0, use db.ConfigGetAsync instead")] - public async Task> ConfigGetAsync(string option) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.ConfigGet(option))).ToConfigDictionary(); - } + /// + [Obsolete("Starting from Redis 8.0, use db.ConfigGetAsync instead")] + public async Task> ConfigGetAsync(string option) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.ConfigGet(option))).ToConfigDictionary(); + } - /// - [Obsolete("Starting from Redis 8.0, use db.ConfigSetAsync instead")] - public async Task ConfigSetAsync(string option, string value) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.ConfigSet(option, value))).OKtoBoolean(); - } + /// + [Obsolete("Starting from Redis 8.0, use db.ConfigSetAsync instead")] + public async Task ConfigSetAsync(string option, string value) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.ConfigSet(option, value))).OKtoBoolean(); + } - /// - public async Task CreateAsync(string indexName, FTCreateParams parameters, Schema schema) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.Create(indexName, parameters, schema))).OKtoBoolean(); - } + /// + public async Task CreateAsync(string indexName, FTCreateParams parameters, Schema schema) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.Create(indexName, parameters, schema))).OKtoBoolean(); + } - /// - public async Task CreateAsync(string indexName, Schema schema) - { - return (await CreateAsync(indexName, new FTCreateParams(), schema)); - } + /// + public async Task CreateAsync(string indexName, Schema schema) + { + return (await CreateAsync(indexName, new(), schema)); + } - /// - public async Task CursorDelAsync(string indexName, long cursorId) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.CursorDel(indexName, cursorId))).OKtoBoolean(); - } + /// + public async Task CursorDelAsync(string indexName, long cursorId) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.CursorDel(indexName, cursorId))).OKtoBoolean(); + } - /// - public async Task CursorReadAsync(string indexName, long cursorId, int? count = null) - { - var resp = (await _db.ExecuteAsync(SearchCommandBuilder.CursorRead(indexName, cursorId, count))).ToArray(); - return new AggregationResult(resp[0], (long)resp[1]); - } + /// + public async Task CursorReadAsync(string indexName, long cursorId, int? count = null) + { + var resp = (await _db.ExecuteAsync(SearchCommandBuilder.CursorRead(indexName, cursorId, count))).ToArray(); + return new(resp[0], (long)resp[1]); + } - /// - public async Task DictAddAsync(string dict, params string[] terms) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.DictAdd(dict, terms))).ToLong(); - } + /// + public async Task DictAddAsync(string dict, params string[] terms) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.DictAdd(dict, terms))).ToLong(); + } - /// - public async Task DictDelAsync(string dict, params string[] terms) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.DictDel(dict, terms))).ToLong(); - } + /// + public async Task DictDelAsync(string dict, params string[] terms) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.DictDel(dict, terms))).ToLong(); + } - /// - public async Task DictDumpAsync(string dict) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.DictDump(dict))).ToArray(); - } + /// + public async Task DictDumpAsync(string dict) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.DictDump(dict))).ToArray(); + } - /// - public async Task DropIndexAsync(string indexName, bool dd = false) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.DropIndex(indexName, dd))).OKtoBoolean(); - } + /// + public async Task DropIndexAsync(string indexName, bool dd = false) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.DropIndex(indexName, dd))).OKtoBoolean(); + } - /// - public async Task ExplainAsync(string indexName, string query, int? dialect = null) - { - dialect = checkAndGetDefaultDialect(dialect); - return (await _db.ExecuteAsync(SearchCommandBuilder.Explain(indexName, query, dialect))).ToString()!; - } + /// + public async Task ExplainAsync(string indexName, string query, int? dialect = null) + { + dialect = CheckAndGetDefaultDialect(dialect); + return (await _db.ExecuteAsync(SearchCommandBuilder.Explain(indexName, query, dialect))).ToString(); + } - /// - public async Task ExplainCliAsync(string indexName, string query, int? dialect = null) - { - dialect = checkAndGetDefaultDialect(dialect); - return (await _db.ExecuteAsync(SearchCommandBuilder.ExplainCli(indexName, query, dialect))).ToArray(); - } + /// + public async Task ExplainCliAsync(string indexName, string query, int? dialect = null) + { + dialect = CheckAndGetDefaultDialect(dialect); + return (await _db.ExecuteAsync(SearchCommandBuilder.ExplainCli(indexName, query, dialect))).ToArray(); + } - /// - public async Task InfoAsync(RedisValue index) => - new InfoResult(await _db.ExecuteAsync(SearchCommandBuilder.Info(index))); + /// + public async Task InfoAsync(RedisValue index) => + new(await _db.ExecuteAsync(SearchCommandBuilder.Info(index))); - /// - [Obsolete("Consider using ProfileOnSearchAsync with Redis CE 8.0 and later")] - public async Task>> ProfileSearchAsync(string indexName, Query q, bool limited = false) - { - setDefaultDialectIfUnset(q); - return (await _db.ExecuteAsync(SearchCommandBuilder.ProfileSearch(indexName, q, limited))) - .ToProfileSearchResult(q); - } + /// + [Obsolete("Consider using ProfileOnSearchAsync with Redis CE 8.0 and later")] + public async Task>> ProfileSearchAsync(string indexName, Query q, bool limited = false) + { + SetDefaultDialectIfUnset(q); + return (await _db.ExecuteAsync(SearchCommandBuilder.ProfileSearch(indexName, q, limited))) + .ToProfileSearchResult(q); + } - /// - public async Task> ProfileOnSearchAsync(string indexName, Query q, bool limited = false) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.ProfileSearch(indexName, q, limited))) - .ParseProfileSearchResult(q); - } - /// - [Obsolete("Consider using ProfileOnSearchAsync with Redis CE 8.0 and later")] - public async Task>> ProfileAggregateAsync(string indexName, AggregationRequest query, bool limited = false) - { - setDefaultDialectIfUnset(query); - return (await _db.ExecuteAsync(SearchCommandBuilder.ProfileAggregate(indexName, query, limited))) - .ToProfileAggregateResult(query); - } - /// - public async Task> ProfileOnAggregateAsync(string indexName, AggregationRequest query, bool limited = false) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.ProfileAggregate(indexName, query, limited))) - .ParseProfileAggregateResult(query); - } + /// + public async Task> ProfileOnSearchAsync(string indexName, Query q, bool limited = false) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.ProfileSearch(indexName, q, limited))) + .ParseProfileSearchResult(q); + } + /// + [Obsolete("Consider using ProfileOnSearchAsync with Redis CE 8.0 and later")] + public async Task>> ProfileAggregateAsync(string indexName, AggregationRequest query, bool limited = false) + { + SetDefaultDialectIfUnset(query); + return (await _db.ExecuteAsync(SearchCommandBuilder.ProfileAggregate(indexName, query, limited))) + .ToProfileAggregateResult(query); + } + /// + public async Task> ProfileOnAggregateAsync(string indexName, AggregationRequest query, bool limited = false) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.ProfileAggregate(indexName, query, limited))) + .ParseProfileAggregateResult(query); + } - /// - public async Task SearchAsync(string indexName, Query q) - { - setDefaultDialectIfUnset(q); - return (await _db.ExecuteAsync(SearchCommandBuilder.Search(indexName, q))).ToSearchResult(q); - } + /// + public async Task SearchAsync(string indexName, Query q) + { + SetDefaultDialectIfUnset(q); + return (await _db.ExecuteAsync(SearchCommandBuilder.Search(indexName, q))).ToSearchResult(q); + } - /// - public async Task>> SpellCheckAsync(string indexName, string query, FTSpellCheckParams? spellCheckParams = null) - { - setDefaultDialectIfUnset(spellCheckParams); - return (await _db.ExecuteAsync(SearchCommandBuilder.SpellCheck(indexName, query, spellCheckParams))).ToFtSpellCheckResult(); - } + /// + public async Task>> SpellCheckAsync(string indexName, string query, FTSpellCheckParams? spellCheckParams = null) + { + SetDefaultDialectIfUnset(spellCheckParams); + return (await _db.ExecuteAsync(SearchCommandBuilder.SpellCheck(indexName, query, spellCheckParams))).ToFtSpellCheckResult(); + } - /// - public async Task SugAddAsync(string key, string str, double score, bool increment = false, string? payload = null) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.SugAdd(key, str, score, increment, payload))).ToLong(); - } + /// + public async Task SugAddAsync(string key, string str, double score, bool increment = false, string? payload = null) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.SugAdd(key, str, score, increment, payload))).ToLong(); + } - /// - public async Task SugDelAsync(string key, string str) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.SugDel(key, str))).ToString() == "1"; + /// + public async Task SugDelAsync(string key, string str) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.SugDel(key, str))).ToString() == "1"; - } + } - /// - public async Task> SugGetAsync(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.SugGet(key, prefix, fuzzy, withScores: false, withPayloads, max))).ToStringList(); + /// + public async Task> SugGetAsync(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.SugGet(key, prefix, fuzzy, withScores: false, withPayloads, max))).ToStringList(); - } + } - /// - public async Task>> SugGetWithScoresAsync(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.SugGet(key, prefix, fuzzy, withScores: true, withPayloads, max))).ToStringDoubleTupleList(); - } + /// + public async Task>> SugGetWithScoresAsync(string key, string prefix, bool fuzzy = false, bool withPayloads = false, int? max = null) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.SugGet(key, prefix, fuzzy, withScores: true, withPayloads, max))).ToStringDoubleTupleList(); + } - /// - public async Task SugLenAsync(string key) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.SugLen(key))).ToLong(); + /// + public async Task SugLenAsync(string key) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.SugLen(key))).ToLong(); - } + } - /// - public async Task>> SynDumpAsync(string indexName) + /// + public async Task>> SynDumpAsync(string indexName) + { + var resp = (await _db.ExecuteAsync(SearchCommandBuilder.SynDump(indexName))).ToArray(); + var result = new Dictionary>(); + for (int i = 0; i < resp.Length; i += 2) { - var resp = (await _db.ExecuteAsync(SearchCommandBuilder.SynDump(indexName))).ToArray(); - var result = new Dictionary>(); - for (int i = 0; i < resp.Length; i += 2) - { - var term = resp[i].ToString(); - var synonyms = (resp[i + 1]).ToArray().Select(x => x.ToString()).ToList(); // TODO: consider leave synonyms as RedisValue[] - result.Add(term!, synonyms!); - } - return result; + var term = resp[i].ToString(); + var synonyms = (resp[i + 1]).ToArray().Select(x => x.ToString()).ToList(); // TODO: consider leave synonyms as RedisValue[] + result.Add(term, synonyms); } + return result; + } - /// - public async Task SynUpdateAsync(string indexName, string synonymGroupId, bool skipInitialScan = false, params string[] terms) - { - return (await _db.ExecuteAsync(SearchCommandBuilder.SynUpdate(indexName, synonymGroupId, skipInitialScan, terms))).OKtoBoolean(); - } + /// + public async Task SynUpdateAsync(string indexName, string synonymGroupId, bool skipInitialScan = false, params string[] terms) + { + return (await _db.ExecuteAsync(SearchCommandBuilder.SynUpdate(indexName, synonymGroupId, skipInitialScan, terms))).OKtoBoolean(); + } - /// - public async Task TagValsAsync(string indexName, string fieldName) => //TODO: consider return Set + /// + public async Task TagValsAsync(string indexName, string fieldName) => //TODO: consider return Set (await _db.ExecuteAsync(SearchCommandBuilder.TagVals(indexName, fieldName))).ToArray(); - } } \ No newline at end of file diff --git a/src/NRedisStack/Search/SearchResult.cs b/src/NRedisStack/Search/SearchResult.cs index 51c34e95..162e5828 100644 --- a/src/NRedisStack/Search/SearchResult.cs +++ b/src/NRedisStack/Search/SearchResult.cs @@ -1,86 +1,85 @@ using StackExchange.Redis; -namespace NRedisStack.Search +namespace NRedisStack.Search; + +/// +/// SearchResult encapsulates the returned result from a search query. +/// It contains publically accessible fields for the total number of results, and an array of +/// objects conatining the actual returned documents. +/// +public class SearchResult { + public long TotalResults { get; } + public List Documents { get; } + /// - /// SearchResult encapsulates the returned result from a search query. - /// It contains publically accessible fields for the total number of results, and an array of - /// objects conatining the actual returned documents. + /// Converts the documents to a list of json strings. only works on a json documents index. /// - public class SearchResult - { - public long TotalResults { get; } - public List Documents { get; } + public List ToJson() => Documents.Select(x => x["json"].ToString()) + .Where(x => !string.IsNullOrEmpty(x)).ToList(); - /// - /// Converts the documents to a list of json strings. only works on a json documents index. - /// - public List ToJson() => Documents.Select(x => x["json"].ToString()) - .Where(x => !string.IsNullOrEmpty(x)).ToList(); + internal SearchResult(RedisResult[] resp, bool hasContent, bool hasScores, bool hasPayloads/*, bool shouldExplainScore*/) + { + // Calculate the step distance to walk over the results. + // The order of results is id, score (if withScore), payLoad (if hasPayloads), fields + int step = 1; + int scoreOffset = 0; + int contentOffset = 1; + int payloadOffset = 0; + if (hasScores) + { + step++; + scoreOffset = 1; + contentOffset++; - internal SearchResult(RedisResult[] resp, bool hasContent, bool hasScores, bool hasPayloads/*, bool shouldExplainScore*/) + } + if (hasContent) { - // Calculate the step distance to walk over the results. - // The order of results is id, score (if withScore), payLoad (if hasPayloads), fields - int step = 1; - int scoreOffset = 0; - int contentOffset = 1; - int payloadOffset = 0; - if (hasScores) + step++; + if (hasPayloads) { + payloadOffset = scoreOffset + 1; step++; - scoreOffset = 1; contentOffset++; + } + } + // the first element is always the number of results + TotalResults = (long)resp[0]; + var docs = new List((resp.Length - 1) / step); + Documents = docs; + for (int i = 1; i < resp.Length; i += step) + { + var id = resp[i].ToString(); + double score = 1.0; + byte[]? payload = null; + RedisValue[]? fields = null; + string[]? scoreExplained = null; + if (hasScores) + { + // if (shouldExplainScore) + // { + // var scoreResult = (RedisResult[])resp[i + scoreOffset]; + // score = (double) scoreResult[0]; + // var redisResultsScoreExplained = (RedisResult[]) scoreResult[1]; + // scoreExplained = FlatRedisResultArray(redisResultsScoreExplained).ToArray(); + // } + //else + //{ + score = (double)resp[i + scoreOffset]; + //} } - if (hasContent) + if (hasPayloads) { - step++; - if (hasPayloads) - { - payloadOffset = scoreOffset + 1; - step++; - contentOffset++; - } + payload = (byte[]?)resp[i + payloadOffset]; } - // the first element is always the number of results - TotalResults = (long)resp[0]; - var docs = new List((resp.Length - 1) / step); - Documents = docs; - for (int i = 1; i < resp.Length; i += step) + if (hasContent) { - var id = resp[i].ToString(); - double score = 1.0; - byte[]? payload = null; - RedisValue[]? fields = null; - string[]? scoreExplained = null; - if (hasScores) - { - // if (shouldExplainScore) - // { - // var scoreResult = (RedisResult[])resp[i + scoreOffset]; - // score = (double) scoreResult[0]; - // var redisResultsScoreExplained = (RedisResult[]) scoreResult[1]; - // scoreExplained = FlatRedisResultArray(redisResultsScoreExplained).ToArray(); - // } - //else - //{ - score = (double)resp[i + scoreOffset]; - //} - } - if (hasPayloads) - { - payload = (byte[]?)resp[i + payloadOffset]; - } - - if (hasContent) - { - fields = (RedisValue[]?)resp[i + contentOffset]; - } - - docs.Add(Document.Load(id!, score, payload, fields, scoreExplained)); + fields = (RedisValue[]?)resp[i + contentOffset]; } + + docs.Add(Document.Load(id, score, payload, fields, scoreExplained)); } } } \ No newline at end of file diff --git a/src/NRedisStack/Search/SortedField.cs b/src/NRedisStack/Search/SortedField.cs index dc9c1e5c..2054b20e 100644 --- a/src/NRedisStack/Search/SortedField.cs +++ b/src/NRedisStack/Search/SortedField.cs @@ -1,30 +1,29 @@ -namespace NRedisStack.Search.Aggregation +namespace NRedisStack.Search.Aggregation; + +public class SortedField { - public class SortedField - { - public enum SortOrder - { - ASC, DESC - } + public enum SortOrder + { + ASC, DESC + } - public string FieldName { get; } - public SortOrder Order { get; } + public string FieldName { get; } + public SortOrder Order { get; } - public SortedField(String fieldName, SortOrder order = SortOrder.ASC) - { - this.FieldName = fieldName; - this.Order = order; - } + public SortedField(String fieldName, SortOrder order = SortOrder.ASC) + { + FieldName = fieldName; + Order = order; + } - public static SortedField Asc(String field) - { - return new SortedField(field, SortOrder.ASC); - } + public static SortedField Asc(String field) + { + return new(field, SortOrder.ASC); + } - public static SortedField Desc(String field) - { - return new SortedField(field, SortOrder.DESC); - } + public static SortedField Desc(String field) + { + return new(field, SortOrder.DESC); } } \ No newline at end of file diff --git a/src/NRedisStack/SerializedCommand.cs b/src/NRedisStack/SerializedCommand.cs deleted file mode 100644 index 3d7cb404..00000000 --- a/src/NRedisStack/SerializedCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace NRedisStack.RedisStackCommands -{ - public class SerializedCommand - { - public string Command { get; } - public object[] Args { get; } - - public SerializedCommand(string command, params object[] args) - { - Command = command; - Args = args; - } - - public SerializedCommand(string command, ICollection args) - { - Command = command; - Args = args.ToArray(); - } - } -} \ No newline at end of file diff --git a/src/NRedisStack/Tdigest/DataTypes/TdigestInformation.cs b/src/NRedisStack/Tdigest/DataTypes/TdigestInformation.cs index b564ccec..9710555e 100644 --- a/src/NRedisStack/Tdigest/DataTypes/TdigestInformation.cs +++ b/src/NRedisStack/Tdigest/DataTypes/TdigestInformation.cs @@ -1,36 +1,35 @@ -namespace NRedisStack.Tdigest.DataTypes +namespace NRedisStack.Tdigest.DataTypes; + +/// +/// This class represents the response for TDIGEST.INFO command. +/// This object has Read-only properties and cannot be generated outside a TDIGEST.INFO response. +/// +public class TdigestInformation { - /// - /// This class represents the response for TDIGEST.INFO command. - /// This object has Read-only properties and cannot be generated outside a TDIGEST.INFO response. - /// - public class TdigestInformation - { - public long Compression { get; private set; } - public long Capacity { get; private set; } - public long MergedNodes { get; private set; } - public long UnmergedNodes { get; private set; } - public double MergedWeight { get; private set; } - public double UnmergedWeight { get; private set; } - public double Observations { get; private set; } - public long TotalCompressions { get; private set; } - public long MemoryUsage { get; private set; } + public long Compression { get; private set; } + public long Capacity { get; private set; } + public long MergedNodes { get; private set; } + public long UnmergedNodes { get; private set; } + public double MergedWeight { get; private set; } + public double UnmergedWeight { get; private set; } + public double Observations { get; private set; } + public long TotalCompressions { get; private set; } + public long MemoryUsage { get; private set; } - internal TdigestInformation(long compression, long capacity, long mergedNodes, - long unmergedNodes, double mergedWeight, - double unmergedWeight, double observations, long totalCompressions, long memoryUsage) + internal TdigestInformation(long compression, long capacity, long mergedNodes, + long unmergedNodes, double mergedWeight, + double unmergedWeight, double observations, long totalCompressions, long memoryUsage) - { - Compression = compression; - Capacity = capacity; - MergedNodes = mergedNodes; - UnmergedNodes = unmergedNodes; - MergedWeight = mergedWeight; - UnmergedWeight = unmergedWeight; - Observations = observations; - TotalCompressions = totalCompressions; - MemoryUsage = memoryUsage; - } + { + Compression = compression; + Capacity = capacity; + MergedNodes = mergedNodes; + UnmergedNodes = unmergedNodes; + MergedWeight = mergedWeight; + UnmergedWeight = unmergedWeight; + Observations = observations; + TotalCompressions = totalCompressions; + MemoryUsage = memoryUsage; } } \ No newline at end of file diff --git a/src/NRedisStack/Tdigest/ITdigestCommands.cs b/src/NRedisStack/Tdigest/ITdigestCommands.cs index 6607d601..76d9db46 100644 --- a/src/NRedisStack/Tdigest/ITdigestCommands.cs +++ b/src/NRedisStack/Tdigest/ITdigestCommands.cs @@ -1,137 +1,135 @@ using NRedisStack.Tdigest.DataTypes; using StackExchange.Redis; -namespace NRedisStack -{ +namespace NRedisStack; - public interface ITdigestCommands - { +public interface ITdigestCommands +{ - /// - /// Adds one or more observations to a t-digest sketch. - /// - /// The name of the sketch. - /// The value of the observation. - /// if executed correctly, error otherwise - /// - bool Add(RedisKey key, params double[] values); + /// + /// Adds one or more observations to a t-digest sketch. + /// + /// The name of the sketch. + /// The value of the observation. + /// if executed correctly, error otherwise + /// + bool Add(RedisKey key, params double[] values); - /// - /// Estimate the fraction of all observations added which are <= value. - /// - /// The name of the sketch. - /// upper limit of observation value. - /// double-reply - estimation of the fraction of all observations added which are <= value - /// - double[] CDF(RedisKey key, params double[] values); + /// + /// Estimate the fraction of all observations added which are <= value. + /// + /// The name of the sketch. + /// upper limit of observation value. + /// double-reply - estimation of the fraction of all observations added which are <= value + /// + double[] CDF(RedisKey key, params double[] values); - /// - /// Allocate memory and initialize a t-digest sketch. - /// - /// The name of the sketch. - /// The compression parameter. - /// if executed correctly, error otherwise - /// - bool Create(RedisKey key, long compression = 100); + /// + /// Allocate memory and initialize a t-digest sketch. + /// + /// The name of the sketch. + /// The compression parameter. + /// if executed correctly, error otherwise + /// + bool Create(RedisKey key, long compression = 100); - /// - /// Returns information about a sketch. - /// - /// The name of the sketch. - /// information about a sketch - /// - TdigestInformation Info(RedisKey key); + /// + /// Returns information about a sketch. + /// + /// The name of the sketch. + /// information about a sketch + /// + TdigestInformation Info(RedisKey key); - /// - /// Get the maximum observation value from the sketch. - /// - /// The name of the sketch. - /// the maximum observation value from the sketch - /// - double Max(RedisKey key); + /// + /// Get the maximum observation value from the sketch. + /// + /// The name of the sketch. + /// the maximum observation value from the sketch + /// + double Max(RedisKey key); - /// - /// Get the minimum observation value from the sketch. - /// - /// The name of the sketch. - /// the minimum observation value from the sketch - /// - double Min(RedisKey key); + /// + /// Get the minimum observation value from the sketch. + /// + /// The name of the sketch. + /// the minimum observation value from the sketch + /// + double Min(RedisKey key); - /// - /// Merges all of the values from 'from' keys to 'destination-key' sketch - /// - /// TSketch to copy observation values to (a t-digest data structure). - /// The compression parameter. - /// If destination already exists, it is overwritten. - /// Sketch to copy observation values from (a t-digest data structure). - /// if executed correctly, error otherwise - /// - bool Merge(RedisKey destinationKey, long compression = default(long), bool overide = false, params RedisKey[] sourceKeys); + /// + /// Merges all of the values from 'from' keys to 'destination-key' sketch + /// + /// TSketch to copy observation values to (a t-digest data structure). + /// The compression parameter. + /// If destination already exists, it is overwritten. + /// Sketch to copy observation values from (a t-digest data structure). + /// if executed correctly, error otherwise + /// + bool Merge(RedisKey destinationKey, long compression = default(long), bool overide = false, params RedisKey[] sourceKeys); - /// - /// Returns estimates of one or more cutoffs such that a specified fraction of the observations - /// added to this t-digest would be less than or equal to each of the specified cutoffs. - /// - /// The name of the sketch (a t-digest data structure). - /// The desired fraction (between 0 and 1 inclusively). - /// An array of results populated with quantile_1, cutoff_1, quantile_2, cutoff_2, ..., quantile_N, cutoff_N. - /// - double[] Quantile(RedisKey key, params double[] quantile); - /// - /// Retrieve the estimated rank of value (the number of observations in the sketch - /// that are smaller than value + half the number of observations that are equal to value). - /// - /// The name of the sketch (a t-digest data structure). - /// input value, for which the rank will be determined. - /// an array of results populated with rank_1, rank_2, ..., rank_N. - /// - long[] Rank(RedisKey key, params long[] values); + /// + /// Returns estimates of one or more cutoffs such that a specified fraction of the observations + /// added to this t-digest would be less than or equal to each of the specified cutoffs. + /// + /// The name of the sketch (a t-digest data structure). + /// The desired fraction (between 0 and 1 inclusively). + /// An array of results populated with quantile_1, cutoff_1, quantile_2, cutoff_2, ..., quantile_N, cutoff_N. + /// + double[] Quantile(RedisKey key, params double[] quantile); + /// + /// Retrieve the estimated rank of value (the number of observations in the sketch + /// that are smaller than value + half the number of observations that are equal to value). + /// + /// The name of the sketch (a t-digest data structure). + /// input value, for which the rank will be determined. + /// an array of results populated with rank_1, rank_2, ..., rank_N. + /// + long[] Rank(RedisKey key, params long[] values); - /// - /// Retrieve the estimated rank of value (the number of observations in the sketch - /// that are larger than value + half the number of observations that are equal to value). - /// - /// The name of the sketch (a t-digest data structure). - /// input value, for which the rank will be determined. - /// an array of results populated with rank_1, rank_2, ..., rank_N. - /// - long[] RevRank(RedisKey key, params long[] values); + /// + /// Retrieve the estimated rank of value (the number of observations in the sketch + /// that are larger than value + half the number of observations that are equal to value). + /// + /// The name of the sketch (a t-digest data structure). + /// input value, for which the rank will be determined. + /// an array of results populated with rank_1, rank_2, ..., rank_N. + /// + long[] RevRank(RedisKey key, params long[] values); - /// - /// Retrieve an estimation of the value with the given the rank. - /// - /// The name of the sketch (a t-digest data structure). - /// input rank, for which the value will be determined. - /// an array of results populated with value_1, value_2, ..., value_N. - /// - double[] ByRank(RedisKey key, params long[] ranks); + /// + /// Retrieve an estimation of the value with the given the rank. + /// + /// The name of the sketch (a t-digest data structure). + /// input rank, for which the value will be determined. + /// an array of results populated with value_1, value_2, ..., value_N. + /// + double[] ByRank(RedisKey key, params long[] ranks); - /// - /// Retrieve an estimation of the value with the given the reverse rank. - /// - /// The name of the sketch (a t-digest data structure). - /// input reverse rank, for which the value will be determined. - /// an array of results populated with value_1, value_2, ..., value_N. - /// - double[] ByRevRank(RedisKey key, params long[] ranks); + /// + /// Retrieve an estimation of the value with the given the reverse rank. + /// + /// The name of the sketch (a t-digest data structure). + /// input reverse rank, for which the value will be determined. + /// an array of results populated with value_1, value_2, ..., value_N. + /// + double[] ByRevRank(RedisKey key, params long[] ranks); - /// - /// Reset the sketch - empty the sketch and re-initialize it - /// - /// The name of the sketch (a t-digest data structure). - /// if executed correctly, error otherwise. - /// - bool Reset(RedisKey key); + /// + /// Reset the sketch - empty the sketch and re-initialize it + /// + /// The name of the sketch (a t-digest data structure). + /// if executed correctly, error otherwise. + /// + bool Reset(RedisKey key); - /// - /// Reset the sketch - empty the sketch and re-initialize it - /// - /// The name of the sketch (a t-digest data structure). - /// Exclude observation values lower than this quantile. - /// Exclude observation values higher than this quantile. - /// estimation of the mean value. Will return NaN if the sketch is empty. - /// - double TrimmedMean(RedisKey key, double lowCutQuantile, double highCutQuantile); - } + /// + /// Reset the sketch - empty the sketch and re-initialize it + /// + /// The name of the sketch (a t-digest data structure). + /// Exclude observation values lower than this quantile. + /// Exclude observation values higher than this quantile. + /// estimation of the mean value. Will return NaN if the sketch is empty. + /// + double TrimmedMean(RedisKey key, double lowCutQuantile, double highCutQuantile); } \ No newline at end of file diff --git a/src/NRedisStack/Tdigest/ITdigestCommandsAsync.cs b/src/NRedisStack/Tdigest/ITdigestCommandsAsync.cs index 7bbc22d9..6d1115d2 100644 --- a/src/NRedisStack/Tdigest/ITdigestCommandsAsync.cs +++ b/src/NRedisStack/Tdigest/ITdigestCommandsAsync.cs @@ -1,134 +1,133 @@ using NRedisStack.Tdigest.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public interface ITdigestCommandsAsync { - public interface ITdigestCommandsAsync - { - /// - /// Adds one or more observations to a t-digest sketch. - /// - /// The name of the sketch. - /// The value of the observation. - /// if executed correctly, error otherwise - /// - Task AddAsync(RedisKey key, params double[] values); + /// + /// Adds one or more observations to a t-digest sketch. + /// + /// The name of the sketch. + /// The value of the observation. + /// if executed correctly, error otherwise + /// + Task AddAsync(RedisKey key, params double[] values); - /// - /// Estimate the fraction of all observations added which are <= value. - /// - /// The name of the sketch. - /// upper limit of observation value. - /// double-reply - estimation of the fraction of all observations added which are <= value - /// - Task CDFAsync(RedisKey key, params double[] values); + /// + /// Estimate the fraction of all observations added which are <= value. + /// + /// The name of the sketch. + /// upper limit of observation value. + /// double-reply - estimation of the fraction of all observations added which are <= value + /// + Task CDFAsync(RedisKey key, params double[] values); - /// - /// Allocate memory and initialize a t-digest sketch. - /// - /// The name of the sketch. - /// The compression parameter. - /// if executed correctly, error otherwise - /// - Task CreateAsync(RedisKey key, long compression = 100); - /// - /// Returns information about a sketch. - /// - /// The name of the sketch. - /// information about a sketch - /// - Task InfoAsync(RedisKey key); + /// + /// Allocate memory and initialize a t-digest sketch. + /// + /// The name of the sketch. + /// The compression parameter. + /// if executed correctly, error otherwise + /// + Task CreateAsync(RedisKey key, long compression = 100); + /// + /// Returns information about a sketch. + /// + /// The name of the sketch. + /// information about a sketch + /// + Task InfoAsync(RedisKey key); - /// - /// Get the maximum observation value from the sketch. - /// - /// The name of the sketch. - /// the maximum observation value from the sketch - /// - Task MaxAsync(RedisKey key); + /// + /// Get the maximum observation value from the sketch. + /// + /// The name of the sketch. + /// the maximum observation value from the sketch + /// + Task MaxAsync(RedisKey key); - /// - /// Get the minimum observation value from the sketch. - /// - /// The name of the sketch. - /// the minimum observation value from the sketch - /// - Task MinAsync(RedisKey key); + /// + /// Get the minimum observation value from the sketch. + /// + /// The name of the sketch. + /// the minimum observation value from the sketch + /// + Task MinAsync(RedisKey key); - /// - /// Merges all of the values from 'from' keys to 'destination-key' sketch - /// - /// TSketch to copy observation values to (a t-digest data structure). - /// The compression parameter. - /// If destination already exists, it is overwritten. - /// Sketch to copy observation values from (a t-digest data structure). - /// if executed correctly, error otherwise - /// - Task MergeAsync(RedisKey destinationKey, long compression = default(long), bool overide = false, params RedisKey[] sourceKeys); + /// + /// Merges all of the values from 'from' keys to 'destination-key' sketch + /// + /// TSketch to copy observation values to (a t-digest data structure). + /// The compression parameter. + /// If destination already exists, it is overwritten. + /// Sketch to copy observation values from (a t-digest data structure). + /// if executed correctly, error otherwise + /// + Task MergeAsync(RedisKey destinationKey, long compression = default(long), bool overide = false, params RedisKey[] sourceKeys); - /// - /// Returns estimates of one or more cutoffs such that a specified fraction of the observations - ///added to this t-digest would be less than or equal to each of the specified cutoffs. - /// - /// The name of the sketch (a t-digest data structure). - /// The desired fraction (between 0 and 1 inclusively). - /// An array of results populated with quantile_1, cutoff_1, quantile_2, cutoff_2, ..., quantile_N, cutoff_N. - /// - Task QuantileAsync(RedisKey key, params double[] quantile); + /// + /// Returns estimates of one or more cutoffs such that a specified fraction of the observations + ///added to this t-digest would be less than or equal to each of the specified cutoffs. + /// + /// The name of the sketch (a t-digest data structure). + /// The desired fraction (between 0 and 1 inclusively). + /// An array of results populated with quantile_1, cutoff_1, quantile_2, cutoff_2, ..., quantile_N, cutoff_N. + /// + Task QuantileAsync(RedisKey key, params double[] quantile); - /// - /// Retrieve the estimated rank of value (the number of observations in the sketch - /// that are smaller than value + half the number of observations that are equal to value). - /// - /// The name of the sketch (a t-digest data structure). - /// input value, for which the rank will be determined. - /// an array of results populated with rank_1, rank_2, ..., rank_N. - /// - Task RankAsync(RedisKey key, params long[] values); + /// + /// Retrieve the estimated rank of value (the number of observations in the sketch + /// that are smaller than value + half the number of observations that are equal to value). + /// + /// The name of the sketch (a t-digest data structure). + /// input value, for which the rank will be determined. + /// an array of results populated with rank_1, rank_2, ..., rank_N. + /// + Task RankAsync(RedisKey key, params long[] values); - /// - /// Retrieve the estimated rank of value (the number of observations in the sketch - /// that are larger than value + half the number of observations that are equal to value). - /// - /// The name of the sketch (a t-digest data structure). - /// input value, for which the rank will be determined. - /// an array of results populated with rank_1, rank_2, ..., rank_N. - /// - Task RevRankAsync(RedisKey key, params long[] values); + /// + /// Retrieve the estimated rank of value (the number of observations in the sketch + /// that are larger than value + half the number of observations that are equal to value). + /// + /// The name of the sketch (a t-digest data structure). + /// input value, for which the rank will be determined. + /// an array of results populated with rank_1, rank_2, ..., rank_N. + /// + Task RevRankAsync(RedisKey key, params long[] values); - /// - /// Retrieve an estimation of the value with the given the rank. - /// - /// The name of the sketch (a t-digest data structure). - /// input rank, for which the value will be determined. - /// an array of results populated with value_1, value_2, ..., value_N. - /// - Task ByRankAsync(RedisKey key, params long[] ranks); + /// + /// Retrieve an estimation of the value with the given the rank. + /// + /// The name of the sketch (a t-digest data structure). + /// input rank, for which the value will be determined. + /// an array of results populated with value_1, value_2, ..., value_N. + /// + Task ByRankAsync(RedisKey key, params long[] ranks); - /// - /// Retrieve an estimation of the value with the given the reverse rank. - /// - /// The name of the sketch (a t-digest data structure). - /// input reverse rank, for which the value will be determined. - /// an array of results populated with value_1, value_2, ..., value_N. - /// - Task ByRevRankAsync(RedisKey key, params long[] ranks); + /// + /// Retrieve an estimation of the value with the given the reverse rank. + /// + /// The name of the sketch (a t-digest data structure). + /// input reverse rank, for which the value will be determined. + /// an array of results populated with value_1, value_2, ..., value_N. + /// + Task ByRevRankAsync(RedisKey key, params long[] ranks); - /// - /// Reset the sketch - empty the sketch and re-initialize it - /// - /// The name of the sketch (a t-digest data structure). - /// if executed correctly, error otherwise. - /// - Task ResetAsync(RedisKey key); + /// + /// Reset the sketch - empty the sketch and re-initialize it + /// + /// The name of the sketch (a t-digest data structure). + /// if executed correctly, error otherwise. + /// + Task ResetAsync(RedisKey key); - /// - /// Reset the sketch - empty the sketch and re-initialize it - /// - /// The name of the sketch (a t-digest data structure). - /// Exclude observation values lower than this quantile. - /// Exclude observation values higher than this quantile. - /// estimation of the mean value. Will return NaN if the sketch is empty. - /// - Task TrimmedMeanAsync(RedisKey key, double lowCutQuantile, double highCutQuantile); - } + /// + /// Reset the sketch - empty the sketch and re-initialize it + /// + /// The name of the sketch (a t-digest data structure). + /// Exclude observation values lower than this quantile. + /// Exclude observation values higher than this quantile. + /// estimation of the mean value. Will return NaN if the sketch is empty. + /// + Task TrimmedMeanAsync(RedisKey key, double lowCutQuantile, double highCutQuantile); } \ No newline at end of file diff --git a/src/NRedisStack/Tdigest/Literals/CommandArgs.cs b/src/NRedisStack/Tdigest/Literals/CommandArgs.cs index 04390e37..0720dedc 100644 --- a/src/NRedisStack/Tdigest/Literals/CommandArgs.cs +++ b/src/NRedisStack/Tdigest/Literals/CommandArgs.cs @@ -1,7 +1,6 @@ -namespace NRedisStack.Literals +namespace NRedisStack.Literals; + +internal class TdigestArgs { - internal class TdigestArgs - { - public const string COMPRESSION = "COMPRESSION"; - } + public const string COMPRESSION = "COMPRESSION"; } \ No newline at end of file diff --git a/src/NRedisStack/Tdigest/Literals/Commands.cs b/src/NRedisStack/Tdigest/Literals/Commands.cs index 66be06eb..186c2faf 100644 --- a/src/NRedisStack/Tdigest/Literals/Commands.cs +++ b/src/NRedisStack/Tdigest/Literals/Commands.cs @@ -1,21 +1,20 @@ -namespace NRedisStack.Literals +namespace NRedisStack.Literals; + +internal class TDIGEST { - internal class TDIGEST - { - public const string CREATE = "TDIGEST.CREATE"; - public const string RESET = "TDIGEST.RESET"; - public const string ADD = "TDIGEST.ADD"; - public const string MERGE = "TDIGEST.MERGE"; - public const string MERGESTORE = "TDIGEST.MERGESTORE"; - public const string MIN = "TDIGEST.MIN"; - public const string MAX = "TDIGEST.MAX"; - public const string QUANTILE = "TDIGEST.QUANTILE"; - public const string CDF = "TDIGEST.CDF"; - public const string TRIMMED_MEAN = "TDIGEST.TRIMMED_MEAN"; - public const string INFO = "TDIGEST.INFO"; - public const string RANK = "TDIGEST.RANK"; - public const string REVRANK = "TDIGEST.REVRANK"; - public const string BYRANK = "TDIGEST.BYRANK"; - public const string BYREVRANK = "TDIGEST.BYREVRANK"; - } + public const string CREATE = "TDIGEST.CREATE"; + public const string RESET = "TDIGEST.RESET"; + public const string ADD = "TDIGEST.ADD"; + public const string MERGE = "TDIGEST.MERGE"; + public const string MERGESTORE = "TDIGEST.MERGESTORE"; + public const string MIN = "TDIGEST.MIN"; + public const string MAX = "TDIGEST.MAX"; + public const string QUANTILE = "TDIGEST.QUANTILE"; + public const string CDF = "TDIGEST.CDF"; + public const string TRIMMED_MEAN = "TDIGEST.TRIMMED_MEAN"; + public const string INFO = "TDIGEST.INFO"; + public const string RANK = "TDIGEST.RANK"; + public const string REVRANK = "TDIGEST.REVRANK"; + public const string BYRANK = "TDIGEST.BYRANK"; + public const string BYREVRANK = "TDIGEST.BYREVRANK"; } \ No newline at end of file diff --git a/src/NRedisStack/Tdigest/TdigestCommandBuilder.cs b/src/NRedisStack/Tdigest/TdigestCommandBuilder.cs index 2517f14d..dbcad0a8 100644 --- a/src/NRedisStack/Tdigest/TdigestCommandBuilder.cs +++ b/src/NRedisStack/Tdigest/TdigestCommandBuilder.cs @@ -2,130 +2,128 @@ using StackExchange.Redis; using NRedisStack.RedisStackCommands; -namespace NRedisStack -{ +namespace NRedisStack; - public static class TdigestCommandBuilder +public static class TdigestCommandBuilder +{ + public static SerializedCommand Add(RedisKey key, params double[] values) { - public static SerializedCommand Add(RedisKey key, params double[] values) + if (values.Length < 0) throw new ArgumentOutOfRangeException(nameof(values)); + var args = new string[values.Length + 1]; + args[0] = key.ToString(); + for (int i = 0; i < values.Length; i++) { - if (values.Length < 0) throw new ArgumentOutOfRangeException(nameof(values)); - var args = new string[values.Length + 1]; - args[0] = key.ToString(); - for (int i = 0; i < values.Length; i++) - { - args[i + 1] = values[i].ToString(); - } - - return new SerializedCommand(TDIGEST.ADD, args); + args[i + 1] = values[i].ToString(); } - public static SerializedCommand CDF(RedisKey key, params double[] values) - { - var args = new List(values.Length + 1) { key }; - foreach (var value in values) args.Add(value); - return new SerializedCommand(TDIGEST.CDF, args); - } + return new(TDIGEST.ADD, args); + } - public static SerializedCommand Create(RedisKey key, long compression = 100) - { - return new SerializedCommand(TDIGEST.CREATE, key, TdigestArgs.COMPRESSION, compression); - } + public static SerializedCommand CDF(RedisKey key, params double[] values) + { + var args = new List(values.Length + 1) { key }; + foreach (var value in values) args.Add(value); + return new(TDIGEST.CDF, args); + } - public static SerializedCommand Info(RedisKey key) - { - return new SerializedCommand(TDIGEST.INFO, key); - } + public static SerializedCommand Create(RedisKey key, long compression = 100) + { + return new(TDIGEST.CREATE, key, TdigestArgs.COMPRESSION, compression); + } - public static SerializedCommand Max(RedisKey key) + public static SerializedCommand Info(RedisKey key) + { + return new(TDIGEST.INFO, key); + } + + public static SerializedCommand Max(RedisKey key) + { + return new(TDIGEST.MAX, key); + } + + public static SerializedCommand Min(RedisKey key) + { + return new(TDIGEST.MIN, key); + } + + public static SerializedCommand Merge(RedisKey destinationKey, long compression = default(long), bool overide = false, params RedisKey[] sourceKeys) + { + if (sourceKeys.Length < 1) throw new ArgumentOutOfRangeException(nameof(sourceKeys)); + + int numkeys = sourceKeys.Length; + var args = new List() { destinationKey, numkeys }; + foreach (var key in sourceKeys) { - return new SerializedCommand(TDIGEST.MAX, key); + args.Add(key); } - public static SerializedCommand Min(RedisKey key) + if (compression != default(long)) { - return new SerializedCommand(TDIGEST.MIN, key); + args.Add("COMPRESSION"); + args.Add(compression); } - public static SerializedCommand Merge(RedisKey destinationKey, long compression = default(long), bool overide = false, params RedisKey[] sourceKeys) + if (overide) { - if (sourceKeys.Length < 1) throw new ArgumentOutOfRangeException(nameof(sourceKeys)); - - int numkeys = sourceKeys.Length; - var args = new List() { destinationKey, numkeys }; - foreach (var key in sourceKeys) - { - args.Add(key); - } - - if (compression != default(long)) - { - args.Add("COMPRESSION"); - args.Add(compression); - } - - if (overide) - { - args.Add("OVERRIDE"); - } - - return new SerializedCommand(TDIGEST.MERGE, args); + args.Add("OVERRIDE"); } - public static SerializedCommand Quantile(RedisKey key, params double[] quantile) - { - if (quantile.Length < 1) throw new ArgumentOutOfRangeException(nameof(quantile)); + return new(TDIGEST.MERGE, args); + } - var args = new List { key }; - foreach (var q in quantile) args.Add(q); + public static SerializedCommand Quantile(RedisKey key, params double[] quantile) + { + if (quantile.Length < 1) throw new ArgumentOutOfRangeException(nameof(quantile)); - return new SerializedCommand(TDIGEST.QUANTILE, args); - } + var args = new List { key }; + foreach (var q in quantile) args.Add(q); - public static SerializedCommand Rank(RedisKey key, params long[] values) - { - if (values.Length < 1) throw new ArgumentOutOfRangeException(nameof(values)); + return new(TDIGEST.QUANTILE, args); + } - var args = new List(values.Length + 1) { key }; - foreach (var v in values) args.Add(v); - return new SerializedCommand(TDIGEST.RANK, args); - } + public static SerializedCommand Rank(RedisKey key, params long[] values) + { + if (values.Length < 1) throw new ArgumentOutOfRangeException(nameof(values)); - public static SerializedCommand RevRank(RedisKey key, params long[] values) - { - if (values.Length < 1) throw new ArgumentOutOfRangeException(nameof(values)); + var args = new List(values.Length + 1) { key }; + foreach (var v in values) args.Add(v); + return new(TDIGEST.RANK, args); + } - var args = new List(values.Length + 1) { key }; - foreach (var v in values) args.Add(v); - return new SerializedCommand(TDIGEST.REVRANK, args); - } + public static SerializedCommand RevRank(RedisKey key, params long[] values) + { + if (values.Length < 1) throw new ArgumentOutOfRangeException(nameof(values)); - public static SerializedCommand ByRank(RedisKey key, params long[] ranks) - { - if (ranks.Length < 1) throw new ArgumentOutOfRangeException(nameof(ranks)); + var args = new List(values.Length + 1) { key }; + foreach (var v in values) args.Add(v); + return new(TDIGEST.REVRANK, args); + } - var args = new List(ranks.Length + 1) { key }; - foreach (var v in ranks) args.Add(v); - return new SerializedCommand(TDIGEST.BYRANK, args); - } + public static SerializedCommand ByRank(RedisKey key, params long[] ranks) + { + if (ranks.Length < 1) throw new ArgumentOutOfRangeException(nameof(ranks)); - public static SerializedCommand ByRevRank(RedisKey key, params long[] ranks) - { - if (ranks.Length < 1) throw new ArgumentOutOfRangeException(nameof(ranks)); + var args = new List(ranks.Length + 1) { key }; + foreach (var v in ranks) args.Add(v); + return new(TDIGEST.BYRANK, args); + } - var args = new List(ranks.Length + 1) { key }; - foreach (var v in ranks) args.Add(v); - return new SerializedCommand(TDIGEST.BYREVRANK, args); - } + public static SerializedCommand ByRevRank(RedisKey key, params long[] ranks) + { + if (ranks.Length < 1) throw new ArgumentOutOfRangeException(nameof(ranks)); - public static SerializedCommand Reset(RedisKey key) - { - return new SerializedCommand(TDIGEST.RESET, key); - } + var args = new List(ranks.Length + 1) { key }; + foreach (var v in ranks) args.Add(v); + return new(TDIGEST.BYREVRANK, args); + } - public static SerializedCommand TrimmedMean(RedisKey key, double lowCutQuantile, double highCutQuantile) - { - return new SerializedCommand(TDIGEST.TRIMMED_MEAN, key, lowCutQuantile, highCutQuantile); - } + public static SerializedCommand Reset(RedisKey key) + { + return new(TDIGEST.RESET, key); + } + + public static SerializedCommand TrimmedMean(RedisKey key, double lowCutQuantile, double highCutQuantile) + { + return new(TDIGEST.TRIMMED_MEAN, key, lowCutQuantile, highCutQuantile); } } \ No newline at end of file diff --git a/src/NRedisStack/Tdigest/TdigestCommands.cs b/src/NRedisStack/Tdigest/TdigestCommands.cs index fd11a3e8..802752e3 100644 --- a/src/NRedisStack/Tdigest/TdigestCommands.cs +++ b/src/NRedisStack/Tdigest/TdigestCommands.cs @@ -1,100 +1,98 @@ using NRedisStack.Tdigest.DataTypes; using StackExchange.Redis; -namespace NRedisStack -{ +namespace NRedisStack; - public class TdigestCommands : TdigestCommandsAsync, ITdigestCommands +public class TdigestCommands : TdigestCommandsAsync, ITdigestCommands +{ + readonly IDatabase _db; + public TdigestCommands(IDatabase db) : base(db) { - IDatabase _db; - public TdigestCommands(IDatabase db) : base(db) - { - _db = db; - } + _db = db; + } - /// - public bool Add(RedisKey key, params double[] values) - { - return _db.Execute(TdigestCommandBuilder.Add(key, values)).OKtoBoolean(); - } + /// + public bool Add(RedisKey key, params double[] values) + { + return _db.Execute(TdigestCommandBuilder.Add(key, values)).OKtoBoolean(); + } - /// - public double[] CDF(RedisKey key, params double[] values) - { - return _db.Execute(TdigestCommandBuilder.CDF(key, values)).ToDoubleArray(); - } + /// + public double[] CDF(RedisKey key, params double[] values) + { + return _db.Execute(TdigestCommandBuilder.CDF(key, values)).ToDoubleArray(); + } - /// - public bool Create(RedisKey key, long compression = 100) - { - return _db.Execute(TdigestCommandBuilder.Create(key, compression)).OKtoBoolean(); - } + /// + public bool Create(RedisKey key, long compression = 100) + { + return _db.Execute(TdigestCommandBuilder.Create(key, compression)).OKtoBoolean(); + } - /// - public TdigestInformation Info(RedisKey key) - { - return _db.Execute(TdigestCommandBuilder.Info(key)).ToTdigestInfo(); - } + /// + public TdigestInformation Info(RedisKey key) + { + return _db.Execute(TdigestCommandBuilder.Info(key)).ToTdigestInfo(); + } - /// - public double Max(RedisKey key) - { - return _db.Execute(TdigestCommandBuilder.Max(key)).ToDouble(); - } + /// + public double Max(RedisKey key) + { + return _db.Execute(TdigestCommandBuilder.Max(key)).ToDouble(); + } - /// - public double Min(RedisKey key) - { - var cmd = TdigestCommandBuilder.Min(key); - var res = _db.Execute(cmd); - return res.ToDouble(); - } + /// + public double Min(RedisKey key) + { + var cmd = TdigestCommandBuilder.Min(key); + var res = _db.Execute(cmd); + return res.ToDouble(); + } - /// - public bool Merge(RedisKey destinationKey, long compression = default(long), bool overide = false, params RedisKey[] sourceKeys) - { - return _db.Execute(TdigestCommandBuilder.Merge(destinationKey, compression, overide, sourceKeys)).OKtoBoolean(); - } + /// + public bool Merge(RedisKey destinationKey, long compression = default(long), bool overide = false, params RedisKey[] sourceKeys) + { + return _db.Execute(TdigestCommandBuilder.Merge(destinationKey, compression, overide, sourceKeys)).OKtoBoolean(); + } - /// - public double[] Quantile(RedisKey key, params double[] quantile) - { - return _db.Execute(TdigestCommandBuilder.Quantile(key, quantile)).ToDoubleArray(); - } + /// + public double[] Quantile(RedisKey key, params double[] quantile) + { + return _db.Execute(TdigestCommandBuilder.Quantile(key, quantile)).ToDoubleArray(); + } - /// - public long[] Rank(RedisKey key, params long[] values) - { - return _db.Execute(TdigestCommandBuilder.Rank(key, values)).ToLongArray(); - } + /// + public long[] Rank(RedisKey key, params long[] values) + { + return _db.Execute(TdigestCommandBuilder.Rank(key, values)).ToLongArray(); + } - /// - public long[] RevRank(RedisKey key, params long[] values) - { - return _db.Execute(TdigestCommandBuilder.RevRank(key, values)).ToLongArray(); - } + /// + public long[] RevRank(RedisKey key, params long[] values) + { + return _db.Execute(TdigestCommandBuilder.RevRank(key, values)).ToLongArray(); + } - /// - public double[] ByRank(RedisKey key, params long[] ranks) - { - return _db.Execute(TdigestCommandBuilder.ByRank(key, ranks)).ToDoubleArray(); - } + /// + public double[] ByRank(RedisKey key, params long[] ranks) + { + return _db.Execute(TdigestCommandBuilder.ByRank(key, ranks)).ToDoubleArray(); + } - /// - public double[] ByRevRank(RedisKey key, params long[] ranks) - { - return _db.Execute(TdigestCommandBuilder.ByRevRank(key, ranks)).ToDoubleArray(); - } + /// + public double[] ByRevRank(RedisKey key, params long[] ranks) + { + return _db.Execute(TdigestCommandBuilder.ByRevRank(key, ranks)).ToDoubleArray(); + } - /// - public bool Reset(RedisKey key) - { - return _db.Execute(TdigestCommandBuilder.Reset(key)).OKtoBoolean(); - } + /// + public bool Reset(RedisKey key) + { + return _db.Execute(TdigestCommandBuilder.Reset(key)).OKtoBoolean(); + } - /// - public double TrimmedMean(RedisKey key, double lowCutQuantile, double highCutQuantile) - { - return _db.Execute(TdigestCommandBuilder.TrimmedMean(key, lowCutQuantile, highCutQuantile)).ToDouble(); - } + /// + public double TrimmedMean(RedisKey key, double lowCutQuantile, double highCutQuantile) + { + return _db.Execute(TdigestCommandBuilder.TrimmedMean(key, lowCutQuantile, highCutQuantile)).ToDouble(); } } \ No newline at end of file diff --git a/src/NRedisStack/Tdigest/TdigestCommandsAsync.cs b/src/NRedisStack/Tdigest/TdigestCommandsAsync.cs index ee162de4..a4a336e2 100644 --- a/src/NRedisStack/Tdigest/TdigestCommandsAsync.cs +++ b/src/NRedisStack/Tdigest/TdigestCommandsAsync.cs @@ -1,99 +1,91 @@ using NRedisStack.Tdigest.DataTypes; using StackExchange.Redis; -namespace NRedisStack -{ +namespace NRedisStack; - public class TdigestCommandsAsync : ITdigestCommandsAsync +public class TdigestCommandsAsync(IDatabaseAsync db) : ITdigestCommandsAsync +{ + /// + public async Task AddAsync(RedisKey key, params double[] values) { - IDatabaseAsync _db; - public TdigestCommandsAsync(IDatabaseAsync db) - { - _db = db; - } - - /// - public async Task AddAsync(RedisKey key, params double[] values) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.Add(key, values))).OKtoBoolean(); - } + return (await db.ExecuteAsync(TdigestCommandBuilder.Add(key, values))).OKtoBoolean(); + } - /// - public async Task CDFAsync(RedisKey key, params double[] values) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.CDF(key, values))).ToDoubleArray(); - } + /// + public async Task CDFAsync(RedisKey key, params double[] values) + { + return (await db.ExecuteAsync(TdigestCommandBuilder.CDF(key, values))).ToDoubleArray(); + } - /// - public async Task CreateAsync(RedisKey key, long compression = 100) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.Create(key, compression))).OKtoBoolean(); - } + /// + public async Task CreateAsync(RedisKey key, long compression = 100) + { + return (await db.ExecuteAsync(TdigestCommandBuilder.Create(key, compression))).OKtoBoolean(); + } - /// - public async Task InfoAsync(RedisKey key) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.Info(key))).ToTdigestInfo(); - } + /// + public async Task InfoAsync(RedisKey key) + { + return (await db.ExecuteAsync(TdigestCommandBuilder.Info(key))).ToTdigestInfo(); + } - /// - public async Task MaxAsync(RedisKey key) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.Max(key))).ToDouble(); - } + /// + public async Task MaxAsync(RedisKey key) + { + return (await db.ExecuteAsync(TdigestCommandBuilder.Max(key))).ToDouble(); + } - /// - public async Task MinAsync(RedisKey key) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.Min(key))).ToDouble(); - } + /// + public async Task MinAsync(RedisKey key) + { + return (await db.ExecuteAsync(TdigestCommandBuilder.Min(key))).ToDouble(); + } - /// - public async Task MergeAsync(RedisKey destinationKey, long compression = default(long), bool overide = false, params RedisKey[] sourceKeys) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.Merge(destinationKey, compression, overide, sourceKeys))).OKtoBoolean(); - } + /// + public async Task MergeAsync(RedisKey destinationKey, long compression = default(long), bool overide = false, params RedisKey[] sourceKeys) + { + return (await db.ExecuteAsync(TdigestCommandBuilder.Merge(destinationKey, compression, overide, sourceKeys))).OKtoBoolean(); + } - ///added to this t-digest would be less than or equal to each of the specified cutoffs. - /// - public async Task QuantileAsync(RedisKey key, params double[] quantile) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.Quantile(key, quantile))).ToDoubleArray(); - } + ///added to this t-digest would be less than or equal to each of the specified cutoffs. + /// + public async Task QuantileAsync(RedisKey key, params double[] quantile) + { + return (await db.ExecuteAsync(TdigestCommandBuilder.Quantile(key, quantile))).ToDoubleArray(); + } - /// - public async Task RankAsync(RedisKey key, params long[] values) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.Rank(key, values))).ToLongArray(); - } + /// + public async Task RankAsync(RedisKey key, params long[] values) + { + return (await db.ExecuteAsync(TdigestCommandBuilder.Rank(key, values))).ToLongArray(); + } - /// - public async Task RevRankAsync(RedisKey key, params long[] values) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.RevRank(key, values))).ToLongArray(); - } + /// + public async Task RevRankAsync(RedisKey key, params long[] values) + { + return (await db.ExecuteAsync(TdigestCommandBuilder.RevRank(key, values))).ToLongArray(); + } - /// - public async Task ByRankAsync(RedisKey key, params long[] ranks) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.ByRank(key, ranks))).ToDoubleArray(); - } + /// + public async Task ByRankAsync(RedisKey key, params long[] ranks) + { + return (await db.ExecuteAsync(TdigestCommandBuilder.ByRank(key, ranks))).ToDoubleArray(); + } - /// - public async Task ByRevRankAsync(RedisKey key, params long[] ranks) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.ByRevRank(key, ranks))).ToDoubleArray(); - } + /// + public async Task ByRevRankAsync(RedisKey key, params long[] ranks) + { + return (await db.ExecuteAsync(TdigestCommandBuilder.ByRevRank(key, ranks))).ToDoubleArray(); + } - /// - public async Task ResetAsync(RedisKey key) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.Reset(key))).OKtoBoolean(); - } + /// + public async Task ResetAsync(RedisKey key) + { + return (await db.ExecuteAsync(TdigestCommandBuilder.Reset(key))).OKtoBoolean(); + } - /// - public async Task TrimmedMeanAsync(RedisKey key, double lowCutQuantile, double highCutQuantile) - { - return (await _db.ExecuteAsync(TdigestCommandBuilder.TrimmedMean(key, lowCutQuantile, highCutQuantile))).ToDouble(); - } + /// + public async Task TrimmedMeanAsync(RedisKey key, double lowCutQuantile, double highCutQuantile) + { + return (await db.ExecuteAsync(TdigestCommandBuilder.TrimmedMean(key, lowCutQuantile, highCutQuantile))).ToDouble(); } } \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/DataTypes/TSParameters.cs b/src/NRedisStack/TimeSeries/DataTypes/TSParameters.cs index f70e9629..ce799501 100644 --- a/src/NRedisStack/TimeSeries/DataTypes/TSParameters.cs +++ b/src/NRedisStack/TimeSeries/DataTypes/TSParameters.cs @@ -1,96 +1,94 @@ using NRedisStack.DataTypes; using NRedisStack.Literals.Enums; -namespace NRedisStack -{ - public class TsBaseParams - { - protected IList parameters; +namespace NRedisStack; - internal TsBaseParams() - { - this.parameters = new List(); - } - - internal TsBaseParams(IList parameters) - { - this.parameters = parameters; - } +public class TsBaseParams +{ + protected IList parameters; - internal object[] ToArray(string key) - { - parameters.Insert(0, key); - return parameters.ToArray(); - } + internal TsBaseParams() + { + parameters = new List(); } - public class TsCreateParams : TsBaseParams + internal TsBaseParams(IList parameters) { - internal TsCreateParams(IList parameters) : base(parameters) { } - - internal TsCreateParams(long? retentionTime, IReadOnlyCollection? labels, bool? uncompressed, - long? chunkSizeBytes, TsDuplicatePolicy? policy) - { - parameters.AddRetentionTime(retentionTime); - parameters.AddChunkSize(chunkSizeBytes); - parameters.AddLabels(labels); - parameters.AddUncompressed(uncompressed); - parameters.AddDuplicatePolicy(policy); - } + this.parameters = parameters; } - public class TsAlterParams : TsBaseParams + internal object[] ToArray(string key) { - internal TsAlterParams(IList parameters) : base(parameters) { } - - internal TsAlterParams(long? retentionTime, long? chunkSizeBytes, TsDuplicatePolicy? policy, IReadOnlyCollection? labels) - { - parameters.AddRetentionTime(retentionTime); - parameters.AddChunkSize(chunkSizeBytes); - parameters.AddDuplicatePolicy(policy); - parameters.AddLabels(labels); - } + parameters.Insert(0, key); + return parameters.ToArray(); } +} - public class TsAddParams : TsBaseParams - { - internal TsAddParams(IList parameters) : base(parameters) { } +public class TsCreateParams : TsBaseParams +{ + internal TsCreateParams(IList parameters) : base(parameters) { } - internal TsAddParams(TimeStamp timestamp, double value, long? retentionTime, IReadOnlyCollection? labels, bool? uncompressed, long? chunkSizeBytes, TsDuplicatePolicy? policy) - { - parameters.Add(timestamp.Value); - parameters.Add(value); - parameters.AddRetentionTime(retentionTime); - parameters.AddChunkSize(chunkSizeBytes); - parameters.AddLabels(labels); - parameters.AddUncompressed(uncompressed); - parameters.AddOnDuplicate(policy); - } + internal TsCreateParams(long? retentionTime, IReadOnlyCollection? labels, bool? uncompressed, + long? chunkSizeBytes, TsDuplicatePolicy? policy) + { + parameters.AddRetentionTime(retentionTime); + parameters.AddChunkSize(chunkSizeBytes); + parameters.AddLabels(labels); + parameters.AddUncompressed(uncompressed); + parameters.AddDuplicatePolicy(policy); } +} - public class TsIncrByParams : TsBaseParams - { - internal TsIncrByParams(IList parameters) : base(parameters) { } +public class TsAlterParams : TsBaseParams +{ + internal TsAlterParams(IList parameters) : base(parameters) { } - internal TsIncrByParams(double value, TimeStamp? timestampMaybe, long? retentionTime, - IReadOnlyCollection? labels, bool? uncompressed, long? chunkSizeBytes) - { - parameters.Add(value); - if (timestampMaybe is { } timestamp) parameters.AddTimeStamp(timestamp); - parameters.AddRetentionTime(retentionTime); - parameters.AddChunkSize(chunkSizeBytes); - if (labels != null) parameters.AddLabels(labels); - parameters.AddUncompressed(uncompressed); - } + internal TsAlterParams(long? retentionTime, long? chunkSizeBytes, TsDuplicatePolicy? policy, IReadOnlyCollection? labels) + { + parameters.AddRetentionTime(retentionTime); + parameters.AddChunkSize(chunkSizeBytes); + parameters.AddDuplicatePolicy(policy); + parameters.AddLabels(labels); } +} - public class TsDecrByParams : TsIncrByParams - { - internal TsDecrByParams(IList parameters) : base(parameters) { } +public class TsAddParams : TsBaseParams +{ + internal TsAddParams(IList parameters) : base(parameters) { } - internal TsDecrByParams(double value, TimeStamp? timestampMaybe, long? retentionTime, IReadOnlyCollection? labels, bool? uncompressed, long? chunkSizeBytes) - : base(value, timestampMaybe, retentionTime, labels, uncompressed, chunkSizeBytes) - { } + internal TsAddParams(TimeStamp timestamp, double value, long? retentionTime, IReadOnlyCollection? labels, bool? uncompressed, long? chunkSizeBytes, TsDuplicatePolicy? policy) + { + parameters.Add(timestamp.Value); + parameters.Add(value); + parameters.AddRetentionTime(retentionTime); + parameters.AddChunkSize(chunkSizeBytes); + parameters.AddLabels(labels); + parameters.AddUncompressed(uncompressed); + parameters.AddOnDuplicate(policy); } +} +public class TsIncrByParams : TsBaseParams +{ + internal TsIncrByParams(IList parameters) : base(parameters) { } + + internal TsIncrByParams(double value, TimeStamp? timestampMaybe, long? retentionTime, + IReadOnlyCollection? labels, bool? uncompressed, long? chunkSizeBytes) + { + parameters.Add(value); + if (timestampMaybe is { } timestamp) parameters.AddTimeStamp(timestamp); + parameters.AddRetentionTime(retentionTime); + parameters.AddChunkSize(chunkSizeBytes); + if (labels != null) parameters.AddLabels(labels); + parameters.AddUncompressed(uncompressed); + } } + +public class TsDecrByParams : TsIncrByParams +{ + internal TsDecrByParams(IList parameters) : base(parameters) { } + + internal TsDecrByParams(double value, TimeStamp? timestampMaybe, long? retentionTime, IReadOnlyCollection? labels, bool? uncompressed, long? chunkSizeBytes) + : base(value, timestampMaybe, retentionTime, labels, uncompressed, chunkSizeBytes) + { } +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesChunck.cs b/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesChunck.cs index f6f7f8f3..967fa8e4 100644 --- a/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesChunck.cs +++ b/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesChunck.cs @@ -1,43 +1,42 @@ -namespace NRedisStack.DataTypes +namespace NRedisStack.DataTypes; + +/// +/// A key-value pair class represetns metadata label of time-series. +/// +public class TimeSeriesChunck { /// - /// A key-value pair class represetns metadata label of time-series. + /// First timestamp present in the chunk /// - public class TimeSeriesChunck - { - /// - /// First timestamp present in the chunk - /// - public long StartTimestamp { get; } + public long StartTimestamp { get; } - /// - /// Last timestamp present in the chunk - /// - public long EndTimestamp { get; } + /// + /// Last timestamp present in the chunk + /// + public long EndTimestamp { get; } - /// - /// Total number of samples in the chunk - /// - public long Samples { get; } + /// + /// Total number of samples in the chunk + /// + public long Samples { get; } - /// - /// The chunk data size in bytes. This is the exact size that used for - /// data only inside the chunk. It does not include other overheads. - /// - public long Size { get; } + /// + /// The chunk data size in bytes. This is the exact size that used for + /// data only inside the chunk. It does not include other overheads. + /// + public long Size { get; } - /// - /// Ratio of size and samples - /// - public string BytesPerSample { get; } + /// + /// Ratio of size and samples + /// + public string BytesPerSample { get; } - public TimeSeriesChunck(long startTimestamp, long endTimestamp, long samples, long size, string bytesPerSample) - { - StartTimestamp = startTimestamp; - EndTimestamp = endTimestamp; - Samples = samples; - Size = size; - BytesPerSample = bytesPerSample; - } + public TimeSeriesChunck(long startTimestamp, long endTimestamp, long samples, long size, string bytesPerSample) + { + StartTimestamp = startTimestamp; + EndTimestamp = endTimestamp; + Samples = samples; + Size = size; + BytesPerSample = bytesPerSample; } -} +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesInformation.cs b/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesInformation.cs index 3478c25a..7f6a8a38 100644 --- a/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesInformation.cs +++ b/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesInformation.cs @@ -1,117 +1,116 @@ using System.Text.Json; using NRedisStack.Literals.Enums; -namespace NRedisStack.DataTypes +namespace NRedisStack.DataTypes; + +/// +/// This class represents the response for TS.INFO command. +/// This object has Read-only properties and cannot be generated outside a TS.INFO response. +/// +public class TimeSeriesInformation { /// - /// This class represents the response for TS.INFO command. - /// This object has Read-only properties and cannot be generated outside a TS.INFO response. + /// Total samples in the time-series. + /// + public long TotalSamples { get; private set; } + + /// + /// Total number of bytes allocated for the time-series. + /// + public long MemoryUsage { get; private set; } + + /// + /// First timestamp present in the time-series. + /// + public TimeStamp? FirstTimeStamp { get; private set; } + + /// + /// Last timestamp present in the time-series. + /// + public TimeStamp? LastTimeStamp { get; private set; } + + /// + /// Retention time, in milliseconds, for the time-series. + /// + public long RetentionTime { get; private set; } + + /// + /// Number of Memory Chunks used for the time-series. + /// + public long ChunkCount { get; private set; } + + /// + /// Maximum Number of samples per Memory Chunk. + /// + [ObsoleteAttribute("This method has been deprecated. Use ChunkSize instead.")] + public long MaxSamplesPerChunk { get; private set; } + + /// + /// Memory Chunk size in Bytes. /// - public class TimeSeriesInformation + public long ChunkSize { get; private set; } + + /// + /// A readonly list of TimeSeriesLabel that represent metadata labels of the time-series. + /// + public IReadOnlyList? Labels { get; private set; } + + /// + /// Source key for the queries time series key. + /// + public string? SourceKey { get; private set; } + + /// + /// A readonly list of TimeSeriesRules that represent compaction Rules of the time-series. + /// + public IReadOnlyList? Rules { get; private set; } + + /// + /// The policy will define handling of duplicate samples. + /// + public TsDuplicatePolicy? DuplicatePolicy { get; private set; } + + /// + /// In DEBUG mode: Key self name. + /// + public string? KeySelfName { get; private set; } + + /// + /// In DEBUG mode: gives more information about the chunks + /// + public IReadOnlyList? Chunks { get; private set; } + + [Obsolete] + internal TimeSeriesInformation(long totalSamples, long memoryUsage, + TimeStamp? firstTimeStamp, TimeStamp? lastTimeStamp, long retentionTime, + long chunkCount, long chunkSize, IReadOnlyList? labels, + string? sourceKey, IReadOnlyList? rules, TsDuplicatePolicy? policy, + string? keySelfName = null, IReadOnlyList? chunks = null) { - /// - /// Total samples in the time-series. - /// - public long TotalSamples { get; private set; } - - /// - /// Total number of bytes allocated for the time-series. - /// - public long MemoryUsage { get; private set; } - - /// - /// First timestamp present in the time-series. - /// - public TimeStamp? FirstTimeStamp { get; private set; } - - /// - /// Last timestamp present in the time-series. - /// - public TimeStamp? LastTimeStamp { get; private set; } - - /// - /// Retention time, in milliseconds, for the time-series. - /// - public long RetentionTime { get; private set; } - - /// - /// Number of Memory Chunks used for the time-series. - /// - public long ChunkCount { get; private set; } - - /// - /// Maximum Number of samples per Memory Chunk. - /// - [ObsoleteAttribute("This method has been deprecated. Use ChunkSize instead.")] - public long MaxSamplesPerChunk { get; private set; } - - /// - /// Memory Chunk size in Bytes. - /// - public long ChunkSize { get; private set; } - - /// - /// A readonly list of TimeSeriesLabel that represent metadata labels of the time-series. - /// - public IReadOnlyList? Labels { get; private set; } - - /// - /// Source key for the queries time series key. - /// - public string? SourceKey { get; private set; } - - /// - /// A readonly list of TimeSeriesRules that represent compaction Rules of the time-series. - /// - public IReadOnlyList? Rules { get; private set; } - - /// - /// The policy will define handling of duplicate samples. - /// - public TsDuplicatePolicy? DuplicatePolicy { get; private set; } - - /// - /// In DEBUG mode: Key self name. - /// - public string? KeySelfName { get; private set; } - - /// - /// In DEBUG mode: gives more information about the chunks - /// - public IReadOnlyList? Chunks { get; private set; } - - [Obsolete] - internal TimeSeriesInformation(long totalSamples, long memoryUsage, - TimeStamp? firstTimeStamp, TimeStamp? lastTimeStamp, long retentionTime, - long chunkCount, long chunkSize, IReadOnlyList? labels, - string? sourceKey, IReadOnlyList? rules, TsDuplicatePolicy? policy, - string? keySelfName = null, IReadOnlyList? chunks = null) - { - TotalSamples = totalSamples; - MemoryUsage = memoryUsage; - FirstTimeStamp = firstTimeStamp; - LastTimeStamp = lastTimeStamp; - RetentionTime = retentionTime; - ChunkCount = chunkCount; - Labels = labels; - SourceKey = sourceKey; - Rules = rules; - // backwards compatible with RedisTimeSeries < v1.4 - MaxSamplesPerChunk = chunkSize / 16; - ChunkSize = chunkSize; - // configure what to do on duplicate sample > v1.4 - DuplicatePolicy = policy; - - // Will be equal to null when DEBUG is not in use: - KeySelfName = keySelfName; - Chunks = chunks; - - } - - /// - /// Implicit cast from TimeSeriesInformation to string. - /// - /// TimeSeriesInformation - public static implicit operator string(TimeSeriesInformation info) => JsonSerializer.Serialize(info); + TotalSamples = totalSamples; + MemoryUsage = memoryUsage; + FirstTimeStamp = firstTimeStamp; + LastTimeStamp = lastTimeStamp; + RetentionTime = retentionTime; + ChunkCount = chunkCount; + Labels = labels; + SourceKey = sourceKey; + Rules = rules; + // backwards compatible with RedisTimeSeries < v1.4 + MaxSamplesPerChunk = chunkSize / 16; + ChunkSize = chunkSize; + // configure what to do on duplicate sample > v1.4 + DuplicatePolicy = policy; + + // Will be equal to null when DEBUG is not in use: + KeySelfName = keySelfName; + Chunks = chunks; + } -} + + /// + /// Implicit cast from TimeSeriesInformation to string. + /// + /// TimeSeriesInformation + public static implicit operator string(TimeSeriesInformation info) => JsonSerializer.Serialize(info); +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesLabel.cs b/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesLabel.cs index 6f27363b..0c6279fe 100644 --- a/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesLabel.cs +++ b/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesLabel.cs @@ -1,53 +1,52 @@ -namespace NRedisStack.DataTypes +namespace NRedisStack.DataTypes; + +/// +/// A key-value pair class represetns metadata label of time-series. +/// +public class TimeSeriesLabel { /// - /// A key-value pair class represetns metadata label of time-series. + /// Label key /// - public class TimeSeriesLabel - { - /// - /// Label key - /// - public string Key { get; } + public string Key { get; } - /// - /// Label value - /// - public string Value { get; } + /// + /// Label value + /// + public string Value { get; } - /// - /// Create a new TimeSeriesLabel out of key and value strings. - /// - /// Key string - /// Value string - public TimeSeriesLabel(string key, string value) => (Key, Value) = (key, value); + /// + /// Create a new TimeSeriesLabel out of key and value strings. + /// + /// Key string + /// Value string + public TimeSeriesLabel(string key, string value) => (Key, Value) = (key, value); - /// - /// Equality of TimeSeriesLabel objects - /// - /// Object to compare - /// If two TimeSeriesLabel objects are equal - public override bool Equals(object? obj) => - obj is TimeSeriesLabel label && - Key == label.Key && - Value == label.Value; + /// + /// Equality of TimeSeriesLabel objects + /// + /// Object to compare + /// If two TimeSeriesLabel objects are equal + public override bool Equals(object? obj) => + obj is TimeSeriesLabel label && + Key == label.Key && + Value == label.Value; - /// - /// Implicit cast from TimeSeriesLabel to string. - /// - /// TimeSeriesLabel - public static implicit operator string(TimeSeriesLabel tsl) => string.Format("Key: {0}, Val:{1}", tsl.Key, tsl.Value); + /// + /// Implicit cast from TimeSeriesLabel to string. + /// + /// TimeSeriesLabel + public static implicit operator string(TimeSeriesLabel tsl) => string.Format("Key: {0}, Val:{1}", tsl.Key, tsl.Value); - /// - /// TimeSeriesLabel object hash code. - /// - /// TimeSeriesLabel object hash code. - public override int GetHashCode() - { - var hashCode = 206514262; - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Key); - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Value); - return hashCode; - } + /// + /// TimeSeriesLabel object hash code. + /// + /// TimeSeriesLabel object hash code. + public override int GetHashCode() + { + var hashCode = 206514262; + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Key); + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Value); + return hashCode; } -} +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesRule.cs b/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesRule.cs index 4deca34f..d66e31dc 100644 --- a/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesRule.cs +++ b/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesRule.cs @@ -1,66 +1,65 @@ using NRedisStack.Literals.Enums; using NRedisStack.Extensions; -namespace NRedisStack.DataTypes +namespace NRedisStack.DataTypes; + +/// +/// A class that represents time-series aggregation rule. +/// +public class TimeSeriesRule { /// - /// A class that represents time-series aggregation rule. + /// Rule's destination key. /// - public class TimeSeriesRule - { - /// - /// Rule's destination key. - /// - public string DestKey { get; private set; } + public string DestKey { get; private set; } - /// - /// Rule's aggregation time bucket. - /// - public long TimeBucket { get; private set; } + /// + /// Rule's aggregation time bucket. + /// + public long TimeBucket { get; private set; } - /// - /// Rule's aggregation type. - /// - public TsAggregation Aggregation { get; private set; } + /// + /// Rule's aggregation type. + /// + public TsAggregation Aggregation { get; private set; } - /// - /// Builds a time-series aggregation rule - /// - /// Rule's destination key. - /// Rule's aggregation time bucket. - /// Rule's aggregation type. - public TimeSeriesRule(string destKey, long timeBucket, TsAggregation aggregation) => - (DestKey, TimeBucket, Aggregation) = (destKey, timeBucket, aggregation); + /// + /// Builds a time-series aggregation rule + /// + /// Rule's destination key. + /// Rule's aggregation time bucket. + /// Rule's aggregation type. + public TimeSeriesRule(string destKey, long timeBucket, TsAggregation aggregation) => + (DestKey, TimeBucket, Aggregation) = (destKey, timeBucket, aggregation); - /// - /// Equality of TimeSeriesRule objects - /// - /// Object to compare - /// If two TimeSeriesRule objects are equal - public override bool Equals(object? obj) => - obj is TimeSeriesRule rule && - DestKey == rule.DestKey && - TimeBucket == rule.TimeBucket && - Aggregation == rule.Aggregation; + /// + /// Equality of TimeSeriesRule objects + /// + /// Object to compare + /// If two TimeSeriesRule objects are equal + public override bool Equals(object? obj) => + obj is TimeSeriesRule rule && + DestKey == rule.DestKey && + TimeBucket == rule.TimeBucket && + Aggregation == rule.Aggregation; - /// - /// Implicit cast from TimeSeriesRule to string. - /// - /// TimeSeriesRule - public static implicit operator string(TimeSeriesRule tsr) => - string.Format("DestinationKey: {0}, TimeBucket: {1}, Aggregation: {2}", tsr.DestKey, tsr.TimeBucket, tsr.Aggregation.AsArg()); + /// + /// Implicit cast from TimeSeriesRule to string. + /// + /// TimeSeriesRule + public static implicit operator string(TimeSeriesRule tsr) => + string.Format("DestinationKey: {0}, TimeBucket: {1}, Aggregation: {2}", tsr.DestKey, tsr.TimeBucket, tsr.Aggregation.AsArg()); - /// - /// TimeSeriesRule object hash code. - /// - /// TimeSeriesRule object hash code. - public override int GetHashCode() - { - var hashCode = 1554951643; - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(DestKey); - hashCode = (hashCode * -1521134295) + TimeBucket.GetHashCode(); - hashCode = (hashCode * -1521134295) + ((int)Aggregation).GetHashCode(); - return hashCode; - } + /// + /// TimeSeriesRule object hash code. + /// + /// TimeSeriesRule object hash code. + public override int GetHashCode() + { + var hashCode = 1554951643; + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(DestKey); + hashCode = (hashCode * -1521134295) + TimeBucket.GetHashCode(); + hashCode = (hashCode * -1521134295) + ((int)Aggregation).GetHashCode(); + return hashCode; } -} +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesTuple.cs b/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesTuple.cs index bc4afd85..5e83280f 100644 --- a/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesTuple.cs +++ b/src/NRedisStack/TimeSeries/DataTypes/TimeSeriesTuple.cs @@ -1,54 +1,53 @@ -namespace NRedisStack.DataTypes +namespace NRedisStack.DataTypes; + +/// +/// A class represents time-series timestamp-value pair +/// +public class TimeSeriesTuple { /// - /// A class represents time-series timestamp-value pair + /// Tuple key - timestamp. /// - public class TimeSeriesTuple - { - /// - /// Tuple key - timestamp. - /// - public TimeStamp Time { get; } + public TimeStamp Time { get; } - /// - /// Tuple value - /// - public double Val { get; } + /// + /// Tuple value + /// + public double Val { get; } - /// - /// Create new TimeSeriesTuple. - /// - /// Timestamp - /// Value - public TimeSeriesTuple(TimeStamp time, double val) => (Time, Val) = (time, val); + /// + /// Create new TimeSeriesTuple. + /// + /// Timestamp + /// Value + public TimeSeriesTuple(TimeStamp time, double val) => (Time, Val) = (time, val); - /// - /// Equality of TimeSeriesTuple objects - /// - /// Object to compare - /// If two TimeSeriesTuple objects are equal - public override bool Equals(object? obj) => - obj is TimeSeriesTuple tuple && - EqualityComparer.Default.Equals(Time, tuple.Time) && - Val == tuple.Val; + /// + /// Equality of TimeSeriesTuple objects + /// + /// Object to compare + /// If two TimeSeriesTuple objects are equal + public override bool Equals(object? obj) => + obj is TimeSeriesTuple tuple && + EqualityComparer.Default.Equals(Time, tuple.Time) && + Val == tuple.Val; - /// - /// Implicit cast from TimeSeriesTuple to string. - /// - /// TimeSeriesTuple - public static implicit operator string(TimeSeriesTuple tst) => - string.Format("Time: {0}, Val:{1}", (string)tst.Time!, tst.Val); + /// + /// Implicit cast from TimeSeriesTuple to string. + /// + /// TimeSeriesTuple + public static implicit operator string(TimeSeriesTuple tst) => + string.Format("Time: {0}, Val:{1}", (string)tst.Time!, tst.Val); - /// - /// TimeSeriesTuple object hash code. - /// - /// TimeSeriesTuple object hash code. - public override int GetHashCode() - { - var hashCode = 459537088; - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Time); - hashCode = (hashCode * -1521134295) + Val.GetHashCode(); - return hashCode; - } + /// + /// TimeSeriesTuple object hash code. + /// + /// TimeSeriesTuple object hash code. + public override int GetHashCode() + { + var hashCode = 459537088; + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Time); + hashCode = (hashCode * -1521134295) + Val.GetHashCode(); + return hashCode; } -} +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/DataTypes/TimeStamp.cs b/src/NRedisStack/TimeSeries/DataTypes/TimeStamp.cs index c7f67b4b..a28bdb37 100644 --- a/src/NRedisStack/TimeSeries/DataTypes/TimeStamp.cs +++ b/src/NRedisStack/TimeSeries/DataTypes/TimeStamp.cs @@ -1,88 +1,87 @@ -namespace NRedisStack.DataTypes +namespace NRedisStack.DataTypes; + +/// +/// A class represents timestamp. +/// Value can be either primitive long, DateTime or one of the strings "-", "+", "*". +/// +public readonly record struct TimeStamp { + private static readonly string[] constants = ["-", "+", "*"]; + /// - /// A class represents timestamp. - /// Value can be either primitive long, DateTime or one of the strings "-", "+", "*". + /// TimeStamp value. /// - public readonly record struct TimeStamp - { - private static readonly string[] constants = { "-", "+", "*" }; - - /// - /// TimeStamp value. - /// - public object Value { get; } + public object Value { get; } - /// - /// Build a TimeStamp from primitive long. - /// - /// long value - public TimeStamp(long timestamp) => Value = timestamp; + /// + /// Build a TimeStamp from primitive long. + /// + /// long value + public TimeStamp(long timestamp) => Value = timestamp; - /// - /// Build a TimeStamp from DateTime. - /// - /// DateTime value - public TimeStamp(DateTime dateTime) => Value = new DateTimeOffset(dateTime).ToUnixTimeMilliseconds(); + /// + /// Build a TimeStamp from DateTime. + /// + /// DateTime value + public TimeStamp(DateTime dateTime) => Value = new DateTimeOffset(dateTime).ToUnixTimeMilliseconds(); - /// - /// Build a TimeStamp from one of the strings "-", "+", "*". - /// If the string is none of the above a NotSupportedException is thrown. - /// - /// String value - public TimeStamp(string timestamp) + /// + /// Build a TimeStamp from one of the strings "-", "+", "*". + /// If the string is none of the above a NotSupportedException is thrown. + /// + /// String value + public TimeStamp(string timestamp) + { + if (Array.IndexOf(constants, timestamp) == -1) { - if (Array.IndexOf(constants, timestamp) == -1) - { - throw new NotSupportedException($"The string {timestamp} cannot be used"); - } - Value = timestamp; + throw new NotSupportedException($"The string {timestamp} cannot be used"); } + Value = timestamp; + } - /// - /// Implicit cast from long to TimeStamp. - /// - /// long value. - public static implicit operator TimeStamp(long l) => new TimeStamp(l); + /// + /// Implicit cast from long to TimeStamp. + /// + /// long value. + public static implicit operator TimeStamp(long l) => new(l); - /// - /// Implicit cast from TimeStamp to long. - /// If the underlying timestamp value is not long or DateTime, an InvalidCastException is thrown. - /// - /// TimeStamp - public static implicit operator long(TimeStamp ts) => - ts.Value is long value ? value : throw new InvalidCastException("Cannot convert string timestamp to long"); + /// + /// Implicit cast from TimeStamp to long. + /// If the underlying timestamp value is not long or DateTime, an InvalidCastException is thrown. + /// + /// TimeStamp + public static implicit operator long(TimeStamp ts) => + ts.Value is long value ? value : throw new InvalidCastException("Cannot convert string timestamp to long"); - /// - /// Implicit cast from string to TimeStamp. - /// Calls the string C'tor. - /// - /// String value - public static implicit operator TimeStamp(string s) => new TimeStamp(s); + /// + /// Implicit cast from string to TimeStamp. + /// Calls the string C'tor. + /// + /// String value + public static implicit operator TimeStamp(string s) => new(s); - /// - /// Implicit cast from TimeStamp to string. - /// - /// TimeStamp - public static implicit operator string?(TimeStamp ts) => ts.Value.ToString(); + /// + /// Implicit cast from TimeStamp to string. + /// + /// TimeStamp + public static implicit operator string?(TimeStamp ts) => ts.Value.ToString(); - /// - /// Implicit cast from DateTime to TimeStamp. - /// - /// DateTime value - public static implicit operator TimeStamp(DateTime dateTime) => new TimeStamp(dateTime); + /// + /// Implicit cast from DateTime to TimeStamp. + /// + /// DateTime value + public static implicit operator TimeStamp(DateTime dateTime) => new(dateTime); - /// - /// Implicit cast from TimeStamp to DateTime. - /// - /// TimeStamp - public static implicit operator DateTime(TimeStamp timeStamp) => DateTimeOffset.FromUnixTimeMilliseconds(timeStamp).DateTime; + /// + /// Implicit cast from TimeStamp to DateTime. + /// + /// TimeStamp + public static implicit operator DateTime(TimeStamp timeStamp) => DateTimeOffset.FromUnixTimeMilliseconds(timeStamp).DateTime; - /// - /// TimeStamp object hash code. - /// - /// TimeStamp object hash code. - public override int GetHashCode() => - -1937169414 + EqualityComparer.Default.GetHashCode(Value); - } -} + /// + /// TimeStamp object hash code. + /// + /// TimeStamp object hash code. + public override int GetHashCode() => + -1937169414 + EqualityComparer.Default.GetHashCode(Value); +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/Extensions/AggregationExtensions.cs b/src/NRedisStack/TimeSeries/Extensions/AggregationExtensions.cs index 2512ffb9..cd22dfaf 100644 --- a/src/NRedisStack/TimeSeries/Extensions/AggregationExtensions.cs +++ b/src/NRedisStack/TimeSeries/Extensions/AggregationExtensions.cs @@ -1,56 +1,55 @@ using NRedisStack.Literals.Enums; -namespace NRedisStack.Extensions +namespace NRedisStack.Extensions; + +internal static class AggregationExtensions { - internal static class AggregationExtensions + public static string AsArg(this TsAggregation aggregation) => aggregation switch { - public static string AsArg(this TsAggregation aggregation) => aggregation switch - { - TsAggregation.Avg => "avg", - TsAggregation.Sum => "sum", - TsAggregation.Min => "min", - TsAggregation.Max => "max", - TsAggregation.Range => "range", - TsAggregation.Count => "count", - TsAggregation.First => "first", - TsAggregation.Last => "last", - TsAggregation.StdP => "std.p", - TsAggregation.StdS => "std.s", - TsAggregation.VarP => "var.p", - TsAggregation.VarS => "var.s", - TsAggregation.Twa => "twa", - _ => throw new ArgumentOutOfRangeException(nameof(aggregation), "Invalid aggregation type"), - }; + TsAggregation.Avg => "avg", + TsAggregation.Sum => "sum", + TsAggregation.Min => "min", + TsAggregation.Max => "max", + TsAggregation.Range => "range", + TsAggregation.Count => "count", + TsAggregation.First => "first", + TsAggregation.Last => "last", + TsAggregation.StdP => "std.p", + TsAggregation.StdS => "std.s", + TsAggregation.VarP => "var.p", + TsAggregation.VarS => "var.s", + TsAggregation.Twa => "twa", + _ => throw new ArgumentOutOfRangeException(nameof(aggregation), "Invalid aggregation type"), + }; - public static TsAggregation AsAggregation(string aggregation) => aggregation switch - { - /*"avg" => TsAggregation.Avg, - "sum" => TsAggregation.Sum, - "min" => TsAggregation.Min, - "max" => TsAggregation.Max, - "range" => TsAggregation.Range, - "count" => TsAggregation.Count, - "first" => TsAggregation.First, - "last" => TsAggregation.Last, - "std.p" => TsAggregation.StdP, - "std.s" => TsAggregation.StdS, - "var.p" => TsAggregation.VarP, - "var.s" => TsAggregation.VarS, - "twa" => TsAggregation.Twa,*/ - "AVG" => TsAggregation.Avg, - "SUM" => TsAggregation.Sum, - "MIN" => TsAggregation.Min, - "MAX" => TsAggregation.Max, - "RANGE" => TsAggregation.Range, - "COUNT" => TsAggregation.Count, - "FIRST" => TsAggregation.First, - "LAST" => TsAggregation.Last, - "STD.P" => TsAggregation.StdP, - "STD.S" => TsAggregation.StdS, - "VAR.P" => TsAggregation.VarP, - "VAR.S" => TsAggregation.VarS, - "TWA" => TsAggregation.Twa, - _ => throw new ArgumentOutOfRangeException(nameof(aggregation), $"Invalid aggregation type '{aggregation}'"), - }; - } -} + public static TsAggregation AsAggregation(string aggregation) => aggregation switch + { + /*"avg" => TsAggregation.Avg, + "sum" => TsAggregation.Sum, + "min" => TsAggregation.Min, + "max" => TsAggregation.Max, + "range" => TsAggregation.Range, + "count" => TsAggregation.Count, + "first" => TsAggregation.First, + "last" => TsAggregation.Last, + "std.p" => TsAggregation.StdP, + "std.s" => TsAggregation.StdS, + "var.p" => TsAggregation.VarP, + "var.s" => TsAggregation.VarS, + "twa" => TsAggregation.Twa,*/ + "AVG" => TsAggregation.Avg, + "SUM" => TsAggregation.Sum, + "MIN" => TsAggregation.Min, + "MAX" => TsAggregation.Max, + "RANGE" => TsAggregation.Range, + "COUNT" => TsAggregation.Count, + "FIRST" => TsAggregation.First, + "LAST" => TsAggregation.Last, + "STD.P" => TsAggregation.StdP, + "STD.S" => TsAggregation.StdS, + "VAR.P" => TsAggregation.VarP, + "VAR.S" => TsAggregation.VarS, + "TWA" => TsAggregation.Twa, + _ => throw new ArgumentOutOfRangeException(nameof(aggregation), $"Invalid aggregation type '{aggregation}'"), + }; +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/Extensions/BucketTimestampsExtensions.cs b/src/NRedisStack/TimeSeries/Extensions/BucketTimestampsExtensions.cs index f3faf88d..ab9eb5f2 100644 --- a/src/NRedisStack/TimeSeries/Extensions/BucketTimestampsExtensions.cs +++ b/src/NRedisStack/TimeSeries/Extensions/BucketTimestampsExtensions.cs @@ -1,15 +1,14 @@ using NRedisStack.Literals.Enums; -namespace NRedisStack.Extensions +namespace NRedisStack.Extensions; + +internal static class TsBucketTimestampsExtensions { - internal static class TsBucketTimestampsExtensions + public static string AsArg(this TsBucketTimestamps bt) => bt switch { - public static string AsArg(this TsBucketTimestamps bt) => bt switch - { - TsBucketTimestamps.low => "-", - TsBucketTimestamps.mid => "~", - TsBucketTimestamps.high => "+", - _ => throw new ArgumentOutOfRangeException(nameof(bt), "Invalid TsBucketTimestamps type"), - }; - } + TsBucketTimestamps.low => "-", + TsBucketTimestamps.mid => "~", + TsBucketTimestamps.high => "+", + _ => throw new ArgumentOutOfRangeException(nameof(bt), "Invalid TsBucketTimestamps type"), + }; } \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/Extensions/DuplicatePolicyExtensions.cs b/src/NRedisStack/TimeSeries/Extensions/DuplicatePolicyExtensions.cs index 1c442e01..47d7e6c2 100644 --- a/src/NRedisStack/TimeSeries/Extensions/DuplicatePolicyExtensions.cs +++ b/src/NRedisStack/TimeSeries/Extensions/DuplicatePolicyExtensions.cs @@ -1,29 +1,28 @@ using NRedisStack.Literals.Enums; -namespace NRedisStack.Extensions +namespace NRedisStack.Extensions; + +internal static class DuplicatePolicyExtensions { - internal static class DuplicatePolicyExtensions + public static string AsArg(this TsDuplicatePolicy policy) => policy switch { - public static string AsArg(this TsDuplicatePolicy policy) => policy switch - { - TsDuplicatePolicy.BLOCK => "BLOCK", - TsDuplicatePolicy.FIRST => "FIRST", - TsDuplicatePolicy.LAST => "LAST", - TsDuplicatePolicy.MIN => "MIN", - TsDuplicatePolicy.MAX => "MAX", - TsDuplicatePolicy.SUM => "SUM", - _ => throw new ArgumentOutOfRangeException(nameof(policy), "Invalid policy type"), - }; + TsDuplicatePolicy.BLOCK => "BLOCK", + TsDuplicatePolicy.FIRST => "FIRST", + TsDuplicatePolicy.LAST => "LAST", + TsDuplicatePolicy.MIN => "MIN", + TsDuplicatePolicy.MAX => "MAX", + TsDuplicatePolicy.SUM => "SUM", + _ => throw new ArgumentOutOfRangeException(nameof(policy), "Invalid policy type"), + }; - public static TsDuplicatePolicy AsPolicy(string policy) => policy switch - { - "BLOCK" => TsDuplicatePolicy.BLOCK, - "FIRST" => TsDuplicatePolicy.FIRST, - "LAST" => TsDuplicatePolicy.LAST, - "MIN" => TsDuplicatePolicy.MIN, - "MAX" => TsDuplicatePolicy.MAX, - "SUM" => TsDuplicatePolicy.SUM, - _ => throw new ArgumentOutOfRangeException(nameof(policy), $"Invalid policy type '{policy}'"), - }; - } -} + public static TsDuplicatePolicy AsPolicy(string policy) => policy switch + { + "BLOCK" => TsDuplicatePolicy.BLOCK, + "FIRST" => TsDuplicatePolicy.FIRST, + "LAST" => TsDuplicatePolicy.LAST, + "MIN" => TsDuplicatePolicy.MIN, + "MAX" => TsDuplicatePolicy.MAX, + "SUM" => TsDuplicatePolicy.SUM, + _ => throw new ArgumentOutOfRangeException(nameof(policy), $"Invalid policy type '{policy}'"), + }; +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/Extensions/ReduceExtensions.cs b/src/NRedisStack/TimeSeries/Extensions/ReduceExtensions.cs index 204d64a3..8ec160ac 100644 --- a/src/NRedisStack/TimeSeries/Extensions/ReduceExtensions.cs +++ b/src/NRedisStack/TimeSeries/Extensions/ReduceExtensions.cs @@ -1,22 +1,21 @@ using NRedisStack.Literals.Enums; -namespace NRedisStack.Extensions +namespace NRedisStack.Extensions; + +internal static class ReduceExtensions { - internal static class ReduceExtensions + public static string AsArg(this TsReduce reduce) => reduce switch { - public static string AsArg(this TsReduce reduce) => reduce switch - { - TsReduce.Sum => "SUM", - TsReduce.Min => "MIN", - TsReduce.Max => "MAX", - TsReduce.Avg => "AVG", - TsReduce.Range => "RANGE", - TsReduce.Count => "COUNT", - TsReduce.StdP => "STD.P", - TsReduce.StdS => "STD.S", - TsReduce.VarP => "VAR.P", - TsReduce.VarS => "VAR.S", - _ => throw new ArgumentOutOfRangeException(nameof(reduce), "Invalid Reduce type"), - }; - } -} + TsReduce.Sum => "SUM", + TsReduce.Min => "MIN", + TsReduce.Max => "MAX", + TsReduce.Avg => "AVG", + TsReduce.Range => "RANGE", + TsReduce.Count => "COUNT", + TsReduce.StdP => "STD.P", + TsReduce.StdS => "STD.S", + TsReduce.VarP => "VAR.P", + TsReduce.VarS => "VAR.S", + _ => throw new ArgumentOutOfRangeException(nameof(reduce), "Invalid Reduce type"), + }; +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/ITimeSeriesCommands.cs b/src/NRedisStack/TimeSeries/ITimeSeriesCommands.cs index 8caec91f..84528adc 100644 --- a/src/NRedisStack/TimeSeries/ITimeSeriesCommands.cs +++ b/src/NRedisStack/TimeSeries/ITimeSeriesCommands.cs @@ -1,333 +1,332 @@ using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; -namespace NRedisStack +namespace NRedisStack; + +public interface ITimeSeriesCommands { - public interface ITimeSeriesCommands - { - #region Create + #region Create - /// - /// Create a new time-series. - /// - /// Key name for timeseries - /// Optional: Maximum age for samples compared to last event time (in milliseconds) - /// Optional: Collaction of label-value pairs that represent metadata labels of the key - /// Optional: Adding this flag will keep data in an uncompressed form - /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. - /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) - /// Optinal: Define handling of duplicate samples behavior (avalible for RedisTimeseries >= 1.4) - /// If the operation executed successfully - /// - bool Create(string key, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null); + /// + /// Create a new time-series. + /// + /// Key name for timeseries + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) + /// Optinal: Define handling of duplicate samples behavior (avalible for RedisTimeseries >= 1.4) + /// If the operation executed successfully + /// + bool Create(string key, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null); - #endregion + #endregion - #region Update + #region Update - /// - /// Update the retention, labels of an existing key. - /// - /// Key name for timeseries - /// Optional: Maximum age for samples compared to last event time (in milliseconds) - /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. - /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) - /// Optinal: Define handling of duplicate samples behavior (avalible for RedisTimeseries >= 1.4) - /// Optional: Collaction of label-value pairs that represent metadata labels of the key - /// If the operation executed successfully - /// - bool Alter(string key, long? retentionTime = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null, IReadOnlyCollection? labels = null); + /// + /// Update the retention, labels of an existing key. + /// + /// Key name for timeseries + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) + /// Optinal: Define handling of duplicate samples behavior (avalible for RedisTimeseries >= 1.4) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// If the operation executed successfully + /// + bool Alter(string key, long? retentionTime = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null, IReadOnlyCollection? labels = null); - /// - /// Append (or create and append) a new sample to the series. - /// - /// Key name for timeseries - /// TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) - /// Numeric data value of the sample. - /// Optional: Maximum age for samples compared to last event time (in milliseconds) - /// Optional: Collaction of label-value pairs that represent metadata labels of the key - /// Optional: Adding this flag will keep data in an uncompressed form - /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. - /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) - /// Optioal: overwrite key and database configuration for DUPLICATE_POLICY - /// The timestamp value of the new sample - /// - TimeStamp Add(string key, TimeStamp timestamp, double value, long? retentionTime = null, - IReadOnlyCollection? labels = null, bool? uncompressed = null, - long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null); + /// + /// Append (or create and append) a new sample to the series. + /// + /// Key name for timeseries + /// TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) + /// Numeric data value of the sample. + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) + /// Optioal: overwrite key and database configuration for DUPLICATE_POLICY + /// The timestamp value of the new sample + /// + TimeStamp Add(string key, TimeStamp timestamp, double value, long? retentionTime = null, + IReadOnlyCollection? labels = null, bool? uncompressed = null, + long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null); - /// - /// Append new samples to multiple series. - /// - /// An Collection of (key, timestamp, value) tuples - /// List of timestamps of the new samples - /// - IReadOnlyList MAdd(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence); + /// + /// Append new samples to multiple series. + /// + /// An Collection of (key, timestamp, value) tuples + /// List of timestamps of the new samples + /// + IReadOnlyList MAdd(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence); - /// - /// Creates a new sample that increments the latest sample's value. - /// - /// Key name for timeseries - /// Delta to add - /// Optional: TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) - /// Optional: Maximum age for samples compared to last event time (in milliseconds) - /// Optional: Collaction of label-value pairs that represent metadata labels of the key - /// Optional: Adding this flag will keep data in an uncompressed form - /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. - /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) - /// The latests sample timestamp (updated sample) - /// - TimeStamp IncrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null); + /// + /// Creates a new sample that increments the latest sample's value. + /// + /// Key name for timeseries + /// Delta to add + /// Optional: TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) + /// The latests sample timestamp (updated sample) + /// + TimeStamp IncrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null); - /// - /// Creates a new sample that decrements the latest sample's value. - /// - /// Key name for timeseries - /// Delta to substract - /// Optional: TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) - /// Optional: Maximum age for samples compared to last event time (in milliseconds) - /// Optional: Collaction of label-value pairs that represent metadata labels of the key - /// Optional: Adding this flag will keep data in an uncompressed form - /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. - /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) - /// The latests sample timestamp (updated sample) - /// - TimeStamp DecrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null); + /// + /// Creates a new sample that decrements the latest sample's value. + /// + /// Key name for timeseries + /// Delta to substract + /// Optional: TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) + /// The latests sample timestamp (updated sample) + /// + TimeStamp DecrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null); - /// - /// Delete data points for a given timeseries and interval range in the form of start and end delete timestamps. - /// The given timestamp interval is closed (inclusive), meaning start and end data points will also be deleted. - /// - /// Key name for timeseries - /// Start timestamp for the range deletion. - /// End timestamp for the range deletion. - /// The count of deleted items - /// - long Del(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp); + /// + /// Delete data points for a given timeseries and interval range in the form of start and end delete timestamps. + /// The given timestamp interval is closed (inclusive), meaning start and end data points will also be deleted. + /// + /// Key name for timeseries + /// Start timestamp for the range deletion. + /// End timestamp for the range deletion. + /// The count of deleted items + /// + long Del(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp); - #endregion + #endregion - #region Aggregation, Compaction, Downsampling + #region Aggregation, Compaction, Downsampling - /// - /// Create a compaction rule. - /// - /// Key name for source time series - /// TimeSeries rule: - /// Key name for destination time series, Aggregation type and Time bucket for aggregation in milliseconds - /// ensures that there is a bucket that starts - /// exactly at alignTimestamp and aligns all other buckets accordingly. - /// It is expressed in milliseconds. The default value is 0 aligned with the epoch - /// If the operation executed successfully - /// - bool CreateRule(string sourceKey, TimeSeriesRule rule, long alignTimestamp = 0); + /// + /// Create a compaction rule. + /// + /// Key name for source time series + /// TimeSeries rule: + /// Key name for destination time series, Aggregation type and Time bucket for aggregation in milliseconds + /// ensures that there is a bucket that starts + /// exactly at alignTimestamp and aligns all other buckets accordingly. + /// It is expressed in milliseconds. The default value is 0 aligned with the epoch + /// If the operation executed successfully + /// + bool CreateRule(string sourceKey, TimeSeriesRule rule, long alignTimestamp = 0); - /// - /// Deletes a compaction rule. - /// - /// Key name for source time series - /// Key name for destination time series - /// If the operation executed successfully - /// - bool DeleteRule(string sourceKey, string destKey); + /// + /// Deletes a compaction rule. + /// + /// Key name for source time series + /// Key name for destination time series + /// If the operation executed successfully + /// + bool DeleteRule(string sourceKey, string destKey); - #endregion + #endregion - #region Query + #region Query - /// - /// Get the last sample. - /// - /// Key name for timeseries - /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports - /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls - /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. - /// When a time series is not a compaction, LATEST is ignored. - /// TimeSeriesTuple that represents the last sample. Null if the series is empty. - /// - TimeSeriesTuple? Get(string key, bool latest = false); + /// + /// Get the last sample. + /// + /// Key name for timeseries + /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports + /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls + /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. + /// When a time series is not a compaction, LATEST is ignored. + /// TimeSeriesTuple that represents the last sample. Null if the series is empty. + /// + TimeSeriesTuple? Get(string key, bool latest = false); - /// - /// Get the last samples matching the specific filter. - /// - /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports - /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls - /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. - /// When a time series is not a compaction, LATEST is ignored. - /// A sequence of filters - /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series - /// Optional: returns a subset of the label-value pairs that represent metadata labels of the time series - /// The command returns the last sample for entries with labels matching the specified filter. - /// - IReadOnlyList<(string key, IReadOnlyList labels, TimeSeriesTuple value)> MGet(IReadOnlyCollection filter, bool latest = false, - bool? withLabels = null, IReadOnlyCollection? selectedLabels = null); + /// + /// Get the last samples matching the specific filter. + /// + /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports + /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls + /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. + /// When a time series is not a compaction, LATEST is ignored. + /// A sequence of filters + /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series + /// Optional: returns a subset of the label-value pairs that represent metadata labels of the time series + /// The command returns the last sample for entries with labels matching the specified filter. + /// + IReadOnlyList<(string key, IReadOnlyList labels, TimeSeriesTuple value)> MGet(IReadOnlyCollection filter, bool latest = false, + bool? withLabels = null, IReadOnlyCollection? selectedLabels = null); - /// - /// Query a range. - /// - /// Key name for timeseries - /// Start timestamp for the range query. "-" can be used to express the minimum possible timestamp. - /// End timestamp for range query, + can be used to express the maximum possible timestamp. - /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports - /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls - /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. - /// When a time series is not a compaction, LATEST is ignored. - /// Optional: List of timestamps to filter the result by specific timestamps - /// Optional: Filter result by value using minimum and maximum - /// Optional: Returned list size. - /// Optional: Timestamp for alignment control for aggregation. - /// Optional: Aggregation type - /// Optional: Time bucket for aggregation in milliseconds - /// Optional: controls how bucket timestamps are reported. - /// Optional: when specified, reports aggregations also for empty buckets - /// A list of TimeSeriesTuple - /// - IReadOnlyList Range(string key, - TimeStamp fromTimeStamp, - TimeStamp toTimeStamp, - bool latest = false, - IReadOnlyCollection? filterByTs = null, - (long, long)? filterByValue = null, - long? count = null, - TimeStamp? align = null, - TsAggregation? aggregation = null, - long? timeBucket = null, - TsBucketTimestamps? bt = null, - bool empty = false); + /// + /// Query a range. + /// + /// Key name for timeseries + /// Start timestamp for the range query. "-" can be used to express the minimum possible timestamp. + /// End timestamp for range query, + can be used to express the maximum possible timestamp. + /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports + /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls + /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. + /// When a time series is not a compaction, LATEST is ignored. + /// Optional: List of timestamps to filter the result by specific timestamps + /// Optional: Filter result by value using minimum and maximum + /// Optional: Returned list size. + /// Optional: Timestamp for alignment control for aggregation. + /// Optional: Aggregation type + /// Optional: Time bucket for aggregation in milliseconds + /// Optional: controls how bucket timestamps are reported. + /// Optional: when specified, reports aggregations also for empty buckets + /// A list of TimeSeriesTuple + /// + IReadOnlyList Range(string key, + TimeStamp fromTimeStamp, + TimeStamp toTimeStamp, + bool latest = false, + IReadOnlyCollection? filterByTs = null, + (long, long)? filterByValue = null, + long? count = null, + TimeStamp? align = null, + TsAggregation? aggregation = null, + long? timeBucket = null, + TsBucketTimestamps? bt = null, + bool empty = false); - /// - /// Query a range in reverse direction. - /// - /// Key name for timeseries - /// Start timestamp for the range query. "-" can be used to express the minimum possible timestamp. - /// End timestamp for range query, + can be used to express the maximum possible timestamp. - /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports - /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls - /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. - /// When a time series is not a compaction, LATEST is ignored. - /// Optional: List of timestamps to filter the result by specific timestamps - /// Optional: Filter result by value using minimum and maximum - /// Optional: Returned list size. - /// Optional: Timestamp for alignment control for aggregation. - /// Optional: Aggregation type - /// Optional: Time bucket for aggregation in milliseconds - /// Optional: controls how bucket timestamps are reported. - /// Optional: when specified, reports aggregations also for empty buckets - /// A list of TimeSeriesTuple - /// - IReadOnlyList RevRange(string key, - TimeStamp fromTimeStamp, - TimeStamp toTimeStamp, - bool latest = false, - IReadOnlyCollection? filterByTs = null, - (long, long)? filterByValue = null, - long? count = null, - TimeStamp? align = null, - TsAggregation? aggregation = null, - long? timeBucket = null, - TsBucketTimestamps? bt = null, - bool empty = false); + /// + /// Query a range in reverse direction. + /// + /// Key name for timeseries + /// Start timestamp for the range query. "-" can be used to express the minimum possible timestamp. + /// End timestamp for range query, + can be used to express the maximum possible timestamp. + /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports + /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls + /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. + /// When a time series is not a compaction, LATEST is ignored. + /// Optional: List of timestamps to filter the result by specific timestamps + /// Optional: Filter result by value using minimum and maximum + /// Optional: Returned list size. + /// Optional: Timestamp for alignment control for aggregation. + /// Optional: Aggregation type + /// Optional: Time bucket for aggregation in milliseconds + /// Optional: controls how bucket timestamps are reported. + /// Optional: when specified, reports aggregations also for empty buckets + /// A list of TimeSeriesTuple + /// + IReadOnlyList RevRange(string key, + TimeStamp fromTimeStamp, + TimeStamp toTimeStamp, + bool latest = false, + IReadOnlyCollection? filterByTs = null, + (long, long)? filterByValue = null, + long? count = null, + TimeStamp? align = null, + TsAggregation? aggregation = null, + long? timeBucket = null, + TsBucketTimestamps? bt = null, + bool empty = false); - /// - /// Query a timestamp range across multiple time-series by filters. - /// - /// Start timestamp for the range query. - can be used to express the minimum possible timestamp. - /// End timestamp for range query, + can be used to express the maximum possible timestamp. - /// A sequence of filters - /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports - /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls - /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. - /// When a time series is not a compaction, LATEST is ignored. - /// Optional: List of timestamps to filter the result by specific timestamps - /// Optional: Filter result by value using minimum and maximum - /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series - /// Optional: Include in the reply only a subset of the key-value pair labels of a series. - /// Optional: Maximum number of returned results per time-series. - /// Optional: Timestamp for alignment control for aggregation. - /// Optional: Aggregation type - /// Optional: Time bucket for aggregation in milliseconds - /// Optional: controls how bucket timestamps are reported. - /// Optional: when specified, reports aggregations also for empty buckets - /// Optional: Grouping by fields the results, and applying reducer functions on each group. - /// A list of (key, labels, values) tuples. Each tuple contains the key name, its labels and the values which satisfies the given range and filters. - /// - IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> MRange( - TimeStamp fromTimeStamp, - TimeStamp toTimeStamp, - IReadOnlyCollection filter, - bool latest = false, - IReadOnlyCollection? filterByTs = null, - (long, long)? filterByValue = null, - bool? withLabels = null, - IReadOnlyCollection? selectLabels = null, - long? count = null, - TimeStamp? align = null, - TsAggregation? aggregation = null, - long? timeBucket = null, - TsBucketTimestamps? bt = null, - bool empty = false, - (string, TsReduce)? groupbyTuple = null); + /// + /// Query a timestamp range across multiple time-series by filters. + /// + /// Start timestamp for the range query. - can be used to express the minimum possible timestamp. + /// End timestamp for range query, + can be used to express the maximum possible timestamp. + /// A sequence of filters + /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports + /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls + /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. + /// When a time series is not a compaction, LATEST is ignored. + /// Optional: List of timestamps to filter the result by specific timestamps + /// Optional: Filter result by value using minimum and maximum + /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series + /// Optional: Include in the reply only a subset of the key-value pair labels of a series. + /// Optional: Maximum number of returned results per time-series. + /// Optional: Timestamp for alignment control for aggregation. + /// Optional: Aggregation type + /// Optional: Time bucket for aggregation in milliseconds + /// Optional: controls how bucket timestamps are reported. + /// Optional: when specified, reports aggregations also for empty buckets + /// Optional: Grouping by fields the results, and applying reducer functions on each group. + /// A list of (key, labels, values) tuples. Each tuple contains the key name, its labels and the values which satisfies the given range and filters. + /// + IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> MRange( + TimeStamp fromTimeStamp, + TimeStamp toTimeStamp, + IReadOnlyCollection filter, + bool latest = false, + IReadOnlyCollection? filterByTs = null, + (long, long)? filterByValue = null, + bool? withLabels = null, + IReadOnlyCollection? selectLabels = null, + long? count = null, + TimeStamp? align = null, + TsAggregation? aggregation = null, + long? timeBucket = null, + TsBucketTimestamps? bt = null, + bool empty = false, + (string, TsReduce)? groupbyTuple = null); - /// - /// Query a timestamp range in reverse order across multiple time-series by filters. - /// - /// Start timestamp for the range query. - can be used to express the minimum possible timestamp. - /// End timestamp for range query, + can be used to express the maximum possible timestamp. - /// A sequence of filters - /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports - /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls - /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. - /// When a time series is not a compaction, LATEST is ignored. - /// Optional: List of timestamps to filter the result by specific timestamps - /// Optional: Filter result by value using minimum and maximum - /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series - /// Optional: Include in the reply only a subset of the key-value pair labels of a series. - /// Optional: Maximum number of returned results per time-series. - /// Optional: Timestamp for alignment control for aggregation. - /// Optional: Aggregation type - /// Optional: Time bucket for aggregation in milliseconds - /// Optional: controls how bucket timestamps are reported. - /// Optional: when specified, reports aggregations also for empty buckets - /// Optional: Grouping by fields the results, and applying reducer functions on each group. - /// A list of (key, labels, values) tuples. Each tuple contains the key name, its labels and the values which satisfies the given range and filters. - /// - IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> MRevRange( - TimeStamp fromTimeStamp, - TimeStamp toTimeStamp, - IReadOnlyCollection filter, - bool latest = false, - IReadOnlyCollection? filterByTs = null, - (long, long)? filterByValue = null, - bool? withLabels = null, - IReadOnlyCollection? selectLabels = null, - long? count = null, - TimeStamp? align = null, - TsAggregation? aggregation = null, - long? timeBucket = null, - TsBucketTimestamps? bt = null, - bool empty = false, - (string, TsReduce)? groupbyTuple = null); + /// + /// Query a timestamp range in reverse order across multiple time-series by filters. + /// + /// Start timestamp for the range query. - can be used to express the minimum possible timestamp. + /// End timestamp for range query, + can be used to express the maximum possible timestamp. + /// A sequence of filters + /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports + /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls + /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. + /// When a time series is not a compaction, LATEST is ignored. + /// Optional: List of timestamps to filter the result by specific timestamps + /// Optional: Filter result by value using minimum and maximum + /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series + /// Optional: Include in the reply only a subset of the key-value pair labels of a series. + /// Optional: Maximum number of returned results per time-series. + /// Optional: Timestamp for alignment control for aggregation. + /// Optional: Aggregation type + /// Optional: Time bucket for aggregation in milliseconds + /// Optional: controls how bucket timestamps are reported. + /// Optional: when specified, reports aggregations also for empty buckets + /// Optional: Grouping by fields the results, and applying reducer functions on each group. + /// A list of (key, labels, values) tuples. Each tuple contains the key name, its labels and the values which satisfies the given range and filters. + /// + IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> MRevRange( + TimeStamp fromTimeStamp, + TimeStamp toTimeStamp, + IReadOnlyCollection filter, + bool latest = false, + IReadOnlyCollection? filterByTs = null, + (long, long)? filterByValue = null, + bool? withLabels = null, + IReadOnlyCollection? selectLabels = null, + long? count = null, + TimeStamp? align = null, + TsAggregation? aggregation = null, + long? timeBucket = null, + TsBucketTimestamps? bt = null, + bool empty = false, + (string, TsReduce)? groupbyTuple = null); - #endregion + #endregion - #region General + #region General - /// - /// Returns the information for a specific time-series key. - /// - /// Key name for timeseries - /// An optional flag to get a more detailed information about the chunks. - /// TimeSeriesInformation for the specific key. - /// - TimeSeriesInformation Info(string key, bool debug = false); + /// + /// Returns the information for a specific time-series key. + /// + /// Key name for timeseries + /// An optional flag to get a more detailed information about the chunks. + /// TimeSeriesInformation for the specific key. + /// + TimeSeriesInformation Info(string key, bool debug = false); - /// - /// Get all the keys matching the filter list. - /// - /// A sequence of filters - /// A list of keys with labels matching the filters. - /// - IReadOnlyList QueryIndex(IReadOnlyCollection filter); + /// + /// Get all the keys matching the filter list. + /// + /// A sequence of filters + /// A list of keys with labels matching the filters. + /// + IReadOnlyList QueryIndex(IReadOnlyCollection filter); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/ITimeSeriesCommandsAsync.cs b/src/NRedisStack/TimeSeries/ITimeSeriesCommandsAsync.cs index dfd46657..0ec00aff 100644 --- a/src/NRedisStack/TimeSeries/ITimeSeriesCommandsAsync.cs +++ b/src/NRedisStack/TimeSeries/ITimeSeriesCommandsAsync.cs @@ -1,332 +1,331 @@ using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; -namespace NRedisStack +namespace NRedisStack; + +public interface ITimeSeriesCommandsAsync { - public interface ITimeSeriesCommandsAsync - { - #region Create + #region Create - /// - /// Create a new time-series. - /// - /// Key name for timeseries - /// Optional: Maximum age for samples compared to last event time (in milliseconds) - /// Optional: Collaction of label-value pairs that represent metadata labels of the key - /// Optional: Adding this flag will keep data in an uncompressed form - /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. - /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) - /// Optinal: Define handling of duplicate samples behavior (avalible for RedisTimeseries >= 1.4) - /// If the operation executed successfully - /// - Task CreateAsync(string key, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null); + /// + /// Create a new time-series. + /// + /// Key name for timeseries + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) + /// Optinal: Define handling of duplicate samples behavior (avalible for RedisTimeseries >= 1.4) + /// If the operation executed successfully + /// + Task CreateAsync(string key, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null); - #endregion + #endregion - #region Update + #region Update - /// - /// Update the retention, labels of an existing key. - /// - /// Key name for timeseries - /// Optional: Maximum age for samples compared to last event time (in milliseconds) - /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. - /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) - /// Optinal: Define handling of duplicate samples behavior (avalible for RedisTimeseries >= 1.4) - /// Optional: Collaction of label-value pairs that represent metadata labels of the key - /// If the operation executed successfully - /// - Task AlterAsync(string key, long? retentionTime = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null, IReadOnlyCollection? labels = null); + /// + /// Update the retention, labels of an existing key. + /// + /// Key name for timeseries + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) + /// Optinal: Define handling of duplicate samples behavior (avalible for RedisTimeseries >= 1.4) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// If the operation executed successfully + /// + Task AlterAsync(string key, long? retentionTime = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null, IReadOnlyCollection? labels = null); - /// - /// Append (or create and append) a new sample to the series. - /// - /// Key name for timeseries - /// TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) - /// Numeric data value of the sample. - /// Optional: Maximum age for samples compared to last event time (in milliseconds) - /// Optional: Collaction of label-value pairs that represent metadata labels of the key - /// Optional: Adding this flag will keep data in an uncompressed form - /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. - /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) - /// Optioal: overwrite key and database configuration for DUPLICATE_POLICY - /// The timestamp value of the new sample - /// - Task AddAsync(string key, TimeStamp timestamp, double value, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null); + /// + /// Append (or create and append) a new sample to the series. + /// + /// Key name for timeseries + /// TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) + /// Numeric data value of the sample. + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) + /// Optioal: overwrite key and database configuration for DUPLICATE_POLICY + /// The timestamp value of the new sample + /// + Task AddAsync(string key, TimeStamp timestamp, double value, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null); - /// - /// Append new samples to multiple series. - /// - /// An Collection of (key, timestamp, value) tuples - /// List of timestamps of the new samples - /// - Task> MAddAsync(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence); + /// + /// Append new samples to multiple series. + /// + /// An Collection of (key, timestamp, value) tuples + /// List of timestamps of the new samples + /// + Task> MAddAsync(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence); - /// - /// Creates a new sample that increments the latest sample's value. - /// - /// Key name for timeseries - /// Delta to add - /// Optional: TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) - /// Optional: Maximum age for samples compared to last event time (in milliseconds) - /// Optional: Collaction of label-value pairs that represent metadata labels of the key - /// Optional: Adding this flag will keep data in an uncompressed form - /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. - /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) - /// The latests sample timestamp (updated sample) - /// - Task IncrByAsync(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null); + /// + /// Creates a new sample that increments the latest sample's value. + /// + /// Key name for timeseries + /// Delta to add + /// Optional: TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) + /// The latests sample timestamp (updated sample) + /// + Task IncrByAsync(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null); - /// - /// Creates a new sample that decrements the latest sample's value. - /// - /// Key name for timeseries - /// Delta to substract - /// Optional: TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) - /// Optional: Maximum age for samples compared to last event time (in milliseconds) - /// Optional: Collaction of label-value pairs that represent metadata labels of the key - /// Optional: Adding this flag will keep data in an uncompressed form - /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. - /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) - /// The latests sample timestamp (updated sample) - /// - Task DecrByAsync(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null); + /// + /// Creates a new sample that decrements the latest sample's value. + /// + /// Key name for timeseries + /// Delta to substract + /// Optional: TimeStamp to add. UNIX timestamp of the sample. * can be used for automatic timestamp (using the system clock) + /// Optional: Maximum age for samples compared to last event time (in milliseconds) + /// Optional: Collaction of label-value pairs that represent metadata labels of the key + /// Optional: Adding this flag will keep data in an uncompressed form + /// Optional: Each time-series uses chunks of memory of fixed size for time series samples. + /// You can alter the default TS_db chunk size by passing the chunk_size argument (in Bytes) + /// The latests sample timestamp (updated sample) + /// + Task DecrByAsync(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null); - /// - /// Delete data points for a given timeseries and interval range in the form of start and end delete timestamps. - /// The given timestamp interval is closed (inclusive), meaning start and end data points will also be deleted. - /// - /// Key name for timeseries - /// Start timestamp for the range deletion. - /// End timestamp for the range deletion. - /// The count of deleted items - /// - Task DelAsync(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp); + /// + /// Delete data points for a given timeseries and interval range in the form of start and end delete timestamps. + /// The given timestamp interval is closed (inclusive), meaning start and end data points will also be deleted. + /// + /// Key name for timeseries + /// Start timestamp for the range deletion. + /// End timestamp for the range deletion. + /// The count of deleted items + /// + Task DelAsync(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp); - #endregion + #endregion - #region Aggregation, Compaction, Downsampling + #region Aggregation, Compaction, Downsampling - /// - /// Create a compaction rule. - /// - /// Key name for source time series - /// TimeSeries rule: - /// Key name for destination time series, Aggregation type and Time bucket for aggregation in milliseconds - /// ensures that there is a bucket that starts - /// exactly at alignTimestamp and aligns all other buckets accordingly. - /// It is expressed in milliseconds. The default value is 0 aligned with the epoch - /// If the operation executed successfully - /// - Task CreateRuleAsync(string sourceKey, TimeSeriesRule rule, long alignTimestamp = 0); + /// + /// Create a compaction rule. + /// + /// Key name for source time series + /// TimeSeries rule: + /// Key name for destination time series, Aggregation type and Time bucket for aggregation in milliseconds + /// ensures that there is a bucket that starts + /// exactly at alignTimestamp and aligns all other buckets accordingly. + /// It is expressed in milliseconds. The default value is 0 aligned with the epoch + /// If the operation executed successfully + /// + Task CreateRuleAsync(string sourceKey, TimeSeriesRule rule, long alignTimestamp = 0); - /// - /// Deletes a compaction rule. - /// - /// Key name for source time series - /// Key name for destination time series - /// If the operation executed successfully - /// - Task DeleteRuleAsync(string sourceKey, string destKey); + /// + /// Deletes a compaction rule. + /// + /// Key name for source time series + /// Key name for destination time series + /// If the operation executed successfully + /// + Task DeleteRuleAsync(string sourceKey, string destKey); - #endregion + #endregion - #region Query + #region Query - /// - /// Get the last sample. - /// - /// Key name for timeseries - /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports - /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls - /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. - /// When a time series is not a compaction, LATEST is ignored. - /// TimeSeriesTuple that represents the last sample. Null if the series is empty. - /// - Task GetAsync(string key, bool latest = false); + /// + /// Get the last sample. + /// + /// Key name for timeseries + /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports + /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls + /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. + /// When a time series is not a compaction, LATEST is ignored. + /// TimeSeriesTuple that represents the last sample. Null if the series is empty. + /// + Task GetAsync(string key, bool latest = false); - /// - /// Get the last samples matching the specific filter. - /// - /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports - /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls - /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. - /// When a time series is not a compaction, LATEST is ignored. - /// A sequence of filters - /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series - /// Optional: returns a subset of the label-value pairs that represent metadata labels of the time series - /// The command returns the last sample for entries with labels matching the specified filter. - /// - Task labels, TimeSeriesTuple value)>> MGetAsync(IReadOnlyCollection filter, bool latest = false, - bool? withLabels = null, IReadOnlyCollection? selectedLabels = null); + /// + /// Get the last samples matching the specific filter. + /// + /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports + /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls + /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. + /// When a time series is not a compaction, LATEST is ignored. + /// A sequence of filters + /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series + /// Optional: returns a subset of the label-value pairs that represent metadata labels of the time series + /// The command returns the last sample for entries with labels matching the specified filter. + /// + Task labels, TimeSeriesTuple value)>> MGetAsync(IReadOnlyCollection filter, bool latest = false, + bool? withLabels = null, IReadOnlyCollection? selectedLabels = null); - /// - /// Query a range. - /// - /// Key name for timeseries - /// Start timestamp for the range query. "-" can be used to express the minimum possible timestamp. - /// End timestamp for range query, + can be used to express the maximum possible timestamp. - /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports - /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls - /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. - /// When a time series is not a compaction, LATEST is ignored. - /// Optional: List of timestamps to filter the result by specific timestamps - /// Optional: Filter result by value using minimum and maximum - /// Optional: Returned list size. - /// Optional: Timestamp for alignment control for aggregation. - /// Optional: Aggregation type - /// Optional: Time bucket for aggregation in milliseconds - /// Optional: controls how bucket timestamps are reported. - /// Optional: when specified, reports aggregations also for empty buckets - /// A list of TimeSeriesTuple - /// - Task> RangeAsync(string key, - TimeStamp fromTimeStamp, - TimeStamp toTimeStamp, - bool latest = false, - IReadOnlyCollection? filterByTs = null, - (long, long)? filterByValue = null, - long? count = null, - TimeStamp? align = null, - TsAggregation? aggregation = null, - long? timeBucket = null, - TsBucketTimestamps? bt = null, - bool empty = false); + /// + /// Query a range. + /// + /// Key name for timeseries + /// Start timestamp for the range query. "-" can be used to express the minimum possible timestamp. + /// End timestamp for range query, + can be used to express the maximum possible timestamp. + /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports + /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls + /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. + /// When a time series is not a compaction, LATEST is ignored. + /// Optional: List of timestamps to filter the result by specific timestamps + /// Optional: Filter result by value using minimum and maximum + /// Optional: Returned list size. + /// Optional: Timestamp for alignment control for aggregation. + /// Optional: Aggregation type + /// Optional: Time bucket for aggregation in milliseconds + /// Optional: controls how bucket timestamps are reported. + /// Optional: when specified, reports aggregations also for empty buckets + /// A list of TimeSeriesTuple + /// + Task> RangeAsync(string key, + TimeStamp fromTimeStamp, + TimeStamp toTimeStamp, + bool latest = false, + IReadOnlyCollection? filterByTs = null, + (long, long)? filterByValue = null, + long? count = null, + TimeStamp? align = null, + TsAggregation? aggregation = null, + long? timeBucket = null, + TsBucketTimestamps? bt = null, + bool empty = false); - /// - /// Query a range in reverse direction. - /// - /// Key name for timeseries - /// Start timestamp for the range query. "-" can be used to express the minimum possible timestamp. - /// End timestamp for range query, + can be used to express the maximum possible timestamp. - /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports - /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls - /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. - /// When a time series is not a compaction, LATEST is ignored. - /// Optional: List of timestamps to filter the result by specific timestamps - /// Optional: Filter result by value using minimum and maximum - /// Optional: Returned list size. - /// Optional: Timestamp for alignment control for aggregation. - /// Optional: Aggregation type - /// Optional: Time bucket for aggregation in milliseconds - /// Optional: controls how bucket timestamps are reported. - /// Optional: when specified, reports aggregations also for empty buckets - /// A list of TimeSeriesTuple - /// - Task> RevRangeAsync(string key, - TimeStamp fromTimeStamp, - TimeStamp toTimeStamp, - bool latest = false, - IReadOnlyCollection? filterByTs = null, - (long, long)? filterByValue = null, - long? count = null, - TimeStamp? align = null, - TsAggregation? aggregation = null, - long? timeBucket = null, - TsBucketTimestamps? bt = null, - bool empty = false); + /// + /// Query a range in reverse direction. + /// + /// Key name for timeseries + /// Start timestamp for the range query. "-" can be used to express the minimum possible timestamp. + /// End timestamp for range query, + can be used to express the maximum possible timestamp. + /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports + /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls + /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. + /// When a time series is not a compaction, LATEST is ignored. + /// Optional: List of timestamps to filter the result by specific timestamps + /// Optional: Filter result by value using minimum and maximum + /// Optional: Returned list size. + /// Optional: Timestamp for alignment control for aggregation. + /// Optional: Aggregation type + /// Optional: Time bucket for aggregation in milliseconds + /// Optional: controls how bucket timestamps are reported. + /// Optional: when specified, reports aggregations also for empty buckets + /// A list of TimeSeriesTuple + /// + Task> RevRangeAsync(string key, + TimeStamp fromTimeStamp, + TimeStamp toTimeStamp, + bool latest = false, + IReadOnlyCollection? filterByTs = null, + (long, long)? filterByValue = null, + long? count = null, + TimeStamp? align = null, + TsAggregation? aggregation = null, + long? timeBucket = null, + TsBucketTimestamps? bt = null, + bool empty = false); - /// - /// Query a timestamp range across multiple time-series by filters. - /// - /// Start timestamp for the range query. - can be used to express the minimum possible timestamp. - /// End timestamp for range query, + can be used to express the maximum possible timestamp. - /// A sequence of filters - /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports - /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls - /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. - /// When a time series is not a compaction, LATEST is ignored. - /// Optional: List of timestamps to filter the result by specific timestamps - /// Optional: Filter result by value using minimum and maximum - /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series - /// Optional: Include in the reply only a subset of the key-value pair labels of a series. - /// Optional: Maximum number of returned results per time-series. - /// Optional: Timestamp for alignment control for aggregation. - /// Optional: Aggregation type - /// Optional: Time bucket for aggregation in milliseconds - /// Optional: controls how bucket timestamps are reported. - /// Optional: when specified, reports aggregations also for empty buckets - /// Optional: Grouping by fields the results, and applying reducer functions on each group. - /// A list of (key, labels, values) tuples. Each tuple contains the key name, its labels and the values which satisfies the given range and filters. - /// - Task labels, IReadOnlyList values)>> MRangeAsync( - TimeStamp fromTimeStamp, - TimeStamp toTimeStamp, - IReadOnlyCollection filter, - bool latest = false, - IReadOnlyCollection? filterByTs = null, - (long, long)? filterByValue = null, - bool? withLabels = null, - IReadOnlyCollection? selectLabels = null, - long? count = null, - TimeStamp? align = null, - TsAggregation? aggregation = null, - long? timeBucket = null, - TsBucketTimestamps? bt = null, - bool empty = false, - (string, TsReduce)? groupbyTuple = null); + /// + /// Query a timestamp range across multiple time-series by filters. + /// + /// Start timestamp for the range query. - can be used to express the minimum possible timestamp. + /// End timestamp for range query, + can be used to express the maximum possible timestamp. + /// A sequence of filters + /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports + /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls + /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. + /// When a time series is not a compaction, LATEST is ignored. + /// Optional: List of timestamps to filter the result by specific timestamps + /// Optional: Filter result by value using minimum and maximum + /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series + /// Optional: Include in the reply only a subset of the key-value pair labels of a series. + /// Optional: Maximum number of returned results per time-series. + /// Optional: Timestamp for alignment control for aggregation. + /// Optional: Aggregation type + /// Optional: Time bucket for aggregation in milliseconds + /// Optional: controls how bucket timestamps are reported. + /// Optional: when specified, reports aggregations also for empty buckets + /// Optional: Grouping by fields the results, and applying reducer functions on each group. + /// A list of (key, labels, values) tuples. Each tuple contains the key name, its labels and the values which satisfies the given range and filters. + /// + Task labels, IReadOnlyList values)>> MRangeAsync( + TimeStamp fromTimeStamp, + TimeStamp toTimeStamp, + IReadOnlyCollection filter, + bool latest = false, + IReadOnlyCollection? filterByTs = null, + (long, long)? filterByValue = null, + bool? withLabels = null, + IReadOnlyCollection? selectLabels = null, + long? count = null, + TimeStamp? align = null, + TsAggregation? aggregation = null, + long? timeBucket = null, + TsBucketTimestamps? bt = null, + bool empty = false, + (string, TsReduce)? groupbyTuple = null); - /// - /// Query a timestamp range in reverse order across multiple time-series by filters. - /// - /// Start timestamp for the range query. - can be used to express the minimum possible timestamp. - /// End timestamp for range query, + can be used to express the maximum possible timestamp. - /// A sequence of filters - /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports - /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls - /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. - /// When a time series is not a compaction, LATEST is ignored. - /// Optional: List of timestamps to filter the result by specific timestamps - /// Optional: Filter result by value using minimum and maximum - /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series - /// Optional: Include in the reply only a subset of the key-value pair labels of a series. - /// Optional: Maximum number of returned results per time-series. - /// Optional: Timestamp for alignment control for aggregation. - /// Optional: Aggregation type - /// Optional: Time bucket for aggregation in milliseconds - /// Optional: controls how bucket timestamps are reported. - /// Optional: when specified, reports aggregations also for empty buckets - /// Optional: Grouping by fields the results, and applying reducer functions on each group. - /// A list of (key, labels, values) tuples. Each tuple contains the key name, its labels and the values which satisfies the given range and filters. - /// - Task labels, IReadOnlyList values)>> MRevRangeAsync( - TimeStamp fromTimeStamp, - TimeStamp toTimeStamp, - IReadOnlyCollection filter, - bool latest = false, - IReadOnlyCollection? filterByTs = null, - (long, long)? filterByValue = null, - bool? withLabels = null, - IReadOnlyCollection? selectLabels = null, - long? count = null, - TimeStamp? align = null, - TsAggregation? aggregation = null, - long? timeBucket = null, - TsBucketTimestamps? bt = null, - bool empty = false, - (string, TsReduce)? groupbyTuple = null); + /// + /// Query a timestamp range in reverse order across multiple time-series by filters. + /// + /// Start timestamp for the range query. - can be used to express the minimum possible timestamp. + /// End timestamp for range query, + can be used to express the maximum possible timestamp. + /// A sequence of filters + /// is used when a time series is a compaction. With LATEST, TS.MRANGE also reports + /// the compacted value of the latest possibly partial bucket, given that this bucket's start time falls + /// within [fromTimestamp, toTimestamp]. Without LATEST, TS.MRANGE does not report the latest possibly partial bucket. + /// When a time series is not a compaction, LATEST is ignored. + /// Optional: List of timestamps to filter the result by specific timestamps + /// Optional: Filter result by value using minimum and maximum + /// Optional: Include in the reply the label-value pairs that represent metadata labels of the time-series + /// Optional: Include in the reply only a subset of the key-value pair labels of a series. + /// Optional: Maximum number of returned results per time-series. + /// Optional: Timestamp for alignment control for aggregation. + /// Optional: Aggregation type + /// Optional: Time bucket for aggregation in milliseconds + /// Optional: controls how bucket timestamps are reported. + /// Optional: when specified, reports aggregations also for empty buckets + /// Optional: Grouping by fields the results, and applying reducer functions on each group. + /// A list of (key, labels, values) tuples. Each tuple contains the key name, its labels and the values which satisfies the given range and filters. + /// + Task labels, IReadOnlyList values)>> MRevRangeAsync( + TimeStamp fromTimeStamp, + TimeStamp toTimeStamp, + IReadOnlyCollection filter, + bool latest = false, + IReadOnlyCollection? filterByTs = null, + (long, long)? filterByValue = null, + bool? withLabels = null, + IReadOnlyCollection? selectLabels = null, + long? count = null, + TimeStamp? align = null, + TsAggregation? aggregation = null, + long? timeBucket = null, + TsBucketTimestamps? bt = null, + bool empty = false, + (string, TsReduce)? groupbyTuple = null); - #endregion + #endregion - #region General + #region General - /// - /// Returns the information for a specific time-series key. - /// - /// Key name for timeseries - /// An optional flag to get a more detailed information about the chunks. - /// TimeSeriesInformation for the specific key. - /// - Task InfoAsync(string key, bool debug = false); + /// + /// Returns the information for a specific time-series key. + /// + /// Key name for timeseries + /// An optional flag to get a more detailed information about the chunks. + /// TimeSeriesInformation for the specific key. + /// + Task InfoAsync(string key, bool debug = false); - /// - /// Get all the keys matching the filter list. - /// - /// A sequence of filters - /// A list of keys with labels matching the filters. - /// - Task> QueryIndexAsync(IReadOnlyCollection filter); + /// + /// Get all the keys matching the filter list. + /// + /// A sequence of filters + /// A list of keys with labels matching the filters. + /// + Task> QueryIndexAsync(IReadOnlyCollection filter); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/Literals/CommandArgs.cs b/src/NRedisStack/TimeSeries/Literals/CommandArgs.cs index 0bdd7812..b39679fa 100644 --- a/src/NRedisStack/TimeSeries/Literals/CommandArgs.cs +++ b/src/NRedisStack/TimeSeries/Literals/CommandArgs.cs @@ -1,29 +1,28 @@ -namespace NRedisStack.Literals +namespace NRedisStack.Literals; + +internal class TimeSeriesArgs { - internal class TimeSeriesArgs - { - public const string RETENTION = "RETENTION"; - public const string LABELS = "LABELS"; - public const string UNCOMPRESSED = "UNCOMPRESSED"; - public const string COMPRESSED = "COMPRESSED"; - public const string COUNT = "COUNT"; - public const string AGGREGATION = "AGGREGATION"; - public const string ALIGN = "ALIGN"; - public const string FILTER = "FILTER"; - public const string WITHLABELS = "WITHLABELS"; - public const string SELECTEDLABELS = "SELECTED_LABELS"; - public const string TIMESTAMP = "TIMESTAMP"; - public const string CHUNK_SIZE = "CHUNK_SIZE"; - public const string DUPLICATE_POLICY = "DUPLICATE_POLICY"; - public const string ON_DUPLICATE = "ON_DUPLICATE"; - public const string GROPUBY = "GROUPBY"; - public const string REDUCE = "REDUCE"; - public const string FILTER_BY_TS = "FILTER_BY_TS"; - public const string FILTER_BY_VALUE = "FILTER_BY_VALUE"; - public const string LATEST = "LATEST"; - public const string DEBUG = "DEBUG"; - public const string BUCKETTIMESTAMP = "BUCKETTIMESTAMP"; - public const string EMPTY = "EMPTY"; - public const String IGNORE = "IGNORE"; - } -} + public const string RETENTION = "RETENTION"; + public const string LABELS = "LABELS"; + public const string UNCOMPRESSED = "UNCOMPRESSED"; + public const string COMPRESSED = "COMPRESSED"; + public const string COUNT = "COUNT"; + public const string AGGREGATION = "AGGREGATION"; + public const string ALIGN = "ALIGN"; + public const string FILTER = "FILTER"; + public const string WITHLABELS = "WITHLABELS"; + public const string SELECTEDLABELS = "SELECTED_LABELS"; + public const string TIMESTAMP = "TIMESTAMP"; + public const string CHUNK_SIZE = "CHUNK_SIZE"; + public const string DUPLICATE_POLICY = "DUPLICATE_POLICY"; + public const string ON_DUPLICATE = "ON_DUPLICATE"; + public const string GROPUBY = "GROUPBY"; + public const string REDUCE = "REDUCE"; + public const string FILTER_BY_TS = "FILTER_BY_TS"; + public const string FILTER_BY_VALUE = "FILTER_BY_VALUE"; + public const string LATEST = "LATEST"; + public const string DEBUG = "DEBUG"; + public const string BUCKETTIMESTAMP = "BUCKETTIMESTAMP"; + public const string EMPTY = "EMPTY"; + public const String IGNORE = "IGNORE"; +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/Literals/Commands.cs b/src/NRedisStack/TimeSeries/Literals/Commands.cs index f0a719e4..efc051c2 100644 --- a/src/NRedisStack/TimeSeries/Literals/Commands.cs +++ b/src/NRedisStack/TimeSeries/Literals/Commands.cs @@ -1,23 +1,22 @@ -namespace NRedisStack.Literals +namespace NRedisStack.Literals; + +internal class TS { - internal class TS - { - public const string CREATE = "TS.CREATE"; - public const string ALTER = "TS.ALTER"; - public const string ADD = "TS.ADD"; - public const string MADD = "TS.MADD"; - public const string INCRBY = "TS.INCRBY"; - public const string DECRBY = "TS.DECRBY"; - public const string DEL = "TS.DEL"; - public const string CREATERULE = "TS.CREATERULE"; - public const string DELETERULE = "TS.DELETERULE"; - public const string RANGE = "TS.RANGE"; - public const string REVRANGE = "TS.REVRANGE"; - public const string MRANGE = "TS.MRANGE"; - public const string MREVRANGE = "TS.MREVRANGE"; - public const string GET = "TS.GET"; - public const string MGET = "TS.MGET"; - public const string INFO = "TS.INFO"; - public const string QUERYINDEX = "TS.QUERYINDEX"; - } -} + public const string CREATE = "TS.CREATE"; + public const string ALTER = "TS.ALTER"; + public const string ADD = "TS.ADD"; + public const string MADD = "TS.MADD"; + public const string INCRBY = "TS.INCRBY"; + public const string DECRBY = "TS.DECRBY"; + public const string DEL = "TS.DEL"; + public const string CREATERULE = "TS.CREATERULE"; + public const string DELETERULE = "TS.DELETERULE"; + public const string RANGE = "TS.RANGE"; + public const string REVRANGE = "TS.REVRANGE"; + public const string MRANGE = "TS.MRANGE"; + public const string MREVRANGE = "TS.MREVRANGE"; + public const string GET = "TS.GET"; + public const string MGET = "TS.MGET"; + public const string INFO = "TS.INFO"; + public const string QUERYINDEX = "TS.QUERYINDEX"; +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/Literals/Enums/Aggregation.cs b/src/NRedisStack/TimeSeries/Literals/Enums/Aggregation.cs index 2b54f515..8e94ddf4 100644 --- a/src/NRedisStack/TimeSeries/Literals/Enums/Aggregation.cs +++ b/src/NRedisStack/TimeSeries/Literals/Enums/Aggregation.cs @@ -1,78 +1,77 @@ -namespace NRedisStack.Literals.Enums +namespace NRedisStack.Literals.Enums; + +/// +/// An aggregation type to be used with a time bucket. +/// +public enum TsAggregation { /// - /// An aggregation type to be used with a time bucket. + /// The average of all samples in the aggregation /// - public enum TsAggregation - { - /// - /// The average of all samples in the aggregation - /// - Avg, + Avg, - /// - /// A sum of all samples in the aggregation - /// - Sum, + /// + /// A sum of all samples in the aggregation + /// + Sum, - /// - /// A minimum sample of all samples in the aggregation - /// - Min, + /// + /// A minimum sample of all samples in the aggregation + /// + Min, - /// - /// A maximum sample of all samples in the aggregation - /// - Max, + /// + /// A maximum sample of all samples in the aggregation + /// + Max, - /// - /// A range of the min and max sample of all samples in the aggregation (range r = max-min) - /// For example if the min sample was 100 and the max was 400, the range aggregation would return 300 - /// - Range, + /// + /// A range of the min and max sample of all samples in the aggregation (range r = max-min) + /// For example if the min sample was 100 and the max was 400, the range aggregation would return 300 + /// + Range, - /// - /// The total number of all samples in the aggregation - /// - Count, + /// + /// The total number of all samples in the aggregation + /// + Count, - /// - /// The first sample in the aggregation - /// - First, + /// + /// The first sample in the aggregation + /// + First, - /// - /// The last sample in the aggregation - /// - Last, + /// + /// The last sample in the aggregation + /// + Last, - /// - /// The standard deviation based on the entire population - /// The standard deviation is a measure of how widely values are dispersed from the average sample in the aggregation - /// - StdP, + /// + /// The standard deviation based on the entire population + /// The standard deviation is a measure of how widely values are dispersed from the average sample in the aggregation + /// + StdP, - /// - /// The standard deviation based on a sample of the population - /// The standard deviation is a measure of how widely values are dispersed from the average sample in the aggregation - /// - StdS, + /// + /// The standard deviation based on a sample of the population + /// The standard deviation is a measure of how widely values are dispersed from the average sample in the aggregation + /// + StdS, - /// - /// The variance based on the entire population - /// The variance is the average of the squared differences from the mean - /// - VarP, + /// + /// The variance based on the entire population + /// The variance is the average of the squared differences from the mean + /// + VarP, - /// - /// The variance based on a sample of the population - /// The variance is the average of the squared differences from the mean - /// - VarS, + /// + /// The variance based on a sample of the population + /// The variance is the average of the squared differences from the mean + /// + VarS, - /// - /// Time-weighted average of all values - /// - Twa, - } -} + /// + /// Time-weighted average of all values + /// + Twa, +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/Literals/Enums/BucketTimestamps.cs b/src/NRedisStack/TimeSeries/Literals/Enums/BucketTimestamps.cs index 54079c09..c1118766 100644 --- a/src/NRedisStack/TimeSeries/Literals/Enums/BucketTimestamps.cs +++ b/src/NRedisStack/TimeSeries/Literals/Enums/BucketTimestamps.cs @@ -1,23 +1,22 @@ -namespace NRedisStack.Literals.Enums +namespace NRedisStack.Literals.Enums; + +/// +/// controls how bucket timestamps are reported. +/// +public enum TsBucketTimestamps { /// - /// controls how bucket timestamps are reported. + /// Timestamp is the start time (default) /// - public enum TsBucketTimestamps - { - /// - /// Timestamp is the start time (default) - /// - low, + low, - /// - /// Timestamp is the mid time (rounded down if not an integer) - /// - mid, + /// + /// Timestamp is the mid time (rounded down if not an integer) + /// + mid, - /// - /// Timestamp is the end time - /// - high, - } + /// + /// Timestamp is the end time + /// + high, } \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/Literals/Enums/DuplicatePolicy.cs b/src/NRedisStack/TimeSeries/Literals/Enums/DuplicatePolicy.cs index 2400bd43..ab3131b8 100644 --- a/src/NRedisStack/TimeSeries/Literals/Enums/DuplicatePolicy.cs +++ b/src/NRedisStack/TimeSeries/Literals/Enums/DuplicatePolicy.cs @@ -1,41 +1,39 @@ -namespace NRedisStack.Literals.Enums +namespace NRedisStack.Literals.Enums; + +/// +/// Policy to handle duplicate samples. +/// The default policy for database-wide is BLOCK. +/// +public enum TsDuplicatePolicy { /// - /// Policy to handle duplicate samples. - /// The default policy for database-wide is BLOCK. + /// An error will occur for any out of order sample. /// - public enum TsDuplicatePolicy - { - /// - /// An error will occur for any out of order sample. - /// - BLOCK, - - /// - /// Ignore the new value. - /// - FIRST, + BLOCK, - /// - /// Override with latest value. - /// - LAST, + /// + /// Ignore the new value. + /// + FIRST, - /// - /// Only override if the value is lower than the existing value. - /// - MIN, + /// + /// Override with latest value. + /// + LAST, - /// - /// Only override if the value is higher than the existing value. - /// - MAX, + /// + /// Only override if the value is lower than the existing value. + /// + MIN, - /// - /// If a previous sample exists, add the new sample to it so that the updated value is equal to (previous + new). - /// If no previous sample exists, set the updated value equal to the new value. - /// - SUM - } -} + /// + /// Only override if the value is higher than the existing value. + /// + MAX, + /// + /// If a previous sample exists, add the new sample to it so that the updated value is equal to (previous + new). + /// If no previous sample exists, set the updated value equal to the new value. + /// + SUM +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/Literals/Enums/Reduce.cs b/src/NRedisStack/TimeSeries/Literals/Enums/Reduce.cs index da3f94ac..8d525607 100644 --- a/src/NRedisStack/TimeSeries/Literals/Enums/Reduce.cs +++ b/src/NRedisStack/TimeSeries/Literals/Enums/Reduce.cs @@ -1,58 +1,57 @@ -namespace NRedisStack.Literals.Enums +namespace NRedisStack.Literals.Enums; + +/// +/// reducer type used to aggregate series that share the same label value. +/// +public enum TsReduce { /// - /// reducer type used to aggregate series that share the same label value. - /// - public enum TsReduce - { - /// - /// A sum of all samples in the group - /// - Sum, - - /// - /// A minimum sample of all samples in the group - /// - Min, - - /// - /// A maximum sample of all samples in the group - /// - Max, - - /// - /// Arithmetic mean of all non-NaN values (since RedisTimeSeries v1.8) - /// - Avg, - - /// - /// Difference between maximum non-NaN value and minimum non-NaN value (since RedisTimeSeries v1.8) - /// - Range, - - /// - /// Number of non-NaN values (since RedisTimeSeries v1.8) - /// - Count, - - /// - /// Population standard deviation of all non-NaN values (since RedisTimeSeries v1.8) - /// - StdP, - - /// - /// Sample standard deviation of all non-NaN values (since RedisTimeSeries v1.8) - /// - StdS, - - /// - /// Population variance of all non-NaN values (since RedisTimeSeries v1.8) - /// - VarP, - - /// - /// Sample variance of all non-NaN values (since RedisTimeSeries v1.8) - /// - VarS - } -} + /// A sum of all samples in the group + /// + Sum, + + /// + /// A minimum sample of all samples in the group + /// + Min, + + /// + /// A maximum sample of all samples in the group + /// + Max, + + /// + /// Arithmetic mean of all non-NaN values (since RedisTimeSeries v1.8) + /// + Avg, + + /// + /// Difference between maximum non-NaN value and minimum non-NaN value (since RedisTimeSeries v1.8) + /// + Range, + + /// + /// Number of non-NaN values (since RedisTimeSeries v1.8) + /// + Count, + + /// + /// Population standard deviation of all non-NaN values (since RedisTimeSeries v1.8) + /// + StdP, + + /// + /// Sample standard deviation of all non-NaN values (since RedisTimeSeries v1.8) + /// + StdS, + + /// + /// Population variance of all non-NaN values (since RedisTimeSeries v1.8) + /// + VarP, + + /// + /// Sample variance of all non-NaN values (since RedisTimeSeries v1.8) + /// + VarS +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/TimeSeriesAux.cs b/src/NRedisStack/TimeSeries/TimeSeriesAux.cs index e9c8d870..232e54f5 100644 --- a/src/NRedisStack/TimeSeries/TimeSeriesAux.cs +++ b/src/NRedisStack/TimeSeries/TimeSeriesAux.cs @@ -3,234 +3,233 @@ using NRedisStack.DataTypes; using NRedisStack.Extensions; -namespace NRedisStack +namespace NRedisStack; + +public static class TimeSeriesAux { - public static class TimeSeriesAux + public static void AddLatest(this IList args, bool latest) { - public static void AddLatest(this IList args, bool latest) - { - if (latest) args.Add(TimeSeriesArgs.LATEST); - } + if (latest) args.Add(TimeSeriesArgs.LATEST); + } - public static void AddCount(this IList args, long? count) + public static void AddCount(this IList args, long? count) + { + if (count.HasValue) { - if (count.HasValue) - { - args.Add(TimeSeriesArgs.COUNT); - args.Add(count.Value); - } + args.Add(TimeSeriesArgs.COUNT); + args.Add(count.Value); } + } - public static void AddAlign(this IList args, TimeStamp? alignMaybe) + public static void AddAlign(this IList args, TimeStamp? alignMaybe) + { + if (alignMaybe is { } align) { - if (alignMaybe is { } align) - { - args.Add(TimeSeriesArgs.ALIGN); - args.Add(align.Value); - } + args.Add(TimeSeriesArgs.ALIGN); + args.Add(align.Value); } + } - public static void AddBucketTimestamp(this IList args, TsBucketTimestamps? bt) + public static void AddBucketTimestamp(this IList args, TsBucketTimestamps? bt) + { + if (bt != null) { - if (bt != null) - { - args.Add(TimeSeriesArgs.BUCKETTIMESTAMP); - args.Add(bt.Value.AsArg()); - } + args.Add(TimeSeriesArgs.BUCKETTIMESTAMP); + args.Add(bt.Value.AsArg()); } + } - public static void AddAggregation(this IList args, TimeStamp? align, - TsAggregation? aggregation, - long? timeBucket, - TsBucketTimestamps? bt, - bool empty) + public static void AddAggregation(this IList args, TimeStamp? align, + TsAggregation? aggregation, + long? timeBucket, + TsBucketTimestamps? bt, + bool empty) + { + if (aggregation == null && (align != null || timeBucket != null || bt != null || empty)) { - if (aggregation == null && (align != null || timeBucket != null || bt != null || empty)) - { - throw new ArgumentException("align, timeBucket, BucketTimestamps or empty cannot be defined without Aggregation"); - } - else - { - args.AddAlign(align); - args.AddAggregation(aggregation, timeBucket); - args.AddBucketTimestamp(bt); - if (empty) args.Add(TimeSeriesArgs.EMPTY); - } + throw new ArgumentException("align, timeBucket, BucketTimestamps or empty cannot be defined without Aggregation"); } - - public static void AddAggregation(this IList args, TsAggregation? aggregation, long? timeBucket) + else { - if (aggregation != null) - { - args.Add(TimeSeriesArgs.AGGREGATION); - args.Add(aggregation.Value.AsArg()); - if (!timeBucket.HasValue) - { - throw new ArgumentException("RANGE Aggregation should have timeBucket value"); - } - args.Add(timeBucket.Value); - } + args.AddAlign(align); + args.AddAggregation(aggregation, timeBucket); + args.AddBucketTimestamp(bt); + if (empty) args.Add(TimeSeriesArgs.EMPTY); } + } - public static void AddFilters(this List args, IReadOnlyCollection filter) + public static void AddAggregation(this IList args, TsAggregation? aggregation, long? timeBucket) + { + if (aggregation != null) { - if (filter == null || filter.Count == 0) - { - throw new ArgumentException("There should be at least one filter on MRANGE/MREVRANGE"); - } - args.Add(TimeSeriesArgs.FILTER); - foreach (string f in filter) + args.Add(TimeSeriesArgs.AGGREGATION); + args.Add(aggregation.Value.AsArg()); + if (!timeBucket.HasValue) { - args.Add(f); + throw new ArgumentException("RANGE Aggregation should have timeBucket value"); } + args.Add(timeBucket.Value); } + } - public static void AddFilterByTs(this List args, IReadOnlyCollection? filter) + public static void AddFilters(this List args, IReadOnlyCollection filter) + { + if (filter == null || filter.Count == 0) { - if (filter != null) - { - args.Add(TimeSeriesArgs.FILTER_BY_TS); - foreach (var ts in filter) - { - args.Add(ts.Value); - } - } + throw new ArgumentException("There should be at least one filter on MRANGE/MREVRANGE"); } - - public static void AddFilterByValue(this List args, (long, long)? filter) + args.Add(TimeSeriesArgs.FILTER); + foreach (string f in filter) { - if (filter != null) - { - args.Add(TimeSeriesArgs.FILTER_BY_VALUE); - args.Add(filter.Value.Item1); - args.Add(filter.Value.Item2); - } - } - - public static void AddWithLabels(this IList args, bool? withLabels, IReadOnlyCollection? selectLabels = null) - { - if (withLabels.HasValue && selectLabels != null) - { - throw new ArgumentException("withLabels and selectLabels cannot be specified together."); - } - - if (withLabels.HasValue && withLabels.Value) - { - args.Add(TimeSeriesArgs.WITHLABELS); - } - - if (selectLabels != null) - { - args.Add(TimeSeriesArgs.SELECTEDLABELS); - foreach (string label in selectLabels) - { - args.Add(label); - } - } + args.Add(f); } + } - public static void AddGroupby(this IList args, (string groupby, TsReduce reduce)? groupbyTuple) + public static void AddFilterByTs(this List args, IReadOnlyCollection? filter) + { + if (filter != null) { - if (groupbyTuple.HasValue) + args.Add(TimeSeriesArgs.FILTER_BY_TS); + foreach (var ts in filter) { - args.Add(TimeSeriesArgs.GROPUBY); - args.Add(groupbyTuple.Value.groupby); - args.Add(TimeSeriesArgs.REDUCE); - args.Add(groupbyTuple.Value.reduce.AsArg()); + args.Add(ts.Value); } } + } - public static void AddTimeStamp(this IList args, TimeStamp timeStamp) + public static void AddFilterByValue(this List args, (long, long)? filter) + { + if (filter != null) { - args.Add(TimeSeriesArgs.TIMESTAMP); - args.Add(timeStamp.Value); + args.Add(TimeSeriesArgs.FILTER_BY_VALUE); + args.Add(filter.Value.Item1); + args.Add(filter.Value.Item2); } + } - public static void AddRule(this IList args, TimeSeriesRule rule) + public static void AddWithLabels(this IList args, bool? withLabels, IReadOnlyCollection? selectLabels = null) + { + if (withLabels.HasValue && selectLabels != null) { - args.Add(rule.DestKey); - args.Add(TimeSeriesArgs.AGGREGATION); - args.Add(rule.Aggregation.AsArg()); - args.Add(rule.TimeBucket); + throw new ArgumentException("withLabels and selectLabels cannot be specified together."); } - public static List BuildTsDelArgs(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp) + if (withLabels.HasValue && withLabels.Value) { - var args = new List - {key, fromTimeStamp.Value, toTimeStamp.Value}; - return args; + args.Add(TimeSeriesArgs.WITHLABELS); } - public static List BuildTsMaddArgs(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) + if (selectLabels != null) { - var args = new List(); - foreach (var tuple in sequence) + args.Add(TimeSeriesArgs.SELECTEDLABELS); + foreach (string label in selectLabels) { - args.Add(tuple.key); - args.Add(tuple.timestamp.Value); - args.Add(tuple.value); + args.Add(label); } - return args; } + } - public static List BuildTsMgetArgs(bool latest, IReadOnlyCollection filter, bool? withLabels = null, IReadOnlyCollection? selectedLabels = null) + public static void AddGroupby(this IList args, (string groupby, TsReduce reduce)? groupbyTuple) + { + if (groupbyTuple.HasValue) { - var args = new List(); - args.AddLatest(latest); - args.AddWithLabels(withLabels, selectedLabels); - args.AddFilters(filter); - return args; + args.Add(TimeSeriesArgs.GROPUBY); + args.Add(groupbyTuple.Value.groupby); + args.Add(TimeSeriesArgs.REDUCE); + args.Add(groupbyTuple.Value.reduce.AsArg()); } + } - public static List BuildRangeArgs(string key, - TimeStamp fromTimeStamp, - TimeStamp toTimeStamp, - bool latest, - IReadOnlyCollection? filterByTs, - (long, long)? filterByValue, - long? count, - TimeStamp? align, - TsAggregation? aggregation, - long? timeBucket, - TsBucketTimestamps? bt, - bool empty) - { - var args = new List() { key, fromTimeStamp.Value, toTimeStamp.Value }; - args.AddLatest(latest); - args.AddFilterByTs(filterByTs); - args.AddFilterByValue(filterByValue); - args.AddCount(count); - args.AddAggregation(align, aggregation, timeBucket, bt, empty); - return args; - } + public static void AddTimeStamp(this IList args, TimeStamp timeStamp) + { + args.Add(TimeSeriesArgs.TIMESTAMP); + args.Add(timeStamp.Value); + } + + public static void AddRule(this IList args, TimeSeriesRule rule) + { + args.Add(rule.DestKey); + args.Add(TimeSeriesArgs.AGGREGATION); + args.Add(rule.Aggregation.AsArg()); + args.Add(rule.TimeBucket); + } + public static List BuildTsDelArgs(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp) + { + var args = new List + {key, fromTimeStamp.Value, toTimeStamp.Value}; + return args; + } - public static List BuildMultiRangeArgs(TimeStamp fromTimeStamp, - TimeStamp toTimeStamp, - IReadOnlyCollection filter, - bool latest, - IReadOnlyCollection? filterByTs, - (long, long)? filterByValue, - bool? withLabels, - IReadOnlyCollection? selectLabels, - long? count, - TimeStamp? align, - TsAggregation? aggregation, - long? timeBucket, - TsBucketTimestamps? bt, - bool empty, - (string, TsReduce)? groupbyTuple) + public static List BuildTsMaddArgs(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) + { + var args = new List(); + foreach (var tuple in sequence) { - var args = new List() { fromTimeStamp.Value, toTimeStamp.Value }; - args.AddLatest(latest); - args.AddFilterByTs(filterByTs); - args.AddFilterByValue(filterByValue); - args.AddWithLabels(withLabels, selectLabels); - args.AddCount(count); - args.AddAggregation(align, aggregation, timeBucket, bt, empty); - args.AddFilters(filter); - args.AddGroupby(groupbyTuple); - return args; + args.Add(tuple.key); + args.Add(tuple.timestamp.Value); + args.Add(tuple.value); } + return args; + } + + public static List BuildTsMgetArgs(bool latest, IReadOnlyCollection filter, bool? withLabels = null, IReadOnlyCollection? selectedLabels = null) + { + var args = new List(); + args.AddLatest(latest); + args.AddWithLabels(withLabels, selectedLabels); + args.AddFilters(filter); + return args; + } + + public static List BuildRangeArgs(string key, + TimeStamp fromTimeStamp, + TimeStamp toTimeStamp, + bool latest, + IReadOnlyCollection? filterByTs, + (long, long)? filterByValue, + long? count, + TimeStamp? align, + TsAggregation? aggregation, + long? timeBucket, + TsBucketTimestamps? bt, + bool empty) + { + var args = new List() { key, fromTimeStamp.Value, toTimeStamp.Value }; + args.AddLatest(latest); + args.AddFilterByTs(filterByTs); + args.AddFilterByValue(filterByValue); + args.AddCount(count); + args.AddAggregation(align, aggregation, timeBucket, bt, empty); + return args; + } + + + public static List BuildMultiRangeArgs(TimeStamp fromTimeStamp, + TimeStamp toTimeStamp, + IReadOnlyCollection filter, + bool latest, + IReadOnlyCollection? filterByTs, + (long, long)? filterByValue, + bool? withLabels, + IReadOnlyCollection? selectLabels, + long? count, + TimeStamp? align, + TsAggregation? aggregation, + long? timeBucket, + TsBucketTimestamps? bt, + bool empty, + (string, TsReduce)? groupbyTuple) + { + var args = new List() { fromTimeStamp.Value, toTimeStamp.Value }; + args.AddLatest(latest); + args.AddFilterByTs(filterByTs); + args.AddFilterByValue(filterByValue); + args.AddWithLabels(withLabels, selectLabels); + args.AddCount(count); + args.AddAggregation(align, aggregation, timeBucket, bt, empty); + args.AddFilters(filter); + args.AddGroupby(groupbyTuple); + return args; } -} +} \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/TimeSeriesCommands.cs b/src/NRedisStack/TimeSeries/TimeSeriesCommands.cs index 4f759524..d2b02e4b 100644 --- a/src/NRedisStack/TimeSeries/TimeSeriesCommands.cs +++ b/src/NRedisStack/TimeSeries/TimeSeriesCommands.cs @@ -1,126 +1,126 @@ using StackExchange.Redis; using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; -namespace NRedisStack +namespace NRedisStack; + +public class TimeSeriesCommands : TimeSeriesCommandsAsync, ITimeSeriesCommands { - public class TimeSeriesCommands : TimeSeriesCommandsAsync, ITimeSeriesCommands + readonly IDatabase _db; + public TimeSeriesCommands(IDatabase db) : base(db) { - IDatabase _db; - public TimeSeriesCommands(IDatabase db) : base(db) - { - _db = db; - } + _db = db; + } - #region Create + #region Create - /// - [Obsolete("Please use the other method with TsCreateParams and check related builder TsCreateParamsBuilder to build parameters.")] - public bool Create(string key, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) - { - return _db.Execute(TimeSeriesCommandsBuilder.Create(key, retentionTime, labels, - uncompressed, chunkSizeBytes, - duplicatePolicy)).OKtoBoolean(); - } + /// + [Obsolete("Please use the other method with TsCreateParams and check related builder TsCreateParamsBuilder to build parameters.")] + public bool Create(string key, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) + { + return _db.Execute(TimeSeriesCommandsBuilder.Create(key, retentionTime, labels, + uncompressed, chunkSizeBytes, + duplicatePolicy)).OKtoBoolean(); + } - /// - public bool Create(string key, TsCreateParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.Create(key, parameters)).OKtoBoolean(); + /// + public bool Create(string key, TsCreateParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.Create(key, parameters)).OKtoBoolean(); - #endregion + #endregion - #region Update + #region Update - /// - [Obsolete("Please use the other method with TsAlterParams and check related builder TsAlterParamsBuilder to build parameters.")] - public bool Alter(string key, long? retentionTime = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null, IReadOnlyCollection? labels = null) - { - return _db.Execute(TimeSeriesCommandsBuilder.Alter(key, retentionTime, chunkSizeBytes, duplicatePolicy, labels)).OKtoBoolean(); - } + /// + [Obsolete("Please use the other method with TsAlterParams and check related builder TsAlterParamsBuilder to build parameters.")] + public bool Alter(string key, long? retentionTime = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null, IReadOnlyCollection? labels = null) + { + return _db.Execute(TimeSeriesCommandsBuilder.Alter(key, retentionTime, chunkSizeBytes, duplicatePolicy, labels)).OKtoBoolean(); + } - /// - public bool Alter(string key, TsAlterParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.Alter(key, parameters)).OKtoBoolean(); + /// + public bool Alter(string key, TsAlterParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.Alter(key, parameters)).OKtoBoolean(); - /// - [Obsolete("Please use the other method with TsAddParams and check related builder TsAddParamsBuilder to build parameters.")] - public TimeStamp Add(string key, TimeStamp timestamp, double value, long? retentionTime = null, + /// + [Obsolete("Please use the other method with TsAddParams and check related builder TsAddParamsBuilder to build parameters.")] + public TimeStamp Add(string key, TimeStamp timestamp, double value, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) - { - return _db.Execute(TimeSeriesCommandsBuilder.Add(key, timestamp, value, retentionTime, labels, - uncompressed, chunkSizeBytes, duplicatePolicy)).ToTimeStamp(); - } - - /// - public TimeStamp Add(string key, TsAddParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.Add(key, parameters)).ToTimeStamp(); - - /// - public IReadOnlyList MAdd(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) - { - return _db.Execute(TimeSeriesCommandsBuilder.MAdd(sequence)).ToTimeStampArray()!; - } - - /// - [Obsolete("Please use the other method with TsIncrByParams and check related builder TsIncryByParamsBuilder to build parameters.")] - public TimeStamp IncrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) - { - return _db.Execute(TimeSeriesCommandsBuilder.IncrBy(key, value, timestamp, retentionTime, - labels, uncompressed, chunkSizeBytes)).ToTimeStamp(); - } - - /// - public TimeStamp IncrBy(string key, TsIncrByParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.IncrBy(key, parameters)).ToTimeStamp(); - - /// - [Obsolete("Please use the other method with TsDecrByParams and check related builder TsDecryByParamsBuilder to build parameters.")] - public TimeStamp DecrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) - { - return _db.Execute(TimeSeriesCommandsBuilder.DecrBy(key, value, timestamp, retentionTime, - labels, uncompressed, chunkSizeBytes)).ToTimeStamp(); - } - - /// - public TimeStamp DecrBy(string key, TsDecrByParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.DecrBy(key, parameters)).ToTimeStamp(); - - /// - public long Del(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp) - { - return _db.Execute(TimeSeriesCommandsBuilder.Del(key, fromTimeStamp, toTimeStamp)).ToLong(); - } - - #endregion - - #region Aggregation, Compaction, Downsampling - - /// - public bool CreateRule(string sourceKey, TimeSeriesRule rule, long alignTimestamp = 0) - { - return _db.Execute(TimeSeriesCommandsBuilder.CreateRule(sourceKey, rule, alignTimestamp)).OKtoBoolean(); - } - - /// - public bool DeleteRule(string sourceKey, string destKey) - { - return _db.Execute(TimeSeriesCommandsBuilder.DeleteRule(sourceKey, destKey)).OKtoBoolean(); - } - - #endregion - - #region Query - - /// - public TimeSeriesTuple? Get(string key, bool latest = false) - { - return _db.Execute(TimeSeriesCommandsBuilder.Get(key, latest)).ToTimeSeriesTuple(); - } - - /// - public IReadOnlyList<(string key, IReadOnlyList labels, TimeSeriesTuple value)> MGet(IReadOnlyCollection filter, bool latest = false, - bool? withLabels = null, IReadOnlyCollection? selectedLabels = null) - { - return _db.Execute(TimeSeriesCommandsBuilder.MGet(filter, latest, withLabels, selectedLabels)).ParseMGetResponse(); - } - - /// - public IReadOnlyList Range(string key, + { + return _db.Execute(TimeSeriesCommandsBuilder.Add(key, timestamp, value, retentionTime, labels, + uncompressed, chunkSizeBytes, duplicatePolicy)).ToTimeStamp(); + } + + /// + public TimeStamp Add(string key, TsAddParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.Add(key, parameters)).ToTimeStamp(); + + /// + public IReadOnlyList MAdd(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) + { + return _db.Execute(TimeSeriesCommandsBuilder.MAdd(sequence)).ToTimeStampArray(); + } + + /// + [Obsolete("Please use the other method with TsIncrByParams and check related builder TsIncryByParamsBuilder to build parameters.")] + public TimeStamp IncrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + { + return _db.Execute(TimeSeriesCommandsBuilder.IncrBy(key, value, timestamp, retentionTime, + labels, uncompressed, chunkSizeBytes)).ToTimeStamp(); + } + + /// + public TimeStamp IncrBy(string key, TsIncrByParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.IncrBy(key, parameters)).ToTimeStamp(); + + /// + [Obsolete("Please use the other method with TsDecrByParams and check related builder TsDecryByParamsBuilder to build parameters.")] + public TimeStamp DecrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + { + return _db.Execute(TimeSeriesCommandsBuilder.DecrBy(key, value, timestamp, retentionTime, + labels, uncompressed, chunkSizeBytes)).ToTimeStamp(); + } + + /// + public TimeStamp DecrBy(string key, TsDecrByParams parameters) => _db.Execute(TimeSeriesCommandsBuilder.DecrBy(key, parameters)).ToTimeStamp(); + + /// + public long Del(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp) + { + return _db.Execute(TimeSeriesCommandsBuilder.Del(key, fromTimeStamp, toTimeStamp)).ToLong(); + } + + #endregion + + #region Aggregation, Compaction, Downsampling + + /// + public bool CreateRule(string sourceKey, TimeSeriesRule rule, long alignTimestamp = 0) + { + return _db.Execute(TimeSeriesCommandsBuilder.CreateRule(sourceKey, rule, alignTimestamp)).OKtoBoolean(); + } + + /// + public bool DeleteRule(string sourceKey, string destKey) + { + return _db.Execute(TimeSeriesCommandsBuilder.DeleteRule(sourceKey, destKey)).OKtoBoolean(); + } + + #endregion + + #region Query + + /// + public TimeSeriesTuple? Get(string key, bool latest = false) + { + return _db.Execute(TimeSeriesCommandsBuilder.Get(key, latest)).ToTimeSeriesTuple(); + } + + /// + public IReadOnlyList<(string key, IReadOnlyList labels, TimeSeriesTuple value)> MGet(IReadOnlyCollection filter, bool latest = false, + bool? withLabels = null, IReadOnlyCollection? selectedLabels = null) + { + return _db.Execute(TimeSeriesCommandsBuilder.MGet(filter, latest, withLabels, selectedLabels)).ParseMGetResponse(); + } + + /// + public IReadOnlyList Range(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, bool latest = false, @@ -132,15 +132,15 @@ public IReadOnlyList Range(string key, long? timeBucket = null, TsBucketTimestamps? bt = null, bool empty = false) - { - return _db.Execute(TimeSeriesCommandsBuilder.Range(key, fromTimeStamp, toTimeStamp, - latest, filterByTs, filterByValue, - count, align, aggregation, timeBucket, - bt, empty)).ToTimeSeriesTupleArray(); - } - - /// - public IReadOnlyList RevRange(string key, + { + return _db.Execute(TimeSeriesCommandsBuilder.Range(key, fromTimeStamp, toTimeStamp, + latest, filterByTs, filterByValue, + count, align, aggregation, timeBucket, + bt, empty)).ToTimeSeriesTupleArray(); + } + + /// + public IReadOnlyList RevRange(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, bool latest = false, @@ -152,15 +152,15 @@ public IReadOnlyList RevRange(string key, long? timeBucket = null, TsBucketTimestamps? bt = null, bool empty = false) - { - return _db.Execute(TimeSeriesCommandsBuilder.RevRange(key, fromTimeStamp, toTimeStamp, - latest, filterByTs, filterByValue, - count, align, aggregation, timeBucket, - bt, empty)).ToTimeSeriesTupleArray(); - } - - /// - public IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> MRange( + { + return _db.Execute(TimeSeriesCommandsBuilder.RevRange(key, fromTimeStamp, toTimeStamp, + latest, filterByTs, filterByValue, + count, align, aggregation, timeBucket, + bt, empty)).ToTimeSeriesTupleArray(); + } + + /// + public IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> MRange( TimeStamp fromTimeStamp, TimeStamp toTimeStamp, IReadOnlyCollection filter, @@ -176,16 +176,16 @@ public IReadOnlyList RevRange(string key, TsBucketTimestamps? bt = null, bool empty = false, (string, TsReduce)? groupbyTuple = null) - { - return _db.Execute(TimeSeriesCommandsBuilder.MRange(fromTimeStamp, toTimeStamp, filter, - latest, filterByTs, filterByValue, - withLabels, selectLabels, count, align, - aggregation, timeBucket, bt, empty, - groupbyTuple)).ParseMRangeResponse(); - } - - /// - public IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> MRevRange( + { + return _db.Execute(TimeSeriesCommandsBuilder.MRange(fromTimeStamp, toTimeStamp, filter, + latest, filterByTs, filterByValue, + withLabels, selectLabels, count, align, + aggregation, timeBucket, bt, empty, + groupbyTuple)).ParseMRangeResponse(); + } + + /// + public IReadOnlyList<(string key, IReadOnlyList labels, IReadOnlyList values)> MRevRange( TimeStamp fromTimeStamp, TimeStamp toTimeStamp, IReadOnlyCollection filter, @@ -201,31 +201,30 @@ public IReadOnlyList RevRange(string key, TsBucketTimestamps? bt = null, bool empty = false, (string, TsReduce)? groupbyTuple = null) - { - return _db.Execute(TimeSeriesCommandsBuilder.MRevRange(fromTimeStamp, toTimeStamp, filter, - latest, filterByTs, filterByValue, - withLabels, selectLabels, count, align, - aggregation, timeBucket, bt, empty, - groupbyTuple)).ParseMRangeResponse(); - } - - #endregion + { + return _db.Execute(TimeSeriesCommandsBuilder.MRevRange(fromTimeStamp, toTimeStamp, filter, + latest, filterByTs, filterByValue, + withLabels, selectLabels, count, align, + aggregation, timeBucket, bt, empty, + groupbyTuple)).ParseMRangeResponse(); + } - #region General + #endregion - /// - [Obsolete] - public TimeSeriesInformation Info(string key, bool debug = false) - { - return _db.Execute(TimeSeriesCommandsBuilder.Info(key, debug)).ToTimeSeriesInfo(); - } + #region General - /// - public IReadOnlyList QueryIndex(IReadOnlyCollection filter) - { - return _db.Execute(TimeSeriesCommandsBuilder.QueryIndex(filter)).ToStringList(); - } + /// + [Obsolete] + public TimeSeriesInformation Info(string key, bool debug = false) + { + return _db.Execute(TimeSeriesCommandsBuilder.Info(key, debug)).ToTimeSeriesInfo(); + } - #endregion + /// + public IReadOnlyList QueryIndex(IReadOnlyCollection filter) + { + return _db.Execute(TimeSeriesCommandsBuilder.QueryIndex(filter)).ToStringList(); } + + #endregion } \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/TimeSeriesCommandsAsync.cs b/src/NRedisStack/TimeSeries/TimeSeriesCommandsAsync.cs index a6486f48..2df4b18e 100644 --- a/src/NRedisStack/TimeSeries/TimeSeriesCommandsAsync.cs +++ b/src/NRedisStack/TimeSeries/TimeSeriesCommandsAsync.cs @@ -1,126 +1,132 @@ using StackExchange.Redis; using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; -namespace NRedisStack +namespace NRedisStack; + +public class TimeSeriesCommandsAsync : ITimeSeriesCommandsAsync { - public class TimeSeriesCommandsAsync : ITimeSeriesCommandsAsync - { - IDatabaseAsync _db; - public TimeSeriesCommandsAsync(IDatabaseAsync db) - { - _db = db; - } - - #region Create - - /// - [Obsolete("Please use the other method with TsCreateParams and check related builder TsCreateParamsBuilder to build parameters.")] - public async Task CreateAsync(string key, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Create(key, retentionTime, labels, - uncompressed, chunkSizeBytes, - duplicatePolicy))).OKtoBoolean(); - } - - /// - public async Task CreateAsync(string key, TsCreateParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Create(key, parameters))).OKtoBoolean(); - - #endregion - - #region Update - - /// - [Obsolete("Please use the other method with TsAlterParams and check related builder TsAlterParamsBuilder to build parameters.")] - public async Task AlterAsync(string key, long? retentionTime = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null, IReadOnlyCollection? labels = null) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Alter(key, retentionTime, chunkSizeBytes, duplicatePolicy, labels))).OKtoBoolean(); - } - - /// - public async Task AlterAsync(string key, TsAlterParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Alter(key, parameters))).OKtoBoolean(); - - /// - [Obsolete("Please use the other method with TsAddParams and check related builder TsAddParamsBuilder to build parameters.")] - public async Task AddAsync(string key, TimeStamp timestamp, double value, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Add(key, timestamp, value, retentionTime, labels, - uncompressed, chunkSizeBytes, duplicatePolicy))).ToTimeStamp(); - } - - /// - public async Task AddAsync(string key, TsAddParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Add(key, parameters))).ToTimeStamp(); - - /// - public async Task> MAddAsync(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.MAdd(sequence))).ToTimeStampArray(); - } - - /// - public async Task IncrByAsync(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.IncrBy(key, value, timestamp, retentionTime, - labels, uncompressed, chunkSizeBytes))).ToTimeStamp(); - } - - - /// - [Obsolete("Please use the other method with TsIncrByParams and check related builder TsIncryByParamsBuilder to build parameters.")] - public async Task IncrByAsync(string key, TsIncrByParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.IncrBy(key, parameters))).ToTimeStamp(); - - - /// - public async Task DecrByAsync(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.DecrBy(key, value, timestamp, retentionTime, - labels, uncompressed, chunkSizeBytes))).ToTimeStamp(); - } - - /// - [Obsolete("Please use the other method with TsDecrByParams and check related builder TsDecryByParamsBuilder to build parameters.")] - public async Task DecrByAsync(string key, TsDecrByParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.DecrBy(key, parameters))).ToTimeStamp(); - - /// - public async Task DelAsync(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Del(key, fromTimeStamp, toTimeStamp))).ToLong(); - } - - #endregion - - #region Aggregation, Compaction, Downsampling - - /// - public async Task CreateRuleAsync(string sourceKey, TimeSeriesRule rule, long alignTimestamp = 0) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.CreateRule(sourceKey, rule, alignTimestamp))).OKtoBoolean(); - } - - /// - public async Task DeleteRuleAsync(string sourceKey, string destKey) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.DeleteRule(sourceKey, destKey))).OKtoBoolean(); - } - - #endregion - - #region Query - - /// - public async Task GetAsync(string key, bool latest = false) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Get(key, latest))).ToTimeSeriesTuple(); - } - - /// - public async Task labels, TimeSeriesTuple value)>> MGetAsync(IReadOnlyCollection filter, bool latest = false, - bool? withLabels = null, IReadOnlyCollection? selectedLabels = null) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.MGet(filter, latest, withLabels, selectedLabels))).ParseMGetResponse(); - } - - /// - public async Task> RangeAsync(string key, + readonly IDatabaseAsync _db; + public TimeSeriesCommandsAsync(IDatabaseAsync db) + { + _db = db; + } + + #region Create + + /// + [Obsolete("Please use the other method with TsCreateParams and check related builder TsCreateParamsBuilder to build parameters.")] + public async Task CreateAsync(string key, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Create(key, retentionTime, labels, + uncompressed, chunkSizeBytes, + duplicatePolicy))).OKtoBoolean(); + } + + /// + public async Task CreateAsync(string key, TsCreateParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Create(key, parameters))).OKtoBoolean(); + + #endregion + + #region Update + + /// + [Obsolete("Please use the other method with TsAlterParams and check related builder TsAlterParamsBuilder to build parameters.")] + public async Task AlterAsync(string key, long? retentionTime = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null, IReadOnlyCollection? labels = null) + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Alter(key, retentionTime, chunkSizeBytes, duplicatePolicy, labels))).OKtoBoolean(); + } + + /// + public async Task AlterAsync(string key, TsAlterParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Alter(key, parameters))).OKtoBoolean(); + + /// + [Obsolete("Please use the other method with TsAddParams and check related builder TsAddParamsBuilder to build parameters.")] + public async Task AddAsync(string key, TimeStamp timestamp, double value, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Add(key, timestamp, value, retentionTime, labels, + uncompressed, chunkSizeBytes, duplicatePolicy))).ToTimeStamp(); + } + + /// + public async Task AddAsync(string key, TsAddParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Add(key, parameters))).ToTimeStamp(); + + /// + public async Task> MAddAsync(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.MAdd(sequence))).ToTimeStampArray(); + } + + /// + public async Task IncrByAsync(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + { + return (await _db.ExecuteAsync( +#pragma warning disable CS0612 + TimeSeriesCommandsBuilder.IncrBy( +#pragma warning restore CS0612 + key, value, timestamp, retentionTime, + labels, uncompressed, chunkSizeBytes))).ToTimeStamp(); + } + + + [Obsolete("Please use the other method with TsIncrByParams and check related builder TsIncryByParamsBuilder to build parameters.")] + public async Task IncrByAsync(string key, TsIncrByParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.IncrBy(key, parameters))).ToTimeStamp(); + + + /// + public async Task DecrByAsync(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + { + return (await _db.ExecuteAsync( +#pragma warning disable CS0612 + TimeSeriesCommandsBuilder.DecrBy( +#pragma warning restore CS0612 + key, value, timestamp, retentionTime, + labels, uncompressed, chunkSizeBytes))).ToTimeStamp(); + } + + [Obsolete("Please use the other method with TsDecrByParams and check related builder TsDecryByParamsBuilder to build parameters.")] + public async Task DecrByAsync(string key, TsDecrByParams parameters) => (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.DecrBy(key, parameters))).ToTimeStamp(); + + /// + public async Task DelAsync(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp) + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Del(key, fromTimeStamp, toTimeStamp))).ToLong(); + } + + #endregion + + #region Aggregation, Compaction, Downsampling + + /// + public async Task CreateRuleAsync(string sourceKey, TimeSeriesRule rule, long alignTimestamp = 0) + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.CreateRule(sourceKey, rule, alignTimestamp))).OKtoBoolean(); + } + + /// + public async Task DeleteRuleAsync(string sourceKey, string destKey) + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.DeleteRule(sourceKey, destKey))).OKtoBoolean(); + } + + #endregion + + #region Query + + /// + public async Task GetAsync(string key, bool latest = false) + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Get(key, latest))).ToTimeSeriesTuple(); + } + + /// + public async Task labels, TimeSeriesTuple value)>> MGetAsync(IReadOnlyCollection filter, bool latest = false, + bool? withLabels = null, IReadOnlyCollection? selectedLabels = null) + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.MGet(filter, latest, withLabels, selectedLabels))).ParseMGetResponse(); + } + + /// + public async Task> RangeAsync(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, bool latest = false, @@ -132,15 +138,15 @@ public async Task> RangeAsync(string key, long? timeBucket = null, TsBucketTimestamps? bt = null, bool empty = false) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Range(key, fromTimeStamp, toTimeStamp, - latest, filterByTs, filterByValue, - count, align, aggregation, timeBucket, - bt, empty))).ToTimeSeriesTupleArray(); - } - - /// - public async Task> RevRangeAsync(string key, + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Range(key, fromTimeStamp, toTimeStamp, + latest, filterByTs, filterByValue, + count, align, aggregation, timeBucket, + bt, empty))).ToTimeSeriesTupleArray(); + } + + /// + public async Task> RevRangeAsync(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, bool latest = false, @@ -152,15 +158,15 @@ public async Task> RevRangeAsync(string key, long? timeBucket = null, TsBucketTimestamps? bt = null, bool empty = false) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.RevRange(key, fromTimeStamp, toTimeStamp, - latest, filterByTs, filterByValue, - count, align, aggregation, timeBucket, - bt, empty))).ToTimeSeriesTupleArray(); - } - - /// - public async Task labels, IReadOnlyList values)>> MRangeAsync( + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.RevRange(key, fromTimeStamp, toTimeStamp, + latest, filterByTs, filterByValue, + count, align, aggregation, timeBucket, + bt, empty))).ToTimeSeriesTupleArray(); + } + + /// + public async Task labels, IReadOnlyList values)>> MRangeAsync( TimeStamp fromTimeStamp, TimeStamp toTimeStamp, IReadOnlyCollection filter, @@ -176,16 +182,16 @@ public async Task> RevRangeAsync(string key, TsBucketTimestamps? bt = null, bool empty = false, (string, TsReduce)? groupbyTuple = null) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.MRange(fromTimeStamp, toTimeStamp, filter, - latest, filterByTs, filterByValue, - withLabels, selectLabels, count, align, - aggregation, timeBucket, bt, empty, - groupbyTuple))).ParseMRangeResponse(); - } - - /// - public async Task labels, IReadOnlyList values)>> MRevRangeAsync( + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.MRange(fromTimeStamp, toTimeStamp, filter, + latest, filterByTs, filterByValue, + withLabels, selectLabels, count, align, + aggregation, timeBucket, bt, empty, + groupbyTuple))).ParseMRangeResponse(); + } + + /// + public async Task labels, IReadOnlyList values)>> MRevRangeAsync( TimeStamp fromTimeStamp, TimeStamp toTimeStamp, IReadOnlyCollection filter, @@ -201,31 +207,30 @@ public async Task> RevRangeAsync(string key, TsBucketTimestamps? bt = null, bool empty = false, (string, TsReduce)? groupbyTuple = null) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.MRevRange(fromTimeStamp, toTimeStamp, filter, - latest, filterByTs, filterByValue, - withLabels, selectLabels, count, align, - aggregation, timeBucket, bt, empty, - groupbyTuple))).ParseMRangeResponse(); - } - - #endregion + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.MRevRange(fromTimeStamp, toTimeStamp, filter, + latest, filterByTs, filterByValue, + withLabels, selectLabels, count, align, + aggregation, timeBucket, bt, empty, + groupbyTuple))).ParseMRangeResponse(); + } - #region General + #endregion - /// - [Obsolete] - public async Task InfoAsync(string key, bool debug = false) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Info(key, debug))).ToTimeSeriesInfo(); - } + #region General - /// - public async Task> QueryIndexAsync(IReadOnlyCollection filter) - { - return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.QueryIndex(filter))).ToStringList(); - } + /// + [Obsolete] + public async Task InfoAsync(string key, bool debug = false) + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.Info(key, debug))).ToTimeSeriesInfo(); + } - #endregion + /// + public async Task> QueryIndexAsync(IReadOnlyCollection filter) + { + return (await _db.ExecuteAsync(TimeSeriesCommandsBuilder.QueryIndex(filter))).ToStringList(); } + + #endregion } \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/TimeSeriesCommandsBuilder.cs b/src/NRedisStack/TimeSeries/TimeSeriesCommandsBuilder.cs index b26d3a13..35d9de3b 100644 --- a/src/NRedisStack/TimeSeries/TimeSeriesCommandsBuilder.cs +++ b/src/NRedisStack/TimeSeries/TimeSeriesCommandsBuilder.cs @@ -3,125 +3,125 @@ using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; -namespace NRedisStack +namespace NRedisStack; + +public static class TimeSeriesCommandsBuilder { - public static class TimeSeriesCommandsBuilder - { - #region Create - - [Obsolete()] - public static SerializedCommand Create(string key, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) - { - var parameters = new TsCreateParams(retentionTime, labels, uncompressed, chunkSizeBytes, duplicatePolicy); - return new SerializedCommand(TS.CREATE, parameters.ToArray(key)); - } - - public static SerializedCommand Create(string key, TsCreateParams parameters) - { - return new SerializedCommand(TS.CREATE, parameters.ToArray(key)); - } - - #endregion - - #region Update - [Obsolete()] - public static SerializedCommand Alter(string key, long? retentionTime = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null, IReadOnlyCollection? labels = null) - { - var parameters = new TsAlterParams(retentionTime, chunkSizeBytes, duplicatePolicy, labels); - return new SerializedCommand(TS.ALTER, parameters.ToArray(key)); - } - - public static SerializedCommand Alter(string key, TsAlterParams parameters) - { - return new SerializedCommand(TS.ALTER, parameters.ToArray(key)); - } - - [Obsolete()] - public static SerializedCommand Add(string key, TimeStamp timestamp, double value, long? retentionTime = null, + #region Create + + [Obsolete()] + public static SerializedCommand Create(string key, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) + { + var parameters = new TsCreateParams(retentionTime, labels, uncompressed, chunkSizeBytes, duplicatePolicy); + return new(TS.CREATE, parameters.ToArray(key)); + } + + public static SerializedCommand Create(string key, TsCreateParams parameters) + { + return new(TS.CREATE, parameters.ToArray(key)); + } + + #endregion + + #region Update + [Obsolete()] + public static SerializedCommand Alter(string key, long? retentionTime = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null, IReadOnlyCollection? labels = null) + { + var parameters = new TsAlterParams(retentionTime, chunkSizeBytes, duplicatePolicy, labels); + return new(TS.ALTER, parameters.ToArray(key)); + } + + public static SerializedCommand Alter(string key, TsAlterParams parameters) + { + return new(TS.ALTER, parameters.ToArray(key)); + } + + [Obsolete()] + public static SerializedCommand Add(string key, TimeStamp timestamp, double value, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null, TsDuplicatePolicy? duplicatePolicy = null) - { - var parameters = new TsAddParams(timestamp, value, retentionTime, labels, uncompressed, chunkSizeBytes, duplicatePolicy); - return new SerializedCommand(TS.ADD, parameters.ToArray(key)); - } - - public static SerializedCommand Add(string key, TsAddParams parameters) - { - return new SerializedCommand(TS.ADD, parameters.ToArray(key)); - } - - public static SerializedCommand MAdd(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) - { - var args = TimeSeriesAux.BuildTsMaddArgs(sequence); - return new SerializedCommand(TS.MADD, args); - } - - [Obsolete()] - public static SerializedCommand IncrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) - { - var parameters = new TsIncrByParams(value, timestamp, retentionTime, labels, uncompressed, chunkSizeBytes); - return new SerializedCommand(TS.INCRBY, parameters.ToArray(key)); - } - - public static SerializedCommand IncrBy(string key, TsIncrByParams parameters) - { - return new SerializedCommand(TS.INCRBY, parameters.ToArray(key)); - } - - [Obsolete()] - public static SerializedCommand DecrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) - { - var parameters = new TsDecrByParams(value, timestamp, retentionTime, labels, uncompressed, chunkSizeBytes); - return new SerializedCommand(TS.DECRBY, parameters.ToArray(key)); - } - - public static SerializedCommand DecrBy(string key, TsDecrByParams parameters) - { - return new SerializedCommand(TS.DECRBY, parameters.ToArray(key)); - } - - public static SerializedCommand Del(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp) - { - var args = TimeSeriesAux.BuildTsDelArgs(key, fromTimeStamp, toTimeStamp); - return new SerializedCommand(TS.DEL, args); - } - - #endregion - - #region Aggregation, Compaction, Downsampling - - public static SerializedCommand CreateRule(string sourceKey, TimeSeriesRule rule, long alignTimestamp = 0) - { - var args = new List { sourceKey }; - args.AddRule(rule); - args.Add(alignTimestamp); - return new SerializedCommand(TS.CREATERULE, args); - } - - public static SerializedCommand DeleteRule(string sourceKey, string destKey) - { - var args = new List { sourceKey, destKey }; - return new SerializedCommand(TS.DELETERULE, args); - } - - #endregion - - #region Query - - public static SerializedCommand Get(string key, bool latest = false) - { - return (latest) ? new SerializedCommand(TS.GET, key, TimeSeriesArgs.LATEST) - : new SerializedCommand(TS.GET, key); - } - - public static SerializedCommand MGet(IReadOnlyCollection filter, bool latest = false, - bool? withLabels = null, IReadOnlyCollection? selectedLabels = null) - { - var args = TimeSeriesAux.BuildTsMgetArgs(latest, filter, withLabels, selectedLabels); - return new SerializedCommand(TS.MGET, args); - } - - public static SerializedCommand Range(string key, + { + var parameters = new TsAddParams(timestamp, value, retentionTime, labels, uncompressed, chunkSizeBytes, duplicatePolicy); + return new(TS.ADD, parameters.ToArray(key)); + } + + public static SerializedCommand Add(string key, TsAddParams parameters) + { + return new(TS.ADD, parameters.ToArray(key)); + } + + public static SerializedCommand MAdd(IReadOnlyCollection<(string key, TimeStamp timestamp, double value)> sequence) + { + var args = TimeSeriesAux.BuildTsMaddArgs(sequence); + return new(TS.MADD, args); + } + + [Obsolete()] + public static SerializedCommand IncrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + { + var parameters = new TsIncrByParams(value, timestamp, retentionTime, labels, uncompressed, chunkSizeBytes); + return new(TS.INCRBY, parameters.ToArray(key)); + } + + public static SerializedCommand IncrBy(string key, TsIncrByParams parameters) + { + return new(TS.INCRBY, parameters.ToArray(key)); + } + + [Obsolete()] + public static SerializedCommand DecrBy(string key, double value, TimeStamp? timestamp = null, long? retentionTime = null, IReadOnlyCollection? labels = null, bool? uncompressed = null, long? chunkSizeBytes = null) + { + var parameters = new TsDecrByParams(value, timestamp, retentionTime, labels, uncompressed, chunkSizeBytes); + return new(TS.DECRBY, parameters.ToArray(key)); + } + + public static SerializedCommand DecrBy(string key, TsDecrByParams parameters) + { + return new(TS.DECRBY, parameters.ToArray(key)); + } + + public static SerializedCommand Del(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp) + { + var args = TimeSeriesAux.BuildTsDelArgs(key, fromTimeStamp, toTimeStamp); + return new(TS.DEL, args); + } + + #endregion + + #region Aggregation, Compaction, Downsampling + + public static SerializedCommand CreateRule(string sourceKey, TimeSeriesRule rule, long alignTimestamp = 0) + { + var args = new List { sourceKey }; + args.AddRule(rule); + args.Add(alignTimestamp); + return new(TS.CREATERULE, args); + } + + public static SerializedCommand DeleteRule(string sourceKey, string destKey) + { + var args = new List { sourceKey, destKey }; + return new(TS.DELETERULE, args); + } + + #endregion + + #region Query + + public static SerializedCommand Get(string key, bool latest = false) + { + return (latest) ? new(TS.GET, key, TimeSeriesArgs.LATEST) + : new SerializedCommand(TS.GET, key); + } + + public static SerializedCommand MGet(IReadOnlyCollection filter, bool latest = false, + bool? withLabels = null, IReadOnlyCollection? selectedLabels = null) + { + var args = TimeSeriesAux.BuildTsMgetArgs(latest, filter, withLabels, selectedLabels); + return new(TS.MGET, args); + } + + public static SerializedCommand Range(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, bool latest = false, @@ -133,15 +133,15 @@ public static SerializedCommand Range(string key, long? timeBucket = null, TsBucketTimestamps? bt = null, bool empty = false) - { - var args = TimeSeriesAux.BuildRangeArgs(key, fromTimeStamp, toTimeStamp, - latest, filterByTs, filterByValue, count, align, - aggregation, timeBucket, bt, empty); + { + var args = TimeSeriesAux.BuildRangeArgs(key, fromTimeStamp, toTimeStamp, + latest, filterByTs, filterByValue, count, align, + aggregation, timeBucket, bt, empty); - return new SerializedCommand(TS.RANGE, args); - } + return new(TS.RANGE, args); + } - public static SerializedCommand RevRange(string key, + public static SerializedCommand RevRange(string key, TimeStamp fromTimeStamp, TimeStamp toTimeStamp, bool latest = false, @@ -153,15 +153,15 @@ public static SerializedCommand RevRange(string key, long? timeBucket = null, TsBucketTimestamps? bt = null, bool empty = false) - { - var args = TimeSeriesAux.BuildRangeArgs(key, fromTimeStamp, toTimeStamp, - latest, filterByTs, filterByValue, count, align, - aggregation, timeBucket, bt, empty); + { + var args = TimeSeriesAux.BuildRangeArgs(key, fromTimeStamp, toTimeStamp, + latest, filterByTs, filterByValue, count, align, + aggregation, timeBucket, bt, empty); - return new SerializedCommand(TS.REVRANGE, args); - } + return new(TS.REVRANGE, args); + } - public static SerializedCommand MRange( + public static SerializedCommand MRange( TimeStamp fromTimeStamp, TimeStamp toTimeStamp, IReadOnlyCollection filter, @@ -177,14 +177,14 @@ public static SerializedCommand MRange( TsBucketTimestamps? bt = null, bool empty = false, (string, TsReduce)? groupbyTuple = null) - { - var args = TimeSeriesAux.BuildMultiRangeArgs(fromTimeStamp, toTimeStamp, filter, latest, filterByTs, - filterByValue, withLabels, selectLabels, count, - align, aggregation, timeBucket, bt, empty, groupbyTuple); - return new SerializedCommand(TS.MRANGE, args); - } - - public static SerializedCommand MRevRange( + { + var args = TimeSeriesAux.BuildMultiRangeArgs(fromTimeStamp, toTimeStamp, filter, latest, filterByTs, + filterByValue, withLabels, selectLabels, count, + align, aggregation, timeBucket, bt, empty, groupbyTuple); + return new(TS.MRANGE, args); + } + + public static SerializedCommand MRevRange( TimeStamp fromTimeStamp, TimeStamp toTimeStamp, IReadOnlyCollection filter, @@ -200,29 +200,28 @@ public static SerializedCommand MRevRange( TsBucketTimestamps? bt = null, bool empty = false, (string, TsReduce)? groupbyTuple = null) - { - var args = TimeSeriesAux.BuildMultiRangeArgs(fromTimeStamp, toTimeStamp, filter, latest, filterByTs, - filterByValue, withLabels, selectLabels, count, - align, aggregation, timeBucket, bt, empty, groupbyTuple); - return new SerializedCommand(TS.MREVRANGE, args); - } - - #endregion + { + var args = TimeSeriesAux.BuildMultiRangeArgs(fromTimeStamp, toTimeStamp, filter, latest, filterByTs, + filterByValue, withLabels, selectLabels, count, + align, aggregation, timeBucket, bt, empty, groupbyTuple); + return new(TS.MREVRANGE, args); + } - #region General + #endregion - public static SerializedCommand Info(string key, bool debug = false) - { - return (debug) ? new SerializedCommand(TS.INFO, key, TimeSeriesArgs.DEBUG) - : new SerializedCommand(TS.INFO, key); - } + #region General - public static SerializedCommand QueryIndex(IReadOnlyCollection filter) - { - var args = new List(filter); - return new SerializedCommand(TS.QUERYINDEX, args); - } + public static SerializedCommand Info(string key, bool debug = false) + { + return (debug) ? new(TS.INFO, key, TimeSeriesArgs.DEBUG) + : new SerializedCommand(TS.INFO, key); + } - #endregion + public static SerializedCommand QueryIndex(IReadOnlyCollection filter) + { + var args = new List(filter); + return new(TS.QUERYINDEX, args); } + + #endregion } \ No newline at end of file diff --git a/src/NRedisStack/TimeSeries/TimeSeriesParamsBuilder.cs b/src/NRedisStack/TimeSeries/TimeSeriesParamsBuilder.cs index 0adf08d6..0b732eee 100644 --- a/src/NRedisStack/TimeSeries/TimeSeriesParamsBuilder.cs +++ b/src/NRedisStack/TimeSeries/TimeSeriesParamsBuilder.cs @@ -3,243 +3,242 @@ using NRedisStack.DataTypes; using NRedisStack.Extensions; -namespace NRedisStack -{ - - public abstract class TsBaseParamsBuilder where T : TsBaseParamsBuilder - { - internal protected long? retentionTime; - internal protected IReadOnlyCollection? labels; - internal protected long? chunkSizeBytes; - internal protected long? ignoreMaxTimeDiff; - internal protected long? ignoreMaxValDiff; +namespace NRedisStack; +public abstract class TsBaseParamsBuilder where T : TsBaseParamsBuilder +{ + internal protected long? retentionTime; + internal protected IReadOnlyCollection? labels; + internal protected long? chunkSizeBytes; + internal protected long? ignoreMaxTimeDiff; + internal protected long? ignoreMaxValDiff; - internal protected double? value; - internal protected TimeStamp? timestamp; - internal protected bool? uncompressed; - internal protected TsDuplicatePolicy? duplicatePolicy; - - internal TsBaseParamsBuilder() - { } - public T AddRetentionTime(long retentionTime) - { - this.retentionTime = retentionTime; - return (T)this; - } - public T AddLabels(IReadOnlyCollection labels) - { - this.labels = labels; - return (T)this; - } - public T AddChunkSizeBytes(long chunkSizeBytes) - { - this.chunkSizeBytes = chunkSizeBytes; - return (T)this; - } + internal protected double? value; + internal protected TimeStamp? timestamp; + internal protected bool? uncompressed; + internal protected TsDuplicatePolicy? duplicatePolicy; - public T AddIgnoreValues(long ignoreMaxTimeDiff, long ignoreMaxValDiff) - { - this.ignoreMaxTimeDiff = ignoreMaxTimeDiff; - this.ignoreMaxValDiff = ignoreMaxValDiff; - return (T)this; - } + internal TsBaseParamsBuilder() + { } - protected T AddValue(double value) - { - this.value = value; - return (T)this; - } + public T AddRetentionTime(long retentionTime) + { + this.retentionTime = retentionTime; + return (T)this; + } + public T AddLabels(IReadOnlyCollection labels) + { + this.labels = labels; + return (T)this; + } + public T AddChunkSizeBytes(long chunkSizeBytes) + { + this.chunkSizeBytes = chunkSizeBytes; + return (T)this; + } - protected T AddTimestamp(TimeStamp timestamp) - { - this.timestamp = timestamp; - return (T)this; - } + public T AddIgnoreValues(long ignoreMaxTimeDiff, long ignoreMaxValDiff) + { + this.ignoreMaxTimeDiff = ignoreMaxTimeDiff; + this.ignoreMaxValDiff = ignoreMaxValDiff; + return (T)this; + } - protected T AddUncompressed(bool uncompressed) - { - this.uncompressed = uncompressed; - return (T)this; - } + protected T AddValue(double value) + { + this.value = value; + return (T)this; + } - protected T AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) - { - this.duplicatePolicy = duplicatePolicy; - return (T)this; - } + protected T AddTimestamp(TimeStamp timestamp) + { + this.timestamp = timestamp; + return (T)this; + } + protected T AddUncompressed(bool uncompressed) + { + this.uncompressed = uncompressed; + return (T)this; } - public static class TsParamsHelper + protected T AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) { - public static void AddRetentionTime(this IList args, long? retentionTime) - { - if (retentionTime.HasValue) - { - args.Add(TimeSeriesArgs.RETENTION); - args.Add(retentionTime); - } - } + this.duplicatePolicy = duplicatePolicy; + return (T)this; + } - public static void AddChunkSize(this IList args, long? chunkSize) - { - if (chunkSize.HasValue) - { - args.Add(TimeSeriesArgs.CHUNK_SIZE); - args.Add(chunkSize); - } - } +} - public static void AddLabels(this IList args, IReadOnlyCollection? labels) +public static class TsParamsHelper +{ + public static void AddRetentionTime(this IList args, long? retentionTime) + { + if (retentionTime.HasValue) { - if (labels != null) - { - args.Add(TimeSeriesArgs.LABELS); - foreach (var label in labels) - { - args.Add(label.Key); - args.Add(label.Value); - } - } + args.Add(TimeSeriesArgs.RETENTION); + args.Add(retentionTime); } + } - public static void AddUncompressed(this IList args, bool? uncompressed) + public static void AddChunkSize(this IList args, long? chunkSize) + { + if (chunkSize.HasValue) { - if (uncompressed.HasValue) - { - args.Add(uncompressed.Value ? TimeSeriesArgs.UNCOMPRESSED : TimeSeriesArgs.COMPRESSED); - } + args.Add(TimeSeriesArgs.CHUNK_SIZE); + args.Add(chunkSize); } + } - public static void AddIgnoreValues(this IList args, long? ignoreMaxTimeDiff, long? ignoreMaxValDiff) + public static void AddLabels(this IList args, IReadOnlyCollection? labels) + { + if (labels != null) { - if (ignoreMaxTimeDiff != null || ignoreMaxValDiff != null) + args.Add(TimeSeriesArgs.LABELS); + foreach (var label in labels) { - args.Add(TimeSeriesArgs.IGNORE); - args.Add(ignoreMaxTimeDiff ?? 0); - args.Add(ignoreMaxValDiff ?? 0); + args.Add(label.Key); + args.Add(label.Value); } } + } - public static void AddDuplicatePolicy(this IList args, TsDuplicatePolicy? policy) + public static void AddUncompressed(this IList args, bool? uncompressed) + { + if (uncompressed.HasValue) { - if (policy.HasValue) - { - args.Add(TimeSeriesArgs.DUPLICATE_POLICY); - args.Add(policy.Value.AsArg()); - } + args.Add(uncompressed.Value ? TimeSeriesArgs.UNCOMPRESSED : TimeSeriesArgs.COMPRESSED); } + } - public static void AddOnDuplicate(this IList args, TsDuplicatePolicy? policy) + public static void AddIgnoreValues(this IList args, long? ignoreMaxTimeDiff, long? ignoreMaxValDiff) + { + if (ignoreMaxTimeDiff != null || ignoreMaxValDiff != null) { - if (policy.HasValue) - { - args.Add(TimeSeriesArgs.ON_DUPLICATE); - args.Add(policy.Value.AsArg()); - } + args.Add(TimeSeriesArgs.IGNORE); + args.Add(ignoreMaxTimeDiff ?? 0); + args.Add(ignoreMaxValDiff ?? 0); } } - public class TsCreateParamsBuilder : TsBaseParamsBuilder + public static void AddDuplicatePolicy(this IList args, TsDuplicatePolicy? policy) { - public TsCreateParams build() + if (policy.HasValue) { - var args = new List(); - args.AddRetentionTime(retentionTime); - args.AddChunkSize(chunkSizeBytes); - args.AddLabels(labels); - args.AddUncompressed(uncompressed); - args.AddDuplicatePolicy(duplicatePolicy); - args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); - return new TsCreateParams(args); + args.Add(TimeSeriesArgs.DUPLICATE_POLICY); + args.Add(policy.Value.AsArg()); } - - public TsCreateParamsBuilder AddUncompressed(bool uncompressed) => base.AddUncompressed(uncompressed); - public TsCreateParamsBuilder AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); - } - public class TsAlterParamsBuilder : TsBaseParamsBuilder + public static void AddOnDuplicate(this IList args, TsDuplicatePolicy? policy) { - public TsAlterParams build() + if (policy.HasValue) { - var args = new List(); - args.AddRetentionTime(retentionTime); - args.AddChunkSize(chunkSizeBytes); - args.AddDuplicatePolicy(duplicatePolicy); - args.AddLabels(labels); - args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); - return new TsAlterParams(args); + args.Add(TimeSeriesArgs.ON_DUPLICATE); + args.Add(policy.Value.AsArg()); } - - public TsAlterParamsBuilder AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); } +} - public class TsAddParamsBuilder : TsBaseParamsBuilder +public class TsCreateParamsBuilder : TsBaseParamsBuilder +{ + public TsCreateParams build() { - public TsAddParams build() - { - if (timestamp == null) throw new NotSupportedException("Operation without 'timestamp' is not supported!"); - if (value == null) throw new NotSupportedException("Operation without 'value' is not supported!"); - - var args = new List { timestamp.Value.Value, value }; - args.AddRetentionTime(retentionTime); - args.AddChunkSize(chunkSizeBytes); - args.AddLabels(labels); - args.AddUncompressed(uncompressed); - args.AddOnDuplicate(duplicatePolicy); - args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); - return new TsAddParams(args); - } + var args = new List(); + args.AddRetentionTime(retentionTime); + args.AddChunkSize(chunkSizeBytes); + args.AddLabels(labels); + args.AddUncompressed(uncompressed); + args.AddDuplicatePolicy(duplicatePolicy); + args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); + return new(args); + } + + public new TsCreateParamsBuilder AddUncompressed(bool uncompressed) => base.AddUncompressed(uncompressed); + public new TsCreateParamsBuilder AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); + +} - public TsAddParamsBuilder AddValue(double value) => base.AddValue(value); - public TsAddParamsBuilder AddTimestamp(TimeStamp timestamp) => base.AddTimestamp(timestamp); - public TsAddParamsBuilder AddUncompressed(bool uncompressed) => base.AddUncompressed(uncompressed); - public TsAddParamsBuilder AddOnDuplicate(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); +public class TsAlterParamsBuilder : TsBaseParamsBuilder +{ + public TsAlterParams build() + { + var args = new List(); + args.AddRetentionTime(retentionTime); + args.AddChunkSize(chunkSizeBytes); + args.AddDuplicatePolicy(duplicatePolicy); + args.AddLabels(labels); + args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); + return new(args); } - public class TsIncrByParamsBuilder : TsBaseParamsBuilder + public new TsAlterParamsBuilder AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); +} + +public class TsAddParamsBuilder : TsBaseParamsBuilder +{ + public TsAddParams build() { - public TsIncrByParams build() - { - if (value == null) throw new NotSupportedException("Operation without 'value' is not supported!"); - - var args = new List { value }; - if (timestamp != null) args.AddTimeStamp(timestamp.Value); - args.AddRetentionTime(retentionTime); - args.AddChunkSize(chunkSizeBytes); - if (labels != null) args.AddLabels(labels); - args.AddUncompressed(uncompressed); - args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); - return new TsIncrByParams(args); - } + if (timestamp == null) throw new NotSupportedException("Operation without 'timestamp' is not supported!"); + if (value == null) throw new NotSupportedException("Operation without 'value' is not supported!"); + + var args = new List { timestamp.Value.Value, value }; + args.AddRetentionTime(retentionTime); + args.AddChunkSize(chunkSizeBytes); + args.AddLabels(labels); + args.AddUncompressed(uncompressed); + args.AddOnDuplicate(duplicatePolicy); + args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); + return new(args); + } + + public new TsAddParamsBuilder AddValue(double value) => base.AddValue(value); + public new TsAddParamsBuilder AddTimestamp(TimeStamp timestamp) => base.AddTimestamp(timestamp); + public new TsAddParamsBuilder AddUncompressed(bool uncompressed) => base.AddUncompressed(uncompressed); + public TsAddParamsBuilder AddOnDuplicate(TsDuplicatePolicy duplicatePolicy) => AddDuplicatePolicy(duplicatePolicy); +} - public TsIncrByParamsBuilder AddValue(double value) => base.AddValue(value); - public TsIncrByParamsBuilder AddTimestamp(TimeStamp timestamp) => base.AddTimestamp(timestamp); - public TsIncrByParamsBuilder AddUncompressed(bool uncompressed) => base.AddUncompressed(uncompressed); - public TsIncrByParamsBuilder AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); +public class TsIncrByParamsBuilder : TsBaseParamsBuilder +{ + public TsIncrByParams build() + { + if (value == null) throw new NotSupportedException("Operation without 'value' is not supported!"); + + var args = new List { value }; + if (timestamp != null) args.AddTimeStamp(timestamp.Value); + args.AddRetentionTime(retentionTime); + args.AddChunkSize(chunkSizeBytes); + if (labels != null) args.AddLabels(labels); + args.AddUncompressed(uncompressed); + args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); + return new(args); } - public class TsDecrByParamsBuilder : TsBaseParamsBuilder + public new TsIncrByParamsBuilder AddValue(double value) => base.AddValue(value); + public new TsIncrByParamsBuilder AddTimestamp(TimeStamp timestamp) => base.AddTimestamp(timestamp); + public new TsIncrByParamsBuilder AddUncompressed(bool uncompressed) => base.AddUncompressed(uncompressed); + public new TsIncrByParamsBuilder AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); +} + +public class TsDecrByParamsBuilder : TsBaseParamsBuilder +{ + public TsDecrByParams build() { - public TsDecrByParams build() - { - if (value == null) throw new NotSupportedException("Operation without 'value' is not supported!"); - - var args = new List { value }; - if (timestamp != null) args.AddTimeStamp(timestamp.Value); - args.AddRetentionTime(retentionTime); - args.AddChunkSize(chunkSizeBytes); - if (labels != null) args.AddLabels(labels); - args.AddUncompressed(uncompressed); - args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); - return new TsDecrByParams(args); - } - public TsDecrByParamsBuilder AddValue(double value) => base.AddValue(value); - public TsDecrByParamsBuilder AddTimestamp(TimeStamp timestamp) => base.AddTimestamp(timestamp); - public TsDecrByParamsBuilder AddUncompressed(bool uncompressed) => base.AddUncompressed(uncompressed); - public TsDecrByParamsBuilder AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); + if (value == null) throw new NotSupportedException("Operation without 'value' is not supported!"); + + var args = new List { value }; + if (timestamp != null) args.AddTimeStamp(timestamp.Value); + args.AddRetentionTime(retentionTime); + args.AddChunkSize(chunkSizeBytes); + if (labels != null) args.AddLabels(labels); + args.AddUncompressed(uncompressed); + args.AddIgnoreValues(ignoreMaxTimeDiff, ignoreMaxValDiff); + return new(args); } + + public new TsDecrByParamsBuilder AddValue(double value) => base.AddValue(value); + public new TsDecrByParamsBuilder AddTimestamp(TimeStamp timestamp) => base.AddTimestamp(timestamp); + public new TsDecrByParamsBuilder AddUncompressed(bool uncompressed) => base.AddUncompressed(uncompressed); + public new TsDecrByParamsBuilder AddDuplicatePolicy(TsDuplicatePolicy duplicatePolicy) => base.AddDuplicatePolicy(duplicatePolicy); } \ No newline at end of file diff --git a/src/NRedisStack/TopK/DataTypes/TopKInformation.cs b/src/NRedisStack/TopK/DataTypes/TopKInformation.cs index 03aae74d..158e0520 100644 --- a/src/NRedisStack/TopK/DataTypes/TopKInformation.cs +++ b/src/NRedisStack/TopK/DataTypes/TopKInformation.cs @@ -1,23 +1,22 @@ -namespace NRedisStack.TopK.DataTypes +namespace NRedisStack.TopK.DataTypes; + +/// +/// This class represents the response for TOPK.INFO command. +/// This object has Read-only properties and cannot be generated outside a TOPK.INFO response. +/// +public class TopKInformation { - /// - /// This class represents the response for TOPK.INFO command. - /// This object has Read-only properties and cannot be generated outside a TOPK.INFO response. - /// - public class TopKInformation - { - public long K { get; private set; } - public long Width { get; private set; } - public long Depth { get; private set; } - public double Decay { get; private set; } + public long K { get; private set; } + public long Width { get; private set; } + public long Depth { get; private set; } + public double Decay { get; private set; } - internal TopKInformation(long k, long width, long depth, double decay) - { - K = k; - Width = width; - Depth = depth; - Decay = decay; - } + internal TopKInformation(long k, long width, long depth, double decay) + { + K = k; + Width = width; + Depth = depth; + Decay = decay; } } \ No newline at end of file diff --git a/src/NRedisStack/TopK/ITopKCommands.cs b/src/NRedisStack/TopK/ITopKCommands.cs index 93913e62..1212f94f 100644 --- a/src/NRedisStack/TopK/ITopKCommands.cs +++ b/src/NRedisStack/TopK/ITopKCommands.cs @@ -1,84 +1,83 @@ using NRedisStack.TopK.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public interface ITopKCommands { - public interface ITopKCommands - { - /// - /// Increases the count of item by increment. - /// - /// The name of the sketch. - /// Items to be added - /// Array of simple-string-reply - if an element was dropped from the TopK list, null otherwise - /// - RedisResult[]? Add(RedisKey key, params RedisValue[] items); + /// + /// Increases the count of item by increment. + /// + /// The name of the sketch. + /// Items to be added + /// Array of simple-string-reply - if an element was dropped from the TopK list, null otherwise + /// + RedisResult[]? Add(RedisKey key, params RedisValue[] items); - /// - /// Returns count for an items. - /// - /// Name of sketch where item is counted - /// Items to be counted. - /// count for responding item. - /// - [Obsolete("TOPK.COUNT is deprecated as of Bloom 2.4.0")] - long[] Count(RedisKey key, params RedisValue[] items); + /// + /// Returns count for an items. + /// + /// Name of sketch where item is counted + /// Items to be counted. + /// count for responding item. + /// + [Obsolete("TOPK.COUNT is deprecated as of Bloom 2.4.0")] + long[] Count(RedisKey key, params RedisValue[] items); - /// - /// Increase the score of an item in the data structure by increment. - /// - /// Name of sketch where item is added. - /// Tuple of The items which counter is to be increased - /// and the Amount by which the item score is to be increased. - /// Score of each item after increment. - /// - RedisResult[] IncrBy(RedisKey key, params Tuple[] itemIncrements); + /// + /// Increase the score of an item in the data structure by increment. + /// + /// Name of sketch where item is added. + /// Tuple of The items which counter is to be increased + /// and the Amount by which the item score is to be increased. + /// Score of each item after increment. + /// + RedisResult[] IncrBy(RedisKey key, params Tuple[] itemIncrements); - /// - /// Return TopK information. - /// - /// Name of the key to return information about. - /// TopK Information. - /// - TopKInformation Info(RedisKey key); + /// + /// Return TopK information. + /// + /// Name of the key to return information about. + /// TopK Information. + /// + TopKInformation Info(RedisKey key); - /// - /// Return full list of items in Top K list. - /// - /// The name of the sketch. - /// return Count of each element is returned. - /// Full list of items in Top K list - /// - RedisResult[] List(RedisKey key, bool withcount = false); + /// + /// Return full list of items in Top K list. + /// + /// The name of the sketch. + /// return Count of each element is returned. + /// Full list of items in Top K list + /// + RedisResult[] List(RedisKey key, bool withcount = false); - /// - /// Returns the count for one or more items in a sketch. - /// - /// The name of the sketch - /// Item to be queried. - /// if item is in Top-K, otherwise/> - /// - bool Query(RedisKey key, RedisValue item); + /// + /// Returns the count for one or more items in a sketch. + /// + /// The name of the sketch + /// Item to be queried. + /// if item is in Top-K, otherwise/> + /// + bool Query(RedisKey key, RedisValue item); - /// - /// Returns the count for one or more items in a sketch. - /// - /// The name of the sketch - /// Items to be queried. - /// Bolean Array where if item is in Top-K, otherwise/> - /// - bool[] Query(RedisKey key, params RedisValue[] items); + /// + /// Returns the count for one or more items in a sketch. + /// + /// The name of the sketch + /// Items to be queried. + /// Bolean Array where if item is in Top-K, otherwise/> + /// + bool[] Query(RedisKey key, params RedisValue[] items); - /// - /// Initializes a TopK with specified parameters. - /// - /// Key under which the sketch is to be found. - /// Number of top occurring items to keep. - /// Number of counters kept in each array. (Default 8) - /// Number of arrays. (Default 7) - /// The probability of reducing a counter in an occupied bucket. (Default 0.9) - /// if executed correctly, error otherwise/> - /// - bool Reserve(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9); - } + /// + /// Initializes a TopK with specified parameters. + /// + /// Key under which the sketch is to be found. + /// Number of top occurring items to keep. + /// Number of counters kept in each array. (Default 8) + /// Number of arrays. (Default 7) + /// The probability of reducing a counter in an occupied bucket. (Default 0.9) + /// if executed correctly, error otherwise/> + /// + bool Reserve(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9); } \ No newline at end of file diff --git a/src/NRedisStack/TopK/ITopKCommandsAsync.cs b/src/NRedisStack/TopK/ITopKCommandsAsync.cs index b23251a4..9bd3bded 100644 --- a/src/NRedisStack/TopK/ITopKCommandsAsync.cs +++ b/src/NRedisStack/TopK/ITopKCommandsAsync.cs @@ -1,83 +1,82 @@ using NRedisStack.TopK.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public interface ITopKCommandsAsync { - public interface ITopKCommandsAsync - { - /// - /// Increases the count of item by increment. - /// - /// The name of the sketch. - /// Items to be added - /// Array of simple-string-reply - if an element was dropped from the TopK list, null otherwise - /// - Task AddAsync(RedisKey key, params RedisValue[] items); + /// + /// Increases the count of item by increment. + /// + /// The name of the sketch. + /// Items to be added + /// Array of simple-string-reply - if an element was dropped from the TopK list, null otherwise + /// + Task AddAsync(RedisKey key, params RedisValue[] items); - /// - /// Returns count for an items. - /// - /// Name of sketch where item is counted - /// Items to be counted. - /// count for responding item. - /// - [Obsolete("TOPK.COUNT is deprecated as of Bloom 2.4.0")] - Task CountAsync(RedisKey key, params RedisValue[] items); + /// + /// Returns count for an items. + /// + /// Name of sketch where item is counted + /// Items to be counted. + /// count for responding item. + /// + [Obsolete("TOPK.COUNT is deprecated as of Bloom 2.4.0")] + Task CountAsync(RedisKey key, params RedisValue[] items); - /// - /// Increase the score of an item in the data structure by increment. - /// - /// Name of sketch where item is added. - /// Tuple of The items which counter is to be increased - /// and the Amount by which the item score is to be increased. - /// Score of each item after increment. - /// - Task IncrByAsync(RedisKey key, params Tuple[] itemIncrements); - /// - /// Return TopK information. - /// - /// Name of the key to return information about. - /// TopK Information. - /// - Task InfoAsync(RedisKey key); + /// + /// Increase the score of an item in the data structure by increment. + /// + /// Name of sketch where item is added. + /// Tuple of The items which counter is to be increased + /// and the Amount by which the item score is to be increased. + /// Score of each item after increment. + /// + Task IncrByAsync(RedisKey key, params Tuple[] itemIncrements); + /// + /// Return TopK information. + /// + /// Name of the key to return information about. + /// TopK Information. + /// + Task InfoAsync(RedisKey key); - /// - /// Return full list of items in Top K list. - /// - /// The name of the sketch. - /// return Count of each element is returned. - /// Full list of items in Top K list - /// - Task ListAsync(RedisKey key, bool withcount = false); + /// + /// Return full list of items in Top K list. + /// + /// The name of the sketch. + /// return Count of each element is returned. + /// Full list of items in Top K list + /// + Task ListAsync(RedisKey key, bool withcount = false); - /// - /// Returns the count for one or more items in a sketch. - /// - /// The name of the sketch - /// Item to be queried. - /// if item is in Top-K, otherwise/> - /// - Task QueryAsync(RedisKey key, RedisValue item); + /// + /// Returns the count for one or more items in a sketch. + /// + /// The name of the sketch + /// Item to be queried. + /// if item is in Top-K, otherwise/> + /// + Task QueryAsync(RedisKey key, RedisValue item); - /// - /// Returns the count for one or more items in a sketch. - /// - /// The name of the sketch - /// Items to be queried. - /// Bolean Array where if item is in Top-K, otherwise/> - /// - Task QueryAsync(RedisKey key, params RedisValue[] items); + /// + /// Returns the count for one or more items in a sketch. + /// + /// The name of the sketch + /// Items to be queried. + /// Bolean Array where if item is in Top-K, otherwise/> + /// + Task QueryAsync(RedisKey key, params RedisValue[] items); - /// - /// Initializes a TopK with specified parameters. - /// - /// Key under which the sketch is to be found. - /// Number of top occurring items to keep. - /// Number of counters kept in each array. (Default 8) - /// Number of arrays. (Default 7) - /// The probability of reducing a counter in an occupied bucket. (Default 0.9) - /// if executed correctly, error otherwise/> - /// - Task ReserveAsync(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9); - } + /// + /// Initializes a TopK with specified parameters. + /// + /// Key under which the sketch is to be found. + /// Number of top occurring items to keep. + /// Number of counters kept in each array. (Default 8) + /// Number of arrays. (Default 7) + /// The probability of reducing a counter in an occupied bucket. (Default 0.9) + /// if executed correctly, error otherwise/> + /// + Task ReserveAsync(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9); } \ No newline at end of file diff --git a/src/NRedisStack/TopK/Literals/CommandArgs.cs b/src/NRedisStack/TopK/Literals/CommandArgs.cs index f70a92f6..7ac84443 100644 --- a/src/NRedisStack/TopK/Literals/CommandArgs.cs +++ b/src/NRedisStack/TopK/Literals/CommandArgs.cs @@ -1,7 +1,6 @@ -namespace NRedisStack.TopK.Literals +namespace NRedisStack.TopK.Literals; + +internal class TopKArgs { - internal class TopKArgs - { - // TOPK doesn't have literals to save, it's here in case they need it in the future - } + // TOPK doesn't have literals to save, it's here in case they need it in the future } \ No newline at end of file diff --git a/src/NRedisStack/TopK/Literals/Commands.cs b/src/NRedisStack/TopK/Literals/Commands.cs index db3dfbad..efaa57a2 100644 --- a/src/NRedisStack/TopK/Literals/Commands.cs +++ b/src/NRedisStack/TopK/Literals/Commands.cs @@ -1,13 +1,12 @@ -namespace NRedisStack.TopK.Literals +namespace NRedisStack.TopK.Literals; + +internal class TOPK { - internal class TOPK - { - public const string RESERVE = "TOPK.RESERVE"; - public const string ADD = "TOPK.ADD"; - public const string INCRBY = "TOPK.INCRBY"; - public const string QUERY = "TOPK.QUERY"; - public const string COUNT = "TOPK.COUNT"; - public const string LIST = "TOPK.LIST"; - public const string INFO = "TOPK.INFO"; - } + public const string RESERVE = "TOPK.RESERVE"; + public const string ADD = "TOPK.ADD"; + public const string INCRBY = "TOPK.INCRBY"; + public const string QUERY = "TOPK.QUERY"; + public const string COUNT = "TOPK.COUNT"; + public const string LIST = "TOPK.LIST"; + public const string INFO = "TOPK.INFO"; } \ No newline at end of file diff --git a/src/NRedisStack/TopK/TopKCommandBuilder.cs b/src/NRedisStack/TopK/TopKCommandBuilder.cs index fd697a1d..2707950c 100644 --- a/src/NRedisStack/TopK/TopKCommandBuilder.cs +++ b/src/NRedisStack/TopK/TopKCommandBuilder.cs @@ -2,66 +2,65 @@ using StackExchange.Redis; using NRedisStack.RedisStackCommands; -namespace NRedisStack +namespace NRedisStack; + +public static class TopKCommandBuilder { - public static class TopKCommandBuilder + public static SerializedCommand Add(RedisKey key, params RedisValue[] items) { - public static SerializedCommand Add(RedisKey key, params RedisValue[] items) - { - if (items.Length < 1) - throw new ArgumentOutOfRangeException(nameof(items)); - - var args = Auxiliary.MergeArgs(key, items); - return new SerializedCommand(TOPK.ADD, args); - } + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); - public static SerializedCommand Count(RedisKey key, params RedisValue[] items) - { - if (items.Length < 1) - throw new ArgumentOutOfRangeException(nameof(items)); + var args = Auxiliary.MergeArgs(key, items); + return new(TOPK.ADD, args); + } - var args = Auxiliary.MergeArgs(key, items); - return new SerializedCommand(TOPK.COUNT, args); - } + public static SerializedCommand Count(RedisKey key, params RedisValue[] items) + { + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); - public static SerializedCommand IncrBy(RedisKey key, params Tuple[] itemIncrements) - { - if (itemIncrements.Length < 1) - throw new ArgumentOutOfRangeException(nameof(itemIncrements)); + var args = Auxiliary.MergeArgs(key, items); + return new(TOPK.COUNT, args); + } - List args = new List { key }; - foreach (var pair in itemIncrements) - { - args.Add(pair.Item1); - args.Add(pair.Item2); - } - return new SerializedCommand(TOPK.INCRBY, args); - } + public static SerializedCommand IncrBy(RedisKey key, params Tuple[] itemIncrements) + { + if (itemIncrements.Length < 1) + throw new ArgumentOutOfRangeException(nameof(itemIncrements)); - public static SerializedCommand Info(RedisKey key) + List args = [key]; + foreach (var pair in itemIncrements) { - return new SerializedCommand(TOPK.INFO, key); + args.Add(pair.Item1); + args.Add(pair.Item2); } + return new(TOPK.INCRBY, args); + } - public static SerializedCommand List(RedisKey key, bool withcount = false) - { - return (withcount) ? new SerializedCommand(TOPK.LIST, key, "WITHCOUNT") - : new SerializedCommand(TOPK.LIST, key); - } + public static SerializedCommand Info(RedisKey key) + { + return new(TOPK.INFO, key); + } - public static SerializedCommand Query(RedisKey key, params RedisValue[] items) - { - if (items.Length < 1) - throw new ArgumentOutOfRangeException(nameof(items)); + public static SerializedCommand List(RedisKey key, bool withcount = false) + { + return (withcount) ? new(TOPK.LIST, key, "WITHCOUNT") + : new SerializedCommand(TOPK.LIST, key); + } - var args = Auxiliary.MergeArgs(key, items); + public static SerializedCommand Query(RedisKey key, params RedisValue[] items) + { + if (items.Length < 1) + throw new ArgumentOutOfRangeException(nameof(items)); - return new SerializedCommand(TOPK.QUERY, args); - } + var args = Auxiliary.MergeArgs(key, items); - public static SerializedCommand Reserve(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) - { - return new SerializedCommand(TOPK.RESERVE, key, topk, width, depth, decay); - } + return new(TOPK.QUERY, args); + } + + public static SerializedCommand Reserve(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) + { + return new(TOPK.RESERVE, key, topk, width, depth, decay); } -} +} \ No newline at end of file diff --git a/src/NRedisStack/TopK/TopKCommands.cs b/src/NRedisStack/TopK/TopKCommands.cs index 4d9bb1a0..2c3ff3b1 100644 --- a/src/NRedisStack/TopK/TopKCommands.cs +++ b/src/NRedisStack/TopK/TopKCommands.cs @@ -1,62 +1,60 @@ using NRedisStack.TopK.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; +public class TopKCommands : TopKCommandsAsync, ITopKCommands { - public class TopKCommands : TopKCommandsAsync, ITopKCommands - { - IDatabase _db; - public TopKCommands(IDatabase db) : base(db) - { - _db = db; - } - - /// - public RedisResult[]? Add(RedisKey key, params RedisValue[] items) - { - return (RedisResult[]?)_db.Execute(TopKCommandBuilder.Add(key, items)); - } - - /// - public long[] Count(RedisKey key, params RedisValue[] items) - { - return _db.Execute(TopKCommandBuilder.Count(key, items)).ToLongArray(); - } - - /// - public RedisResult[] IncrBy(RedisKey key, params Tuple[] itemIncrements) - { - return _db.Execute(TopKCommandBuilder.IncrBy(key, itemIncrements)).ToArray(); - } - - /// - public TopKInformation Info(RedisKey key) - { - return _db.Execute(TopKCommandBuilder.Info(key)).ToTopKInfo(); - } - - /// - public RedisResult[] List(RedisKey key, bool withcount = false) - { - return _db.Execute(TopKCommandBuilder.List(key, withcount)).ToArray(); - } - - /// - public bool Query(RedisKey key, RedisValue item) - { - return _db.Execute(TopKCommandBuilder.Query(key, item)).ToString() == "1"; - } - - /// - public bool[] Query(RedisKey key, params RedisValue[] items) - { - return _db.Execute(TopKCommandBuilder.Query(key, items)).ToBooleanArray(); - } - - /// - public bool Reserve(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) - { - return _db.Execute(TopKCommandBuilder.Reserve(key, topk, width, depth, decay)).OKtoBoolean(); - } - } -} + readonly IDatabase _db; + public TopKCommands(IDatabase db) : base(db) + { + _db = db; + } + + /// + public RedisResult[]? Add(RedisKey key, params RedisValue[] items) + { + return (RedisResult[]?)_db.Execute(TopKCommandBuilder.Add(key, items)); + } + + /// + public long[] Count(RedisKey key, params RedisValue[] items) + { + return _db.Execute(TopKCommandBuilder.Count(key, items)).ToLongArray(); + } + + /// + public RedisResult[] IncrBy(RedisKey key, params Tuple[] itemIncrements) + { + return _db.Execute(TopKCommandBuilder.IncrBy(key, itemIncrements)).ToArray(); + } + + /// + public TopKInformation Info(RedisKey key) + { + return _db.Execute(TopKCommandBuilder.Info(key)).ToTopKInfo(); + } + + /// + public RedisResult[] List(RedisKey key, bool withcount = false) + { + return _db.Execute(TopKCommandBuilder.List(key, withcount)).ToArray(); + } + + /// + public bool Query(RedisKey key, RedisValue item) + { + return _db.Execute(TopKCommandBuilder.Query(key, item)).ToString() == "1"; + } + + /// + public bool[] Query(RedisKey key, params RedisValue[] items) + { + return _db.Execute(TopKCommandBuilder.Query(key, items)).ToBooleanArray(); + } + + /// + public bool Reserve(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) + { + return _db.Execute(TopKCommandBuilder.Reserve(key, topk, width, depth, decay)).OKtoBoolean(); + } +} \ No newline at end of file diff --git a/src/NRedisStack/TopK/TopKCommandsAsync.cs b/src/NRedisStack/TopK/TopKCommandsAsync.cs index 0fd9656a..c2897d5f 100644 --- a/src/NRedisStack/TopK/TopKCommandsAsync.cs +++ b/src/NRedisStack/TopK/TopKCommandsAsync.cs @@ -1,62 +1,60 @@ using NRedisStack.TopK.DataTypes; using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; +public class TopKCommandsAsync : ITopKCommandsAsync { - public class TopKCommandsAsync : ITopKCommandsAsync - { - IDatabaseAsync _db; - public TopKCommandsAsync(IDatabaseAsync db) - { - _db = db; - } - - /// - public async Task AddAsync(RedisKey key, params RedisValue[] items) - { - return (RedisResult[]?)await _db.ExecuteAsync(TopKCommandBuilder.Add(key, items)); - } - - /// - public async Task CountAsync(RedisKey key, params RedisValue[] items) - { - return (await _db.ExecuteAsync(TopKCommandBuilder.Count(key, items))).ToLongArray(); - } - - /// - public async Task IncrByAsync(RedisKey key, params Tuple[] itemIncrements) - { - return (await _db.ExecuteAsync(TopKCommandBuilder.IncrBy(key, itemIncrements))).ToArray(); - } - - /// - public async Task InfoAsync(RedisKey key) - { - return (await _db.ExecuteAsync(TopKCommandBuilder.Info(key))).ToTopKInfo(); - } - - /// - public async Task ListAsync(RedisKey key, bool withcount = false) - { - return (await _db.ExecuteAsync(TopKCommandBuilder.List(key, withcount))).ToArray(); - } - - /// - public async Task QueryAsync(RedisKey key, RedisValue item) - { - return (await _db.ExecuteAsync(TopKCommandBuilder.Query(key, item))).ToString() == "1"; - } - - /// - public async Task QueryAsync(RedisKey key, params RedisValue[] items) - { - return (await _db.ExecuteAsync(TopKCommandBuilder.Query(key, items))).ToBooleanArray(); - } - - /// - public async Task ReserveAsync(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) - { - return (await _db.ExecuteAsync(TopKCommandBuilder.Reserve(key, topk, width, depth, decay))).OKtoBoolean(); - } + readonly IDatabaseAsync _db; + public TopKCommandsAsync(IDatabaseAsync db) + { + _db = db; + } + + /// + public async Task AddAsync(RedisKey key, params RedisValue[] items) + { + return (RedisResult[]?)await _db.ExecuteAsync(TopKCommandBuilder.Add(key, items)); + } + + /// + public async Task CountAsync(RedisKey key, params RedisValue[] items) + { + return (await _db.ExecuteAsync(TopKCommandBuilder.Count(key, items))).ToLongArray(); + } + + /// + public async Task IncrByAsync(RedisKey key, params Tuple[] itemIncrements) + { + return (await _db.ExecuteAsync(TopKCommandBuilder.IncrBy(key, itemIncrements))).ToArray(); + } + + /// + public async Task InfoAsync(RedisKey key) + { + return (await _db.ExecuteAsync(TopKCommandBuilder.Info(key))).ToTopKInfo(); + } + + /// + public async Task ListAsync(RedisKey key, bool withcount = false) + { + return (await _db.ExecuteAsync(TopKCommandBuilder.List(key, withcount))).ToArray(); + } + + /// + public async Task QueryAsync(RedisKey key, RedisValue item) + { + return (await _db.ExecuteAsync(TopKCommandBuilder.Query(key, item))).ToString() == "1"; + } + + /// + public async Task QueryAsync(RedisKey key, params RedisValue[] items) + { + return (await _db.ExecuteAsync(TopKCommandBuilder.Query(key, items))).ToBooleanArray(); + } + + /// + public async Task ReserveAsync(RedisKey key, long topk, long width = 7, long depth = 8, double decay = 0.9) + { + return (await _db.ExecuteAsync(TopKCommandBuilder.Reserve(key, topk, width, depth, decay))).OKtoBoolean(); } } \ No newline at end of file diff --git a/src/NRedisStack/Transactions.cs b/src/NRedisStack/Transactions.cs index a9530895..0d157316 100644 --- a/src/NRedisStack/Transactions.cs +++ b/src/NRedisStack/Transactions.cs @@ -1,31 +1,30 @@ using StackExchange.Redis; -namespace NRedisStack +namespace NRedisStack; + +public class Transaction { - public class Transaction - { - private ITransaction _transaction; - public IDatabaseAsync Db => _transaction; + private readonly ITransaction _transaction; + public IDatabaseAsync Db => _transaction; - public Transaction(IDatabase db) - { - db.SetInfoInPipeline(); - _transaction = db.CreateTransaction(); - } + public Transaction(IDatabase db) + { + db.SetInfoInPipeline(); + _transaction = db.CreateTransaction(); + } - public ConditionResult AddCondition(Condition condition) => _transaction.AddCondition(condition); + public ConditionResult AddCondition(Condition condition) => _transaction.AddCondition(condition); - public bool Execute(CommandFlags flags = CommandFlags.None) => _transaction.Execute(flags); + public bool Execute(CommandFlags flags = CommandFlags.None) => _transaction.Execute(flags); - public Task ExecuteAsync(CommandFlags flags = CommandFlags.None) => _transaction.ExecuteAsync(flags); + public Task ExecuteAsync(CommandFlags flags = CommandFlags.None) => _transaction.ExecuteAsync(flags); - public BloomCommandsAsync Bf => new BloomCommandsAsync(_transaction); - public CmsCommandsAsync Cms => new CmsCommandsAsync(_transaction); - public CuckooCommandsAsync Cf => new CuckooCommandsAsync(_transaction); - public JsonCommandsAsync Json => new JsonCommandsAsync(_transaction); - public SearchCommandsAsync Ft => new SearchCommandsAsync(_transaction); - public TdigestCommandsAsync Tdigest => new TdigestCommandsAsync(_transaction); - public TimeSeriesCommandsAsync Ts => new TimeSeriesCommandsAsync(_transaction); - public TopKCommandsAsync TopK => new TopKCommandsAsync(_transaction); - } -} + public BloomCommandsAsync Bf => new(_transaction); + public CmsCommandsAsync Cms => new(_transaction); + public CuckooCommandsAsync Cf => new(_transaction); + public JsonCommandsAsync Json => new(_transaction); + public SearchCommandsAsync Ft => new(_transaction); + public TdigestCommandsAsync Tdigest => new(_transaction); + public TimeSeriesCommandsAsync Ts => new(_transaction); + public TopKCommandsAsync TopK => new(_transaction); +} \ No newline at end of file diff --git a/tests/Doc/Bf_tutorial.cs b/tests/Doc/Bf_tutorial.cs index efe29630..0cc16100 100644 --- a/tests/Doc/Bf_tutorial.cs +++ b/tests/Doc/Bf_tutorial.cs @@ -13,17 +13,17 @@ namespace Doc; // REMOVE_END // HIDE_START -public class Bf_tutorial +public class BfTutorial // REMOVE_START : AbstractNRedisStackTest, IDisposable // REMOVE_END { // REMOVE_START - public Bf_tutorial(EndpointsFixture fixture) : base(fixture) { } + public BfTutorial(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -56,11 +56,11 @@ public void run() }); Console.WriteLine(string.Join(", ", res4)); // >>> True, True, True - bool[] res5 = db.BF().MExists("bikes:models", new RedisValue[]{ + bool[] res5 = db.BF().MExists("bikes:models", [ "Rocky Mountain Racer", "Cloudy City Cruiser", "Windy City Wippet" - }); + ]); Console.WriteLine(string.Join(", ", res5)); // >>> True, True, True // STEP_END diff --git a/tests/Doc/Bitmap_tutorial.cs b/tests/Doc/Bitmap_tutorial.cs index be521a9f..2770752b 100644 --- a/tests/Doc/Bitmap_tutorial.cs +++ b/tests/Doc/Bitmap_tutorial.cs @@ -12,17 +12,17 @@ namespace Doc; // REMOVE_END // HIDE_START -public class Bitmap_tutorial +public class BitmapTutorial // REMOVE_START : AbstractNRedisStackTest, IDisposable // REMOVE_END { // REMOVE_START - public Bitmap_tutorial(EndpointsFixture fixture) : base(fixture) { } + public BitmapTutorial(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection diff --git a/tests/Doc/CmdsGenericExample.cs b/tests/Doc/CmdsGenericExample.cs index 3080ff43..f9c0517d 100644 --- a/tests/Doc/CmdsGenericExample.cs +++ b/tests/Doc/CmdsGenericExample.cs @@ -14,16 +14,14 @@ namespace Doc; // HIDE_START public class CmdsGenericExample // REMOVE_START -: AbstractNRedisStackTest, IDisposable + (EndpointsFixture fixture) : AbstractNRedisStackTest(fixture), IDisposable // REMOVE_END { // REMOVE_START - public CmdsGenericExample(EndpointsFixture fixture) : base(fixture) { } - [SkipIfRedis(Comparison.LessThan, "7.0.0")] - [InlineData] // No parameters passed, but still uses Theory + [SkipIfRedisFact(Comparison.LessThan, "7.0.0")] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -56,7 +54,7 @@ public void run() bool delResult2 = db.StringSet("key2", "World"); Console.WriteLine(delResult2); // >>> true - long delResult3 = db.KeyDelete(new RedisKey[] { "key1", "key2", "key3" }); + long delResult3 = db.KeyDelete(["key1", "key2", "key3"]); Console.WriteLine(delResult3); // >>> 2 // STEP_END diff --git a/tests/Doc/CmdsHashExample.cs b/tests/Doc/CmdsHashExample.cs index 09eaf3ee..46a19cd9 100644 --- a/tests/Doc/CmdsHashExample.cs +++ b/tests/Doc/CmdsHashExample.cs @@ -20,7 +20,7 @@ public CmdsHashExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -59,10 +59,10 @@ public void run() db.HashSet( "myhash", - new HashEntry[] { - new HashEntry("field2", "Hi"), - new HashEntry("field3", "World") - } + [ + new("field2", "Hi"), + new("field3", "World") + ] ); RedisValue res6 = db.HashGet("myhash", "field2"); @@ -90,10 +90,10 @@ public void run() // STEP_START hgetall db.HashSet("myhash", - new HashEntry[] { - new HashEntry("field1", "Hello"), - new HashEntry("field2", "World") - } + [ + new("field1", "Hello"), + new("field2", "World") + ] ); HashEntry[] hGetAllResult = db.HashGetAll("myhash"); @@ -110,10 +110,10 @@ public void run() // STEP_START hvals db.HashSet("myhash", - new HashEntry[] { - new HashEntry("field1", "Hello"), - new HashEntry("field2", "World") - } + [ + new("field1", "Hello"), + new("field2", "World") + ] ); RedisValue[] hValsResult = db.HashValues("myhash"); diff --git a/tests/Doc/CmdsListExample.cs b/tests/Doc/CmdsListExample.cs index 140a4b64..158db82c 100644 --- a/tests/Doc/CmdsListExample.cs +++ b/tests/Doc/CmdsListExample.cs @@ -22,7 +22,7 @@ public CmdsListExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -57,7 +57,7 @@ public void run() // REMOVE_END // STEP_START lpop - long lPopResult1 = db.ListRightPush("mylist", new RedisValue[] { "one", "two", "three", "four", "five" }); + long lPopResult1 = db.ListRightPush("mylist", ["one", "two", "three", "four", "five"]); Console.WriteLine(lPopResult1); // >>> 5 RedisValue lPopResult2 = db.ListLeftPop("mylist"); @@ -102,7 +102,7 @@ public void run() // REMOVE_END // STEP_START lrange - long lRangeResult1 = db.ListRightPush("mylist", new RedisValue[] { "one", "two", "three" }); + long lRangeResult1 = db.ListRightPush("mylist", ["one", "two", "three"]); Console.WriteLine(lRangeResult1); // >>> 3 RedisValue[] lRangeResult2 = db.ListRange("mylist", 0, 0); @@ -133,7 +133,7 @@ public void run() // REMOVE_END // STEP_START rpop - long rPopResult1 = db.ListRightPush("mylist", new RedisValue[] { "one", "two", "three", "four", "five" }); + long rPopResult1 = db.ListRightPush("mylist", ["one", "two", "three", "four", "five"]); Console.WriteLine(rPopResult1); // >>> 5 RedisValue rPopResult2 = db.ListRightPop("mylist"); diff --git a/tests/Doc/CmdsSetExample.cs b/tests/Doc/CmdsSetExample.cs index 51c07063..3f1fc285 100644 --- a/tests/Doc/CmdsSetExample.cs +++ b/tests/Doc/CmdsSetExample.cs @@ -17,7 +17,7 @@ public CmdsSetExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { // REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -56,7 +56,7 @@ public void run() // STEP_START smembers long sMembersResult1 = db.SetAdd( - "myset", new RedisValue[] { "Hello", "World" } + "myset", ["Hello", "World"] ); Console.WriteLine(sMembersResult1); // >>> 2 diff --git a/tests/Doc/CmdsSortedSetExamples.cs b/tests/Doc/CmdsSortedSetExamples.cs index 997f222c..852b5606 100644 --- a/tests/Doc/CmdsSortedSetExamples.cs +++ b/tests/Doc/CmdsSortedSetExamples.cs @@ -22,7 +22,7 @@ public CmdsSortedSet(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -77,10 +77,10 @@ public void run() long zAddResult3 = db.SortedSetAdd( "myzset", - new SortedSetEntry[] { - new SortedSetEntry("two", 2), - new SortedSetEntry("three", 3) - } + [ + new("two", 2), + new("three", 3) + ] ); Console.WriteLine(zAddResult3); // >>> 2 @@ -245,11 +245,11 @@ public void run() // STEP_START zrange1 long zRangeResult1 = db.SortedSetAdd( "myzset", - new SortedSetEntry[] { - new SortedSetEntry("one", 1), - new SortedSetEntry("two", 2), - new SortedSetEntry("three", 3) - } + [ + new("one", 1), + new("two", 2), + new("three", 3) + ] ); Console.WriteLine(zRangeResult1); // >>> 3 @@ -279,11 +279,11 @@ public void run() // STEP_START zrange2 long zRangeResult5 = db.SortedSetAdd( "myzset", - new SortedSetEntry[] { - new SortedSetEntry("one", 1), - new SortedSetEntry("two", 2), - new SortedSetEntry("three", 3) - } + [ + new("one", 1), + new("two", 2), + new("three", 3) + ] ); SortedSetEntry[] zRangeResult6 = db.SortedSetRangeByRankWithScores("myzset", 0, 1); @@ -302,11 +302,11 @@ public void run() // STEP_START zrange3 long zRangeResult7 = db.SortedSetAdd( "myzset", - new SortedSetEntry[] { - new SortedSetEntry("one", 1), - new SortedSetEntry("two", 2), - new SortedSetEntry("three", 3) - } + [ + new("one", 1), + new("two", 2), + new("three", 3) + ] ); RedisValue[] zRangeResult8 = db.SortedSetRangeByScore( diff --git a/tests/Doc/CmdsStringExample.cs b/tests/Doc/CmdsStringExample.cs index 1d888f4d..d4d3e29c 100644 --- a/tests/Doc/CmdsStringExample.cs +++ b/tests/Doc/CmdsStringExample.cs @@ -22,7 +22,7 @@ public CmdsStringExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection diff --git a/tests/Doc/Cms_tutorial.cs b/tests/Doc/Cms_tutorial.cs index 4d194fcc..10d19bd8 100644 --- a/tests/Doc/Cms_tutorial.cs +++ b/tests/Doc/Cms_tutorial.cs @@ -14,17 +14,17 @@ namespace Doc; // REMOVE_END // HIDE_START -public class Cms_tutorial +public class CmsTutorial // REMOVE_START : AbstractNRedisStackTest, IDisposable // REMOVE_END { // REMOVE_START - public Cms_tutorial(EndpointsFixture fixture) : base(fixture) { } + public CmsTutorial(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -48,10 +48,10 @@ public void run() Console.WriteLine(res2); // >>> 100 long[] res3 = db.CMS().IncrBy("bikes:profit", - new Tuple[]{ - new Tuple("Rocky Mountain Racer", 200), - new Tuple("Cloudy City Cruiser", 150) - } + [ + new("Rocky Mountain Racer", 200), + new("Cloudy City Cruiser", 150) + ] ); Console.WriteLine(string.Join(", ", res3)); // >>> 200, 150 diff --git a/tests/Doc/Cuckoo_tutorial.cs b/tests/Doc/Cuckoo_tutorial.cs index e6f6a67f..24a8f061 100644 --- a/tests/Doc/Cuckoo_tutorial.cs +++ b/tests/Doc/Cuckoo_tutorial.cs @@ -13,17 +13,17 @@ namespace Doc; // REMOVE_END // HIDE_START -public class Cuckoo_tutorial +public class CuckooTutorial // REMOVE_START : AbstractNRedisStackTest, IDisposable // REMOVE_END { // REMOVE_START - public Cuckoo_tutorial(EndpointsFixture fixture) : base(fixture) { } + public CuckooTutorial(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection diff --git a/tests/Doc/Doc.csproj b/tests/Doc/Doc.csproj index 9cd87ea0..03a7dbd8 100644 --- a/tests/Doc/Doc.csproj +++ b/tests/Doc/Doc.csproj @@ -1,8 +1,10 @@ - net6.0;net7.0;net8.0;net481 - net6.0;net7.0;net8.0 + net6.0;net7.0;net8.0;net481 false + + + $(Nowarn);CS0612;CS0618 @@ -11,7 +13,12 @@ - + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/Doc/Geo_tutorial.cs b/tests/Doc/Geo_tutorial.cs index 9f7ac6d5..180feb89 100644 --- a/tests/Doc/Geo_tutorial.cs +++ b/tests/Doc/Geo_tutorial.cs @@ -12,17 +12,17 @@ namespace Doc; // REMOVE_END // HIDE_START -public class Geo_tutorial +public class GeoTutorial // REMOVE_START : AbstractNRedisStackTest, IDisposable // REMOVE_END { // REMOVE_START - public Geo_tutorial(EndpointsFixture fixture) : base(fixture) { } + public GeoTutorial(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection diff --git a/tests/Doc/HashExample.cs b/tests/Doc/HashExample.cs index 991fbbef..b057284c 100644 --- a/tests/Doc/HashExample.cs +++ b/tests/Doc/HashExample.cs @@ -18,7 +18,7 @@ public HashExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -30,13 +30,12 @@ public void run() db.KeyDelete("bike:1"); //HIDE_END //STEP_START set_get_all - db.HashSet("bike:1", new HashEntry[] - { - new HashEntry("model", "Deimos"), - new HashEntry("brand", "Ergonom"), - new HashEntry("type", "Enduro bikes"), - new HashEntry("price", 4972) - }); + db.HashSet("bike:1", [ + new("model", "Deimos"), + new("brand", "Ergonom"), + new("type", "Enduro bikes"), + new("price", 4972) + ]); Console.WriteLine("Hash Created"); // Hash Created @@ -66,7 +65,7 @@ public void run() //REMOVE_END //STEP_START hmget - var values = db.HashGet("bike:1", new RedisValue[] { "model", "price" }); + var values = db.HashGet("bike:1", ["model", "price"]); Console.WriteLine(string.Join(" ", values)); // Deimos 4972 //REMOVE_START @@ -127,7 +126,7 @@ public void run() //REMOVE_END // Owners: 1 - var stats = db.HashGet("bike:1", new RedisValue[] { "crashes", "owners" }); + var stats = db.HashGet("bike:1", ["crashes", "owners"]); Console.WriteLine($"Bike stats: crashes={stats[0]}, owners={stats[1]}"); //REMOVE_START Assert.Equal(1, stats[0]); diff --git a/tests/Doc/Hll_tutorial.cs b/tests/Doc/Hll_tutorial.cs index 27aa8bcd..d55891ff 100644 --- a/tests/Doc/Hll_tutorial.cs +++ b/tests/Doc/Hll_tutorial.cs @@ -12,17 +12,17 @@ namespace Doc; // REMOVE_END // HIDE_START -public class Hll_tutorial +public class HllTutorial // REMOVE_START : AbstractNRedisStackTest, IDisposable // REMOVE_END { // REMOVE_START - public Hll_tutorial(EndpointsFixture fixture) : base(fixture) { } + public HllTutorial(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -33,19 +33,19 @@ public void run() var db = muxer.GetDatabase(); //REMOVE_START // Clear any keys here before using them in tests. - db.KeyDelete(new RedisKey[] { "{bikes}", "commuter_{bikes}", "all_{bikes}" }); + db.KeyDelete(["{bikes}", "commuter_{bikes}", "all_{bikes}"]); //REMOVE_END // HIDE_END // STEP_START pfadd - bool res1 = db.HyperLogLogAdd("{bikes}", new RedisValue[] { "Hyperion", "Deimos", "Phoebe", "Quaoar" }); + bool res1 = db.HyperLogLogAdd("{bikes}", ["Hyperion", "Deimos", "Phoebe", "Quaoar"]); Console.WriteLine(res1); // >>> True long res2 = db.HyperLogLogLength("{bikes}"); Console.WriteLine(res2); // >>> 4 - bool res3 = db.HyperLogLogAdd("commuter_{bikes}", new RedisValue[] { "Salacia", "Mimas", "Quaoar" }); + bool res3 = db.HyperLogLogAdd("commuter_{bikes}", ["Salacia", "Mimas", "Quaoar"]); Console.WriteLine(res3); // >>> True db.HyperLogLogMerge("all_{bikes}", "{bikes}", "commuter_{bikes}"); diff --git a/tests/Doc/HomeJsonExample.cs b/tests/Doc/HomeJsonExample.cs index f04a7ac2..a5888ee7 100644 --- a/tests/Doc/HomeJsonExample.cs +++ b/tests/Doc/HomeJsonExample.cs @@ -26,7 +26,7 @@ public HomeJsonExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -41,7 +41,7 @@ public void run() //REMOVE_START // Clear any keys here before using them in tests. - db.KeyDelete(new RedisKey[] { "user:1", "user:2", "user:3" }); + db.KeyDelete(["user:1", "user:2", "user:3"]); try { db.FT().DropIndex("idx:users"); } catch { } //REMOVE_END // HIDE_END @@ -106,7 +106,7 @@ public void run() // STEP_START query1 SearchResult findPaulResult = db.FT().Search( "idx:users", - new Query("Paul @age:[30 40]") + new("Paul @age:[30 40]") ); Console.WriteLine(string.Join( ", ", @@ -190,32 +190,32 @@ public void run() // REMOVE_END // STEP_START add_hash_data - db.HashSet("huser:1", new HashEntry[] { + db.HashSet("huser:1", [ new("name", "Paul John"), new("email", "paul.john@example.com"), new("age", 42), new("city", "London") - }); + ]); - db.HashSet("huser:2", new HashEntry[] { + db.HashSet("huser:2", [ new("name", "Eden Zamir"), new("email", "eden.zamir@example.com"), new("age", 29), new("city", "Tel Aviv") - }); + ]); - db.HashSet("huser:3", new HashEntry[] { + db.HashSet("huser:3", [ new("name", "Paul Zamir"), new("email", "paul.zamir@example.com"), new("age", 35), new("city", "Tel Aviv") - }); + ]); // STEP_END // STEP_START query1_hash SearchResult findPaulHashResult = db.FT().Search( "hash-idx:users", - new Query("Paul @age:[30 40]") + new("Paul @age:[30 40]") ); foreach (Document doc in findPaulHashResult.Documents) diff --git a/tests/Doc/HomeProbExample.cs b/tests/Doc/HomeProbExample.cs index b8eef729..46bf2894 100644 --- a/tests/Doc/HomeProbExample.cs +++ b/tests/Doc/HomeProbExample.cs @@ -21,7 +21,7 @@ public HomeProbExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { // REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -33,13 +33,13 @@ public void run() var db = muxer.GetDatabase(); // REMOVE_START // Clear any keys here before using them in tests. - db.KeyDelete(new RedisKey[] { + db.KeyDelete([ "recorded_users", "other_users", "group:1", "group:2", "both_groups", "items_sold", "male_heights", "female_heights", "all_heights", "top_3_songs" - }); + ]); // REMOVE_END // HIDE_END @@ -57,7 +57,7 @@ public void run() Console.WriteLine(res3); // >>> false // STEP_END // REMOVE_START - Assert.Equal(new bool[] { true, true, true, true }, res1); + Assert.Equal(new[] { true, true, true, true }, res1); // REMOVE_END // STEP_START cuckoo @@ -84,7 +84,7 @@ public void run() Assert.True(res4); Assert.True(res5); Assert.True(res6); - Assert.Equal(new bool[] { true, true, false }, res7); + Assert.Equal(new[] { true, true, false }, res7); Assert.True(res8); Assert.False(res9); // REMOVE_END @@ -92,7 +92,7 @@ public void run() // STEP_START hyperloglog bool res10 = db.HyperLogLogAdd( "group:1", - new RedisValue[] { "andy", "cameron", "david" } + ["andy", "cameron", "david"] ); Console.WriteLine(res10); // >>> true @@ -101,7 +101,7 @@ public void run() bool res12 = db.HyperLogLogAdd( "group:2", - new RedisValue[] { "kaitlyn", "michelle", "paolo", "rachel" } + ["kaitlyn", "michelle", "paolo", "rachel"] ); Console.WriteLine(res12); // >>> true @@ -133,22 +133,22 @@ public void run() long[] res16 = db.CMS().IncrBy( "items_sold", - new Tuple[]{ + [ new("bread", 300), new("tea", 200), new("coffee", 200), new("beer", 100) - } + ] ); Console.WriteLine(string.Join(", ", res16)); // >>> 300, 200, 200, 100 long[] res17 = db.CMS().IncrBy( "items_sold", - new Tuple[]{ + [ new("bread", 100), - new("coffee", 150), - } + new("coffee", 150) + ] ); Console.WriteLine(string.Join(", ", res17)); // >>> 400, 350 @@ -217,13 +217,13 @@ public void run() Assert.True(res20); Assert.Equal(152.0, res21); Assert.Equal(196.0, res22); - Assert.Equal(new double[] { 181.0 }, res23); - Assert.Equal(new double[] { 0.7857142857142857 }, res24); + Assert.Equal(new[] { 181.0 }, res23); + Assert.Equal(new[] { 0.7857142857142857 }, res24); Assert.True(res25); Assert.True(res26); - Assert.Equal(new double[] { 170.0 }, res27); + Assert.Equal(new[] { 170.0 }, res27); Assert.True(res28); - Assert.Equal(new double[] { 175.5 }, res29); + Assert.Equal(new[] { 175.5 }, res29); // REMOVE_END // STEP_START topk @@ -303,7 +303,7 @@ public void run() ) ); - Assert.Equal(new bool[] { true, false }, res33); + Assert.Equal(new[] { true, false }, res33); // REMOVE_END } } \ No newline at end of file diff --git a/tests/Doc/Json_tutorial.cs b/tests/Doc/Json_tutorial.cs index c9430e1a..5d746488 100644 --- a/tests/Doc/Json_tutorial.cs +++ b/tests/Doc/Json_tutorial.cs @@ -14,17 +14,17 @@ namespace Doc; // REMOVE_END // HIDE_START -public class Json_tutorial +public class JsonTutorial // REMOVE_START : AbstractNRedisStackTest, IDisposable // REMOVE_END { // REMOVE_START - public Json_tutorial(EndpointsFixture fixture) : base(fixture) { } + public JsonTutorial(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection diff --git a/tests/Doc/ListTutorial.cs b/tests/Doc/ListTutorial.cs index 8bbb2bc9..e87e0b03 100644 --- a/tests/Doc/ListTutorial.cs +++ b/tests/Doc/ListTutorial.cs @@ -21,7 +21,7 @@ public ListExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -140,10 +140,10 @@ public void run() //REMOVE_END //STEP_START variadic - long res19 = db.ListRightPush("bikes:repairs", new RedisValue[] { "bike:1", "bike:2", "bike:3" }); + long res19 = db.ListRightPush("bikes:repairs", ["bike:1", "bike:2", "bike:3"]); Console.WriteLine(res19); // >>> 3 - long res20 = db.ListLeftPush("bikes:repairs", new RedisValue[] { "bike:important_bike", "bike:very_important_bike" }); + long res20 = db.ListLeftPush("bikes:repairs", ["bike:important_bike", "bike:very_important_bike"]); Console.WriteLine(res20); // >>> 5 RedisValue[] res21 = db.ListRange("bikes:repairs", 0, -1); @@ -159,7 +159,7 @@ public void run() //REMOVE_END //STEP_START lpop_rpop - long res22 = db.ListRightPush("bikes:repairs", new RedisValue[] { "bike:1", "bike:2", "bike:3" }); + long res22 = db.ListRightPush("bikes:repairs", ["bike:1", "bike:2", "bike:3"]); Console.WriteLine(res22); // >>> 3 RedisValue res23 = db.ListRightPop("bikes:repairs"); @@ -184,7 +184,7 @@ public void run() //REMOVE_END //STEP_START ltrim - long res27 = db.ListLeftPush("bikes:repairs", new RedisValue[] { "bike:1", "bike:2", "bike:3", "bike:4", "bike:5" }); + long res27 = db.ListLeftPush("bikes:repairs", ["bike:1", "bike:2", "bike:3", "bike:4", "bike:5"]); Console.WriteLine(res27); // >>> 5 db.ListTrim("bikes:repairs", 0, 2); @@ -199,7 +199,7 @@ public void run() //REMOVE_END //STEP_START ltrim_end_of_list - long res29 = db.ListRightPush("bikes:repairs", new RedisValue[] { "bike:1", "bike:2", "bike:3", "bike:4", "bike:5" }); + long res29 = db.ListRightPush("bikes:repairs", ["bike:1", "bike:2", "bike:3", "bike:4", "bike:5"]); Console.WriteLine(res29); // >>> 5 db.ListTrim("bikes:repairs", -3, -1); @@ -214,20 +214,20 @@ public void run() //REMOVE_END //STEP_START brpop - long res31 = db.ListRightPush("bikes:repairs", new RedisValue[] { "bike:1", "bike:2" }); + long res31 = db.ListRightPush("bikes:repairs", ["bike:1", "bike:2"]); Console.WriteLine(res31); // >>> 2 - Tuple? res32 = db.BRPop(new RedisKey[] { "bikes:repairs" }, 1); + Tuple? res32 = db.BRPop(["bikes:repairs"], 1); if (res32 != null) Console.WriteLine($"{res32.Item1} -> {res32.Item2}"); // >>> "bikes:repairs -> bike:2" - Tuple? res33 = db.BRPop(new RedisKey[] { "bikes:repairs" }, 1); + Tuple? res33 = db.BRPop(["bikes:repairs"], 1); if (res33 != null) Console.WriteLine($"{res33.Item1} -> {res33.Item2}"); // >>> "bikes:repairs -> bike:1" - Tuple? res34 = db.BRPop(new RedisKey[] { "bikes:repairs" }, 1); + Tuple? res34 = db.BRPop(["bikes:repairs"], 1); Console.WriteLine(res34); // >>> "Null" //STEP_END @@ -246,7 +246,7 @@ public void run() bool res35 = db.KeyDelete("new_bikes"); Console.WriteLine(res35); // >>> False - long res36 = db.ListRightPush("new_bikes", new RedisValue[] { "bike:1", "bike:2", "bike:3" }); + long res36 = db.ListRightPush("new_bikes", ["bike:1", "bike:2", "bike:3"]); Console.WriteLine(res36); // >>> 3 //STEP_END @@ -264,7 +264,7 @@ public void run() try { - long res39 = db.ListRightPush("new_bikes", new RedisValue[] { "bike:2", "bike:3" }); + long res39 = db.ListRightPush("new_bikes", ["bike:2", "bike:3"]); } catch (Exception e) { @@ -279,7 +279,7 @@ public void run() //REMOVE_END //STEP_START rule_2 - long res40 = db.ListLeftPush("bikes:repairs", new RedisValue[] { "bike:1", "bike:2", "bike:3" }); + long res40 = db.ListLeftPush("bikes:repairs", ["bike:1", "bike:2", "bike:3"]); Console.WriteLine(res40); // >>> 3 bool res41 = db.KeyExists("bikes:repairs"); @@ -325,7 +325,7 @@ public void run() //REMOVE_END //STEP_START ltrim.1 - long res49 = db.ListLeftPush("bikes:repairs", new RedisValue[] { "bike:1", "bike:2", "bike:3", "bike:4", "bike:5" }); + long res49 = db.ListLeftPush("bikes:repairs", ["bike:1", "bike:2", "bike:3", "bike:4", "bike:5"]); Console.WriteLine(res49); // >>> 5 db.ListTrim("bikes:repairs", 0, 2); diff --git a/tests/Doc/PipeTransExample.cs b/tests/Doc/PipeTransExample.cs index 2ad8b949..140b904b 100644 --- a/tests/Doc/PipeTransExample.cs +++ b/tests/Doc/PipeTransExample.cs @@ -17,22 +17,22 @@ public PipeTransExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public async Task run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection SkipIfTargetConnectionDoesNotExist(EndpointsFixture.Env.Standalone); - var _ = GetCleanDatabase(EndpointsFixture.Env.Standalone); + _ = GetCleanDatabase(EndpointsFixture.Env.Standalone); //REMOVE_END var muxer = ConnectionMultiplexer.Connect("localhost:6379"); var db = muxer.GetDatabase(); // REMOVE_START - db.KeyDelete(new RedisKey[] { + db.KeyDelete([ "counter:1", "counter:2", "counter:3", "seat:0", "seat:1", "seat:2", "seat:3", "seat:4", "customer:39182", "Details" - }); + ]); // REMOVE_END // STEP_START basic_pipe @@ -40,7 +40,7 @@ public async Task run() for (int i = 0; i < 5; i++) { - pipeline.Db.StringSetAsync($"seat:{i}", $"#{i}"); + _ = pipeline.Db.StringSetAsync($"seat:{i}", $"#{i}"); } pipeline.Execute(); @@ -62,9 +62,9 @@ public async Task run() // STEP_START basic_trans var trans = new Transaction(db); - trans.Db.StringIncrementAsync("counter:1", 1); - trans.Db.StringIncrementAsync("counter:2", 2); - trans.Db.StringIncrementAsync("counter:3", 3); + _ = trans.Db.StringIncrementAsync("counter:1", 1); + _ = trans.Db.StringIncrementAsync("counter:2", 2); + _ = trans.Db.StringIncrementAsync("counter:3", 3); trans.Execute(); @@ -88,12 +88,12 @@ public async Task run() watchedTrans.AddCondition(Condition.KeyNotExists("customer:39182")); - watchedTrans.Db.HashSetAsync( + _ = watchedTrans.Db.HashSetAsync( "customer:39182", - new HashEntry[]{ - new HashEntry("name", "David"), - new HashEntry("age", "27") - } + [ + new("name", "David"), + new("age", "27") + ] ); bool succeeded = watchedTrans.Execute(); @@ -108,11 +108,11 @@ public async Task run() Console.WriteLine(resp7); // >>> true db.HashSet("Details", "SerialNumber", "12345A", When.NotExists); - string resp8 = db.HashGet("Details", "SerialNumber"); + string resp8 = db.HashGet("Details", "SerialNumber")!; Console.WriteLine(resp8); // >>> 12345 db.HashSet("Details", "SerialNumber", "12345A"); - string resp9 = db.HashGet("Details", "SerialNumber"); + string resp9 = db.HashGet("Details", "SerialNumber")!; Console.WriteLine(resp9); // >>> 12345A // STEP_END // REMOVE_START diff --git a/tests/Doc/QueryAggExample.cs b/tests/Doc/QueryAggExample.cs index b86c4654..efaec41c 100644 --- a/tests/Doc/QueryAggExample.cs +++ b/tests/Doc/QueryAggExample.cs @@ -26,7 +26,7 @@ public QueryAggExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection diff --git a/tests/Doc/QueryEmExample.cs b/tests/Doc/QueryEmExample.cs index 608868e0..6627efe7 100644 --- a/tests/Doc/QueryEmExample.cs +++ b/tests/Doc/QueryEmExample.cs @@ -25,7 +25,7 @@ public QueryEmExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -213,7 +213,7 @@ public void run() // STEP_START em1 SearchResult res1 = db.FT().Search( "idx:bicycle", - new Query("@price:[270 270]") + new("@price:[270 270]") ); Console.WriteLine(res1.TotalResults); // >>> 1 @@ -236,7 +236,7 @@ public void run() // STEP_START em2 SearchResult res3 = db.FT().Search( "idx:bicycle", - new Query("@condition:{new}") + new("@condition:{new}") ); Console.WriteLine(res3.TotalResults); // >>> 4 // STEP_END @@ -277,7 +277,7 @@ public void run() // STEP_START em4 SearchResult res5 = db.FT().Search( "idx:bicycle", - new Query("@description:\"rough terrain\"") + new("@description:\"rough terrain\"") ); Console.WriteLine(res5.TotalResults); // >>> 1 // STEP_END diff --git a/tests/Doc/QueryFtExample.cs b/tests/Doc/QueryFtExample.cs index 687f01be..9a7f2895 100644 --- a/tests/Doc/QueryFtExample.cs +++ b/tests/Doc/QueryFtExample.cs @@ -25,7 +25,7 @@ public QueryFtExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -211,7 +211,7 @@ public void run() // STEP_START ft1 SearchResult res1 = db.FT().Search( "idx:bicycle", - new Query("@description: kids") + new("@description: kids") ); Console.WriteLine(res1); // >>> 2 // STEP_END @@ -225,7 +225,7 @@ public void run() // STEP_START ft2 SearchResult res2 = db.FT().Search( "idx:bicycle", - new Query("@model: ka*") + new("@model: ka*") ); Console.WriteLine(res2.TotalResults); // >>> 1 // STEP_END @@ -239,7 +239,7 @@ public void run() // STEP_START ft3 SearchResult res3 = db.FT().Search( "idx:bicycle", - new Query("@brand: *bikes") + new("@brand: *bikes") ); Console.WriteLine(res3.TotalResults); // >>> 2 // STEP_END @@ -253,7 +253,7 @@ public void run() // STEP_START ft4 SearchResult res4 = db.FT().Search( "idx:bicycle", - new Query("%optamized%") + new("%optamized%") ); Console.WriteLine(res4.TotalResults); // >>> 1 // STEP_END @@ -267,7 +267,7 @@ public void run() // STEP_START ft5 SearchResult res5 = db.FT().Search( "idx:bicycle", - new Query("%%optamised%%") + new("%%optamised%%") ); Console.WriteLine(res5.TotalResults); // >>> 1 // STEP_END diff --git a/tests/Doc/QueryRangeExample.cs b/tests/Doc/QueryRangeExample.cs index 30a758a9..26274fa7 100644 --- a/tests/Doc/QueryRangeExample.cs +++ b/tests/Doc/QueryRangeExample.cs @@ -25,7 +25,7 @@ public QueryRangeExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -211,7 +211,7 @@ public void run() // STEP_START range1 SearchResult res1 = db.FT().Search( "idx:bicycle", - new Query("@price:[500 1000]") + new("@price:[500 1000]") ); Console.WriteLine(res1.TotalResults); // >>> 3 // STEP_END diff --git a/tests/Doc/SearchQuickstartExample.cs b/tests/Doc/SearchQuickstartExample.cs index df9fa2e8..7a561574 100644 --- a/tests/Doc/SearchQuickstartExample.cs +++ b/tests/Doc/SearchQuickstartExample.cs @@ -21,7 +21,7 @@ public SearchQuickstartExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection diff --git a/tests/Doc/SetGetExample.cs b/tests/Doc/SetGetExample.cs index fc2dd70d..cf636563 100644 --- a/tests/Doc/SetGetExample.cs +++ b/tests/Doc/SetGetExample.cs @@ -18,7 +18,7 @@ public SetGetExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection diff --git a/tests/Doc/SetsTutorial.cs b/tests/Doc/SetsTutorial.cs index 1d2be52d..ea9e47b9 100644 --- a/tests/Doc/SetsTutorial.cs +++ b/tests/Doc/SetsTutorial.cs @@ -1,7 +1,6 @@ // EXAMPLE: sets_tutorial // HIDE_START -using System.Data.Common; using NRedisStack.Tests; using StackExchange.Redis; @@ -23,7 +22,7 @@ public SetsExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -41,16 +40,16 @@ public void run() // STEP_START sadd - long res1 = db.SetAdd("bikes:racing:france", new RedisValue[] { "bike:1" }); + long res1 = db.SetAdd("bikes:racing:france", ["bike:1"]); Console.WriteLine(res1); // >>> 1 - long res2 = db.SetAdd("bikes:racing:france", new RedisValue[] { "bike:1" }); + long res2 = db.SetAdd("bikes:racing:france", ["bike:1"]); Console.WriteLine(res2); // >>> 0 - long res3 = db.SetAdd("bikes:racing:france", new RedisValue[] { "bike:2", "bike:3" }); + long res3 = db.SetAdd("bikes:racing:france", ["bike:2", "bike:3"]); Console.WriteLine(res3); // >>> 2 - long res4 = db.SetAdd("bikes:racing:usa", new RedisValue[] { "bike:1", "bike:4" }); + long res4 = db.SetAdd("bikes:racing:usa", ["bike:1", "bike:4"]); Console.WriteLine(res4); // >>> 2 // STEP_END @@ -79,10 +78,10 @@ public void run() // STEP_START sinter - long res7 = db.SetAdd("{bikes:racing}:france", new RedisValue[] { "bike:1", "bike:2", "bike:3" }); - long res8 = db.SetAdd("{bikes:racing}:usa", new RedisValue[] { "bike:1", "bike:4" }); + long res7 = db.SetAdd("{bikes:racing}:france", ["bike:1", "bike:2", "bike:3"]); + long res8 = db.SetAdd("{bikes:racing}:usa", ["bike:1", "bike:4"]); - RedisValue[] res9 = db.SetCombine(SetOperation.Intersect, new RedisKey[] { "{bikes:racing}:france", "{bikes:racing}:usa" }); + RedisValue[] res9 = db.SetCombine(SetOperation.Intersect, ["{bikes:racing}:france", "{bikes:racing}:usa"]); Console.WriteLine(string.Join(", ", res9)); // >>> bike:1 // STEP_END @@ -95,7 +94,7 @@ public void run() // STEP_START scard - long res10 = db.SetAdd("bikes:racing:france", new RedisValue[] { "bike:1", "bike:2", "bike:3" }); + long res10 = db.SetAdd("bikes:racing:france", ["bike:1", "bike:2", "bike:3"]); long res11 = db.SetLength("bikes:racing:france"); Console.WriteLine(res11); // >>> 3 // STEP_END @@ -108,7 +107,7 @@ public void run() // STEP_START sadd_smembers - long res12 = db.SetAdd("bikes:racing:france", new RedisValue[] { "bike:1", "bike:2", "bike:3" }); + long res12 = db.SetAdd("bikes:racing:france", ["bike:1", "bike:2", "bike:3"]); RedisValue[] res13 = db.SetMembers("bikes:racing:france"); Console.WriteLine(string.Join(", ", res13)); // >>> bike:3, bike:2, bike:1 // STEP_END @@ -123,7 +122,7 @@ public void run() bool res14 = db.SetContains("bikes:racing:france", "bike:1"); Console.WriteLine(res14); // >>> true - bool[] res15 = db.SetContains("bikes:racing:france", new RedisValue[] { "bike:2", "bike:3", "bike:4" }); + bool[] res15 = db.SetContains("bikes:racing:france", ["bike:2", "bike:3", "bike:4"]); Console.WriteLine(string.Join(", ", res15)); // >>> True, True, False // STEP_END @@ -135,9 +134,9 @@ public void run() // STEP_START sdiff - long res16 = db.SetAdd("{bikes:racing}:france", new RedisValue[] { "bike:1", "bike:2", "bike:3" }); - long res17 = db.SetAdd("{bikes:racing}:usa", new RedisValue[] { "bike:1", "bike:4" }); - RedisValue[] res18 = db.SetCombine(SetOperation.Difference, new RedisKey[] { "{bikes:racing}:france", "{bikes:racing}:usa" }); + long res16 = db.SetAdd("{bikes:racing}:france", ["bike:1", "bike:2", "bike:3"]); + long res17 = db.SetAdd("{bikes:racing}:usa", ["bike:1", "bike:4"]); + RedisValue[] res18 = db.SetCombine(SetOperation.Difference, ["{bikes:racing}:france", "{bikes:racing}:usa"]); Console.WriteLine(string.Join(", ", res18)); // >>> bike:2, bike:3 // STEP_END @@ -149,23 +148,26 @@ public void run() // STEP_START multisets - long res19 = db.SetAdd("{bikes:racing}:france", new RedisValue[] { "bike:1", "bike:2", "bike:3" }); - long res20 = db.SetAdd("{bikes:racing}:usa", new RedisValue[] { "bike:1", "bike:4" }); - long res21 = db.SetAdd("{bikes:racing}:italy", new RedisValue[] { "bike:1", "bike:2", "bike:3", "bike:4" }); + long res19 = db.SetAdd("{bikes:racing}:france", ["bike:1", "bike:2", "bike:3"]); + long res20 = db.SetAdd("{bikes:racing}:usa", ["bike:1", "bike:4"]); + long res21 = db.SetAdd("{bikes:racing}:italy", ["bike:1", "bike:2", "bike:3", "bike:4"]); - RedisValue[] res22 = db.SetCombine(SetOperation.Intersect, new RedisKey[] { "{bikes:racing}:france", "{bikes:racing}:usa", "{bikes:racing}:italy" }); + RedisValue[] res22 = db.SetCombine(SetOperation.Intersect, ["{bikes:racing}:france", "{bikes:racing}:usa", "{bikes:racing}:italy" + ]); Console.WriteLine(string.Join(", ", res22)); // >>> bike:1 - RedisValue[] res23 = db.SetCombine(SetOperation.Union, new RedisKey[] { "{bikes:racing}:france", "{bikes:racing}:usa", "{bikes:racing}:italy" }); + RedisValue[] res23 = db.SetCombine(SetOperation.Union, ["{bikes:racing}:france", "{bikes:racing}:usa", "{bikes:racing}:italy" + ]); Console.WriteLine(string.Join(", ", res23)); // >>> bike:1, bike:2, bike:3, bike:4 - RedisValue[] res24 = db.SetCombine(SetOperation.Difference, new RedisKey[] { "{bikes:racing}:france", "{bikes:racing}:usa", "{bikes:racing}:italy" }); + RedisValue[] res24 = db.SetCombine(SetOperation.Difference, ["{bikes:racing}:france", "{bikes:racing}:usa", "{bikes:racing}:italy" + ]); Console.WriteLine(string.Join(", ", res24)); // >>> - RedisValue[] res25 = db.SetCombine(SetOperation.Difference, new RedisKey[] { "{bikes:racing}:usa", "{bikes:racing}:france" }); + RedisValue[] res25 = db.SetCombine(SetOperation.Difference, ["{bikes:racing}:usa", "{bikes:racing}:france"]); Console.WriteLine(string.Join(", ", res25)); // >>> bike:4 - RedisValue[] res26 = db.SetCombine(SetOperation.Difference, new RedisKey[] { "{bikes:racing}:france", "{bikes:racing}:usa" }); + RedisValue[] res26 = db.SetCombine(SetOperation.Difference, ["{bikes:racing}:france", "{bikes:racing}:usa"]); Console.WriteLine(string.Join(", ", res26)); // >>> bike:2, bike:3 // STEP_END @@ -181,7 +183,7 @@ public void run() // STEP_START srem - long res27 = db.SetAdd("bikes:racing:france", new RedisValue[] { "bike:1", "bike:2", "bike:3", "bike:4", "bike:5" }); + long res27 = db.SetAdd("bikes:racing:france", ["bike:1", "bike:2", "bike:3", "bike:4", "bike:5"]); bool res28 = db.SetRemove("bikes:racing:france", "bike:1"); Console.WriteLine(res28); // >>> True diff --git a/tests/Doc/SortedSetExample.cs b/tests/Doc/SortedSetExample.cs index 320de270..6be0dcdf 100644 --- a/tests/Doc/SortedSetExample.cs +++ b/tests/Doc/SortedSetExample.cs @@ -19,7 +19,7 @@ public SortedSetExample(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -46,13 +46,13 @@ public void run() Assert.True(res2); //REMOVE_END - long res3 = db.SortedSetAdd("racer_scores", new[]{ - new SortedSetEntry("Sam-Bodden", 8), - new SortedSetEntry("Royce", 10), - new SortedSetEntry("Ford", 6), - new SortedSetEntry("Prickett", 14), - new SortedSetEntry("Castilla", 12) - }); + long res3 = db.SortedSetAdd("racer_scores", [ + new("Sam-Bodden", 8), + new("Royce", 10), + new("Ford", 6), + new("Prickett", 14), + new("Castilla", 12) + ]); Console.WriteLine(res3); // >>> 4 //REMOVE_START Assert.Equal(4, res3); @@ -133,14 +133,14 @@ public void run() //STEP_END //STEP_START zadd_lex - long res13 = db.SortedSetAdd("racer_scores", new[] { - new SortedSetEntry("Norem", 0), - new SortedSetEntry("Sam-Bodden", 0), - new SortedSetEntry("Royce", 0), - new SortedSetEntry("Ford", 0), - new SortedSetEntry("Prickett", 0), - new SortedSetEntry("Castilla", 0) - }); + long res13 = db.SortedSetAdd("racer_scores", [ + new("Norem", 0), + new("Sam-Bodden", 0), + new("Royce", 0), + new("Ford", 0), + new("Prickett", 0), + new("Castilla", 0) + ]); Console.WriteLine(res13); // >>> 3 //REMOVE_START Assert.Equal(3, res13); diff --git a/tests/Doc/StreamTutorial.cs b/tests/Doc/StreamTutorial.cs index 73703d15..902fff5a 100644 --- a/tests/Doc/StreamTutorial.cs +++ b/tests/Doc/StreamTutorial.cs @@ -1,7 +1,6 @@ // EXAMPLE: stream_tutorial // HIDE_START -using System.Runtime.CompilerServices; using NRedisStack.Tests; using StackExchange.Redis; @@ -23,7 +22,7 @@ public StreamTutorial(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -43,34 +42,34 @@ public void run() // STEP_START xadd RedisValue res1 = db.StreamAdd( "race:france", - new NameValueEntry[] { - new NameValueEntry("rider", "Castilla"), - new NameValueEntry("speed", 30.2), - new NameValueEntry("position", 1), - new NameValueEntry("location_id", 1) - } + [ + new("rider", "Castilla"), + new("speed", 30.2), + new("position", 1), + new("location_id", 1) + ] ); Console.WriteLine(res1); // >>> 1712668482289-0 RedisValue res2 = db.StreamAdd( "race:france", - new NameValueEntry[] { - new NameValueEntry("rider", "Norem"), - new NameValueEntry("speed", 28.8), - new NameValueEntry("position", 3), - new NameValueEntry("location_id", 1) - } + [ + new("rider", "Norem"), + new("speed", 28.8), + new("position", 3), + new("location_id", 1) + ] ); Console.WriteLine(res2); // >>> 1712668766534-1 RedisValue res3 = db.StreamAdd( "race:france", - new NameValueEntry[]{ - new NameValueEntry("rider", "Prickett"), - new NameValueEntry("speed", 29.7), - new NameValueEntry("position", 2), - new NameValueEntry("location_id", 1) - } + [ + new("rider", "Prickett"), + new("speed", 29.7), + new("position", 2), + new("location_id", 1) + ] ); Console.WriteLine(res3); // >>> 1712669055705-0 @@ -122,12 +121,12 @@ public void run() // STEP_START xadd_2 RedisValue res6 = db.StreamAdd( "race:france", - new NameValueEntry[]{ - new NameValueEntry("rider", "Castilla"), - new NameValueEntry("speed", 29.9), - new NameValueEntry("position", 1), - new NameValueEntry("location_id", 2) - } + [ + new("rider", "Castilla"), + new("speed", 29.9), + new("position", 1), + new("location_id", 2) + ] ); Console.WriteLine(res6); // >>> 1712675674750-0 @@ -153,18 +152,18 @@ public void run() // STEP_START xadd_id RedisValue res8 = db.StreamAdd( "race:usa", - new NameValueEntry[] { - new NameValueEntry("racer", "Castilla") - }, + [ + new("racer", "Castilla") + ], "0-1" ); Console.WriteLine(res8); // >>> 0-1 RedisValue res9 = db.StreamAdd( "race:usa", - new NameValueEntry[]{ - new NameValueEntry("racer", "Norem") - }, + [ + new("racer", "Norem") + ], "0-2" ); Console.WriteLine(res9); // >>> 0-2 @@ -181,9 +180,9 @@ public void run() { RedisValue res10 = db.StreamAdd( "race:usa", - new NameValueEntry[]{ - new NameValueEntry("racer", "Prickett") - }, + [ + new("racer", "Prickett") + ], "0-1" ); } @@ -206,9 +205,9 @@ public void run() { res11 = db.StreamAdd( "race:usa", - new NameValueEntry[]{ - new NameValueEntry("rider", "Norem") - }, + [ + new("rider", "Norem") + ], "0-*" ); @@ -368,27 +367,27 @@ public void run() // STEP_START xgroup_read RedisValue groupRes = db.StreamAdd( "race:italy", - new NameValueEntry[] { new NameValueEntry("rider", "Castilla") } + [new("rider", "Castilla")] ); // 1712744323758-0 groupRes = db.StreamAdd( "race:italy", - new NameValueEntry[] { new NameValueEntry("rider", "Royce") } + [new("rider", "Royce")] ); // 1712744358384-0 groupRes = db.StreamAdd( "race:italy", - new NameValueEntry[] { new NameValueEntry("rider", "Sam-Bodden") } + [new("rider", "Sam-Bodden")] ); // 1712744379676-0 groupRes = db.StreamAdd( "race:italy", - new NameValueEntry[] { new NameValueEntry("rider", "Prickett") } + [new("rider", "Prickett")] ); // 1712744399401-0 groupRes = db.StreamAdd( "race:italy", - new NameValueEntry[] { new NameValueEntry("rider", "Norem") } + [new("rider", "Norem")] ); // 1712744413117-0 StreamEntry[] res21 = db.StreamReadGroup("race:italy", "italy_riders", "Alice", ">", 1); @@ -507,7 +506,7 @@ public void run() // STEP_START xclaim StreamEntry[] res29 = db.StreamClaim( - "race:italy", "italy_riders", "Alice", 60000, new RedisValue[] { 1712744358384 - 0 } + "race:italy", "italy_riders", "Alice", 60000, [1712744358384 - 0] ); foreach (StreamEntry entry in res29) @@ -599,15 +598,15 @@ public void run() // STEP_START maxlen db.StreamAdd( - "race:italy", new NameValueEntry[] { new NameValueEntry("rider", "Jones") }, null, 2, true + "race:italy", [new("rider", "Jones")], null, 2, true ); db.StreamAdd( - "race:italy", new NameValueEntry[] { new NameValueEntry("rider", "Wood") }, null, 2, true + "race:italy", [new("rider", "Wood")], null, 2, true ); db.StreamAdd( - "race:italy", new NameValueEntry[] { new NameValueEntry("rider", "Henshaw") }, null, 2, true + "race:italy", [new("rider", "Henshaw")], null, 2, true ); long res35 = db.StreamLength("race:italy"); @@ -629,7 +628,7 @@ public void run() // >>> 1712758342134-0: [rider: Henshaw] db.StreamAdd( - "race:italy", new NameValueEntry[] { new NameValueEntry("rider", "Smith") }, null, 2, false + "race:italy", [new("rider", "Smith")], null, 2, false ); StreamEntry[] res37 = db.StreamRange("race:italy", "-", "+"); @@ -680,7 +679,7 @@ public void run() // >>> 1712759694003-0: [rider: Henshaw] // >>> 1712759694003-1: [rider: Smith] - long res41 = db.StreamDelete("race:italy", new RedisValue[] { "1712759694003-1" }); + long res41 = db.StreamDelete("race:italy", ["1712759694003-1"]); Console.WriteLine(res41); // >>> 1 StreamEntry[] res42 = db.StreamRange("race:italy", "-", "+"); diff --git a/tests/Doc/StringSnippets.cs b/tests/Doc/StringSnippets.cs index be76d7f3..7812ff32 100644 --- a/tests/Doc/StringSnippets.cs +++ b/tests/Doc/StringSnippets.cs @@ -19,7 +19,7 @@ public StringSnippets(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -32,7 +32,7 @@ public void run() //HIDE_END //REMOVE_START - db.KeyDelete(new RedisKey[] { "bike:1", "bike:2", "bike:3", "total_crashes" }); + db.KeyDelete(["bike:1", "bike:2", "bike:3", "total_crashes"]); //REMOVE_END // STEP_START set_get @@ -61,12 +61,11 @@ public void run() //REMOVE_END //STEP_START mset - var res5 = db.StringSet(new KeyValuePair[] - { + var res5 = db.StringSet([ new ("bike:1", "Deimos"), new("bike:2", "Ares"), new("bike:3", "Vanth") - }); + ]); Console.WriteLine(res5); - var res6 = db.StringGet(new RedisKey[] { "bike:1", "bike:2", "bike:3" }); + var res6 = db.StringGet(["bike:1", "bike:2", "bike:3"]); Console.WriteLine(res6); //STEP_END diff --git a/tests/Doc/Tdigest_tutorial.cs b/tests/Doc/Tdigest_tutorial.cs index 216c82a0..d8deb091 100644 --- a/tests/Doc/Tdigest_tutorial.cs +++ b/tests/Doc/Tdigest_tutorial.cs @@ -13,17 +13,17 @@ namespace Doc; // REMOVE_END // HIDE_START -public class Tdigest_tutorial +public class TdigestTutorial // REMOVE_START : AbstractNRedisStackTest, IDisposable // REMOVE_END { // REMOVE_START - public Tdigest_tutorial(EndpointsFixture fixture) : base(fixture) { } + public TdigestTutorial(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection diff --git a/tests/Doc/TimeSeriesTutorial.cs b/tests/Doc/TimeSeriesTutorial.cs index 8422884d..a82bc948 100644 --- a/tests/Doc/TimeSeriesTutorial.cs +++ b/tests/Doc/TimeSeriesTutorial.cs @@ -28,7 +28,7 @@ public TimeSeriesTutorial(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { // REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection @@ -42,13 +42,13 @@ public void run() // REMOVE_START // Clear any keys here before using them in tests. - db.KeyDelete(new RedisKey[] { + db.KeyDelete([ "thermometer:1", "thermometer:2", "thermometer:3", "rg:1", "rg:2", "rg:3", "rg:4", "sensor3", "wind:1", "wind:2", "wind:3", "wind:4", "hyg:1", "hyg:compacted" - }); + ]); // REMOVE_END // STEP_START create @@ -93,8 +93,8 @@ public void run() // STEP_START create_labels var labels = new List { - new TimeSeriesLabel("location", "UK"), - new TimeSeriesLabel("type", "Mercury") + new("location", "UK"), + new("type", "Mercury") }; long res6 = db.TS().Add( "thermometer:3", @@ -261,8 +261,8 @@ public void run() // data points. var labels2 = new List { - new TimeSeriesLabel("location", "us"), - new TimeSeriesLabel("unit", "cm") + new("location", "us"), + new("unit", "cm") }; bool res20 = db.TS().Create( "rg:2", @@ -274,8 +274,8 @@ public void run() var labels3 = new List { - new TimeSeriesLabel("location", "us"), - new TimeSeriesLabel("unit", "in") + new("location", "us"), + new("unit", "in") }; bool res21 = db.TS().Create( @@ -288,8 +288,8 @@ public void run() var labels4 = new List { - new TimeSeriesLabel("location", "uk"), - new TimeSeriesLabel("unit", "mm") + new("location", "uk"), + new("unit", "mm") }; bool res22 = db.TS().Create( "rg:4", @@ -369,7 +369,7 @@ public void run() var res28 = db.TS().MGet(filters); Console.WriteLine(res28.Count); // >>> 2 - foreach (var (key, labels_result, value) in res28) + foreach (var (key, labelsResult, value) in res28) { Console.WriteLine($"{key}: ({value.Time.Value}, {value.Val})"); } @@ -386,9 +386,9 @@ public void run() ); Console.WriteLine(res29.Count); // >>> 2 - foreach (var (key, labels_result, value) in res29) + foreach (var (key, labelsResult, value) in res29) { - var unitLabel = labels_result.FirstOrDefault(l => l.Key == "unit"); + var unitLabel = labelsResult.FirstOrDefault(l => l.Key == "unit"); Console.WriteLine($"{key} (unit: {unitLabel?.Value}): ({value.Time.Value}, {value.Val})"); } // >>> rg:2 (unit: cm): (4, 1.78) @@ -406,10 +406,10 @@ public void run() ); Console.WriteLine(res30.Count); // >>> 1 - foreach (var (key, labels_result, values) in res30) + foreach (var (key, labelsResult, values) in res30) { Console.WriteLine($"{key}:"); - Console.WriteLine($" Labels: ({string.Join(", ", labels_result.Select(l => $"{l.Key}={l.Value}"))})"); + Console.WriteLine($" Labels: ({string.Join(", ", labelsResult.Select(l => $"{l.Key}={l.Value}"))})"); Console.WriteLine($" Values: [{string.Join(", ", values.Select(t => $"({t.Time.Value}, {t.Val})"))}]"); } // >>> rg:4: @@ -429,9 +429,9 @@ public void run() ); Console.WriteLine(res31.Count); // >>> 2 - foreach (var (key, labels_result, values) in res31) + foreach (var (key, labelsResult, values) in res31) { - var locationLabel = labels_result.FirstOrDefault(l => l.Key == "location"); + var locationLabel = labelsResult.FirstOrDefault(l => l.Key == "location"); Console.WriteLine($"{key} (location: {locationLabel?.Value})"); Console.WriteLine($" Values: [{string.Join(", ", values.Select(t => $"({t.Time.Value}, {t.Val})"))}]"); } @@ -521,7 +521,7 @@ public void run() // REMOVE_END // STEP_START agg_multi - var ukLabels = new List { new TimeSeriesLabel("country", "uk") }; + var ukLabels = new List { new("country", "uk") }; bool res37 = db.TS().Create( "wind:1", @@ -539,7 +539,7 @@ public void run() ); Console.WriteLine(res38); // >>> True - var usLabels = new List { new TimeSeriesLabel("country", "us") }; + var usLabels = new List { new("country", "us") }; bool res39 = db.TS().Create( "wind:3", new TsCreateParamsBuilder() @@ -607,7 +607,7 @@ public void run() ); Console.WriteLine(res44.Count); // >>> 2 - foreach (var (key, labels_result, values) in res44) + foreach (var (key, labelsResult, values) in res44) { Console.WriteLine($"{key}:"); Console.WriteLine($" Values: [{string.Join(", ", values.Select(t => $"({t.Time.Value}, {t.Val})"))}]"); @@ -628,7 +628,7 @@ public void run() ); Console.WriteLine(res45.Count); // >>> 2 - foreach (var (key, labels_result, values) in res45) + foreach (var (key, labelsResult, values) in res45) { Console.WriteLine($"{key}:"); Console.WriteLine($" Values: [{string.Join(", ", values.Select(t => $"({t.Time.Value}, {t.Val})"))}]"); diff --git a/tests/Doc/Topk_tutorial.cs b/tests/Doc/Topk_tutorial.cs index 8f7304f9..5004bda4 100644 --- a/tests/Doc/Topk_tutorial.cs +++ b/tests/Doc/Topk_tutorial.cs @@ -13,17 +13,16 @@ namespace Doc; // REMOVE_END // HIDE_START -public class Topk_tutorial +public class TopkTutorial // REMOVE_START -: AbstractNRedisStackTest, IDisposable + (EndpointsFixture fixture) : AbstractNRedisStackTest(fixture), IDisposable // REMOVE_END { // REMOVE_START - public Topk_tutorial(EndpointsFixture fixture) : base(fixture) { } [SkippableFact] // REMOVE_END - public void run() + public void Run() { //REMOVE_START // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection diff --git a/tests/NRedisStack.Tests/AbstractNRedisStackTest.cs b/tests/NRedisStack.Tests/AbstractNRedisStackTest.cs index 77ec122c..0b385074 100644 --- a/tests/NRedisStack.Tests/AbstractNRedisStackTest.cs +++ b/tests/NRedisStack.Tests/AbstractNRedisStackTest.cs @@ -18,10 +18,10 @@ public abstract class AbstractNRedisStackTest : IClassFixture, protected internal AbstractNRedisStackTest(EndpointsFixture endpointsFixture) { - this.EndpointsFixture = endpointsFixture; + EndpointsFixture = endpointsFixture; } - protected ConnectionMultiplexer GetConnection(string endpointId = EndpointsFixture.Env.Standalone) => EndpointsFixture.GetConnectionById(this.DefaultConnectionConfig, endpointId); + protected ConnectionMultiplexer GetConnection(string endpointId = EndpointsFixture.Env.Standalone) => EndpointsFixture.GetConnectionById(DefaultConnectionConfig, endpointId); protected ConnectionMultiplexer GetConnection(ConfigurationOptions configurationOptions, string endpointId = EndpointsFixture.Env.Standalone) => EndpointsFixture.GetConnectionById(configurationOptions, endpointId); @@ -58,7 +58,7 @@ protected void SkipIfTargetConnectionDoesNotExist(string id) Skip.IfNot(EndpointsFixture.IsTargetConnectionExist(id), $"The connection with id '{id}' is not configured."); } - private List keyNames = new List(); + private List keyNames = []; protected internal string CreateKeyName([CallerMemberName] string memberName = "") => CreateKeyNames(1, memberName)[0]; @@ -95,10 +95,10 @@ public void Dispose() //Redis.GetDatabase().ExecuteBroadcast("FLUSHALL"); } - public async Task DisposeAsync() - { - //var redis = Redis.GetDatabase(); - // await redis.KeyDeleteAsync(keyNames.Select(i => (RedisKey)i).ToArray()); - //await redis.ExecuteBroadcastAsync("FLUSHALL"); - } + public Task DisposeAsync() => Task.CompletedTask; + /*{ + var redis = Redis.GetDatabase(); + await redis.KeyDeleteAsync(keyNames.Select(i => (RedisKey)i).ToArray()); + await redis.ExecuteBroadcastAsync("FLUSHALL"); + }*/ } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/Bloom/BloomTests.cs b/tests/NRedisStack.Tests/Bloom/BloomTests.cs index 9f5c3380..52e77df8 100644 --- a/tests/NRedisStack.Tests/Bloom/BloomTests.cs +++ b/tests/NRedisStack.Tests/Bloom/BloomTests.cs @@ -94,10 +94,10 @@ public void TestAddExistsMulti(string endpointId) var items2 = new RedisValue[] { "newElement", "bar", "baz" }; var result = bf.MAdd(key, items); - Assert.Equal(new bool[] { true, true, true }, result); + Assert.Equal(new[] { true, true, true }, result); result = bf.MAdd(key, items2); - Assert.Equal(new bool[] { true, false, false }, result); + Assert.Equal(new[] { true, false, false }, result); } [SkippableTheory] @@ -110,10 +110,10 @@ public async Task TestAddExistsMultiAsync(string endpointId) var items2 = new RedisValue[] { "newElement", "bar", "baz" }; var result = await bf.MAddAsync(key, items); - Assert.Equal(new bool[] { true, true, true }, result); + Assert.Equal(new[] { true, true, true }, result); result = await bf.MAddAsync(key, items2); - Assert.Equal(new bool[] { true, false, false }, result); + Assert.Equal(new[] { true, false, false }, result); } [SkippableTheory] @@ -138,7 +138,7 @@ public void TestExample(string endpointId) var allItems = new RedisValue[] { "foo", "bar", "baz", "bat", "Mark", "nonexist" }; var rv = bf.MExists("simpleBloom", allItems); // All items except the last one will be 'true' - Assert.Equal(new bool[] { true, true, true, true, true, false }, rv); + Assert.Equal(new[] { true, true, true, true, true, false }, rv); // Reserve a "customized" bloom filter bf.Reserve("specialBloom", 0.0001, 10000); @@ -167,7 +167,7 @@ public async Task TestExampleAsync(string endpointId) var allItems = new RedisValue[] { "foo", "bar", "baz", "bat", "Mark", "nonexist" }; var rv = await bf.MExistsAsync("simpleBloom", allItems); // All items except the last one will be 'true' - Assert.Equal(new bool[] { true, true, true, true, true, false }, rv); + Assert.Equal(new[] { true, true, true, true, true, false }, rv); // Reserve a "customized" bloom filter await bf.ReserveAsync("specialBloom", 0.0001, 10000); @@ -181,7 +181,7 @@ public void TestInsert(string endpointId) IDatabase db = GetCleanDatabase(endpointId); var bf = db.BF(); - RedisValue[] items = new RedisValue[] { "item1", "item2", "item3" }; + RedisValue[] items = ["item1", "item2", "item3"]; bf.Insert("key", items); @@ -197,7 +197,7 @@ public async Task TestInsertAsync(string endpointId) IDatabase db = GetCleanDatabase(endpointId); var bf = db.BF(); - RedisValue[] items = new RedisValue[] { "item1", "item2", "item3" }; + RedisValue[] items = ["item1", "item2", "item3"]; await bf.InsertAsync("key", items); @@ -213,7 +213,7 @@ public void TestExistsNonExist(string endpointId) IDatabase db = GetCleanDatabase(endpointId); var bf = db.BF(); - RedisValue item = new RedisValue("item"); + RedisValue item = new("item"); Assert.False(bf.Exists("NonExistKey", item)); } @@ -224,7 +224,7 @@ public async Task TestExistsNonExistAsync(string endpointId) IDatabase db = GetCleanDatabase(endpointId); var bf = db.BF(); - RedisValue item = new RedisValue("item"); + RedisValue item = new("item"); Assert.False(await bf.ExistsAsync("NonExistKey", item)); } @@ -369,7 +369,7 @@ public void TestInsertArgsError(string endpointId) IDatabase db = GetCleanDatabase(endpointId); var bf = db.BF(); - RedisValue[] items = new RedisValue[] { "item1", "item2", "item3" }; + RedisValue[] items = ["item1", "item2", "item3"]; // supose to throw exception: Assert.Throws(() => bf.Insert("key3", items, 100, 0.01, 2, nocreate: true, nonscaling: true)); } diff --git a/tests/NRedisStack.Tests/CommunityEditionUpdatesTests.cs b/tests/NRedisStack.Tests/CommunityEditionUpdatesTests.cs index 3d4dd0ab..672bbf9f 100644 --- a/tests/NRedisStack.Tests/CommunityEditionUpdatesTests.cs +++ b/tests/NRedisStack.Tests/CommunityEditionUpdatesTests.cs @@ -17,7 +17,7 @@ private IServer getAnyPrimary(IConnectionMultiplexer muxer) throw new InvalidOperationException("Requires a primary endpoint (found none)"); } - [SkipIfRedis(Comparison.LessThan, "7.9.0")] + [SkipIfRedisTheory(Comparison.LessThan, "7.9.0")] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] public void ConfigSearchSettings(string endpointId) { @@ -46,7 +46,7 @@ public void ConfigSearchSettings(string endpointId) Assert.Single(server.ConfigGet("search-default-dialect")); } - [SkipIfRedis(Comparison.LessThan, "7.9.0")] + [SkipIfRedisTheory(Comparison.LessThan, "7.9.0")] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] public void ConfigTimeSeriesSettings(string endpointId) { @@ -69,7 +69,7 @@ public void ConfigTimeSeriesSettings(string endpointId) Assert.Single(server.ConfigGet("ts-ignore-max-val-diff")); } - [SkipIfRedis(Comparison.LessThan, "7.9.0")] + [SkipIfRedisTheory(Comparison.LessThan, "7.9.0")] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] public void ConfigProbabilisticSettings(string endpointId) { @@ -98,7 +98,7 @@ public void ConfigProbabilisticSettings(string endpointId) Assert.Single(server.ConfigGet("cf-max-iterations")); } - [SkipIfRedis(Comparison.LessThan, "7.9.0")] + [SkipIfRedisTheory(Comparison.LessThan, "7.9.0")] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] public void InfoSearchSection(string endpointId) { diff --git a/tests/NRedisStack.Tests/Core Commands/CoreTests.cs b/tests/NRedisStack.Tests/Core Commands/CoreTests.cs index 61b8ec41..a9ec0995 100644 --- a/tests/NRedisStack.Tests/Core Commands/CoreTests.cs +++ b/tests/NRedisStack.Tests/Core Commands/CoreTests.cs @@ -8,14 +8,10 @@ namespace NRedisStack.Tests.Core; -public class CoreTests : AbstractNRedisStackTest, IDisposable +public class CoreTests(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable { - public CoreTests(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } - // TODO: understand why this test fails on enterprise - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.1.242")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.1.242")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestSimpleSetInfo(string endpointId) { @@ -28,7 +24,7 @@ public void TestSimpleSetInfo(string endpointId) Assert.Contains($"lib-name=TestLibraryName lib-ver=1.2.3", info); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.1.242")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.1.242")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestSimpleSetInfoAsync(string endpointId) { @@ -41,7 +37,7 @@ public async Task TestSimpleSetInfoAsync(string endpointId) Assert.Contains($"lib-name=TestLibraryName lib-ver=1.2.3", info); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.1.242")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.1.242")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestSetInfoDefaultValue(string endpointId) { @@ -54,7 +50,7 @@ public void TestSetInfoDefaultValue(string endpointId) Assert.Contains($"lib-name=NRedisStack(.NET_v{Environment.Version}) lib-ver={GetNRedisStackVersion()}", info); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.1.242")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.1.242")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestSetInfoDefaultValueAsync(string endpointId) { @@ -67,7 +63,7 @@ public async Task TestSetInfoDefaultValueAsync(string endpointId) Assert.Contains($"lib-name=NRedisStack(.NET_v{Environment.Version}) lib-ver={GetNRedisStackVersion()}", info); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.1.242")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.1.242")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestSetInfoWithValue(string endpointId) { @@ -80,7 +76,7 @@ public void TestSetInfoWithValue(string endpointId) Assert.Contains($"NRedisStack(MyLibraryName;v1.0.0;.NET_v{Environment.Version}) lib-ver={GetNRedisStackVersion()}", info); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.1.242")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.1.242")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestSetInfoWithValueAsync(string endpointId) { @@ -93,7 +89,7 @@ public async Task TestSetInfoWithValueAsync(string endpointId) Assert.Contains($"NRedisStack(MyLibraryName;v1.0.0;.NET_v{Environment.Version}) lib-ver={GetNRedisStackVersion()}", info); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.1.242")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.1.242")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestSetInfoNull(string endpointId) { @@ -105,8 +101,8 @@ public void TestSetInfoNull(string endpointId) var infoAfter = db.Execute("CLIENT", "INFO").ToString(); // Find the indices of "lib-name=" in the strings - int infoAfterLibNameIndex = infoAfter!.IndexOf("lib-name="); - int infoBeforeLibNameIndex = infoBefore!.IndexOf("lib-name="); + int infoAfterLibNameIndex = infoAfter.IndexOf("lib-name="); + int infoBeforeLibNameIndex = infoBefore.IndexOf("lib-name="); // Extract the sub-strings starting from "lib-name=" string infoAfterLibNameToEnd = infoAfter.Substring(infoAfterLibNameIndex); @@ -116,7 +112,7 @@ public void TestSetInfoNull(string endpointId) Assert.Equal(infoAfterLibNameToEnd, infoBeforeLibNameToEnd); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.1.242")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.1.242")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestSetInfoNullAsync(string endpointId) { @@ -128,8 +124,8 @@ public async Task TestSetInfoNullAsync(string endpointId) var infoAfter = (await db.ExecuteAsync("CLIENT", "INFO")).ToString(); // Find the indices of "lib-name=" in the strings - int infoAfterLibNameIndex = infoAfter!.IndexOf("lib-name="); - int infoBeforeLibNameIndex = infoBefore!.IndexOf("lib-name="); + int infoAfterLibNameIndex = infoAfter.IndexOf("lib-name="); + int infoBeforeLibNameIndex = infoBefore.IndexOf("lib-name="); // Extract the sub-strings starting from "lib-name=" string infoAfterLibNameToEnd = infoAfter.Substring(infoAfterLibNameIndex); @@ -139,7 +135,7 @@ public async Task TestSetInfoNullAsync(string endpointId) Assert.Equal(infoAfterLibNameToEnd, infoBeforeLibNameToEnd); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBZMPop(string endpointId) { @@ -157,7 +153,7 @@ public void TestBZMPop(string endpointId) var resultWithDefaultOrder = db.BZMPop(0, sortedSetKey, MinMaxModifier.Min, 2); Assert.NotNull(resultWithDefaultOrder); - Assert.Equal(sortedSetKey, resultWithDefaultOrder!.Item1); + Assert.Equal(sortedSetKey, resultWithDefaultOrder.Item1); Assert.Equal(2, resultWithDefaultOrder.Item2.Count); Assert.Equal("a", resultWithDefaultOrder.Item2[0].Value.ToString()); Assert.Equal("c", resultWithDefaultOrder.Item2[1].Value.ToString()); @@ -166,12 +162,12 @@ public void TestBZMPop(string endpointId) var resultWithDescendingOrder = db.BZMPop(0, sortedSetKey, MinMaxModifier.Max, 1); Assert.NotNull(resultWithDescendingOrder); - Assert.Equal(sortedSetKey, resultWithDescendingOrder!.Item1); + Assert.Equal(sortedSetKey, resultWithDescendingOrder.Item1); Assert.Single(resultWithDescendingOrder.Item2); Assert.Equal("d", resultWithDescendingOrder.Item2[0].Value.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBZMPopAsync(string endpointId) { @@ -189,7 +185,7 @@ public async Task TestBZMPopAsync(string endpointId) var resultWithDefaultOrder = await db.BZMPopAsync(0, sortedSetKey, MinMaxModifier.Min, 2); Assert.NotNull(resultWithDefaultOrder); - Assert.Equal(sortedSetKey, resultWithDefaultOrder!.Item1); + Assert.Equal(sortedSetKey, resultWithDefaultOrder.Item1); Assert.Equal(2, resultWithDefaultOrder.Item2.Count); Assert.Equal("a", resultWithDefaultOrder.Item2[0].Value.ToString()); Assert.Equal("c", resultWithDefaultOrder.Item2[1].Value.ToString()); @@ -198,12 +194,12 @@ public async Task TestBZMPopAsync(string endpointId) var resultWithDescendingOrder = await db.BZMPopAsync(0, sortedSetKey, MinMaxModifier.Max, 1); Assert.NotNull(resultWithDescendingOrder); - Assert.Equal(sortedSetKey, resultWithDescendingOrder!.Item1); + Assert.Equal(sortedSetKey, resultWithDescendingOrder.Item1); Assert.Single(resultWithDescendingOrder.Item2); Assert.Equal("d", resultWithDescendingOrder.Item2[0].Value.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBZMPopNull(string endpointId) { @@ -215,7 +211,7 @@ public void TestBZMPopNull(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBZMPopNullAsync(string endpointId) { @@ -227,7 +223,7 @@ public async Task TestBZMPopNullAsync(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBZMPopMultiplexerTimeout(string endpointId) { @@ -243,7 +239,7 @@ public void TestBZMPopMultiplexerTimeout(string endpointId) Assert.Throws(() => db.BZMPop(0, "my-set", MinMaxModifier.Min)); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBZMPopMultiplexerTimeoutAsync(string endpointId) { @@ -259,7 +255,7 @@ public async Task TestBZMPopMultiplexerTimeoutAsync(string endpointId) await Assert.ThrowsAsync(async () => await db.BZMPopAsync(0, "my-set", MinMaxModifier.Min)); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBZMPopMultipleSets(string endpointId) { @@ -274,34 +270,34 @@ public void TestBZMPopMultipleSets(string endpointId) var result = db.BZMPop(0, "set-two", MinMaxModifier.Max); Assert.NotNull(result); - Assert.Equal("set-two", result!.Item1); + Assert.Equal("set-two", result.Item1); Assert.Single(result.Item2); Assert.Equal("d", result.Item2[0].Value.ToString()); - result = db.BZMPop(0, new[] { new RedisKey("set-two"), new RedisKey("set-one") }, MinMaxModifier.Min); + result = db.BZMPop(0, [new("set-two"), new("set-one")], MinMaxModifier.Min); Assert.NotNull(result); - Assert.Equal("set-two", result!.Item1); + Assert.Equal("set-two", result.Item1); Assert.Single(result.Item2); Assert.Equal("e", result.Item2[0].Value.ToString()); - result = db.BZMPop(0, new[] { new RedisKey("set-two"), new RedisKey("set-one") }, MinMaxModifier.Max); + result = db.BZMPop(0, [new("set-two"), new("set-one")], MinMaxModifier.Max); Assert.NotNull(result); - Assert.Equal("set-one", result!.Item1); + Assert.Equal("set-one", result.Item1); Assert.Single(result.Item2); Assert.Equal("b", result.Item2[0].Value.ToString()); result = db.BZMPop(0, "set-one", MinMaxModifier.Min, count: 2); Assert.NotNull(result); - Assert.Equal("set-one", result!.Item1); + Assert.Equal("set-one", result.Item1); Assert.Equal(2, result.Item2.Count); Assert.Equal("a", result.Item2[0].Value.ToString()); Assert.Equal("c", result.Item2[1].Value.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBZMPopMultipleSetsAsync(string endpointId) { @@ -316,43 +312,43 @@ public async Task TestBZMPopMultipleSetsAsync(string endpointId) var result = await db.BZMPopAsync(0, "set-two", MinMaxModifier.Max); Assert.NotNull(result); - Assert.Equal("set-two", result!.Item1); + Assert.Equal("set-two", result.Item1); Assert.Single(result.Item2); Assert.Equal("d", result.Item2[0].Value.ToString()); - result = await db.BZMPopAsync(0, new[] { new RedisKey("set-two"), new RedisKey("set-one") }, MinMaxModifier.Min); + result = await db.BZMPopAsync(0, [new("set-two"), new("set-one")], MinMaxModifier.Min); Assert.NotNull(result); - Assert.Equal("set-two", result!.Item1); + Assert.Equal("set-two", result.Item1); Assert.Single(result.Item2); Assert.Equal("e", result.Item2[0].Value.ToString()); - result = await db.BZMPopAsync(0, new[] { new RedisKey("set-two"), new RedisKey("set-one") }, MinMaxModifier.Max); + result = await db.BZMPopAsync(0, [new("set-two"), new("set-one")], MinMaxModifier.Max); Assert.NotNull(result); - Assert.Equal("set-one", result!.Item1); + Assert.Equal("set-one", result.Item1); Assert.Single(result.Item2); Assert.Equal("b", result.Item2[0].Value.ToString()); result = await db.BZMPopAsync(0, "set-one", MinMaxModifier.Min, count: 2); Assert.NotNull(result); - Assert.Equal("set-one", result!.Item1); + Assert.Equal("set-one", result.Item1); Assert.Equal(2, result.Item2.Count); Assert.Equal("a", result.Item2[0].Value.ToString()); Assert.Equal("c", result.Item2[1].Value.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBZMPopNoKeysProvided(string endpointId) { var db = GetCleanDatabase(endpointId); - Assert.Throws(() => db.BZMPop(0, Array.Empty(), MinMaxModifier.Min)); + Assert.Throws(() => db.BZMPop(0, [], MinMaxModifier.Min)); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBZMPopWithOrderEnum(string endpointId) { @@ -368,7 +364,7 @@ public void TestBZMPopWithOrderEnum(string endpointId) var resultWithDefaultOrder = db.BZMPop(0, sortedSetKey, Order.Ascending.ToMinMax()); Assert.NotNull(resultWithDefaultOrder); - Assert.Equal(sortedSetKey, resultWithDefaultOrder!.Item1); + Assert.Equal(sortedSetKey, resultWithDefaultOrder.Item1); Assert.Single(resultWithDefaultOrder.Item2); Assert.Equal("a", resultWithDefaultOrder.Item2[0].Value.ToString()); @@ -376,12 +372,12 @@ public void TestBZMPopWithOrderEnum(string endpointId) var resultWithDescendingOrder = db.BZMPop(0, sortedSetKey, Order.Descending.ToMinMax()); Assert.NotNull(resultWithDescendingOrder); - Assert.Equal(sortedSetKey, resultWithDescendingOrder!.Item1); + Assert.Equal(sortedSetKey, resultWithDescendingOrder.Item1); Assert.Single(resultWithDescendingOrder.Item2); Assert.Equal("b", resultWithDescendingOrder.Item2[0].Value.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBZPopMin(string endpointId) { @@ -395,12 +391,12 @@ public void TestBZPopMin(string endpointId) var result = db.BZPopMin(sortedSetKey, 0); Assert.NotNull(result); - Assert.Equal(sortedSetKey, result!.Item1); + Assert.Equal(sortedSetKey, result.Item1); Assert.Equal("a", result.Item2.Value.ToString()); Assert.Equal(1.5, result.Item2.Score); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBZPopMinAsync(string endpointId) { @@ -414,12 +410,12 @@ public async Task TestBZPopMinAsync(string endpointId) var result = await db.BZPopMinAsync(sortedSetKey, 0); Assert.NotNull(result); - Assert.Equal(sortedSetKey, result!.Item1); + Assert.Equal(sortedSetKey, result.Item1); Assert.Equal("a", result.Item2.Value.ToString()); Assert.Equal(1.5, result.Item2.Score); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBZPopMinNull(string endpointId) { @@ -431,7 +427,7 @@ public void TestBZPopMinNull(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBZPopMinNullAsync(string endpointId) { @@ -443,7 +439,7 @@ public async Task TestBZPopMinNullAsync(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBZPopMinMultipleSets(string endpointId) { @@ -453,20 +449,20 @@ public void TestBZPopMinMultipleSets(string endpointId) db.SortedSetAdd("set-one", "b", 5.1); db.SortedSetAdd("set-two", "e", 7.76); - var result = db.BZPopMin(new[] { new RedisKey("set-two"), new RedisKey("set-one") }, 0); + var result = db.BZPopMin([new("set-two"), new("set-one")], 0); Assert.NotNull(result); - Assert.Equal("set-two", result!.Item1); + Assert.Equal("set-two", result.Item1); Assert.Equal("e", result.Item2.Value.ToString()); - result = db.BZPopMin(new[] { new RedisKey("set-two"), new RedisKey("set-one") }, 0); + result = db.BZPopMin([new("set-two"), new("set-one")], 0); Assert.NotNull(result); - Assert.Equal("set-one", result!.Item1); + Assert.Equal("set-one", result.Item1); Assert.Equal("a", result.Item2.Value.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBZPopMinMultipleSetsAsync(string endpointId) { @@ -476,20 +472,20 @@ public async Task TestBZPopMinMultipleSetsAsync(string endpointId) db.SortedSetAdd("set-one", "b", 5.1); db.SortedSetAdd("set-two", "e", 7.76); - var result = await db.BZPopMinAsync(new[] { new RedisKey("set-two"), new RedisKey("set-one") }, 0); + var result = await db.BZPopMinAsync([new("set-two"), new("set-one")], 0); Assert.NotNull(result); - Assert.Equal("set-two", result!.Item1); + Assert.Equal("set-two", result.Item1); Assert.Equal("e", result.Item2.Value.ToString()); - result = await db.BZPopMinAsync(new[] { new RedisKey("set-two"), new RedisKey("set-one") }, 0); + result = await db.BZPopMinAsync([new("set-two"), new("set-one")], 0); Assert.NotNull(result); - Assert.Equal("set-one", result!.Item1); + Assert.Equal("set-one", result.Item1); Assert.Equal("a", result.Item2.Value.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBZPopMax(string endpointId) { @@ -503,12 +499,12 @@ public void TestBZPopMax(string endpointId) var result = db.BZPopMax(sortedSetKey, 0); Assert.NotNull(result); - Assert.Equal(sortedSetKey, result!.Item1); + Assert.Equal(sortedSetKey, result.Item1); Assert.Equal("b", result.Item2.Value.ToString()); Assert.Equal(5.1, result.Item2.Score); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBZPopMaxAsync(string endpointId) { @@ -522,12 +518,12 @@ public async Task TestBZPopMaxAsync(string endpointId) var result = await db.BZPopMaxAsync(sortedSetKey, 0); Assert.NotNull(result); - Assert.Equal(sortedSetKey, result!.Item1); + Assert.Equal(sortedSetKey, result.Item1); Assert.Equal("b", result.Item2.Value.ToString()); Assert.Equal(5.1, result.Item2.Score); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBZPopMaxNull(string endpointId) { @@ -539,7 +535,7 @@ public void TestBZPopMaxNull(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBZPopMaxNullAsync(string endpointId) { @@ -551,7 +547,7 @@ public async Task TestBZPopMaxNullAsync(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBZPopMaxMultipleSets(string endpointId) { @@ -561,20 +557,20 @@ public void TestBZPopMaxMultipleSets(string endpointId) db.SortedSetAdd("set-one", "b", 5.1); db.SortedSetAdd("set-two", "e", 7.76); - var result = db.BZPopMax(new[] { new RedisKey("set-two"), new RedisKey("set-one") }, 0); + var result = db.BZPopMax([new("set-two"), new("set-one")], 0); Assert.NotNull(result); - Assert.Equal("set-two", result!.Item1); + Assert.Equal("set-two", result.Item1); Assert.Equal("e", result.Item2.Value.ToString()); - result = db.BZPopMax(new[] { new RedisKey("set-two"), new RedisKey("set-one") }, 0); + result = db.BZPopMax([new("set-two"), new("set-one")], 0); Assert.NotNull(result); - Assert.Equal("set-one", result!.Item1); + Assert.Equal("set-one", result.Item1); Assert.Equal("b", result.Item2.Value.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBZPopMaxMultipleSetsAsync(string endpointId) { @@ -584,20 +580,20 @@ public async Task TestBZPopMaxMultipleSetsAsync(string endpointId) db.SortedSetAdd("set-one", "b", 5.1); db.SortedSetAdd("set-two", "e", 7.76); - var result = await db.BZPopMaxAsync(new[] { new RedisKey("set-two"), new RedisKey("set-one") }, 0); + var result = await db.BZPopMaxAsync([new("set-two"), new("set-one")], 0); Assert.NotNull(result); - Assert.Equal("set-two", result!.Item1); + Assert.Equal("set-two", result.Item1); Assert.Equal("e", result.Item2.Value.ToString()); - result = await db.BZPopMaxAsync(new[] { new RedisKey("set-two"), new RedisKey("set-one") }, 0); + result = await db.BZPopMaxAsync([new("set-two"), new("set-one")], 0); Assert.NotNull(result); - Assert.Equal("set-one", result!.Item1); + Assert.Equal("set-one", result.Item1); Assert.Equal("b", result.Item2.Value.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBLMPop(string endpointId) { @@ -613,7 +609,7 @@ public void TestBLMPop(string endpointId) var resultWithDefaultOrder = db.BLMPop(0, "my-list", ListSide.Left, 2); Assert.NotNull(resultWithDefaultOrder); - Assert.Equal("my-list", resultWithDefaultOrder!.Item1); + Assert.Equal("my-list", resultWithDefaultOrder.Item1); Assert.Equal(2, resultWithDefaultOrder.Item2.Count); Assert.Equal("a", resultWithDefaultOrder.Item2[0].ToString()); Assert.Equal("b", resultWithDefaultOrder.Item2[1].ToString()); @@ -622,12 +618,12 @@ public void TestBLMPop(string endpointId) var resultWithDescendingOrder = db.BLMPop(0, "my-list", ListSide.Right, 1); Assert.NotNull(resultWithDescendingOrder); - Assert.Equal("my-list", resultWithDescendingOrder!.Item1); + Assert.Equal("my-list", resultWithDescendingOrder.Item1); Assert.Single(resultWithDescendingOrder.Item2); Assert.Equal("e", resultWithDescendingOrder.Item2[0].ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBLMPopAsync(string endpointId) { @@ -643,7 +639,7 @@ public async Task TestBLMPopAsync(string endpointId) var resultWithDefaultOrder = await db.BLMPopAsync(0, "my-list", ListSide.Left, 2); Assert.NotNull(resultWithDefaultOrder); - Assert.Equal("my-list", resultWithDefaultOrder!.Item1); + Assert.Equal("my-list", resultWithDefaultOrder.Item1); Assert.Equal(2, resultWithDefaultOrder.Item2.Count); Assert.Equal("a", resultWithDefaultOrder.Item2[0].ToString()); Assert.Equal("b", resultWithDefaultOrder.Item2[1].ToString()); @@ -652,12 +648,12 @@ public async Task TestBLMPopAsync(string endpointId) var resultWithDescendingOrder = await db.BLMPopAsync(0, "my-list", ListSide.Right, 1); Assert.NotNull(resultWithDescendingOrder); - Assert.Equal("my-list", resultWithDescendingOrder!.Item1); + Assert.Equal("my-list", resultWithDescendingOrder.Item1); Assert.Single(resultWithDescendingOrder.Item2); Assert.Equal("e", resultWithDescendingOrder.Item2[0].ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBLMPopNull(string endpointId) { @@ -669,7 +665,7 @@ public void TestBLMPopNull(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBLMPopNullAsync(string endpointId) { @@ -681,7 +677,7 @@ public async Task TestBLMPopNullAsync(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBLMPopMultipleLists(string endpointId) { @@ -696,34 +692,34 @@ public void TestBLMPopMultipleLists(string endpointId) var result = db.BLMPop(0, "list-two", ListSide.Right); Assert.NotNull(result); - Assert.Equal("list-two", result!.Item1); + Assert.Equal("list-two", result.Item1); Assert.Single(result.Item2); Assert.Equal("e", result.Item2[0].ToString()); - result = db.BLMPop(0, new[] { new RedisKey("list-two"), new RedisKey("list-one") }, ListSide.Left); + result = db.BLMPop(0, [new("list-two"), new("list-one")], ListSide.Left); Assert.NotNull(result); - Assert.Equal("list-two", result!.Item1); + Assert.Equal("list-two", result.Item1); Assert.Single(result.Item2); Assert.Equal("d", result.Item2[0].ToString()); - result = db.BLMPop(0, new[] { new RedisKey("list-two"), new RedisKey("list-one") }, ListSide.Right); + result = db.BLMPop(0, [new("list-two"), new("list-one")], ListSide.Right); Assert.NotNull(result); - Assert.Equal("list-one", result!.Item1); + Assert.Equal("list-one", result.Item1); Assert.Single(result.Item2); Assert.Equal("c", result.Item2[0].ToString()); result = db.BLMPop(0, "list-one", ListSide.Left, count: 2); Assert.NotNull(result); - Assert.Equal("list-one", result!.Item1); + Assert.Equal("list-one", result.Item1); Assert.Equal(2, result.Item2.Count); Assert.Equal("a", result.Item2[0].ToString()); Assert.Equal("b", result.Item2[1].ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBLMPopMultipleListsAsync(string endpointId) { @@ -738,43 +734,43 @@ public async Task TestBLMPopMultipleListsAsync(string endpointId) var result = await db.BLMPopAsync(0, "list-two", ListSide.Right); Assert.NotNull(result); - Assert.Equal("list-two", result!.Item1); + Assert.Equal("list-two", result.Item1); Assert.Single(result.Item2); Assert.Equal("e", result.Item2[0].ToString()); - result = await db.BLMPopAsync(0, new[] { new RedisKey("list-two"), new RedisKey("list-one") }, ListSide.Left); + result = await db.BLMPopAsync(0, [new("list-two"), new("list-one")], ListSide.Left); Assert.NotNull(result); - Assert.Equal("list-two", result!.Item1); + Assert.Equal("list-two", result.Item1); Assert.Single(result.Item2); Assert.Equal("d", result.Item2[0].ToString()); - result = await db.BLMPopAsync(0, new[] { new RedisKey("list-two"), new RedisKey("list-one") }, ListSide.Right); + result = await db.BLMPopAsync(0, [new("list-two"), new("list-one")], ListSide.Right); Assert.NotNull(result); - Assert.Equal("list-one", result!.Item1); + Assert.Equal("list-one", result.Item1); Assert.Single(result.Item2); Assert.Equal("c", result.Item2[0].ToString()); result = await db.BLMPopAsync(0, "list-one", ListSide.Left, count: 2); Assert.NotNull(result); - Assert.Equal("list-one", result!.Item1); + Assert.Equal("list-one", result.Item1); Assert.Equal(2, result.Item2.Count); Assert.Equal("a", result.Item2[0].ToString()); Assert.Equal("b", result.Item2[1].ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBLMPopNoKeysProvided(string endpointId) { var db = GetCleanDatabase(endpointId); - Assert.Throws(() => db.BLMPop(0, Array.Empty(), ListSide.Left)); + Assert.Throws(() => db.BLMPop(0, [], ListSide.Left)); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBLPop(string endpointId) { @@ -786,11 +782,11 @@ public void TestBLPop(string endpointId) var result = db.BLPop("my-list", 0); Assert.NotNull(result); - Assert.Equal("my-list", result!.Item1); + Assert.Equal("my-list", result.Item1); Assert.Equal("a", result.Item2.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBLPopAsync(string endpointId) { @@ -802,11 +798,11 @@ public async Task TestBLPopAsync(string endpointId) var result = await db.BLPopAsync("my-list", 0); Assert.NotNull(result); - Assert.Equal("my-list", result!.Item1); + Assert.Equal("my-list", result.Item1); Assert.Equal("a", result.Item2.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBLPopNull(string endpointId) { @@ -818,7 +814,7 @@ public void TestBLPopNull(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBLPopNullAsync(string endpointId) { @@ -830,7 +826,7 @@ public async Task TestBLPopNullAsync(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBLPopMultipleLists(string endpointId) { @@ -840,20 +836,20 @@ public void TestBLPopMultipleLists(string endpointId) db.ListRightPush("list-one", "b"); db.ListRightPush("list-two", "e"); - var result = db.BLPop(new[] { new RedisKey("list-two"), new RedisKey("list-one") }, 0); + var result = db.BLPop([new("list-two"), new("list-one")], 0); Assert.NotNull(result); - Assert.Equal("list-two", result!.Item1); + Assert.Equal("list-two", result.Item1); Assert.Equal("e", result.Item2.ToString()); - result = db.BLPop(new[] { new RedisKey("list-two"), new RedisKey("list-one") }, 0); + result = db.BLPop([new("list-two"), new("list-one")], 0); Assert.NotNull(result); - Assert.Equal("list-one", result!.Item1); + Assert.Equal("list-one", result.Item1); Assert.Equal("a", result.Item2.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBLPopMultipleListsAsync(string endpointId) { @@ -863,20 +859,20 @@ public async Task TestBLPopMultipleListsAsync(string endpointId) db.ListRightPush("list-one", "b"); db.ListRightPush("list-two", "e"); - var result = await db.BLPopAsync(new[] { new RedisKey("list-two"), new RedisKey("list-one") }, 0); + var result = await db.BLPopAsync([new("list-two"), new("list-one")], 0); Assert.NotNull(result); - Assert.Equal("list-two", result!.Item1); + Assert.Equal("list-two", result.Item1); Assert.Equal("e", result.Item2.ToString()); - result = await db.BLPopAsync(new[] { new RedisKey("list-two"), new RedisKey("list-one") }, 0); + result = await db.BLPopAsync([new("list-two"), new("list-one")], 0); Assert.NotNull(result); - Assert.Equal("list-one", result!.Item1); + Assert.Equal("list-one", result.Item1); Assert.Equal("a", result.Item2.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBRPop(string endpointId) { @@ -888,11 +884,11 @@ public void TestBRPop(string endpointId) var result = db.BRPop("my-list", 0); Assert.NotNull(result); - Assert.Equal("my-list", result!.Item1); + Assert.Equal("my-list", result.Item1); Assert.Equal("b", result.Item2.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBRPopAsync(string endpointId) { @@ -904,11 +900,11 @@ public async Task TestBRPopAsync(string endpointId) var result = await db.BRPopAsync("my-list", 0); Assert.NotNull(result); - Assert.Equal("my-list", result!.Item1); + Assert.Equal("my-list", result.Item1); Assert.Equal("b", result.Item2.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBRPopNull(string endpointId) { @@ -920,7 +916,7 @@ public void TestBRPopNull(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBRPopNullAsync(string endpointId) { @@ -932,7 +928,7 @@ public async Task TestBRPopNullAsync(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBRPopMultipleLists(string endpointId) { @@ -942,20 +938,20 @@ public void TestBRPopMultipleLists(string endpointId) db.ListRightPush("list-one", "b"); db.ListRightPush("list-two", "e"); - var result = db.BRPop(new[] { new RedisKey("list-two"), new RedisKey("list-one") }, 0); + var result = db.BRPop([new("list-two"), new("list-one")], 0); Assert.NotNull(result); - Assert.Equal("list-two", result!.Item1); + Assert.Equal("list-two", result.Item1); Assert.Equal("e", result.Item2.ToString()); - result = db.BRPop(new[] { new RedisKey("list-two"), new RedisKey("list-one") }, 0); + result = db.BRPop([new("list-two"), new("list-one")], 0); Assert.NotNull(result); - Assert.Equal("list-one", result!.Item1); + Assert.Equal("list-one", result.Item1); Assert.Equal("b", result.Item2.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBRPopMultipleListsAsync(string endpointId) { @@ -965,20 +961,20 @@ public async Task TestBRPopMultipleListsAsync(string endpointId) db.ListRightPush("list-one", "b"); db.ListRightPush("list-two", "e"); - var result = await db.BRPopAsync(new[] { new RedisKey("list-two"), new RedisKey("list-one") }, 0); + var result = await db.BRPopAsync([new("list-two"), new("list-one")], 0); Assert.NotNull(result); - Assert.Equal("list-two", result!.Item1); + Assert.Equal("list-two", result.Item1); Assert.Equal("e", result.Item2.ToString()); - result = await db.BRPopAsync(new[] { new RedisKey("list-two"), new RedisKey("list-one") }, 0); + result = await db.BRPopAsync([new("list-two"), new("list-one")], 0); Assert.NotNull(result); - Assert.Equal("list-one", result!.Item1); + Assert.Equal("list-one", result.Item1); Assert.Equal("b", result.Item2.ToString()); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "6.2.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "6.2.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBLMove(string endpointId) { @@ -1035,7 +1031,7 @@ public void TestBLMove(string endpointId) Assert.Equal("c", db.ListGetByIndex("list-two", 1)); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "6.2.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "6.2.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBLMoveAsync(string endpointId) { @@ -1092,7 +1088,7 @@ public async Task TestBLMoveAsync(string endpointId) Assert.Equal("c", db.ListGetByIndex("list-two", 1)); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.2.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.2.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestBRPopLPush(string endpointId) { @@ -1113,7 +1109,7 @@ public void TestBRPopLPush(string endpointId) Assert.Equal("b", db.ListLeftPop("list-two")); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "2.2.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "2.2.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestBRPopLPushAsync(string endpointId) { @@ -1134,7 +1130,7 @@ public async Task TestBRPopLPushAsync(string endpointId) Assert.Equal("b", db.ListLeftPop("list-two")); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestXRead(string endpointId) { @@ -1149,7 +1145,7 @@ public void TestXRead(string endpointId) Assert.NotNull(result); Assert.Single(result); - StreamEntry streamEntry = result![0]; + StreamEntry streamEntry = result[0]; var lastKey = streamEntry.Id; Assert.Single(streamEntry.Values); Assert.Equal("a", streamEntry.Values[0].Name); @@ -1160,13 +1156,13 @@ public void TestXRead(string endpointId) Assert.NotNull(result); Assert.Single(result); - streamEntry = result![0]; + streamEntry = result[0]; Assert.Single(streamEntry.Values); Assert.Equal("b", streamEntry.Values[0].Name); Assert.Equal(7, streamEntry.Values[0].Value); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestXReadAsync(string endpointId) { @@ -1181,7 +1177,7 @@ public async Task TestXReadAsync(string endpointId) Assert.NotNull(result); Assert.Single(result); - StreamEntry streamEntry = result![0]; + StreamEntry streamEntry = result[0]; var lastKey = streamEntry.Id; Assert.Single(streamEntry.Values); Assert.Equal("a", streamEntry.Values[0].Name); @@ -1192,13 +1188,13 @@ public async Task TestXReadAsync(string endpointId) Assert.NotNull(result); Assert.Single(result); - streamEntry = result![0]; + streamEntry = result[0]; Assert.Single(streamEntry.Values); Assert.Equal("b", streamEntry.Values[0].Name); Assert.Equal(7, streamEntry.Values[0].Value); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestXReadMultipleStreams(string endpointId) { @@ -1209,46 +1205,46 @@ public void TestXReadMultipleStreams(string endpointId) db.StreamAdd("stream-two", "c", "foo"); db.StreamAdd("stream-two", "d", "bar"); - var result = db.XRead(new RedisKey[] { "stream-one", "stream-two" }, - new RedisValue[] { StreamSpecialIds.AllMessagesId, StreamSpecialIds.AllMessagesId }, + var result = db.XRead(["stream-one", "stream-two"], + [StreamSpecialIds.AllMessagesId, StreamSpecialIds.AllMessagesId], count: 1, timeoutMilliseconds: 1000); Assert.NotNull(result); - Assert.Equal(2, result!.Length); + Assert.Equal(2, result.Length); - Assert.Equal("stream-one", result![0].Key); - Assert.Single(result![0].Entries); - var lastKeyOne = result![0].Entries[0].Id; - Assert.Single(result![0].Entries[0].Values); - Assert.Equal("a", result![0].Entries[0].Values[0].Name); - Assert.Equal(1, result![0].Entries[0].Values[0].Value); + Assert.Equal("stream-one", result[0].Key); + Assert.Single(result[0].Entries); + var lastKeyOne = result[0].Entries[0].Id; + Assert.Single(result[0].Entries[0].Values); + Assert.Equal("a", result[0].Entries[0].Values[0].Name); + Assert.Equal(1, result[0].Entries[0].Values[0].Value); - Assert.Equal("stream-two", result![1].Key); - Assert.Single(result![1].Entries); - var lastKeyTwo = result![1].Entries[0].Id; - Assert.Single(result![1].Entries[0].Values); - Assert.Equal("c", result![1].Entries[0].Values[0].Name); - Assert.Equal("foo", result![1].Entries[0].Values[0].Value); + Assert.Equal("stream-two", result[1].Key); + Assert.Single(result[1].Entries); + var lastKeyTwo = result[1].Entries[0].Id; + Assert.Single(result[1].Entries[0].Values); + Assert.Equal("c", result[1].Entries[0].Values[0].Name); + Assert.Equal("foo", result[1].Entries[0].Values[0].Value); - result = db.XRead(new RedisKey[] { "stream-one", "stream-two" }, - new RedisValue[] { lastKeyOne, lastKeyTwo }, + result = db.XRead(["stream-one", "stream-two"], + [lastKeyOne, lastKeyTwo], count: 1, timeoutMilliseconds: 1000); Assert.NotNull(result); - Assert.Equal(2, result!.Length); + Assert.Equal(2, result.Length); - Assert.Single(result![0].Entries); - Assert.Single(result![0].Entries[0].Values); - Assert.Equal("b", result![0].Entries[0].Values[0].Name); - Assert.Equal(7, result![0].Entries[0].Values[0].Value); + Assert.Single(result[0].Entries); + Assert.Single(result[0].Entries[0].Values); + Assert.Equal("b", result[0].Entries[0].Values[0].Name); + Assert.Equal(7, result[0].Entries[0].Values[0].Value); - Assert.Single(result![1].Entries); - Assert.Single(result![1].Entries[0].Values); - Assert.Equal("d", result![1].Entries[0].Values[0].Name); - Assert.Equal("bar", result![1].Entries[0].Values[0].Value); + Assert.Single(result[1].Entries); + Assert.Single(result[1].Entries[0].Values); + Assert.Equal("d", result[1].Entries[0].Values[0].Name); + Assert.Equal("bar", result[1].Entries[0].Values[0].Value); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestXReadMultipleStreamsAsync(string endpointId) { @@ -1259,44 +1255,44 @@ public async Task TestXReadMultipleStreamsAsync(string endpointId) db.StreamAdd("stream-two", "c", "foo"); db.StreamAdd("stream-two", "d", "bar"); - var result = await db.XReadAsync(new RedisKey[] { "stream-one", "stream-two" }, - new RedisValue[] { StreamSpecialIds.AllMessagesId, StreamSpecialIds.AllMessagesId }, + var result = await db.XReadAsync(["stream-one", "stream-two"], + [StreamSpecialIds.AllMessagesId, StreamSpecialIds.AllMessagesId], count: 1, timeoutMilliseconds: 1000); Assert.NotNull(result); - Assert.Equal(2, result!.Length); + Assert.Equal(2, result.Length); - Assert.Single(result![0].Entries); - var lastKeyOne = result![0].Entries[0].Id; - Assert.Single(result![0].Entries[0].Values); - Assert.Equal("a", result![0].Entries[0].Values[0].Name); - Assert.Equal(1, result![0].Entries[0].Values[0].Value); + Assert.Single(result[0].Entries); + var lastKeyOne = result[0].Entries[0].Id; + Assert.Single(result[0].Entries[0].Values); + Assert.Equal("a", result[0].Entries[0].Values[0].Name); + Assert.Equal(1, result[0].Entries[0].Values[0].Value); - Assert.Single(result![1].Entries); - var lastKeyTwo = result![1].Entries[0].Id; - Assert.Single(result![1].Entries[0].Values); - Assert.Equal("c", result![1].Entries[0].Values[0].Name); - Assert.Equal("foo", result![1].Entries[0].Values[0].Value); + Assert.Single(result[1].Entries); + var lastKeyTwo = result[1].Entries[0].Id; + Assert.Single(result[1].Entries[0].Values); + Assert.Equal("c", result[1].Entries[0].Values[0].Name); + Assert.Equal("foo", result[1].Entries[0].Values[0].Value); - result = await db.XReadAsync(new RedisKey[] { "stream-one", "stream-two" }, - new RedisValue[] { lastKeyOne, lastKeyTwo }, + result = await db.XReadAsync(["stream-one", "stream-two"], + [lastKeyOne, lastKeyTwo], count: 1, timeoutMilliseconds: 1000); Assert.NotNull(result); - Assert.Equal(2, result!.Length); + Assert.Equal(2, result.Length); - Assert.Single(result![0].Entries); - Assert.Single(result![0].Entries[0].Values); - Assert.Equal("b", result![0].Entries[0].Values[0].Name); - Assert.Equal(7, result![0].Entries[0].Values[0].Value); + Assert.Single(result[0].Entries); + Assert.Single(result[0].Entries[0].Values); + Assert.Equal("b", result[0].Entries[0].Values[0].Name); + Assert.Equal(7, result[0].Entries[0].Values[0].Value); - Assert.Single(result![1].Entries); - Assert.Single(result![1].Entries[0].Values); - Assert.Equal("d", result![1].Entries[0].Values[0].Name); - Assert.Equal("bar", result![1].Entries[0].Values[0].Value); + Assert.Single(result[1].Entries); + Assert.Single(result[1].Entries[0].Values); + Assert.Equal("d", result[1].Entries[0].Values[0].Name); + Assert.Equal("bar", result[1].Entries[0].Values[0].Value); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestXReadOnlyNewMessages(string endpointId) { @@ -1311,7 +1307,7 @@ public void TestXReadOnlyNewMessages(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestXReadOnlyNewMessagesAsync(string endpointId) { @@ -1326,27 +1322,27 @@ public async Task TestXReadOnlyNewMessagesAsync(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestXReadNoKeysProvided(string endpointId) { var db = GetCleanDatabase(endpointId); - Assert.Throws(() => db.XRead(Array.Empty(), - new RedisValue[] { StreamSpecialIds.NewMessagesId })); + Assert.Throws(() => db.XRead([], + [StreamSpecialIds.NewMessagesId])); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestXReadMismatchedKeysAndPositionsCountsProvided(string endpointId) { var db = GetCleanDatabase(endpointId); - Assert.Throws(() => db.XRead(new RedisKey[] { "my-stream" }, - new RedisValue[] { StreamSpecialIds.NewMessagesId, StreamSpecialIds.NewMessagesId })); + Assert.Throws(() => db.XRead(["my-stream"], + [StreamSpecialIds.NewMessagesId, StreamSpecialIds.NewMessagesId])); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestXReadGroup(string endpointId) { @@ -1367,10 +1363,10 @@ public void TestXReadGroup(string endpointId) Assert.NotNull(result); Assert.Single(result); - var consumerAIdOne = result![0].Id; + var consumerAIdOne = result[0].Id; Assert.Single(result[0].Values); - Assert.Equal("a", result![0].Values[0].Name); - Assert.Equal(1, result![0].Values[0].Value); + Assert.Equal("a", result[0].Values[0].Name); + Assert.Equal(1, result[0].Values[0].Value); result = db.XReadGroup("my-group", "consumer-b", "my-stream", StreamSpecialIds.UndeliveredMessagesId, count: 1, timeoutMilliseconds: 1000); @@ -1378,10 +1374,10 @@ public void TestXReadGroup(string endpointId) Assert.NotNull(result); Assert.Single(result); - var consumerBIdOne = result![0].Id; + var consumerBIdOne = result[0].Id; Assert.Single(result[0].Values); - Assert.Equal("b", result![0].Values[0].Name); - Assert.Equal(7, result![0].Values[0].Value); + Assert.Equal("b", result[0].Values[0].Name); + Assert.Equal(7, result[0].Values[0].Value); // Read another message from each consumer, don't ACK anything. result = db.XReadGroup("my-group", "consumer-a", @@ -1390,10 +1386,10 @@ public void TestXReadGroup(string endpointId) Assert.NotNull(result); Assert.Single(result); - var consumerAIdTwo = result![0].Id; - Assert.Single(result![0].Values); - Assert.Equal("c", result![0].Values[0].Name); - Assert.Equal(11, result![0].Values[0].Value); + var consumerAIdTwo = result[0].Id; + Assert.Single(result[0].Values); + Assert.Equal("c", result[0].Values[0].Name); + Assert.Equal(11, result[0].Values[0].Value); result = db.XReadGroup("my-group", "consumer-b", "my-stream", StreamSpecialIds.UndeliveredMessagesId, count: 1, timeoutMilliseconds: 1000); @@ -1401,10 +1397,10 @@ public void TestXReadGroup(string endpointId) Assert.NotNull(result); Assert.Single(result); - var consumerBIdTwo = result![0].Id; - Assert.Single(result![0].Values); - Assert.Equal("d", result![0].Values[0].Name); - Assert.Equal(12, result![0].Values[0].Value); + var consumerBIdTwo = result[0].Id; + Assert.Single(result[0].Values); + Assert.Equal("d", result[0].Values[0].Name); + Assert.Equal(12, result[0].Values[0].Value); // Since we didn't ACK anything, the pending messages can be re-read with the right ID. result = db.XReadGroup("my-group", "consumer-a", @@ -1413,9 +1409,9 @@ public void TestXReadGroup(string endpointId) Assert.NotNull(result); Assert.Single(result); - Assert.Single(result![0].Values); - Assert.Equal("a", result![0].Values[0].Name); - Assert.Equal(1, result![0].Values[0].Value); + Assert.Single(result[0].Values); + Assert.Equal("a", result[0].Values[0].Name); + Assert.Equal(1, result[0].Values[0].Value); result = db.XReadGroup("my-group", "consumer-b", "my-stream", StreamSpecialIds.AllMessagesId, count: 1, timeoutMilliseconds: 1000); @@ -1423,13 +1419,13 @@ public void TestXReadGroup(string endpointId) Assert.NotNull(result); Assert.Single(result); - Assert.Single(result![0].Values); - Assert.Equal("b", result![0].Values[0].Name); - Assert.Equal(7, result![0].Values[0].Value); + Assert.Single(result[0].Values); + Assert.Equal("b", result[0].Values[0].Name); + Assert.Equal(7, result[0].Values[0].Value); // ACK the messages. var ackedMessagesCount = db.StreamAcknowledge("my-stream", "my-group", - new[] { consumerAIdOne, consumerAIdTwo, consumerBIdOne, consumerBIdTwo }); + [consumerAIdOne, consumerAIdTwo, consumerBIdOne, consumerBIdTwo]); Assert.Equal(4, ackedMessagesCount); // After ACK we don't see anything pending. @@ -1446,7 +1442,7 @@ public void TestXReadGroup(string endpointId) Assert.Empty(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestXReadGroupAsync(string endpointId) { @@ -1467,10 +1463,10 @@ public async Task TestXReadGroupAsync(string endpointId) Assert.NotNull(result); Assert.Single(result); - var consumerAIdOne = result![0].Id; + var consumerAIdOne = result[0].Id; Assert.Single(result[0].Values); - Assert.Equal("a", result![0].Values[0].Name); - Assert.Equal(1, result![0].Values[0].Value); + Assert.Equal("a", result[0].Values[0].Name); + Assert.Equal(1, result[0].Values[0].Value); result = await db.XReadGroupAsync("my-group", "consumer-b", "my-stream", StreamSpecialIds.UndeliveredMessagesId, count: 1, timeoutMilliseconds: 1000); @@ -1478,10 +1474,10 @@ public async Task TestXReadGroupAsync(string endpointId) Assert.NotNull(result); Assert.Single(result); - var consumerBIdOne = result![0].Id; + var consumerBIdOne = result[0].Id; Assert.Single(result[0].Values); - Assert.Equal("b", result![0].Values[0].Name); - Assert.Equal(7, result![0].Values[0].Value); + Assert.Equal("b", result[0].Values[0].Name); + Assert.Equal(7, result[0].Values[0].Value); // Read another message from each consumer, don't ACK anything. result = await db.XReadGroupAsync("my-group", "consumer-a", @@ -1490,10 +1486,10 @@ public async Task TestXReadGroupAsync(string endpointId) Assert.NotNull(result); Assert.Single(result); - var consumerAIdTwo = result![0].Id; - Assert.Single(result![0].Values); - Assert.Equal("c", result![0].Values[0].Name); - Assert.Equal(11, result![0].Values[0].Value); + var consumerAIdTwo = result[0].Id; + Assert.Single(result[0].Values); + Assert.Equal("c", result[0].Values[0].Name); + Assert.Equal(11, result[0].Values[0].Value); result = await db.XReadGroupAsync("my-group", "consumer-b", "my-stream", StreamSpecialIds.UndeliveredMessagesId, count: 1, timeoutMilliseconds: 1000); @@ -1501,10 +1497,10 @@ public async Task TestXReadGroupAsync(string endpointId) Assert.NotNull(result); Assert.Single(result); - var consumerBIdTwo = result![0].Id; - Assert.Single(result![0].Values); - Assert.Equal("d", result![0].Values[0].Name); - Assert.Equal(12, result![0].Values[0].Value); + var consumerBIdTwo = result[0].Id; + Assert.Single(result[0].Values); + Assert.Equal("d", result[0].Values[0].Name); + Assert.Equal(12, result[0].Values[0].Value); // Since we didn't ACK anything, the pending messages can be re-read with the right ID. result = await db.XReadGroupAsync("my-group", "consumer-a", @@ -1513,9 +1509,9 @@ public async Task TestXReadGroupAsync(string endpointId) Assert.NotNull(result); Assert.Single(result); - Assert.Single(result![0].Values); - Assert.Equal("a", result![0].Values[0].Name); - Assert.Equal(1, result![0].Values[0].Value); + Assert.Single(result[0].Values); + Assert.Equal("a", result[0].Values[0].Name); + Assert.Equal(1, result[0].Values[0].Value); result = await db.XReadGroupAsync("my-group", "consumer-b", "my-stream", StreamSpecialIds.AllMessagesId, count: 1, timeoutMilliseconds: 1000); @@ -1523,13 +1519,13 @@ public async Task TestXReadGroupAsync(string endpointId) Assert.NotNull(result); Assert.Single(result); - Assert.Single(result![0].Values); - Assert.Equal("b", result![0].Values[0].Name); - Assert.Equal(7, result![0].Values[0].Value); + Assert.Single(result[0].Values); + Assert.Equal("b", result[0].Values[0].Name); + Assert.Equal(7, result[0].Values[0].Value); // ACK the messages. var ackedMessagesCount = db.StreamAcknowledge("my-stream", "my-group", - new[] { consumerAIdOne, consumerAIdTwo, consumerBIdOne, consumerBIdTwo }); + [consumerAIdOne, consumerAIdTwo, consumerBIdOne, consumerBIdTwo]); Assert.Equal(4, ackedMessagesCount); // After ACK we don't see anything pending. @@ -1546,7 +1542,7 @@ public async Task TestXReadGroupAsync(string endpointId) Assert.Empty(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestXReadGroupNoAck(string endpointId) { @@ -1567,9 +1563,9 @@ public void TestXReadGroupNoAck(string endpointId) Assert.NotNull(result); Assert.Single(result); - Assert.Single(result![0].Values); - Assert.Equal("a", result![0].Values[0].Name); - Assert.Equal(1, result![0].Values[0].Value); + Assert.Single(result[0].Values); + Assert.Equal("a", result[0].Values[0].Name); + Assert.Equal(1, result[0].Values[0].Value); // We don't see anything pending because of the NOACK. result = db.XReadGroup("my-group", "consumer-a", @@ -1579,7 +1575,7 @@ public void TestXReadGroupNoAck(string endpointId) Assert.Empty(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestXReadGroupMultipleStreams(string endpointId) { @@ -1597,43 +1593,43 @@ public void TestXReadGroupMultipleStreams(string endpointId) db.StreamAdd("stream-two", "d", 17); var result = db.XReadGroup("my-group", "consumer-a", - new RedisKey[] { "stream-one", "stream-two" }, - new RedisValue[] { StreamSpecialIds.UndeliveredMessagesId, StreamSpecialIds.UndeliveredMessagesId }, + ["stream-one", "stream-two"], + [StreamSpecialIds.UndeliveredMessagesId, StreamSpecialIds.UndeliveredMessagesId], count: 1, timeoutMilliseconds: 1000); Assert.NotNull(result); - Assert.Equal(2, result!.Length); + Assert.Equal(2, result.Length); - Assert.Single(result![0].Entries); - Assert.Single(result![0].Entries[0].Values); - Assert.Equal("a", result![0].Entries[0].Values[0].Name); - Assert.Equal(1, result![0].Entries[0].Values[0].Value); + Assert.Single(result[0].Entries); + Assert.Single(result[0].Entries[0].Values); + Assert.Equal("a", result[0].Entries[0].Values[0].Name); + Assert.Equal(1, result[0].Entries[0].Values[0].Value); - Assert.Single(result![1].Entries); - Assert.Single(result![1].Entries[0].Values); - Assert.Equal("b", result![1].Entries[0].Values[0].Name); - Assert.Equal(7, result![1].Entries[0].Values[0].Value); + Assert.Single(result[1].Entries); + Assert.Single(result[1].Entries[0].Values); + Assert.Equal("b", result[1].Entries[0].Values[0].Name); + Assert.Equal(7, result[1].Entries[0].Values[0].Value); result = db.XReadGroup("my-group", "consumer-b", - new RedisKey[] { "stream-one", "stream-two" }, - new RedisValue[] { StreamSpecialIds.UndeliveredMessagesId, StreamSpecialIds.UndeliveredMessagesId }, + ["stream-one", "stream-two"], + [StreamSpecialIds.UndeliveredMessagesId, StreamSpecialIds.UndeliveredMessagesId], count: 1, timeoutMilliseconds: 1000); Assert.NotNull(result); - Assert.Equal(2, result!.Length); + Assert.Equal(2, result.Length); - Assert.Single(result![0].Entries); - Assert.Single(result![0].Entries[0].Values); - Assert.Equal("c", result![0].Entries[0].Values[0].Name); - Assert.Equal(11, result![0].Entries[0].Values[0].Value); + Assert.Single(result[0].Entries); + Assert.Single(result[0].Entries[0].Values); + Assert.Equal("c", result[0].Entries[0].Values[0].Name); + Assert.Equal(11, result[0].Entries[0].Values[0].Value); - Assert.Single(result![1].Entries); - Assert.Single(result![1].Entries[0].Values); - Assert.Equal("d", result![1].Entries[0].Values[0].Name); - Assert.Equal(17, result![1].Entries[0].Values[0].Value); + Assert.Single(result[1].Entries); + Assert.Single(result[1].Entries[0].Values); + Assert.Equal("d", result[1].Entries[0].Values[0].Name); + Assert.Equal(17, result[1].Entries[0].Values[0].Value); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestXReadGroupMultipleStreamsAsync(string endpointId) { @@ -1651,43 +1647,43 @@ public async Task TestXReadGroupMultipleStreamsAsync(string endpointId) db.StreamAdd("stream-two", "d", 17); var result = await db.XReadGroupAsync("my-group", "consumer-a", - new RedisKey[] { "stream-one", "stream-two" }, - new RedisValue[] { StreamSpecialIds.UndeliveredMessagesId, StreamSpecialIds.UndeliveredMessagesId }, + ["stream-one", "stream-two"], + [StreamSpecialIds.UndeliveredMessagesId, StreamSpecialIds.UndeliveredMessagesId], count: 1, timeoutMilliseconds: 1000); Assert.NotNull(result); - Assert.Equal(2, result!.Length); + Assert.Equal(2, result.Length); - Assert.Single(result![0].Entries); - Assert.Single(result![0].Entries[0].Values); - Assert.Equal("a", result![0].Entries[0].Values[0].Name); - Assert.Equal(1, result![0].Entries[0].Values[0].Value); + Assert.Single(result[0].Entries); + Assert.Single(result[0].Entries[0].Values); + Assert.Equal("a", result[0].Entries[0].Values[0].Name); + Assert.Equal(1, result[0].Entries[0].Values[0].Value); - Assert.Single(result![1].Entries); - Assert.Single(result![1].Entries[0].Values); - Assert.Equal("b", result![1].Entries[0].Values[0].Name); - Assert.Equal(7, result![1].Entries[0].Values[0].Value); + Assert.Single(result[1].Entries); + Assert.Single(result[1].Entries[0].Values); + Assert.Equal("b", result[1].Entries[0].Values[0].Name); + Assert.Equal(7, result[1].Entries[0].Values[0].Value); result = await db.XReadGroupAsync("my-group", "consumer-b", - new RedisKey[] { "stream-one", "stream-two" }, - new RedisValue[] { StreamSpecialIds.UndeliveredMessagesId, StreamSpecialIds.UndeliveredMessagesId }, + ["stream-one", "stream-two"], + [StreamSpecialIds.UndeliveredMessagesId, StreamSpecialIds.UndeliveredMessagesId], count: 1, timeoutMilliseconds: 1000); Assert.NotNull(result); - Assert.Equal(2, result!.Length); + Assert.Equal(2, result.Length); - Assert.Single(result![0].Entries); - Assert.Single(result![0].Entries[0].Values); - Assert.Equal("c", result![0].Entries[0].Values[0].Name); - Assert.Equal(11, result![0].Entries[0].Values[0].Value); + Assert.Single(result[0].Entries); + Assert.Single(result[0].Entries[0].Values); + Assert.Equal("c", result[0].Entries[0].Values[0].Name); + Assert.Equal(11, result[0].Entries[0].Values[0].Value); - Assert.Single(result![1].Entries); - Assert.Single(result![1].Entries[0].Values); - Assert.Equal("d", result![1].Entries[0].Values[0].Name); - Assert.Equal(17, result![1].Entries[0].Values[0].Value); + Assert.Single(result[1].Entries); + Assert.Single(result[1].Entries[0].Values); + Assert.Equal("d", result[1].Entries[0].Values[0].Name); + Assert.Equal(17, result[1].Entries[0].Values[0].Value); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestXReadGroupNull(string endpointId) { @@ -1703,7 +1699,7 @@ public void TestXReadGroupNull(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestXReadGroupNullAsync(string endpointId) { @@ -1719,23 +1715,23 @@ public async Task TestXReadGroupNullAsync(string endpointId) Assert.Null(result); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestXReadGroupNoKeysProvided(string endpointId) { var db = GetCleanDatabase(endpointId); Assert.Throws(() => db.XReadGroup("my-group", "consumer", - Array.Empty(), new RedisValue[] { StreamSpecialIds.NewMessagesId })); + [], [StreamSpecialIds.NewMessagesId])); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "5.0.0")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "5.0.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestXReadGroupMismatchedKeysAndPositionsCountsProvided(string endpointId) { var db = GetCleanDatabase(endpointId); Assert.Throws(() => db.XReadGroup("my-group", "consumer", - new RedisKey[] { "my-stream" }, new RedisValue[] { StreamSpecialIds.NewMessagesId, StreamSpecialIds.NewMessagesId })); + ["my-stream"], [StreamSpecialIds.NewMessagesId, StreamSpecialIds.NewMessagesId])); } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/CountMinSketch/CmsTests.cs b/tests/NRedisStack.Tests/CountMinSketch/CmsTests.cs index a3f1998d..16b25369 100644 --- a/tests/NRedisStack.Tests/CountMinSketch/CmsTests.cs +++ b/tests/NRedisStack.Tests/CountMinSketch/CmsTests.cs @@ -4,14 +4,10 @@ namespace NRedisStack.Tests.CuckooFilter; -public class CmsTests : AbstractNRedisStackTest, IDisposable +public class CmsTests(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable { private readonly string key = "CMS_TESTS"; - public CmsTests(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } - [SkippableTheory] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] @@ -142,8 +138,8 @@ public void TestIncrByMultipleArgs(string endpointId) cms.IncrBy(key, "foo", 5L); var itemIncrements = new Tuple[2]; - itemIncrements[0] = new Tuple("foo", 5); - itemIncrements[1] = new Tuple("bar", 15); + itemIncrements[0] = new("foo", 5); + itemIncrements[1] = new("bar", 15); var resp = cms.IncrBy(key, itemIncrements); Assert.Equal(new long[] { 10, 15 }, resp); @@ -165,8 +161,8 @@ public async Task TestIncrByMultipleArgsAsync(string endpointId) await cms.IncrByAsync(key, "foo", 5L); var itemIncrements = new Tuple[2]; - itemIncrements[0] = new Tuple("foo", 5); - itemIncrements[1] = new Tuple("bar", 15); + itemIncrements[0] = new("foo", 5); + itemIncrements[1] = new("bar", 15); var resp = await cms.IncrByAsync(key, itemIncrements); Assert.Equal(new long[] { 10, 15 }, resp); @@ -187,8 +183,8 @@ public void TestQuery(string endpointId) cms.InitByDim(key, 1000, 5); var itemIncrements = new Tuple[2]; - itemIncrements[0] = new Tuple("foo", 10); - itemIncrements[1] = new Tuple("bar", 15); + itemIncrements[0] = new("foo", 10); + itemIncrements[1] = new("bar", 15); cms.IncrBy(key, itemIncrements); @@ -205,8 +201,8 @@ public async Task TestQueryAsync(string endpointId) await cms.InitByDimAsync(key, 1000, 5); var itemIncrements = new Tuple[2]; - itemIncrements[0] = new Tuple("foo", 10); - itemIncrements[1] = new Tuple("bar", 15); + itemIncrements[0] = new("foo", 10); + itemIncrements[1] = new("bar", 15); await cms.IncrByAsync(key, itemIncrements); @@ -214,7 +210,7 @@ public async Task TestQueryAsync(string endpointId) Assert.Equal(new long[] { 10, 15 }, resp); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestMerge(string endpointId) { @@ -226,44 +222,44 @@ public void TestMerge(string endpointId) cms.InitByDim("C", 1000, 5); var aValues = new Tuple[3]; - aValues[0] = new Tuple("foo", 5); - aValues[1] = new Tuple("bar", 3); - aValues[2] = new Tuple("baz", 9); + aValues[0] = new("foo", 5); + aValues[1] = new("bar", 3); + aValues[2] = new("baz", 9); cms.IncrBy("A", aValues); var bValues = new Tuple[3]; - bValues[0] = new Tuple("foo", 2); - bValues[1] = new Tuple("bar", 3); - bValues[2] = new Tuple("baz", 1); + bValues[0] = new("foo", 2); + bValues[1] = new("bar", 3); + bValues[2] = new("baz", 1); cms.IncrBy("B", bValues); var q1 = cms.Query("A", new RedisValue[] { "foo", "bar", "baz" }); - Assert.Equal(new long[] { 5L, 3L, 9L }, q1); + Assert.Equal(new[] { 5L, 3L, 9L }, q1); var q2 = cms.Query("B", new RedisValue[] { "foo", "bar", "baz" }); - Assert.Equal(new long[] { 2L, 3L, 1L }, q2); + Assert.Equal(new[] { 2L, 3L, 1L }, q2); - cms.Merge("C", 2, new RedisValue[] { "A", "B" }); + cms.Merge("C", 2, ["A", "B"]); var q3 = cms.Query("C", new RedisValue[] { "foo", "bar", "baz" }); - Assert.Equal(new long[] { 7L, 6L, 10L }, q3); + Assert.Equal(new[] { 7L, 6L, 10L }, q3); - cms.Merge("C", 2, new RedisValue[] { "A", "B" }, new long[] { 1, 2 }); + cms.Merge("C", 2, ["A", "B"], [1, 2]); var q4 = cms.Query("C", new RedisValue[] { "foo", "bar", "baz" }); - Assert.Equal(new long[] { 9L, 9L, 11L }, q4); + Assert.Equal(new[] { 9L, 9L, 11L }, q4); - cms.Merge("C", 2, new RedisValue[] { "A", "B" }, new long[] { 2, 3 }); + cms.Merge("C", 2, ["A", "B"], [2, 3]); var q5 = cms.Query("C", new RedisValue[] { "foo", "bar", "baz" }); - Assert.Equal(new long[] { 16L, 15L, 21L }, q5); + Assert.Equal(new[] { 16L, 15L, 21L }, q5); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestMergeAsync(string endpointId) { @@ -275,40 +271,40 @@ public async Task TestMergeAsync(string endpointId) await cms.InitByDimAsync("C", 1000, 5); var aValues = new Tuple[3]; - aValues[0] = new Tuple("foo", 5); - aValues[1] = new Tuple("bar", 3); - aValues[2] = new Tuple("baz", 9); + aValues[0] = new("foo", 5); + aValues[1] = new("bar", 3); + aValues[2] = new("baz", 9); await cms.IncrByAsync("A", aValues); var bValues = new Tuple[3]; - bValues[0] = new Tuple("foo", 2); - bValues[1] = new Tuple("bar", 3); - bValues[2] = new Tuple("baz", 1); + bValues[0] = new("foo", 2); + bValues[1] = new("bar", 3); + bValues[2] = new("baz", 1); await cms.IncrByAsync("B", bValues); var q1 = await cms.QueryAsync("A", new RedisValue[] { "foo", "bar", "baz" }); - Assert.Equal(new long[] { 5L, 3L, 9L }, q1); + Assert.Equal(new[] { 5L, 3L, 9L }, q1); var q2 = await cms.QueryAsync("B", new RedisValue[] { "foo", "bar", "baz" }); - Assert.Equal(new long[] { 2L, 3L, 1L }, q2); + Assert.Equal(new[] { 2L, 3L, 1L }, q2); - await cms.MergeAsync("C", 2, new RedisValue[] { "A", "B" }); + await cms.MergeAsync("C", 2, ["A", "B"]); var q3 = await cms.QueryAsync("C", new RedisValue[] { "foo", "bar", "baz" }); - Assert.Equal(new long[] { 7L, 6L, 10L }, q3); + Assert.Equal(new[] { 7L, 6L, 10L }, q3); - await cms.MergeAsync("C", 2, new RedisValue[] { "A", "B" }, new long[] { 1, 2 }); + await cms.MergeAsync("C", 2, ["A", "B"], [1, 2]); var q4 = await cms.QueryAsync("C", new RedisValue[] { "foo", "bar", "baz" }); - Assert.Equal(new long[] { 9L, 9L, 11L }, q4); + Assert.Equal(new[] { 9L, 9L, 11L }, q4); - await cms.MergeAsync("C", 2, new RedisValue[] { "A", "B" }, new long[] { 2, 3 }); + await cms.MergeAsync("C", 2, ["A", "B"], [2, 3]); var q5 = await cms.QueryAsync("C", new RedisValue[] { "foo", "bar", "baz" }); - Assert.Equal(new long[] { 16L, 15L, 21L }, q5); + Assert.Equal(new[] { 16L, 15L, 21L }, q5); } diff --git a/tests/NRedisStack.Tests/CuckooFilter/CuckooTests.cs b/tests/NRedisStack.Tests/CuckooFilter/CuckooTests.cs index 8e60716e..7af86e67 100644 --- a/tests/NRedisStack.Tests/CuckooFilter/CuckooTests.cs +++ b/tests/NRedisStack.Tests/CuckooFilter/CuckooTests.cs @@ -116,7 +116,7 @@ public void TestCountFilterExist(string endpointId) var db = GetCleanDatabase(endpointId); var cf = db.CF(); - cf.Insert(key, new RedisValue[] { "foo" }); + cf.Insert(key, ["foo"]); Assert.Equal(0, cf.Count(key, "notExistItem")); } @@ -127,7 +127,7 @@ public async Task TestCountFilterExistAsync(string endpointId) var db = GetCleanDatabase(endpointId); var cf = db.CF(); - await cf.InsertAsync(key, new RedisValue[] { "foo" }); + await cf.InsertAsync(key, ["foo"]); Assert.Equal(0, await cf.CountAsync(key, "notExistItem")); } @@ -138,7 +138,7 @@ public void TestCountItemExist(string endpointId) var db = GetCleanDatabase(endpointId); var cf = db.CF(); - cf.Insert(key, new RedisValue[] { "foo" }); + cf.Insert(key, ["foo"]); Assert.Equal(1, cf.Count(key, "foo")); } @@ -149,7 +149,7 @@ public async Task TestCountItemExistAsync(string endpointId) var db = GetCleanDatabase(endpointId); var cf = db.CF(); - await cf.InsertAsync(key, new RedisValue[] { "foo" }); + await cf.InsertAsync(key, ["foo"]); Assert.Equal(1, await cf.CountAsync(key, "foo")); } @@ -236,7 +236,7 @@ public void TestInsert(string endpointId) var db = GetCleanDatabase(endpointId); var cf = db.CF(); - RedisValue[] items = new RedisValue[] { "item1", "item2", "item3" }; + RedisValue[] items = ["item1", "item2", "item3"]; cf.Insert("key", items); @@ -252,7 +252,7 @@ public async Task TestInsertAsync(string endpointId) var db = GetCleanDatabase(endpointId); var cf = db.CF(); - RedisValue[] items = new RedisValue[] { "item1", "item2", "item3" }; + RedisValue[] items = ["item1", "item2", "item3"]; await cf.InsertAsync("key", items); @@ -268,12 +268,12 @@ public void TestInsertNX(string endpointId) var db = GetCleanDatabase(endpointId); var cf = db.CF(); - RedisValue[] items = new RedisValue[] { "item1", "item2", "item3" }; + RedisValue[] items = ["item1", "item2", "item3"]; Assert.Throws(() => cf.InsertNX(key, items, 1024, true)); var result = cf.InsertNX(key, items, 1024); cf.InsertNX(key, items, 10245, true); - var trues = new bool[] { true, true, true }; + var trues = new[] { true, true, true }; Assert.Equal(result, trues); Assert.True(cf.Exists(key, "item1")); @@ -283,10 +283,10 @@ public void TestInsertNX(string endpointId) Assert.Equal(cf.MExists(key, items), trues); result = cf.InsertNX(key, items); - Assert.Equal(result, new bool[] { false, false, false }); + Assert.Equal(result, new[] { false, false, false }); // test empty items: - Assert.Throws(() => cf.InsertNX(key, new RedisValue[] { })); + Assert.Throws(() => cf.InsertNX(key, [])); } [SkippableTheory] @@ -296,12 +296,12 @@ public async Task TestInsertNXAsync(string endpointId) var db = GetCleanDatabase(endpointId); var cf = db.CF(); - RedisValue[] items = new RedisValue[] { "item1", "item2", "item3" }; + RedisValue[] items = ["item1", "item2", "item3"]; await Assert.ThrowsAsync(async () => await cf.InsertNXAsync(key, items, 1024, true)); var result = await cf.InsertNXAsync(key, items, 1024); await cf.InsertNXAsync(key, items, 10245, true); - var trues = new bool[] { true, true, true }; + var trues = new[] { true, true, true }; Assert.Equal(result, trues); Assert.True(await cf.ExistsAsync(key, "item1")); @@ -311,10 +311,10 @@ public async Task TestInsertNXAsync(string endpointId) Assert.Equal(await cf.MExistsAsync(key, items), trues); result = await cf.InsertNXAsync(key, items); - Assert.Equal(result, new bool[] { false, false, false }); + Assert.Equal(result, new[] { false, false, false }); // test empty items: - await Assert.ThrowsAsync(async () => await cf.InsertNXAsync(key, new RedisValue[] { })); + await Assert.ThrowsAsync(async () => await cf.InsertNXAsync(key, [])); } [SkippableTheory] @@ -324,7 +324,7 @@ public void TestExistsNonExist(string endpointId) var db = GetCleanDatabase(endpointId); var cf = db.CF(); - RedisValue item = new RedisValue("item"); + RedisValue item = new("item"); Assert.False(cf.Exists("NonExistKey", item)); } @@ -335,7 +335,7 @@ public async Task TestExistsNonExistAsync(string endpointId) var db = GetCleanDatabase(endpointId); var cf = db.CF(); - RedisValue item = new RedisValue("item"); + RedisValue item = new("item"); Assert.False(await cf.ExistsAsync("NonExistKey", item)); } diff --git a/tests/NRedisStack.Tests/EndpointsFixture.cs b/tests/NRedisStack.Tests/EndpointsFixture.cs index 00ba786a..0a1adf7c 100644 --- a/tests/NRedisStack.Tests/EndpointsFixture.cs +++ b/tests/NRedisStack.Tests/EndpointsFixture.cs @@ -48,23 +48,23 @@ public static class Env public static IEnumerable AllEnvironments() { - yield return new object[] { Standalone }; - yield return new object[] { Cluster }; + yield return [Standalone]; + yield return [Cluster]; // TODO(imalinovskiy): Add support for Sentinel } public static IEnumerable StandaloneOnly() { - yield return new object[] { Standalone }; + yield return [Standalone]; } } private readonly string? redisEndpointsPath = Environment.GetEnvironmentVariable("REDIS_ENDPOINTS_CONFIG_PATH") ?? "endpoints.json"; - private Dictionary redisEndpoints = new(); + private readonly Dictionary redisEndpoints = new(); public static readonly bool IsEnterprise = Environment.GetEnvironmentVariable("IS_ENTERPRISE") == "true"; - public static Version RedisVersion = new Version(Environment.GetEnvironmentVariable("REDIS_VERSION") ?? "0.0.0"); + public static Version RedisVersion = new(Environment.GetEnvironmentVariable("REDIS_VERSION") ?? "0.0.0"); public EndpointsFixture() { @@ -73,7 +73,7 @@ public EndpointsFixture() string json = File.ReadAllText(redisEndpointsPath); var parsedEndpoints = JsonSerializer.Deserialize>(json); - redisEndpoints = parsedEndpoints ?? throw new Exception("Failed to parse the Redis endpoints configuration."); + redisEndpoints = parsedEndpoints ?? throw new("Failed to parse the Redis endpoints configuration."); } else { diff --git a/tests/NRedisStack.Tests/Examples/ExampleTests.cs b/tests/NRedisStack.Tests/Examples/ExampleTests.cs index 98a988d3..a788aacd 100644 --- a/tests/NRedisStack.Tests/Examples/ExampleTests.cs +++ b/tests/NRedisStack.Tests/Examples/ExampleTests.cs @@ -1,3 +1,4 @@ +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; using NRedisStack.Search; @@ -10,14 +11,11 @@ namespace NRedisStack.Tests; -public class ExampleTests : AbstractNRedisStackTest, IDisposable +public class ExampleTests(EndpointsFixture endpointsFixture, ITestOutputHelper testOutputHelper) + : AbstractNRedisStackTest(endpointsFixture), IDisposable { - private readonly ITestOutputHelper testOutputHelper; + private readonly ITestOutputHelper testOutputHelper = testOutputHelper; - public ExampleTests(EndpointsFixture endpointsFixture, ITestOutputHelper testOutputHelper) : base(endpointsFixture) - { - this.testOutputHelper = testOutputHelper; - } // private readonly string key = "EXAMPLES_TESTS"; [SkippableTheory] @@ -33,13 +31,13 @@ public void HSETandSearch(string endpointId) var ft = db.FT(); // Use HSET to add a field-value pair to a hash - db.HashSet("professor:5555", new HashEntry[] { new("first", "Albert"), new("last", "Blue"), new("age", "55") }); - db.HashSet("student:1111", new HashEntry[] { new("first", "Joe"), new("last", "Dod"), new("age", "18") }); - db.HashSet("pupil:2222", new HashEntry[] { new("first", "Jen"), new("last", "Rod"), new("age", "14") }); - db.HashSet("student:3333", new HashEntry[] { new("first", "El"), new("last", "Mark"), new("age", "17") }); - db.HashSet("pupil:4444", new HashEntry[] { new("first", "Pat"), new("last", "Shu"), new("age", "21") }); - db.HashSet("student:5555", new HashEntry[] { new("first", "Joen"), new("last", "Ko"), new("age", "20") }); - db.HashSet("teacher:6666", new HashEntry[] { new("first", "Pat"), new("last", "Rod"), new("age", "20") }); + db.HashSet("professor:5555", [new("first", "Albert"), new("last", "Blue"), new("age", "55")]); + db.HashSet("student:1111", [new("first", "Joe"), new("last", "Dod"), new("age", "18")]); + db.HashSet("pupil:2222", [new("first", "Jen"), new("last", "Rod"), new("age", "14")]); + db.HashSet("student:3333", [new("first", "El"), new("last", "Mark"), new("age", "17")]); + db.HashSet("pupil:4444", [new("first", "Pat"), new("last", "Shu"), new("age", "21")]); + db.HashSet("student:5555", [new("first", "Joen"), new("last", "Ko"), new("age", "20")]); + db.HashSet("teacher:6666", [new("first", "Pat"), new("last", "Rod"), new("age", "20")]); // Create the schema to index first and last as text fields, and age as a numeric field var schema = new Schema().AddTextField("first").AddTextField("last").AddNumericField("age"); @@ -49,22 +47,22 @@ public void HSETandSearch(string endpointId) ft.Create("example_index", parameters, schema); //sleep: - System.Threading.Thread.Sleep(2000); + Thread.Sleep(2000); // Search all hashes in the index - var noFilters = ft.Search("example_index", new Query()); + var noFilters = ft.Search("example_index", new()); // noFilters now contains: student:1111, student:5555, pupil:4444, student:3333 // Search for hashes with a first name starting with Jo - var startWithJo = ft.Search("example_index", new Query("@first:Jo*")); + var startWithJo = ft.Search("example_index", new("@first:Jo*")); // startWithJo now contains: student:1111 (Joe), student:5555 (Joen) // Search for hashes with first name of Pat - var namedPat = ft.Search("example_index", new Query("@first:Pat")); + var namedPat = ft.Search("example_index", new("@first:Pat")); // namedPat now contains pupil:4444 (Pat). teacher:6666 (Pat) is not included because it does not have a prefix of student: or pupil: // Search for hashes with last name of Rod - var lastNameRod = ft.Search("example_index", new Query("@last:Rod")); + var lastNameRod = ft.Search("example_index", new("@last:Rod")); // lastNameRod is empty because there are no hashes with a last name of Rod that match the index definition Assert.Equal(4, noFilters.TotalResults); Assert.Equal(2, startWithJo.TotalResults); @@ -153,7 +151,7 @@ public async Task JsonWithSearchPipeline(string endpointId) // Search for all indexed person records Task.Delay(2000).Wait(); - var getAllPersons = await db.FT().SearchAsync("person-idx", new Query()); + var getAllPersons = await db.FT().SearchAsync("person-idx", new()); // Get the total count of people records that indexed. @@ -168,7 +166,7 @@ public async Task JsonWithSearchPipeline(string endpointId) // Assert.Equal("person:01", firstPerson?.Id); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task PipelineWithAsync(string endpointId) { @@ -183,8 +181,8 @@ public async Task PipelineWithAsync(string endpointId) var pipeline = new Pipeline(db); // Create metadata labels for time-series. - TimeSeriesLabel label1 = new TimeSeriesLabel("temp", "TLV"); - TimeSeriesLabel label2 = new TimeSeriesLabel("temp", "JLM"); + TimeSeriesLabel label1 = new("temp", "TLV"); + TimeSeriesLabel label2 = new("temp", "JLM"); var labels1 = new List { label1 }; var labels2 = new List { label2 }; @@ -194,21 +192,19 @@ public async Task PipelineWithAsync(string endpointId) // Adding multiple sequence of time-series data. List<(string, TimeStamp, double)> sequence1 = - new() - { - ("temp:TLV", 1000, 30), - ("temp:TLV", 1010, 35), - ("temp:TLV", 1020, 9999), - ("temp:TLV", 1030, 40) - }; + [ + ("temp:TLV", 1000, 30), + ("temp:TLV", 1010, 35), + ("temp:TLV", 1020, 9999), + ("temp:TLV", 1030, 40) + ]; List<(string, TimeStamp, double)> sequence2 = - new() - { - ("temp:JLM", 1005, 30), - ("temp:JLM", 1015, 35), - ("temp:JLM", 1025, 9999), - ("temp:JLM", 1035, 40) - }; + [ + ("temp:JLM", 1005, 30), + ("temp:JLM", 1015, 35), + ("temp:JLM", 1025, 9999), + ("temp:JLM", 1035, 40) + ]; // Adding multiple samples to multiple series. _ = pipeline.Ts.MAddAsync(sequence1); @@ -229,7 +225,7 @@ public async Task PipelineWithAsync(string endpointId) Assert.Equal("temp:JLM", response[0].key); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TransactionExample(string endpointId) { @@ -292,7 +288,7 @@ public void TestJsonConvert(string endpointId) json.Set("doc:" + i, "$", "{\"name\":\"foo\"}"); } - var res = ft.Search("test", new Query("@name:{foo}")); + var res = ft.Search("test", new("@name:{foo}")); var docs = res.ToJson(); @@ -658,7 +654,7 @@ public void BasicJsonExamplesTest(string endpointId) Thread.Sleep(2000); res = json.Get(key: "ex2:3", - paths: new[] { "$.field1", "$.field2" }, + paths: ["$.field1", "$.field2"], indent: "\t", newLine: "\n" ); @@ -1034,7 +1030,7 @@ public void BasicQueryOperationsTest(string endpointId) Thread.Sleep(2000); // Find all documents for a given index: - var res = ft.Search("idx1", new Query("*")).ToJson(); + var res = ft.Search("idx1", new("*")).ToJson(); Assert.NotNull(res); // Assert.Equal(3, res!.Count); @@ -1049,98 +1045,93 @@ public void BasicQueryOperationsTest(string endpointId) // Find all documents with a given word in a text field: - res = ft.Search("idx1", new Query("@description:Slippers")).ToJson(); + res = ft.Search("idx1", new("@description:Slippers")).ToJson(); var expected = "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}"; - Assert.Equal(expected, res![0].ToString()); + Assert.Equal(expected, res[0].ToString()); // Find all documents with a given phrase in a text field: - res = ft.Search("idx1", new Query("@description:(\"Blue Shirt\")")).ToJson(); + res = ft.Search("idx1", new("@description:(\"Blue Shirt\")")).ToJson(); expected = "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}"; - Assert.Equal(expected, res![0]); + Assert.Equal(expected, res[0]); // Find all documents with a numeric field in a given range: - res = ft.Search("idx1", new Query("@price:[40,130]")).ToJson(); + res = ft.Search("idx1", new("@price:[40,130]")).ToJson(); expectedList = - new List - { - "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}", - "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" - }; + [ + "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}", + "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" + ]; SortAndCompare(expectedList, res); // Find all documents that contain a given value in an array field (tag): - res = ft.Search("idx1", new Query("@season:{Spring}")).ToJson(); + res = ft.Search("idx1", new("@season:{Spring}")).ToJson(); expected = "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}"; Assert.Equal(expected, res[0]); // Find all documents contain both a numeric field in a range and a word in a text field: - res = ft.Search("idx1", new Query("@price:[40, 100] @description:Blue")).ToJson(); + res = ft.Search("idx1", new("@price:[40, 100] @description:Blue")).ToJson(); expected = "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}"; Assert.Equal(expected, res[0]); // Find all documents that either match tag value or text value: - res = ft.Search("idx1", new Query("(@gender:{Women})|(@city:Boston)")).ToJson(); + res = ft.Search("idx1", new("(@gender:{Women})|(@city:Boston)")).ToJson(); expectedList = - new List - { - "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}", - "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}" - }; + [ + "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}", + "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}" + ]; SortAndCompare(expectedList, res); // Find all documents that do not contain a given word in a text field: - res = ft.Search("idx1", new Query("-(@description:Shirt)")).ToJson(); + res = ft.Search("idx1", new("-(@description:Shirt)")).ToJson(); expectedList = - new List - { - "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}", - "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" - }; + [ + "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}", + "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" + ]; SortAndCompare(expectedList, res); // Find all documents that have a word that begins with a given prefix value: - res = ft.Search("idx1", new Query("@description:Nav*")).ToJson(); + res = ft.Search("idx1", new("@description:Nav*")).ToJson(); expectedList = - new List - { - "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}", - "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" - }; + [ + "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}", + "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" + ]; SortAndCompare(expectedList, res); // Find all documents that contain a word that ends with a given suffix value: - res = ft.Search("idx1", new Query("@description:*Watch")).ToJson(); + res = ft.Search("idx1", new("@description:*Watch")).ToJson(); expected = "{\"id\":59263,\"gender\":\"Women\",\"season\":[\"Fall\",\"Winter\",\"Spring\",\"Summer\"],\"description\":\"Titan Women Silver Watch\",\"price\":129.99,\"city\":\"Dallas\",\"coords\":\"-96.808891, 32.779167\"}"; Assert.Equal(expected, res[0].ToString()); // Find all documents that contain a word that is within 1 Levenshtein distance of a given word: - res = ft.Search("idx1", new Query("@description:%wavy%")).ToJson(); + res = ft.Search("idx1", new("@description:%wavy%")).ToJson(); expectedList = - new List - { - "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}", - "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" - }; + [ + "{\"id\":15970,\"gender\":\"Men\",\"season\":[\"Fall\",\"Winter\"],\"description\":\"Turtle Check Men Navy Blue Shirt\",\"price\":34.95,\"city\":\"Boston\",\"coords\":\"-71.057083, 42.361145\"}", + "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}" + ]; SortAndCompare(expectedList, res); // Find all documents that have geographic coordinates within a given range of a given coordinate. // Colorado Springs coords(long, lat) = -104.800644, 38.846127: - res = ft.Search("idx1", new Query("@coords:[-104.800644 38.846127 100 mi]")).ToJson(); + res = ft.Search("idx1", new("@coords:[-104.800644 38.846127 100 mi]")).ToJson(); expected = "{\"id\":46885,\"gender\":\"Boys\",\"season\":[\"Fall\"],\"description\":\"Ben 10 Boys Navy Blue Slippers\",\"price\":45.99,\"city\":\"Denver\",\"coords\":\"-104.991531, 39.742043\"}"; @@ -1159,26 +1150,22 @@ public void AdvancedQueryOperationsTest(string endpointId) // Vector Similarity Search (VSS) // Data load: - db.HashSet("vec:1", new HashEntry[] - { - new("vector", (new float[] { 1f, 1f, 1f, 1f }).SelectMany(BitConverter.GetBytes).ToArray()), + db.HashSet("vec:1", [ + new("vector", (new[] { 1f, 1f, 1f, 1f }).SelectMany(BitConverter.GetBytes).ToArray()), new("tag", "A") - }); - db.HashSet("vec:2", new HashEntry[] - { - new("vector", (new float[] { 2f, 2f, 2f, 2f }).SelectMany(BitConverter.GetBytes).ToArray()), + ]); + db.HashSet("vec:2", [ + new("vector", (new[] { 2f, 2f, 2f, 2f }).SelectMany(BitConverter.GetBytes).ToArray()), new("tag", "A") - }); - db.HashSet("vec:3", new HashEntry[] - { - new("vector", (new float[] { 3f, 3f, 3f, 3f }).SelectMany(BitConverter.GetBytes).ToArray()), + ]); + db.HashSet("vec:3", [ + new("vector", (new[] { 3f, 3f, 3f, 3f }).SelectMany(BitConverter.GetBytes).ToArray()), new("tag", "B") - }); - db.HashSet("vec:4", new HashEntry[] - { - new("vector", (new float[] { 4f, 4f, 4f, 4f }).SelectMany(BitConverter.GetBytes).ToArray()), + ]); + db.HashSet("vec:4", [ + new("vector", (new[] { 4f, 4f, 4f, 4f }).SelectMany(BitConverter.GetBytes).ToArray()), new("tag", "A") - }); + ]); // Index creation: try @@ -1194,7 +1181,7 @@ public void AdvancedQueryOperationsTest(string endpointId) new Schema() .AddTagField("tag") .AddVectorField("vector", VectorField.VectorAlgo.FLAT, - new Dictionary() + new() { ["TYPE"] = "FLOAT32", ["DIM"] = "4", @@ -1206,13 +1193,13 @@ public void AdvancedQueryOperationsTest(string endpointId) Thread.Sleep(2000); // Search: - float[] vec = new[] { 2f, 3f, 3f, 3f }; + float[] vec = [2f, 3f, 3f, 3f]; var res = ft.Search("vss_idx", new Query("*=>[KNN 2 @vector $query_vec]") .AddParam("query_vec", vec.SelectMany(BitConverter.GetBytes).ToArray()) .SetSortBy("__vector_score") .Dialect(2)); - HashSet resSet = new HashSet(); + HashSet resSet = []; foreach (var doc in res.Documents) { foreach (var item in doc.GetProperties()) @@ -1224,11 +1211,11 @@ public void AdvancedQueryOperationsTest(string endpointId) } } - HashSet expectedResSet = new HashSet() - { + HashSet expectedResSet = + [ "id: vec:3, score: 1", - "id: vec:2, score: 3", - }; + "id: vec:2, score: 3" + ]; Assert.Equal(expectedResSet, resSet); @@ -1252,11 +1239,10 @@ public void AdvancedQueryOperationsTest(string endpointId) } expectedResSet = - new HashSet - { - "id: vec:2, score: 3", - "id: vec:4, score: 7" - }; + [ + "id: vec:2, score: 3", + "id: vec:4, score: 7" + ]; //Advanced Search Queries: // data load: diff --git a/tests/NRedisStack.Tests/Json/JsonTests.cs b/tests/NRedisStack.Tests/Json/JsonTests.cs index 2532e0fc..952d3359 100644 --- a/tests/NRedisStack.Tests/Json/JsonTests.cs +++ b/tests/NRedisStack.Tests/Json/JsonTests.cs @@ -7,12 +7,8 @@ namespace NRedisStack.Tests; -public class JsonTests : AbstractNRedisStackTest, IDisposable +public class JsonTests(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable { - public JsonTests(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } - [SkippableTheory] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] public void TestSetFromFile(string endpointId) @@ -154,10 +150,10 @@ public void TestResp(string endpointId) //assert var i = 0; - Assert.Equal("{", respResult[i++]!.ToString()); - Assert.Equal("name", respResult[i++]!.ToString()); - Assert.Equal("Steve", respResult[i++]!.ToString()); - Assert.Equal("age", respResult[i++]!.ToString()); + Assert.Equal("{", respResult[i++].ToString()); + Assert.Equal("name", respResult[i++].ToString()); + Assert.Equal("Steve", respResult[i++].ToString()); + Assert.Equal("age", respResult[i++].ToString()); Assert.Equal(33, (long)respResult[i]!); conn.GetDatabase().KeyDelete(key); } @@ -180,10 +176,10 @@ public async Task TestRespAsync(string endpointId) //assert var i = 0; - Assert.Equal("{", respResult[i++]!.ToString()); - Assert.Equal("name", respResult[i++]!.ToString()); - Assert.Equal("Steve", respResult[i++]!.ToString()); - Assert.Equal("age", respResult[i++]!.ToString()); + Assert.Equal("{", respResult[i++].ToString()); + Assert.Equal("name", respResult[i++].ToString()); + Assert.Equal("Steve", respResult[i++].ToString()); + Assert.Equal("age", respResult[i++].ToString()); Assert.Equal(33, (long)respResult[i]!); conn.GetDatabase().KeyDelete(key); } @@ -712,7 +708,7 @@ public void Get(string endpointId) var jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; result = commands.Get(caseInsensitiveKey, "$", jsonOptions); Assert.NotNull(result); - Assert.Equal("Alice", result!.Name); + Assert.Equal("Alice", result.Name); Assert.Equal(35, result.Age); var people = commands.GetEnumerable(complexKey, "$..a").ToArray(); Assert.Equal(2, people.Length); @@ -740,7 +736,7 @@ public async Task GetAsync(string endpointId) var jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; result = await commands.GetAsync(caseInsensitiveKey, "$", jsonOptions); Assert.NotNull(result); - Assert.Equal("Alice", result!.Name); + Assert.Equal("Alice", result.Name); Assert.Equal(35, result.Age); var people = (await commands.GetEnumerableAsync(complexKey, "$..a")).ToArray(); Assert.Equal(2, people.Length); @@ -750,7 +746,7 @@ public async Task GetAsync(string endpointId) Assert.Equal(35, people[1]!.Age); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.1.242")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.1.242")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void MSet(string endpointId) { @@ -759,11 +755,11 @@ public void MSet(string endpointId) var key1 = keys[0]; var key2 = keys[1]; - KeyPathValue[] values = new[] - { - new KeyPathValue(key1, "$", new { a = "hello" }), - new KeyPathValue(key2, "$", new { a = "world" }) - }; + KeyPathValue[] values = + [ + new(key1, "$", new { a = "hello" }), + new(key2, "$", new { a = "world" }) + ]; commands.MSet(values); var result = commands.MGet(keys.Select(x => new RedisKey(x)).ToArray(), "$.a"); @@ -772,10 +768,10 @@ public void MSet(string endpointId) Assert.Equal("[\"world\"]", result[1].ToString()); // test errors: - Assert.Throws(() => commands.MSet(new KeyPathValue[0])); + Assert.Throws(() => commands.MSet([])); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.1.242")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.1.242")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task MSetAsync(string endpointId) { @@ -783,11 +779,11 @@ public async Task MSetAsync(string endpointId) var keys = CreateKeyNames(2); var key1 = keys[0]; var key2 = keys[1]; - KeyPathValue[] values = new[] - { - new KeyPathValue(key1, "$", new { a = "hello" }), - new KeyPathValue(key2, "$", new { a = "world" }) - }; + KeyPathValue[] values = + [ + new(key1, "$", new { a = "hello" }), + new(key2, "$", new { a = "world" }) + ]; await commands.MSetAsync(values); var result = await commands.MGetAsync(keys.Select(x => new RedisKey(x)).ToArray(), "$.a"); @@ -796,10 +792,10 @@ public async Task MSetAsync(string endpointId) Assert.Equal("[\"world\"]", result[1].ToString()); // test errors: - await Assert.ThrowsAsync(async () => await commands.MSetAsync(new KeyPathValue[0])); + await Assert.ThrowsAsync(async () => await commands.MSetAsync([])); } - [SkipIfRedis("7.1.242")] + [SkipIfRedisTheory("7.1.242")] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] public void Merge(string endpointId) { @@ -819,7 +815,7 @@ public void Merge(string endpointId) Assert.Equal("{\"person\":{\"name\":\"John Doe\",\"phone\":\"123-456-7890\",\"address\":{\"home\":\"123 Main Street\",\"work\":\"Redis office\"}}}", commands.Get("test_merge").ToString()); } - [SkipIfRedis("7.1.242")] + [SkipIfRedisTheory("7.1.242")] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] public async Task MergeAsync(string endpointId) { @@ -839,7 +835,7 @@ public async Task MergeAsync(string endpointId) Assert.Equal("{\"person\":{\"name\":\"John Doe\",\"phone\":\"123-456-7890\",\"address\":{\"home\":\"123 Main Street\",\"work\":\"Redis office\"}}}", (await commands.GetAsync("test_merge")).ToString()); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void MGet(string endpointId) { @@ -855,7 +851,7 @@ public void MGet(string endpointId) Assert.Equal("[\"world\"]", result[1].ToString()); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task MGetAsync(string endpointId) { @@ -979,8 +975,8 @@ public void TestMultiPathGet(string endpointId) var keys = CreateKeyNames(1); var key = keys[0]; commands.Set(key, "$", new { a = "hello", b = new { a = "world" } }); - var res = commands.Get(key, new[] { "$..a", "$.b" }).ToString(); - var obj = JsonSerializer.Deserialize(res!); + var res = commands.Get(key, ["$..a", "$.b"]).ToString(); + var obj = JsonSerializer.Deserialize(res); Assert.True(obj!.ContainsKey("$..a")); Assert.True(obj.ContainsKey("$.b")); if (obj["$..a"] is JsonArray arr) @@ -1004,8 +1000,8 @@ public async Task TestMultiPathGetAsync(string endpointId) var keys = CreateKeyNames(1); var key = keys[0]; await commands.SetAsync(key, "$", new { a = "hello", b = new { a = "world" } }); - var res = (await commands.GetAsync(key, new[] { "$..a", "$.b" })).ToString(); - var obj = JsonSerializer.Deserialize(res!); + var res = (await commands.GetAsync(key, ["$..a", "$.b"])).ToString(); + var obj = JsonSerializer.Deserialize(res); Assert.True(obj!.ContainsKey("$..a")); Assert.True(obj.ContainsKey("$.b")); if (obj["$..a"] is JsonArray arr) @@ -1136,7 +1132,7 @@ public async Task TestSetFromDirectoryAsync(string endpointId) public void TestJsonCommandBuilder() { var getBuild1 = JsonCommandBuilder.Get("key", "indent", "newline", "space", "path"); - var getBuild2 = JsonCommandBuilder.Get("key", new string[] { "path1", "path2", "path3" }, "indent", "newline", "space"); + var getBuild2 = JsonCommandBuilder.Get("key", ["path1", "path2", "path3"], "indent", "newline", "space"); var expectedArgs1 = new object[] { "key", "INDENT", "indent", "NEWLINE", "newline", "SPACE", "space", "path" }; var expectedArgs2 = new object[] { "key", "INDENT", "indent", "NEWLINE", "newline", "SPACE", "space", "path1", "path2", "path3" }; @@ -1204,10 +1200,10 @@ public void TestSetWithSerializationOptions(string endpointId) Person? result = commands.Get(key, serializerOptions: jsonOptions); Assert.NotNull(result); - Assert.Equal(person.Name, result!.Name); - Assert.Equal(person.Age, result!.Age); - Assert.NotNull(result!.Birthday); - Assert.Equal(person.Birthday, result!.Birthday); + Assert.Equal(person.Name, result.Name); + Assert.Equal(person.Age, result.Age); + Assert.NotNull(result.Birthday); + Assert.Equal(person.Birthday, result.Birthday); } [SkippableTheory] @@ -1224,13 +1220,13 @@ public async Task TestSetWithSerializationOptionsAsync(string endpointId) Person? result = await commands.GetAsync(key, serializerOptions: jsonOptions); Assert.NotNull(result); - Assert.Equal(person.Name, result!.Name); - Assert.Equal(person.Age, result!.Age); - Assert.NotNull(result!.Birthday); - Assert.Equal(person.Birthday, result!.Birthday); + Assert.Equal(person.Name, result.Name); + Assert.Equal(person.Age, result.Age); + Assert.NotNull(result.Birthday); + Assert.Equal(person.Birthday, result.Birthday); } - [SkipIfRedis("7.1.242")] + [SkipIfRedisTheory("7.1.242")] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] public void MergeWithSerializationOptions(string endpointId) { @@ -1247,11 +1243,11 @@ public void MergeWithSerializationOptions(string endpointId) RedisResult rr = commands.Get(key); Assert.False(rr.IsNull); - string actual = rr.ToString()!; + string actual = rr.ToString(); Assert.Equal(expected, actual); } - [SkipIfRedis("7.1.242")] + [SkipIfRedisTheory("7.1.242")] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] public async Task MergeWithSerializationOptionsAsync(string endpointId) { @@ -1268,7 +1264,7 @@ public async Task MergeWithSerializationOptionsAsync(string endpointId) RedisResult rr = await commands.GetAsync(key); Assert.False(rr.IsNull); - string actual = rr.ToString()!; + string actual = rr.ToString(); Assert.Equal(expected, actual); } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/NRedisStack.Tests.csproj b/tests/NRedisStack.Tests/NRedisStack.Tests.csproj index f8565f16..465b3fbf 100644 --- a/tests/NRedisStack.Tests/NRedisStack.Tests.csproj +++ b/tests/NRedisStack.Tests/NRedisStack.Tests.csproj @@ -1,8 +1,8 @@ - net6.0;net7.0;net8.0;net481 - net6.0;net7.0;net8.0 + net6.0;net7.0;net8.0;net481 false + true @@ -22,7 +22,15 @@ - + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + diff --git a/tests/NRedisStack.Tests/PipelineTests.cs b/tests/NRedisStack.Tests/PipelineTests.cs index 2c329fa7..b504f7fd 100644 --- a/tests/NRedisStack.Tests/PipelineTests.cs +++ b/tests/NRedisStack.Tests/PipelineTests.cs @@ -14,7 +14,7 @@ public PipelineTests(EndpointsFixture endpointsFixture) : base(endpointsFixture) private const string key = "PIPELINE_TESTS"; - [SkipIfRedis(Comparison.GreaterThanOrEqual, "7.1.242")] + [SkipIfRedisTheory(Comparison.GreaterThanOrEqual, "7.1.242")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] [Obsolete] public void TestModulesPipeline(string endpointId) @@ -27,7 +27,7 @@ public void TestModulesPipeline(string endpointId) _ = pipeline.Cms.InitByDimAsync("cms-key", 100, 5); _ = pipeline.Cf.ReserveAsync("cf-key", 100); _ = pipeline.Json.SetAsync("json-key", "$", "{}"); - _ = pipeline.Ft.CreateAsync("ft-key", new FTCreateParams(), new Schema().AddTextField("txt")); + _ = pipeline.Ft.CreateAsync("ft-key", new(), new Schema().AddTextField("txt")); _ = pipeline.Tdigest.CreateAsync("tdigest-key", 100); _ = pipeline.Ts.CreateAsync("ts-key", 100); _ = pipeline.TopK.ReserveAsync("topk-key", 100, 100, 100); @@ -75,7 +75,7 @@ public void TestModulesPipelineWithoutGraph(string endpointId) _ = pipeline.Cms.InitByDimAsync("cms-key", 100, 5); _ = pipeline.Cf.ReserveAsync("cf-key", 100); _ = pipeline.Json.SetAsync("json-key", "$", "{}"); - _ = pipeline.Ft.CreateAsync("ft-key", new FTCreateParams(), new Schema().AddTextField("txt")); + _ = pipeline.Ft.CreateAsync("ft-key", new(), new Schema().AddTextField("txt")); _ = pipeline.Tdigest.CreateAsync("tdigest-key", 100); _ = pipeline.Ts.CreateAsync("ts-key", 100); _ = pipeline.TopK.ReserveAsync("topk-key", 100, 100, 100); @@ -160,7 +160,7 @@ public void TestJsonPipeline(string endpointId) [SkippableTheory] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] [Obsolete] - public async void Issue401_TestPipelineAsInitialCommand(string endpointId) + public async Task Issue401_TestPipelineAsInitialCommand(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); diff --git a/tests/NRedisStack.Tests/Search/IndexCreationTests.cs b/tests/NRedisStack.Tests/Search/IndexCreationTests.cs index 789bc778..9833789c 100644 --- a/tests/NRedisStack.Tests/Search/IndexCreationTests.cs +++ b/tests/NRedisStack.Tests/Search/IndexCreationTests.cs @@ -6,14 +6,11 @@ namespace NRedisStack.Tests.Search; -public class IndexCreationTests : AbstractNRedisStackTest, IDisposable +public class IndexCreationTests(EndpointsFixture endpointsFixture) + : AbstractNRedisStackTest(endpointsFixture), IDisposable { private readonly string index = "MISSING_EMPTY_INDEX"; - public IndexCreationTests(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } - private static readonly string INDEXMISSING = "INDEXMISSING"; private static readonly string INDEXEMPTY = "INDEXEMPTY"; private static readonly string SORTABLE = "SORTABLE"; @@ -42,7 +39,7 @@ public void TestMissingEmptyFieldCommandArgs() Assert.Equal(expectedArgs, cmd.Args); } - [SkipIfRedis(Comparison.LessThan, "7.3.240")] + [SkipIfRedisTheory(Comparison.LessThan, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestMissingFields(string endpointId) { @@ -68,37 +65,38 @@ public void TestMissingFields(string endpointId) var hashWithMissingFields = new HashEntry[] { new("field1", "value1"), new("field2", "value2") }; db.HashSet("hashWithMissingFields", hashWithMissingFields); - Polygon polygon = new GeometryFactory().CreatePolygon(new Coordinate[] { new Coordinate(1, 1), new Coordinate(10, 10), new Coordinate(100, 100), new Coordinate(1, 1), }); + Polygon polygon = new GeometryFactory().CreatePolygon([new(1, 1), new(10, 10), new(100, 100), new(1, 1) + ]); var hashWithAllFields = new HashEntry[] { new("text1", "value1"), new("tag1", "value2"), new("numeric1", "3.141"), new("geo1", "-0.441,51.458"), new("geoshape1", polygon.ToString()), new("vector1", "aaaaaaaa") }; db.HashSet("hashWithAllFields", hashWithAllFields); - var result = ft.Search(index, new Query("ismissing(@text1)")); + var result = ft.Search(index, new("ismissing(@text1)")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithMissingFields", result.Documents[0].Id); - result = ft.Search(index, new Query("ismissing(@tag1)")); + result = ft.Search(index, new("ismissing(@tag1)")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithMissingFields", result.Documents[0].Id); - result = ft.Search(index, new Query("ismissing(@numeric1)")); + result = ft.Search(index, new("ismissing(@numeric1)")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithMissingFields", result.Documents[0].Id); - result = ft.Search(index, new Query("ismissing(@geo1)")); + result = ft.Search(index, new("ismissing(@geo1)")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithMissingFields", result.Documents[0].Id); - result = ft.Search(index, new Query("ismissing(@geoshape1)")); + result = ft.Search(index, new("ismissing(@geoshape1)")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithMissingFields", result.Documents[0].Id); - result = ft.Search(index, new Query("ismissing(@vector1)")); + result = ft.Search(index, new("ismissing(@vector1)")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithMissingFields", result.Documents[0].Id); } - [SkipIfRedis(Comparison.LessThan, "7.3.240")] + [SkipIfRedisTheory(Comparison.LessThan, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestEmptyFields(string endpointId) { @@ -117,44 +115,44 @@ public void TestEmptyFields(string endpointId) var hashWithAllFields = new HashEntry[] { new("text1", "value1"), new("tag1", "value2") }; db.HashSet("hashWithAllFields", hashWithAllFields); - var result = ft.Search(index, new Query("@text1:''")); + var result = ft.Search(index, new("@text1:''")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithEmptyFields", result.Documents[0].Id); - result = ft.Search(index, new Query("@tag1:{''}")); + result = ft.Search(index, new("@tag1:{''}")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithEmptyFields", result.Documents[0].Id); } - [SkipIfRedis(Comparison.LessThan, "7.3.240")] + [SkipIfRedisTheory(Comparison.LessThan, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestCreateFloat16VectorField(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(2); - var schema = new Schema().AddVectorField("v", Schema.VectorField.VectorAlgo.FLAT, new Dictionary() + var schema = new Schema().AddVectorField("v", Schema.VectorField.VectorAlgo.FLAT, new() { ["TYPE"] = "FLOAT16", ["DIM"] = "5", ["DISTANCE_METRIC"] = "L2", - }).AddVectorField("v2", Schema.VectorField.VectorAlgo.FLAT, new Dictionary() + }).AddVectorField("v2", Schema.VectorField.VectorAlgo.FLAT, new() { ["TYPE"] = "BFLOAT16", ["DIM"] = "4", ["DISTANCE_METRIC"] = "L2", }); - Assert.True(ft.Create("idx", new FTCreateParams(), schema)); + Assert.True(ft.Create("idx", new(), schema)); - short[] vec1 = new short[] { 2, 1, 2, 2, 2 }; + short[] vec1 = [2, 1, 2, 2, 2]; byte[] vec1ToBytes = new byte[vec1.Length * sizeof(short)]; Buffer.BlockCopy(vec1, 0, vec1ToBytes, 0, vec1ToBytes.Length); - short[] vec2 = new short[] { 1, 2, 2, 2 }; + short[] vec2 = [1, 2, 2, 2]; byte[] vec2ToBytes = new byte[vec2.Length * sizeof(short)]; Buffer.BlockCopy(vec2, 0, vec2ToBytes, 0, vec2ToBytes.Length); - var entries = new HashEntry[] { new HashEntry("v", vec1ToBytes), new HashEntry("v2", vec2ToBytes) }; + var entries = new HashEntry[] { new("v", vec1ToBytes), new("v2", vec2ToBytes) }; db.HashSet("a", entries); db.HashSet("b", entries); db.HashSet("c", entries); @@ -168,29 +166,29 @@ public void TestCreateFloat16VectorField(string endpointId) Assert.Equal(2, res.TotalResults); } - [SkipIfRedis(Comparison.LessThan, "7.9.0")] + [SkipIfRedisTheory(Comparison.LessThan, "7.9.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestCreateInt8VectorField(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(2); - var schema = new Schema().AddVectorField("v", Schema.VectorField.VectorAlgo.FLAT, new Dictionary() + var schema = new Schema().AddVectorField("v", Schema.VectorField.VectorAlgo.FLAT, new() { ["TYPE"] = "INT8", ["DIM"] = "5", ["DISTANCE_METRIC"] = "L2", - }).AddVectorField("v2", Schema.VectorField.VectorAlgo.FLAT, new Dictionary() + }).AddVectorField("v2", Schema.VectorField.VectorAlgo.FLAT, new() { ["TYPE"] = "UINT8", ["DIM"] = "4", ["DISTANCE_METRIC"] = "L2", }); - Assert.True(ft.Create("idx", new FTCreateParams(), schema)); + Assert.True(ft.Create("idx", new(), schema)); - byte[] vec1 = new byte[] { 2, 1, 2, 2, 2 }; - byte[] vec2 = new byte[] { 1, 2, 2, 2 }; + byte[] vec1 = [2, 1, 2, 2, 2]; + byte[] vec2 = [1, 2, 2, 2]; - var entries = new HashEntry[] { new HashEntry("v", vec1), new HashEntry("v2", vec2) }; + var entries = new HashEntry[] { new("v", vec1), new("v2", vec2) }; db.HashSet("a", entries); db.HashSet("b", entries); db.HashSet("c", entries); @@ -225,7 +223,7 @@ public void TestMissingSortableFieldCommandArgs() Assert.Equal(expectedArgs, cmd.Args); } - [SkipIfRedis(Comparison.LessThan, "7.3.240")] + [SkipIfRedisTheory(Comparison.LessThan, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestCombiningMissingEmptySortableFields(string endpointId) { @@ -252,32 +250,33 @@ public void TestCombiningMissingEmptySortableFields(string endpointId) var sampleHash = new HashEntry[] { new("field1", "value1"), new("field2", "value2") }; db.HashSet("hashWithMissingFields", sampleHash); - Polygon polygon = new GeometryFactory().CreatePolygon(new Coordinate[] { new Coordinate(1, 1), new Coordinate(10, 10), new Coordinate(100, 100), new Coordinate(1, 1), }); + Polygon polygon = new GeometryFactory().CreatePolygon([new(1, 1), new(10, 10), new(100, 100), new(1, 1) + ]); var hashWithAllFields = new HashEntry[] { new("text1", "value1"), new("tag1", "value2"), new("numeric1", "3.141"), new("geo1", "-0.441,51.458"), new("geoshape1", polygon.ToString()), new("vector1", "aaaaaaaa") }; db.HashSet("hashWithAllFields", hashWithAllFields); - var result = ft.Search(idx, new Query("ismissing(@text1)")); + var result = ft.Search(idx, new("ismissing(@text1)")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithMissingFields", result.Documents[0].Id); - result = ft.Search(idx, new Query("ismissing(@tag1)")); + result = ft.Search(idx, new("ismissing(@tag1)")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithMissingFields", result.Documents[0].Id); - result = ft.Search(idx, new Query("ismissing(@numeric1)")); + result = ft.Search(idx, new("ismissing(@numeric1)")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithMissingFields", result.Documents[0].Id); - result = ft.Search(idx, new Query("ismissing(@geo1)")); + result = ft.Search(idx, new("ismissing(@geo1)")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithMissingFields", result.Documents[0].Id); - result = ft.Search(idx, new Query("ismissing(@geoshape1)")); + result = ft.Search(idx, new("ismissing(@geoshape1)")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithMissingFields", result.Documents[0].Id); - result = ft.Search(idx, new Query("ismissing(@vector1)")); + result = ft.Search(idx, new("ismissing(@vector1)")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithMissingFields", result.Documents[0].Id); } diff --git a/tests/NRedisStack.Tests/Search/SearchTests.cs b/tests/NRedisStack.Tests/Search/SearchTests.cs index 9c059e2f..119faeff 100644 --- a/tests/NRedisStack.Tests/Search/SearchTests.cs +++ b/tests/NRedisStack.Tests/Search/SearchTests.cs @@ -1,3 +1,4 @@ +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using Xunit; using StackExchange.Redis; using NRedisStack.RedisStackCommands; @@ -11,7 +12,7 @@ namespace NRedisStack.Tests.Search; -public class SearchTests : AbstractNRedisStackTest, IDisposable +public class SearchTests(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable { // private readonly string key = "SEARCH_TESTS"; private readonly string index = "TEST_INDEX"; @@ -38,7 +39,7 @@ private void AddDocument(IDatabase db, Document doc) private void AddDocument(IDatabase db, string key, Dictionary objDictionary) { - Dictionary strDictionary = new Dictionary(); + Dictionary strDictionary = new(); // HashEntry[] hash = new HashEntry[objDictionary.Count()]; // for(int i = 0; i < objDictionary.Count(); i++) // { @@ -55,18 +56,18 @@ private void AddDocument(IDatabase db, string key, Dictionary ob db.Execute("HSET", nameValue); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] public void TestAggregationRequestVerbatim(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - Schema sc = new Schema(); + Schema sc = new(); sc.AddTextField("name", 1.0, sortable: true); ft.Create(index, FTCreateParams.CreateParams(), sc); AddDocument(db, new Document("data1").Set("name", "hello kitty")); - AggregationRequest r = new AggregationRequest("kitti"); + AggregationRequest r = new("kitti"); AggregationResult res = ft.Aggregate(index, r); Assert.Equal(1, res.TotalResults); @@ -78,18 +79,18 @@ public void TestAggregationRequestVerbatim(string endpointId) Assert.Equal(0, res.TotalResults); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] public async Task TestAggregationRequestVerbatimAsync(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - Schema sc = new Schema(); + Schema sc = new(); sc.AddTextField("name", 1.0, sortable: true); ft.Create(index, FTCreateParams.CreateParams(), sc); AddDocument(db, new Document("data1").Set("name", "hello kitty")); - AggregationRequest r = new AggregationRequest("kitti"); + AggregationRequest r = new("kitti"); AggregationResult res = await ft.AggregateAsync(index, r); Assert.Equal(1, res.TotalResults); @@ -107,7 +108,7 @@ public void TestAggregationRequestTimeout(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - Schema sc = new Schema(); + Schema sc = new(); sc.AddTextField("name", 1.0, sortable: true); sc.AddNumericField("count", sortable: true); ft.Create(index, FTCreateParams.CreateParams(), sc); @@ -129,7 +130,7 @@ public async Task TestAggregationRequestTimeoutAsync(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - Schema sc = new Schema(); + Schema sc = new(); sc.AddTextField("name", 1.0, sortable: true); sc.AddNumericField("count", sortable: true); ft.Create(index, FTCreateParams.CreateParams(), sc); @@ -151,7 +152,7 @@ public void TestAggregations(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - Schema sc = new Schema(); + Schema sc = new(); sc.AddTextField("name", 1.0, true); sc.AddNumericField("count", true); ft.Create(index, FTCreateParams.CreateParams(), sc); @@ -190,7 +191,7 @@ public async Task TestAggregationsAsync(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - Schema sc = new Schema(); + Schema sc = new(); sc.AddTextField("name", 1.0, true); sc.AddNumericField("count", true); await ft.CreateAsync(index, FTCreateParams.CreateParams(), sc); @@ -231,7 +232,7 @@ public void TestAggregationsLoad(string endpointId) IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); var sc = new Schema().AddTextField("t1").AddTextField("t2"); - ft.Create("idx", new FTCreateParams(), sc); + ft.Create("idx", new(), sc); AddDocument(db, new Document("doc1").Set("t1", "hello").Set("t2", "world")); @@ -259,7 +260,7 @@ public async Task TestAggregationsLoadAsync(string endpointId) IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); var sc = new Schema().AddTextField("t1").AddTextField("t2"); - await ft.CreateAsync("idx", new FTCreateParams(), sc); + await ft.CreateAsync("idx", new(), sc); AddDocument(db, new Document("doc1").Set("t1", "hello").Set("t2", "world")); @@ -288,7 +289,7 @@ public void TestAggregationRequestParamsDialect(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - Schema sc = new Schema(); + Schema sc = new(); sc.AddTextField("name", 1.0, sortable: true); sc.AddNumericField("count", sortable: true); ft.Create(index, FTCreateParams.CreateParams(), sc); @@ -296,7 +297,7 @@ public void TestAggregationRequestParamsDialect(string endpointId) AddDocument(db, new Document("data2").Set("name", "def").Set("count", 5)); AddDocument(db, new Document("data3").Set("name", "def").Set("count", 25)); - Dictionary parameters = new Dictionary(); + Dictionary parameters = new(); parameters.Add("name", "abc"); parameters.Add("count", "10"); @@ -319,7 +320,7 @@ public async Task TestAggregationRequestParamsDialectAsync(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - Schema sc = new Schema(); + Schema sc = new(); sc.AddTextField("name", 1.0, sortable: true); sc.AddNumericField("count", sortable: true); ft.Create(index, FTCreateParams.CreateParams(), sc); @@ -327,7 +328,7 @@ public async Task TestAggregationRequestParamsDialectAsync(string endpointId) AddDocument(db, new Document("data2").Set("name", "def").Set("count", 5)); AddDocument(db, new Document("data3").Set("name", "def").Set("count", 25)); - Dictionary parameters = new Dictionary(); + Dictionary parameters = new(); parameters.Add("name", "abc"); parameters.Add("count", "10"); @@ -351,7 +352,7 @@ public void TestAggregationRequestParamsWithDefaultDialect(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(2); - Schema sc = new Schema(); + Schema sc = new(); sc.AddTextField("name", 1.0, sortable: true); sc.AddNumericField("count", sortable: true); ft.Create(index, FTCreateParams.CreateParams(), sc); @@ -359,7 +360,7 @@ public void TestAggregationRequestParamsWithDefaultDialect(string endpointId) AddDocument(db, new Document("data2").Set("name", "def").Set("count", 5)); AddDocument(db, new Document("data3").Set("name", "def").Set("count", 25)); - Dictionary parameters = new Dictionary(); + Dictionary parameters = new(); parameters.Add("name", "abc"); parameters.Add("count", "10"); @@ -382,7 +383,7 @@ public async Task TestAggregationRequestParamsWithDefaultDialectAsync(string end { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(2); - Schema sc = new Schema(); + Schema sc = new(); sc.AddTextField("name", 1.0, sortable: true); sc.AddNumericField("count", sortable: true); ft.Create(index, FTCreateParams.CreateParams(), sc); @@ -390,7 +391,7 @@ public async Task TestAggregationRequestParamsWithDefaultDialectAsync(string end AddDocument(db, new Document("data2").Set("name", "def").Set("count", 5)); AddDocument(db, new Document("data3").Set("name", "def").Set("count", 25)); - Dictionary parameters = new Dictionary(); + Dictionary parameters = new(); parameters.Add("name", "abc"); parameters.Add("count", "10"); @@ -425,7 +426,7 @@ public void TestAlias(string endpointId) Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - Dictionary doc = new Dictionary(); + Dictionary doc = new(); doc.Add("field1", "value"); AddDocument(db, "doc1", doc); @@ -454,7 +455,7 @@ public async Task TestAliasAsync(string endpointId) Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - Dictionary doc = new Dictionary(); + Dictionary doc = new(); doc.Add("field1", "value"); AddDocument(db, "doc1", doc); @@ -479,7 +480,7 @@ public void TestApplyAndFilterAggregations(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - Schema sc = new Schema(); + Schema sc = new(); sc.AddTextField("name", 1.0, sortable: true); sc.AddNumericField("subj1", sortable: true); sc.AddNumericField("subj2", sortable: true); @@ -526,24 +527,24 @@ public void TestCreate(string endpointId) Assert.True(ft.Create(index, parameters, schema)); - db.HashSet("profesor:5555", new HashEntry[] { new("first", "Albert"), new("last", "Blue"), new("age", "55") }); - db.HashSet("student:1111", new HashEntry[] { new("first", "Joe"), new("last", "Dod"), new("age", "18") }); - db.HashSet("pupil:2222", new HashEntry[] { new("first", "Jen"), new("last", "Rod"), new("age", "14") }); - db.HashSet("student:3333", new HashEntry[] { new("first", "El"), new("last", "Mark"), new("age", "17") }); - db.HashSet("pupil:4444", new HashEntry[] { new("first", "Pat"), new("last", "Shu"), new("age", "21") }); - db.HashSet("student:5555", new HashEntry[] { new("first", "Joen"), new("last", "Ko"), new("age", "20") }); - db.HashSet("teacher:6666", new HashEntry[] { new("first", "Pat"), new("last", "Rod"), new("age", "20") }); + db.HashSet("profesor:5555", [new("first", "Albert"), new("last", "Blue"), new("age", "55")]); + db.HashSet("student:1111", [new("first", "Joe"), new("last", "Dod"), new("age", "18")]); + db.HashSet("pupil:2222", [new("first", "Jen"), new("last", "Rod"), new("age", "14")]); + db.HashSet("student:3333", [new("first", "El"), new("last", "Mark"), new("age", "17")]); + db.HashSet("pupil:4444", [new("first", "Pat"), new("last", "Shu"), new("age", "21")]); + db.HashSet("student:5555", [new("first", "Joen"), new("last", "Ko"), new("age", "20")]); + db.HashSet("teacher:6666", [new("first", "Pat"), new("last", "Rod"), new("age", "20")]); - var noFilters = ft.Search(index, new Query()); + var noFilters = ft.Search(index, new()); Assert.Equal(4, noFilters.TotalResults); - var res1 = ft.Search(index, new Query("@first:Jo*")); + var res1 = ft.Search(index, new("@first:Jo*")); Assert.Equal(2, res1.TotalResults); - var res2 = ft.Search(index, new Query("@first:Pat")); + var res2 = ft.Search(index, new("@first:Pat")); Assert.Equal(1, res2.TotalResults); - var res3 = ft.Search(index, new Query("@last:Rod")); + var res3 = ft.Search(index, new("@last:Rod")); Assert.Equal(0, res3.TotalResults); } @@ -556,20 +557,20 @@ public async Task TestCreateAsync(string endpointId) var schema = new Schema().AddTextField("first").AddTextField("last").AddNumericField("age"); var parameters = FTCreateParams.CreateParams().Filter("@age>16").Prefix("student:", "pupil:"); Assert.True(await ft.CreateAsync(index, parameters, schema)); - db.HashSet("profesor:5555", new HashEntry[] { new("first", "Albert"), new("last", "Blue"), new("age", "55") }); - db.HashSet("student:1111", new HashEntry[] { new("first", "Joe"), new("last", "Dod"), new("age", "18") }); - db.HashSet("pupil:2222", new HashEntry[] { new("first", "Jen"), new("last", "Rod"), new("age", "14") }); - db.HashSet("student:3333", new HashEntry[] { new("first", "El"), new("last", "Mark"), new("age", "17") }); - db.HashSet("pupil:4444", new HashEntry[] { new("first", "Pat"), new("last", "Shu"), new("age", "21") }); - db.HashSet("student:5555", new HashEntry[] { new("first", "Joen"), new("last", "Ko"), new("age", "20") }); - db.HashSet("teacher:6666", new HashEntry[] { new("first", "Pat"), new("last", "Rod"), new("age", "20") }); - var noFilters = ft.Search(index, new Query()); + db.HashSet("profesor:5555", [new("first", "Albert"), new("last", "Blue"), new("age", "55")]); + db.HashSet("student:1111", [new("first", "Joe"), new("last", "Dod"), new("age", "18")]); + db.HashSet("pupil:2222", [new("first", "Jen"), new("last", "Rod"), new("age", "14")]); + db.HashSet("student:3333", [new("first", "El"), new("last", "Mark"), new("age", "17")]); + db.HashSet("pupil:4444", [new("first", "Pat"), new("last", "Shu"), new("age", "21")]); + db.HashSet("student:5555", [new("first", "Joen"), new("last", "Ko"), new("age", "20")]); + db.HashSet("teacher:6666", [new("first", "Pat"), new("last", "Rod"), new("age", "20")]); + var noFilters = ft.Search(index, new()); Assert.Equal(4, noFilters.TotalResults); - var res1 = ft.Search(index, new Query("@first:Jo*")); + var res1 = ft.Search(index, new("@first:Jo*")); Assert.Equal(2, res1.TotalResults); - var res2 = ft.Search(index, new Query("@first:Pat")); + var res2 = ft.Search(index, new("@first:Pat")); Assert.Equal(1, res2.TotalResults); - var res3 = ft.Search(index, new Query("@last:Rod")); + var res3 = ft.Search(index, new("@last:Rod")); Assert.Equal(0, res3.TotalResults); } @@ -583,21 +584,21 @@ public void CreateNoParams(string endpointId) Schema sc = new Schema().AddTextField("first", 1.0).AddTextField("last", 1.0).AddNumericField("age"); Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - db.HashSet("student:1111", new HashEntry[] { new("first", "Joe"), new("last", "Dod"), new("age", 18) }); - db.HashSet("student:3333", new HashEntry[] { new("first", "El"), new("last", "Mark"), new("age", 17) }); - db.HashSet("pupil:4444", new HashEntry[] { new("first", "Pat"), new("last", "Shu"), new("age", 21) }); - db.HashSet("student:5555", new HashEntry[] { new("first", "Joen"), new("last", "Ko"), new("age", 20) }); + db.HashSet("student:1111", [new("first", "Joe"), new("last", "Dod"), new("age", 18)]); + db.HashSet("student:3333", [new("first", "El"), new("last", "Mark"), new("age", 17)]); + db.HashSet("pupil:4444", [new("first", "Pat"), new("last", "Shu"), new("age", 21)]); + db.HashSet("student:5555", [new("first", "Joen"), new("last", "Ko"), new("age", 20)]); - SearchResult noFilters = ft.Search(index, new Query()); + SearchResult noFilters = ft.Search(index, new()); Assert.Equal(4, noFilters.TotalResults); - SearchResult res1 = ft.Search(index, new Query("@first:Jo*")); + SearchResult res1 = ft.Search(index, new("@first:Jo*")); Assert.Equal(2, res1.TotalResults); - SearchResult res2 = ft.Search(index, new Query("@first:Pat")); + SearchResult res2 = ft.Search(index, new("@first:Pat")); Assert.Equal(1, res2.TotalResults); - SearchResult res3 = ft.Search(index, new Query("@last:Rod")); + SearchResult res3 = ft.Search(index, new("@last:Rod")); Assert.Equal(0, res3.TotalResults); } @@ -611,21 +612,21 @@ public async Task CreateNoParamsAsync(string endpointId) Schema sc = new Schema().AddTextField("first", 1.0).AddTextField("last", 1.0).AddNumericField("age"); Assert.True(await ft.CreateAsync(index, FTCreateParams.CreateParams(), sc)); - db.HashSet("student:1111", new HashEntry[] { new("first", "Joe"), new("last", "Dod"), new("age", 18) }); - db.HashSet("student:3333", new HashEntry[] { new("first", "El"), new("last", "Mark"), new("age", 17) }); - db.HashSet("pupil:4444", new HashEntry[] { new("first", "Pat"), new("last", "Shu"), new("age", 21) }); - db.HashSet("student:5555", new HashEntry[] { new("first", "Joen"), new("last", "Ko"), new("age", 20) }); + db.HashSet("student:1111", [new("first", "Joe"), new("last", "Dod"), new("age", 18)]); + db.HashSet("student:3333", [new("first", "El"), new("last", "Mark"), new("age", 17)]); + db.HashSet("pupil:4444", [new("first", "Pat"), new("last", "Shu"), new("age", 21)]); + db.HashSet("student:5555", [new("first", "Joen"), new("last", "Ko"), new("age", 20)]); - SearchResult noFilters = ft.Search(index, new Query()); + SearchResult noFilters = ft.Search(index, new()); Assert.Equal(4, noFilters.TotalResults); - SearchResult res1 = ft.Search(index, new Query("@first:Jo*")); + SearchResult res1 = ft.Search(index, new("@first:Jo*")); Assert.Equal(2, res1.TotalResults); - SearchResult res2 = ft.Search(index, new Query("@first:Pat")); + SearchResult res2 = ft.Search(index, new("@first:Pat")); Assert.Equal(1, res2.TotalResults); - SearchResult res3 = ft.Search(index, new Query("@last:Rod")); + SearchResult res3 = ft.Search(index, new("@last:Rod")); Assert.Equal(0, res3.TotalResults); } @@ -640,25 +641,25 @@ public void CreateWithFieldNames(string endpointId) Assert.True(ft.Create(index, FTCreateParams.CreateParams().Prefix("student:", "pupil:"), sc)); - db.HashSet("profesor:5555", new HashEntry[] { new("first", "Albert"), new("last", "Blue"), new("age", "55") }); - db.HashSet("student:1111", new HashEntry[] { new("first", "Joe"), new("last", "Dod"), new("age", "18") }); - db.HashSet("pupil:2222", new HashEntry[] { new("first", "Jen"), new("last", "Rod"), new("age", "14") }); - db.HashSet("student:3333", new HashEntry[] { new("first", "El"), new("last", "Mark"), new("age", "17") }); - db.HashSet("pupil:4444", new HashEntry[] { new("first", "Pat"), new("last", "Shu"), new("age", "21") }); - db.HashSet("student:5555", new HashEntry[] { new("first", "Joen"), new("last", "Ko"), new("age", "20") }); - db.HashSet("teacher:6666", new HashEntry[] { new("first", "Pat"), new("last", "Rod"), new("age", "20") }); + db.HashSet("profesor:5555", [new("first", "Albert"), new("last", "Blue"), new("age", "55")]); + db.HashSet("student:1111", [new("first", "Joe"), new("last", "Dod"), new("age", "18")]); + db.HashSet("pupil:2222", [new("first", "Jen"), new("last", "Rod"), new("age", "14")]); + db.HashSet("student:3333", [new("first", "El"), new("last", "Mark"), new("age", "17")]); + db.HashSet("pupil:4444", [new("first", "Pat"), new("last", "Shu"), new("age", "21")]); + db.HashSet("student:5555", [new("first", "Joen"), new("last", "Ko"), new("age", "20")]); + db.HashSet("teacher:6666", [new("first", "Pat"), new("last", "Rod"), new("age", "20")]); - SearchResult noFilters = ft.Search(index, new Query()); + SearchResult noFilters = ft.Search(index, new()); Assert.Equal(5, noFilters.TotalResults); - SearchResult asAttribute = ft.Search(index, new Query("@given:Jo*")); + SearchResult asAttribute = ft.Search(index, new("@given:Jo*")); Assert.Equal(2, asAttribute.TotalResults); - SearchResult nonAttribute = ft.Search(index, new Query("@last:Rod")); + SearchResult nonAttribute = ft.Search(index, new("@last:Rod")); Assert.Equal(1, nonAttribute.TotalResults); } - [SkipIfRedis(Comparison.LessThan, "7.9.0")] + [SkipIfRedisTheory(Comparison.LessThan, "7.9.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void FailWhenAttributeNotExist(string endpointId) { @@ -668,7 +669,7 @@ public void FailWhenAttributeNotExist(string endpointId) .AddField(new TextField(FieldName.Of("last"))); Assert.True(ft.Create(index, FTCreateParams.CreateParams().Prefix("student:", "pupil:"), sc)); - RedisServerException exc = Assert.Throws(() => ft.Search(index, new Query("@first:Jo*"))); + RedisServerException exc = Assert.Throws(() => ft.Search(index, new("@first:Jo*"))); } [SkippableTheory] @@ -682,25 +683,25 @@ public async Task CreateWithFieldNamesAsync(string endpointId) Assert.True(await ft.CreateAsync(index, FTCreateParams.CreateParams().Prefix("student:", "pupil:"), sc)); - db.HashSet("profesor:5555", new HashEntry[] { new("first", "Albert"), new("last", "Blue"), new("age", "55") }); - db.HashSet("student:1111", new HashEntry[] { new("first", "Joe"), new("last", "Dod"), new("age", "18") }); - db.HashSet("pupil:2222", new HashEntry[] { new("first", "Jen"), new("last", "Rod"), new("age", "14") }); - db.HashSet("student:3333", new HashEntry[] { new("first", "El"), new("last", "Mark"), new("age", "17") }); - db.HashSet("pupil:4444", new HashEntry[] { new("first", "Pat"), new("last", "Shu"), new("age", "21") }); - db.HashSet("student:5555", new HashEntry[] { new("first", "Joen"), new("last", "Ko"), new("age", "20") }); - db.HashSet("teacher:6666", new HashEntry[] { new("first", "Pat"), new("last", "Rod"), new("age", "20") }); + db.HashSet("profesor:5555", [new("first", "Albert"), new("last", "Blue"), new("age", "55")]); + db.HashSet("student:1111", [new("first", "Joe"), new("last", "Dod"), new("age", "18")]); + db.HashSet("pupil:2222", [new("first", "Jen"), new("last", "Rod"), new("age", "14")]); + db.HashSet("student:3333", [new("first", "El"), new("last", "Mark"), new("age", "17")]); + db.HashSet("pupil:4444", [new("first", "Pat"), new("last", "Shu"), new("age", "21")]); + db.HashSet("student:5555", [new("first", "Joen"), new("last", "Ko"), new("age", "20")]); + db.HashSet("teacher:6666", [new("first", "Pat"), new("last", "Rod"), new("age", "20")]); - SearchResult noFilters = await ft.SearchAsync(index, new Query()); + SearchResult noFilters = await ft.SearchAsync(index, new()); Assert.Equal(5, noFilters.TotalResults); - SearchResult asAttribute = await ft.SearchAsync(index, new Query("@given:Jo*")); + SearchResult asAttribute = await ft.SearchAsync(index, new("@given:Jo*")); Assert.Equal(2, asAttribute.TotalResults); - SearchResult nonAttribute = await ft.SearchAsync(index, new Query("@last:Rod")); + SearchResult nonAttribute = await ft.SearchAsync(index, new("@last:Rod")); Assert.Equal(1, nonAttribute.TotalResults); } - [SkipIfRedis(Comparison.LessThan, "7.9.0")] + [SkipIfRedisTheory(Comparison.LessThan, "7.9.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task FailWhenAttributeNotExistAsync(string endpointId) { @@ -710,10 +711,10 @@ public async Task FailWhenAttributeNotExistAsync(string endpointId) .AddField(new TextField(FieldName.Of("last"))); Assert.True(await ft.CreateAsync(index, FTCreateParams.CreateParams().Prefix("student:", "pupil:"), sc)); - RedisServerException exc = await Assert.ThrowsAsync(async () => await ft.SearchAsync(index, new Query("@first:Jo*"))); + RedisServerException exc = await Assert.ThrowsAsync(async () => await ft.SearchAsync(index, new("@first:Jo*"))); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void AlterAdd(string endpointId) { @@ -724,7 +725,7 @@ public void AlterAdd(string endpointId) Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); //sleep: - System.Threading.Thread.Sleep(2000); + Thread.Sleep(2000); var fields = new HashEntry("title", "hello world"); //fields.("title", "hello world"); @@ -732,7 +733,7 @@ public void AlterAdd(string endpointId) { db.HashSet($"doc{i}", fields.Name, fields.Value); } - SearchResult res = ft.Search(index, new Query("hello world")); + SearchResult res = ft.Search(index, new("hello world")); Assert.Equal(100, res.TotalResults); Assert.True(ft.Alter(index, new Schema().AddTagField("tags").AddTextField("name", weight: 0.5))); @@ -743,7 +744,7 @@ public void AlterAdd(string endpointId) // assertTrue(client.updateDocument(string.format("doc%d", i), 1.0, fields2)); db.HashSet($"doc{i}", fields2); } - SearchResult res2 = ft.Search(index, new Query("@tags:{tagA}")); + SearchResult res2 = ft.Search(index, new("@tags:{tagA}")); Assert.Equal(100, res2.TotalResults); var info = ft.Info(index); @@ -777,7 +778,7 @@ public void AlterAdd(string endpointId) Assert.Equal(4, info.CursorStats.Count); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task AlterAddAsync(string endpointId) { @@ -788,7 +789,7 @@ public async Task AlterAddAsync(string endpointId) Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); //sleep: - System.Threading.Thread.Sleep(2000); + Thread.Sleep(2000); var fields = new HashEntry("title", "hello world"); //fields.("title", "hello world"); @@ -796,7 +797,7 @@ public async Task AlterAddAsync(string endpointId) { db.HashSet($"doc{i}", fields.Name, fields.Value); } - SearchResult res = ft.Search(index, new Query("hello world")); + SearchResult res = ft.Search(index, new("hello world")); Assert.Equal(100, res.TotalResults); Assert.True(await ft.AlterAsync(index, new Schema().AddTagField("tags").AddTextField("name", weight: 0.5))); @@ -807,7 +808,7 @@ public async Task AlterAddAsync(string endpointId) // assertTrue(client.updateDocument(string.format("doc%d", i), 1.0, fields2)); db.HashSet($"doc{i}", fields2); } - SearchResult res2 = ft.Search(index, new Query("@tags:{tagA}")); + SearchResult res2 = ft.Search(index, new("@tags:{tagA}")); Assert.Equal(100, res2.TotalResults); var info = await ft.InfoAsync(index); @@ -838,7 +839,7 @@ public async Task AlterAddAsync(string endpointId) Assert.Equal(4, info.CursorStats.Count); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void AlterAddSortable(string endpointId) { @@ -849,7 +850,7 @@ public void AlterAddSortable(string endpointId) Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); //sleep: - System.Threading.Thread.Sleep(2000); + Thread.Sleep(2000); var fields = new HashEntry("title", "hello world"); //fields.("title", "hello world"); @@ -857,7 +858,7 @@ public void AlterAddSortable(string endpointId) { db.HashSet($"doc{i}", fields.Name, fields.Value); } - SearchResult res = ft.Search(index, new Query("hello world")); + SearchResult res = ft.Search(index, new("hello world")); Assert.Equal(100, res.TotalResults); Assert.True(ft.Alter(index, new Schema().AddTagField("tags").AddTextField("name", weight: 0.5))); @@ -868,7 +869,7 @@ public void AlterAddSortable(string endpointId) // assertTrue(client.updateDocument(string.format("doc%d", i), 1.0, fields2)); db.HashSet($"doc{i}", fields2); } - SearchResult res2 = ft.Search(index, new Query("@tags:{tagA}")); + SearchResult res2 = ft.Search(index, new("@tags:{tagA}")); Assert.Equal(100, res2.TotalResults); var info = ft.Info(index); @@ -901,7 +902,7 @@ public void AlterAddSortable(string endpointId) Assert.Equal(4, info.CursorStats.Count); } - [SkipIfRedis(Comparison.LessThan, "7.3.0")] + [SkipIfRedisTheory(Comparison.LessThan, "7.3.0")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void InfoWithIndexEmptyAndIndexMissing(string endpointId) { @@ -920,8 +921,8 @@ public void InfoWithIndexEmptyAndIndexMissing(string endpointId) .AddTagField("tag1", emptyIndex: true, missingIndex: true) .AddNumericField("numeric1", missingIndex: true) .AddGeoField("geo1", missingIndex: true) - .AddGeoShapeField("geoshape1", Schema.GeoShapeField.CoordinateSystem.FLAT, missingIndex: true) - .AddVectorField("vector1", Schema.VectorField.VectorAlgo.FLAT, vectorAttrs, missingIndex: true); + .AddGeoShapeField("geoshape1", GeoShapeField.CoordinateSystem.FLAT, missingIndex: true) + .AddVectorField("vector1", VectorField.VectorAlgo.FLAT, vectorAttrs, missingIndex: true); Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); var info = ft.Info(index); @@ -936,7 +937,7 @@ public void InfoWithIndexEmptyAndIndexMissing(string endpointId) } } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task AlterAddSortableAsync(string endpointId) { @@ -947,7 +948,7 @@ public async Task AlterAddSortableAsync(string endpointId) Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); //sleep: - System.Threading.Thread.Sleep(2000); + Thread.Sleep(2000); var fields = new HashEntry("title", "hello world"); //fields.("title", "hello world"); @@ -955,7 +956,7 @@ public async Task AlterAddSortableAsync(string endpointId) { db.HashSet($"doc{i}", fields.Name, fields.Value); } - SearchResult res = ft.Search(index, new Query("hello world")); + SearchResult res = ft.Search(index, new("hello world")); Assert.Equal(100, res.TotalResults); Assert.True(await ft.AlterAsync(index, new Schema().AddTagField("tags").AddTextField("name", weight: 0.5))); @@ -966,7 +967,7 @@ public async Task AlterAddSortableAsync(string endpointId) // assertTrue(client.updateDocument(string.format("doc%d", i), 1.0, fields2)); db.HashSet($"doc{i}", fields2); } - SearchResult res2 = ft.Search(index, new Query("@tags:{tagA}")); + SearchResult res2 = ft.Search(index, new("@tags:{tagA}")); Assert.Equal(100, res2.TotalResults); var info = await ft.InfoAsync(index); @@ -998,7 +999,7 @@ public async Task AlterAddSortableAsync(string endpointId) } // TODO : fix with FT.CONFIG response change - [SkipIfRedis(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestConfig(string endpointId) { @@ -1010,7 +1011,7 @@ public void TestConfig(string endpointId) } // TODO : fix with FT.CONFIG response change - [SkipIfRedis(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestConfigAsnyc(string endpointId) { @@ -1022,7 +1023,7 @@ public async Task TestConfigAsnyc(string endpointId) } // TODO : fix with FT.CONFIG response change - [SkipIfRedis(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void configOnTimeout(string endpointId) { @@ -1035,7 +1036,7 @@ public void configOnTimeout(string endpointId) } // TODO : fix with FT.CONFIG response change - [SkipIfRedis(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task configOnTimeoutAsync(string endpointId) { @@ -1048,7 +1049,7 @@ public async Task configOnTimeoutAsync(string endpointId) } // TODO : fix with FT.CONFIG response change - [SkipIfRedis(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestDialectConfig(string endpointId) { @@ -1071,7 +1072,7 @@ public void TestDialectConfig(string endpointId) } // TODO : fix with FT.CONFIG response change - [SkipIfRedis(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestDialectConfigAsync(string endpointId) { @@ -1099,7 +1100,7 @@ public async Task TestCursor(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - Schema sc = new Schema(); + Schema sc = new(); sc.AddTextField("name", 1.0, sortable: true); sc.AddNumericField("count", sortable: true); ft.Create(index, FTCreateParams.CreateParams(), sc); @@ -1161,7 +1162,7 @@ public async Task TestCursorAsync(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - Schema sc = new Schema(); + Schema sc = new(); sc.AddTextField("name", 1.0, sortable: true); sc.AddNumericField("count", sortable: true); ft.Create(index, FTCreateParams.CreateParams(), sc); @@ -1217,7 +1218,7 @@ public async Task TestCursorAsync(string endpointId) catch (RedisException) { } } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestAggregationGroupBy(string endpointId) { @@ -1225,26 +1226,26 @@ public void TestAggregationGroupBy(string endpointId) var ft = db.FT(); // Creating the index definition and schema - ft.Create("idx", new FTCreateParams(), new Schema().AddNumericField("random_num") + ft.Create("idx", new(), new Schema().AddNumericField("random_num") .AddTextField("title") .AddTextField("body") .AddTextField("parent")); // Indexing a document - AddDocument(db, "search", new Dictionary(){ + AddDocument(db, "search", new(){ { "title", "RediSearch" }, { "body", "Redisearch impements a search engine on top of redis" }, { "parent", "redis" }, { "random_num", 10 }}); - AddDocument(db, "ai", new Dictionary + AddDocument(db, "ai", new() { { "title", "RedisAI" }, { "body", "RedisAI executes Deep Learning/Machine Learning models and managing their data." }, { "parent", "redis" }, { "random_num", 3 }}); - AddDocument(db, "json", new Dictionary + AddDocument(db, "json", new() { { "title", "RedisJson" }, { "body", "RedisJSON implements ECMA-404 The JSON Data Interchange Standard as a native data type." }, @@ -1321,7 +1322,7 @@ public void TestAggregationGroupBy(string endpointId) // TODO: complete this assert after handling multi bulk reply actual = (List)res.Get("random"); Assert.Equal(2, actual.Count); - List possibleValues = new List() { "RediSearch", "RedisAI", "RedisJson" }; + List possibleValues = ["RediSearch", "RedisAI", "RedisJson"]; Assert.Contains(actual[0].ToString(), possibleValues); Assert.Contains(actual[1].ToString(), possibleValues); @@ -1331,7 +1332,7 @@ public void TestAggregationGroupBy(string endpointId) res = db.FT().Aggregate("idx", req).GetRow(0); actual = (List)res.Get("docs"); - expected = new List { "ai", "search", "json" }; + expected = ["ai", "search", "json"]; Assert.True(!expected.Except(actual).Any() && expected.Count == actual.Count); } @@ -1364,21 +1365,21 @@ public void TestDropIndex(string endpointId) Schema sc = new Schema().AddTextField("title", 1.0); Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - Dictionary fields = new Dictionary(); + Dictionary fields = new(); fields.Add("title", "hello world"); for (int i = 0; i < 100; i++) { AddDocument(db, $"doc{i}", fields); } - SearchResult res = ft.Search(index, new Query("hello world")); + SearchResult res = ft.Search(index, new("hello world")); Assert.Equal(100, res.TotalResults); Assert.True(ft.DropIndex(index)); try { - ft.Search(index, new Query("hello world")); + ft.Search(index, new("hello world")); //fail("Index should not exist."); } catch (RedisServerException ex) @@ -1397,21 +1398,21 @@ public async Task TestDropIndexAsync(string endpointId) Schema sc = new Schema().AddTextField("title", 1.0); Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - Dictionary fields = new Dictionary(); + Dictionary fields = new(); fields.Add("title", "hello world"); for (int i = 0; i < 100; i++) { AddDocument(db, $"doc{i}", fields); } - SearchResult res = ft.Search(index, new Query("hello world")); + SearchResult res = ft.Search(index, new("hello world")); Assert.Equal(100, res.TotalResults); Assert.True(await ft.DropIndexAsync(index)); try { - ft.Search(index, new Query("hello world")); + ft.Search(index, new("hello world")); //fail("Index should not exist."); } catch (RedisServerException ex) @@ -1430,14 +1431,14 @@ public void dropIndexDD(string endpointId) Schema sc = new Schema().AddTextField("title", 1.0); Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - Dictionary fields = new Dictionary(); + Dictionary fields = new(); fields.Add("title", "hello world"); for (int i = 0; i < 100; i++) { AddDocument(db, $"doc{i}", fields); } - SearchResult res = ft.Search(index, new Query("hello world")); + SearchResult res = ft.Search(index, new("hello world")); Assert.Equal(100, res.TotalResults); Assert.True(ft.DropIndex(index, true)); @@ -1456,14 +1457,14 @@ public async Task dropIndexDDAsync(string endpointId) Schema sc = new Schema().AddTextField("title", 1.0); Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - Dictionary fields = new Dictionary(); + Dictionary fields = new(); fields.Add("title", "hello world"); for (int i = 0; i < 100; i++) { AddDocument(db, $"doc{i}", fields); } - SearchResult res = ft.Search(index, new Query("hello world")); + SearchResult res = ft.Search(index, new("hello world")); Assert.Equal(100, res.TotalResults); Assert.True(await ft.DropIndexAsync(index, true)); @@ -1492,7 +1493,7 @@ public async Task TestDictionaryAsync(string endpointId) Assert.Empty((await ft.DictDumpAsync("dict"))); } - string explainQuery = "@f3:f3_val @f2:f2_val @f1:f1_val"; + readonly string explainQuery = "@f3:f3_val @f2:f2_val @f1:f1_val"; [SkippableTheory] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestExplain(string endpointId) @@ -1540,7 +1541,7 @@ public async Task TestExplainAsync(string endpointId) Assert.False(res.Length == 0); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] public void TestExplainCli(string endpointId) { @@ -1563,7 +1564,7 @@ public void TestExplainCli(string endpointId) Assert.False(res.Length == 0); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] public async Task TestExplainCliAsync(string endpointId) { @@ -1639,10 +1640,10 @@ public void TestSynonym(string endpointId) Dictionary> dump = ft.SynDump(index); - Dictionary> expected = new Dictionary>(); - expected.Add("girl", new List() { group1_str }); - expected.Add("baby", new List() { group1_str }); - expected.Add("child", new List() { group1_str, group2_str }); + Dictionary> expected = new(); + expected.Add("girl", [group1_str]); + expected.Add("baby", [group1_str]); + expected.Add("child", [group1_str, group2_str]); Assert.Equal(expected, dump); } @@ -1665,10 +1666,10 @@ public async Task TestSynonymAsync(string endpointId) Dictionary> dump = await ft.SynDumpAsync(index); - Dictionary> expected = new Dictionary>(); - expected.Add("girl", new List() { group1_str }); - expected.Add("baby", new List() { group1_str }); - expected.Add("child", new List() { group1_str, group2_str }); + Dictionary> expected = new(); + expected.Add("girl", [group1_str]); + expected.Add("baby", [group1_str]); + expected.Add("child", [group1_str, group2_str]); Assert.Equal(expected, dump); } @@ -1696,35 +1697,35 @@ public async Task GetTagFieldSyncAsync(string endpointId) .AddTagField("category"); Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - Dictionary fields1 = new Dictionary(); + Dictionary fields1 = new(); fields1.Add("title", "hello world"); fields1.Add("category", "red"); // assertTrue(client.AddDocument(db, "foo", fields1)); AddDocument(db, "foo", fields1); - Dictionary fields2 = new Dictionary(); + Dictionary fields2 = new(); fields2.Add("title", "hello world"); fields2.Add("category", "blue"); // assertTrue(client.AddDocument(db, "bar", fields2)); AddDocument(db, "bar", fields2); - Dictionary fields3 = new Dictionary(); + Dictionary fields3 = new(); fields3.Add("title", "hello world"); fields3.Add("category", "green,yellow"); // assertTrue(client.AddDocument(db, "baz", fields3)); AddDocument(db, "baz", fields3); - Dictionary fields4 = new Dictionary(); + Dictionary fields4 = new(); fields4.Add("title", "hello world"); fields4.Add("category", "orange;purple"); // assertTrue(client.AddDocument(db, "qux", fields4)); AddDocument(db, "qux", fields4); - Assert.Equal(1, ft.Search(index, new Query("@category:{red}")).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("@category:{blue}")).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("hello @category:{red}")).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("hello @category:{blue}")).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("@category:{yellow}")).TotalResults); - Assert.Equal(0, ft.Search(index, new Query("@category:{purple}")).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("@category:{orange\\;purple}")).TotalResults); - Assert.Equal(4, ft.Search(index, new Query("hello")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@category:{red}")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@category:{blue}")).TotalResults); + Assert.Equal(1, ft.Search(index, new("hello @category:{red}")).TotalResults); + Assert.Equal(1, ft.Search(index, new("hello @category:{blue}")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@category:{yellow}")).TotalResults); + Assert.Equal(0, ft.Search(index, new("@category:{purple}")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@category:{orange\\;purple}")).TotalResults); + Assert.Equal(4, ft.Search(index, new("hello")).TotalResults); var SyncRes = ft.TagVals(index, "category"); int i = 0; @@ -1754,35 +1755,35 @@ public async Task TestGetTagFieldWithNonDefaultSeparatorSyncAsync(string endpoin .AddTagField("category", separator: ";"); Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - Dictionary fields1 = new Dictionary(); + Dictionary fields1 = new(); fields1.Add("title", "hello world"); fields1.Add("category", "red"); // assertTrue(client.AddDocument(db, "foo", fields1)); AddDocument(db, "foo", fields1); - Dictionary fields2 = new Dictionary(); + Dictionary fields2 = new(); fields2.Add("title", "hello world"); fields2.Add("category", "blue"); // assertTrue(client.AddDocument(db, "bar", fields2)); AddDocument(db, "bar", fields2); - Dictionary fields3 = new Dictionary(); + Dictionary fields3 = new(); fields3.Add("title", "hello world"); fields3.Add("category", "green;yellow"); AddDocument(db, "baz", fields3); // assertTrue(client.AddDocument(db, "baz", fields3)); - Dictionary fields4 = new Dictionary(); + Dictionary fields4 = new(); fields4.Add("title", "hello world"); fields4.Add("category", "orange,purple"); // assertTrue(client.AddDocument(db, "qux", fields4)); AddDocument(db, "qux", fields4); - Assert.Equal(1, ft.Search(index, new Query("@category:{red}")).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("@category:{blue}")).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("hello @category:{red}")).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("hello @category:{blue}")).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("hello @category:{yellow}")).TotalResults); - Assert.Equal(0, ft.Search(index, new Query("@category:{purple}")).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("@category:{orange\\,purple}")).TotalResults); - Assert.Equal(4, ft.Search(index, new Query("hello")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@category:{red}")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@category:{blue}")).TotalResults); + Assert.Equal(1, ft.Search(index, new("hello @category:{red}")).TotalResults); + Assert.Equal(1, ft.Search(index, new("hello @category:{blue}")).TotalResults); + Assert.Equal(1, ft.Search(index, new("hello @category:{yellow}")).TotalResults); + Assert.Equal(0, ft.Search(index, new("@category:{purple}")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@category:{orange\\,purple}")).TotalResults); + Assert.Equal(4, ft.Search(index, new("hello")).TotalResults); var SyncRes = ft.TagVals(index, "category"); int i = 0; @@ -1879,15 +1880,17 @@ public void TestFilters(string endpointId) .AddTextField("txt") .AddNumericField("num") .AddGeoField("loc"); - ft.Create("idx", new FTCreateParams(), sc); + ft.Create("idx", new(), sc); // Add the two documents to the index - AddDocument(db, "doc1", new Dictionary { + AddDocument(db, "doc1", new() + { { "txt", "foo bar" }, { "num", "3.141" }, { "loc", "-0.441,51.458" } }); - AddDocument(db, "doc2", new Dictionary { + AddDocument(db, "doc2", new() + { { "txt", "foo baz" }, { "num", "2" }, { "loc", "-0.1,51.2" } @@ -1929,15 +1932,17 @@ public async Task TestFiltersAsync(string endpointId) .AddTextField("txt") .AddNumericField("num") .AddGeoField("loc"); - await ft.CreateAsync("idx", new FTCreateParams(), sc); + await ft.CreateAsync("idx", new(), sc); // Add the two documents to the index - AddDocument(db, "doc1", new Dictionary { + AddDocument(db, "doc1", new() + { { "txt", "foo bar" }, { "num", "3.141" }, { "loc", "-0.441,51.458" } }); - AddDocument(db, "doc2", new Dictionary { + AddDocument(db, "doc2", new() + { { "txt", "foo baz" }, { "num", "2" }, { "loc", "-0.1,51.2" } @@ -2060,7 +2065,7 @@ public void TestQueryCommandBuilder() // test that the command not throw an exception: var db = GetCleanDatabase(); var ft = db.FT(); - ft.Create("idx", new FTCreateParams(), new Schema().AddTextField("txt")); + ft.Create("idx", new(), new Schema().AddTextField("txt")); var res = ft.Search("idx", testQuery); Assert.Empty(res.Documents); } @@ -2095,7 +2100,7 @@ public void TestQueryCommandBuilderReturnField() // test that the command not throw an exception: var db = GetCleanDatabase(); var ft = db.FT(); - ft.Create("idx", new FTCreateParams(), new Schema().AddTextField("txt")); + ft.Create("idx", new(), new Schema().AddTextField("txt")); var res = ft.Search("idx", testQuery); Assert.Empty(res.Documents); } @@ -2127,8 +2132,8 @@ public void TestFieldsCommandBuilder() .AddNumericField(FieldName.Of("num"), true, true) .AddGeoField(FieldName.Of("loc"), true, true) .AddTagField(FieldName.Of("tag"), true, true, true, ";", true, true) - .AddVectorField("vec", VectorField.VectorAlgo.FLAT, new Dictionary { { "dim", 10 } }); - var buildCommand = SearchCommandBuilder.Create("idx", new FTCreateParams(), sc); + .AddVectorField("vec", VectorField.VectorAlgo.FLAT, new() { { "dim", 10 } }); + var buildCommand = SearchCommandBuilder.Create("idx", new(), sc); var expectedArgs = new List { "idx", "SCHEMA", @@ -2180,9 +2185,9 @@ public void TestLimit(string endpointId) IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - ft.Create("idx", new FTCreateParams(), new Schema().AddTextField("t1").AddTextField("t2")); - Document doc1 = new Document("doc1", new Dictionary { { "t1", "a" }, { "t2", "b" } }); - Document doc2 = new Document("doc2", new Dictionary { { "t1", "b" }, { "t2", "a" } }); + ft.Create("idx", new(), new Schema().AddTextField("t1").AddTextField("t2")); + Document doc1 = new("doc1", new() { { "t1", "a" }, { "t2", "b" } }); + Document doc2 = new("doc2", new() { { "t1", "b" }, { "t2", "a" } }); AddDocument(db, doc1); AddDocument(db, doc2); @@ -2200,9 +2205,9 @@ public async Task TestLimitAsync(string endpointId) IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - ft.Create("idx", new FTCreateParams(), new Schema().AddTextField("t1").AddTextField("t2")); - Document doc1 = new Document("doc1", new Dictionary { { "t1", "a" }, { "t2", "b" } }); - Document doc2 = new Document("doc2", new Dictionary { { "t1", "b" }, { "t2", "a" } }); + ft.Create("idx", new(), new Schema().AddTextField("t1").AddTextField("t2")); + Document doc1 = new("doc1", new() { { "t1", "a" }, { "t2", "b" } }); + Document doc2 = new("doc2", new() { { "t1", "b" }, { "t2", "a" } }); AddDocument(db, doc1); AddDocument(db, doc2); @@ -2218,7 +2223,7 @@ public void Test_List() { IDatabase db = GetCleanDatabase(); var ft = db.FT(); - Assert.Equal(ft._List(), new RedisResult[] { }); + Assert.Equal(ft._List(), []); } [Fact] @@ -2226,20 +2231,20 @@ public async Task Test_ListAsync() { IDatabase db = GetCleanDatabase(); var ft = db.FT(); - Assert.Equal(await ft._ListAsync(), new RedisResult[] { }); + Assert.Equal(await ft._ListAsync(), []); } [Fact] public void TestVectorCount_Issue70() { - var schema = new Schema().AddVectorField("fieldTest", Schema.VectorField.VectorAlgo.HNSW, new Dictionary() + var schema = new Schema().AddVectorField("fieldTest", VectorField.VectorAlgo.HNSW, new() { ["TYPE"] = "FLOAT32", ["DIM"] = "128", ["DISTANCE_METRIC"] = "COSINE" }); - var actual = SearchCommandBuilder.Create("test", new FTCreateParams(), schema); + var actual = SearchCommandBuilder.Create("test", new(), schema); var expected = new List() { "test", @@ -2276,7 +2281,7 @@ public void VectorSimilaritySearch(string endpointId) json.Set("vec:3", "$", "{\"vector\":[3,3,3,3]}"); json.Set("vec:4", "$", "{\"vector\":[4,4,4,4]}"); - var schema = new Schema().AddVectorField(FieldName.Of("$.vector").As("vector"), Schema.VectorField.VectorAlgo.FLAT, new Dictionary() + var schema = new Schema().AddVectorField(FieldName.Of("$.vector").As("vector"), VectorField.VectorAlgo.FLAT, new() { ["TYPE"] = "FLOAT32", ["DIM"] = "4", @@ -2286,7 +2291,7 @@ public void VectorSimilaritySearch(string endpointId) var idxDef = new FTCreateParams().On(IndexDataType.JSON).Prefix("vec:"); Assert.True(ft.Create("vss_idx", idxDef, schema)); - float[] vec = new float[] { 2, 2, 2, 2 }; + float[] vec = [2, 2, 2, 2]; byte[] queryVec = MemoryMarshal.Cast(vec).ToArray(); @@ -2303,7 +2308,7 @@ public void VectorSimilaritySearch(string endpointId) Assert.Equal(0, res.Documents[0]["__vector_score"]); var jsonRes = res.ToJson(); - Assert.Equal("{\"vector\":[2,2,2,2]}", jsonRes![0]); + Assert.Equal("{\"vector\":[2,2,2,2]}", jsonRes[0]); } [SkippableTheory] @@ -2314,14 +2319,14 @@ public void QueryingVectorFields(string endpointId) var ft = db.FT(); var json = db.JSON(); - var schema = new Schema().AddVectorField("v", Schema.VectorField.VectorAlgo.HNSW, new Dictionary() + var schema = new Schema().AddVectorField("v", VectorField.VectorAlgo.HNSW, new() { ["TYPE"] = "FLOAT32", ["DIM"] = "2", ["DISTANCE_METRIC"] = "L2", }); - ft.Create("idx", new FTCreateParams(), schema); + ft.Create("idx", new(), schema); db.HashSet("a", "v", "aaaaaaaa"); db.HashSet("b", "v", "aaaabaaa"); @@ -2343,7 +2348,7 @@ public async Task TestVectorFieldJson_Issue102Async() await json.SetAsync("1", "$", "{\"vec\":[1,2,3,4]}"); // FT.CREATE my_index ON JSON SCHEMA $.vec as vector VECTOR FLAT 6 TYPE FLOAT32 DIM 4 DISTANCE_METRIC L2 - var schema = new Schema().AddVectorField(FieldName.Of("$.vec").As("vector"), Schema.VectorField.VectorAlgo.FLAT, new Dictionary() + var schema = new Schema().AddVectorField(FieldName.Of("$.vec").As("vector"), VectorField.VectorAlgo.FLAT, new() { ["TYPE"] = "FLOAT32", ["DIM"] = "4", @@ -2361,7 +2366,7 @@ public void TestQueryAddParam_DefaultDialect(string endpointId) var ft = db.FT(2); var sc = new Schema().AddNumericField("numval"); - Assert.True(ft.Create("idx", new FTCreateParams(), sc)); + Assert.True(ft.Create("idx", new(), sc)); db.HashSet("1", "numval", 1); db.HashSet("2", "numval", 2); @@ -2380,7 +2385,7 @@ public async Task TestQueryAddParam_DefaultDialectAsync(string endpointId) var ft = db.FT(2); var sc = new Schema().AddNumericField("numval"); - Assert.True(await ft.CreateAsync("idx", new FTCreateParams(), sc)); + Assert.True(await ft.CreateAsync("idx", new(), sc)); db.HashSet("1", "numval", 1); db.HashSet("2", "numval", 2); @@ -2399,7 +2404,7 @@ public void TestQueryParamsWithParams_DefaultDialect(string endpointId) var ft = db.FT(2); var sc = new Schema().AddNumericField("numval"); - Assert.True(ft.Create("idx", new FTCreateParams(), sc)); + Assert.True(ft.Create("idx", new(), sc)); db.HashSet("1", "numval", 1); db.HashSet("2", "numval", 2); @@ -2414,7 +2419,7 @@ public void TestQueryParamsWithParams_DefaultDialect(string endpointId) ["min"] = 1, ["max"] = 2 }; - query = new Query("@numval:[$min $max]"); + query = new("@numval:[$min $max]"); res = ft.Search("idx", query.Params(paramValue)); Assert.Equal(2, res.TotalResults); } @@ -2426,11 +2431,11 @@ public void TestBasicSpellCheck(string endpointId) IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - ft.Create(index, new FTCreateParams(), new Schema().AddTextField("name").AddTextField("body")); + ft.Create(index, new(), new Schema().AddTextField("name").AddTextField("body")); - db.HashSet("doc1", new HashEntry[] { new HashEntry("name", "name1"), new HashEntry("body", "body1") }); - db.HashSet("doc1", new HashEntry[] { new HashEntry("name", "name2"), new HashEntry("body", "body2") }); - db.HashSet("doc1", new HashEntry[] { new HashEntry("name", "name2"), new HashEntry("body", "name2") }); + db.HashSet("doc1", [new("name", "name1"), new("body", "body1")]); + db.HashSet("doc1", [new("name", "name2"), new("body", "body2")]); + db.HashSet("doc1", [new("name", "name2"), new("body", "name2")]); var reply = ft.SpellCheck(index, "name"); Assert.Single(reply.Keys); @@ -2446,11 +2451,11 @@ public async Task TestBasicSpellCheckAsync(string endpointId) IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - ft.Create(index, new FTCreateParams(), new Schema().AddTextField("name").AddTextField("body")); + ft.Create(index, new(), new Schema().AddTextField("name").AddTextField("body")); - db.HashSet("doc1", new HashEntry[] { new HashEntry("name", "name1"), new HashEntry("body", "body1") }); - db.HashSet("doc1", new HashEntry[] { new HashEntry("name", "name2"), new HashEntry("body", "body2") }); - db.HashSet("doc1", new HashEntry[] { new HashEntry("name", "name2"), new HashEntry("body", "name2") }); + db.HashSet("doc1", [new("name", "name1"), new("body", "body1")]); + db.HashSet("doc1", [new("name", "name2"), new("body", "body2")]); + db.HashSet("doc1", [new("name", "name2"), new("body", "name2")]); var reply = await ft.SpellCheckAsync(index, "name"); Assert.Single(reply.Keys); @@ -2466,11 +2471,11 @@ public void TestCrossTermDictionary(string endpointId) IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - ft.Create(index, new FTCreateParams(), new Schema().AddTextField("name").AddTextField("body")); + ft.Create(index, new(), new Schema().AddTextField("name").AddTextField("body")); ft.DictAdd("slang", "timmies", "toque", "toonie", "serviette", "kerfuffle", "chesterfield"); var expected = new Dictionary>() { - ["tooni"] = new Dictionary() + ["tooni"] = new() { ["toonie"] = 0d } @@ -2490,11 +2495,11 @@ public async Task TestCrossTermDictionaryAsync(string endpointId) IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - ft.Create(index, new FTCreateParams(), new Schema().AddTextField("name").AddTextField("body")); + ft.Create(index, new(), new Schema().AddTextField("name").AddTextField("body")); ft.DictAdd("slang", "timmies", "toque", "toonie", "serviette", "kerfuffle", "chesterfield"); var expected = new Dictionary>() { - ["tooni"] = new Dictionary() + ["tooni"] = new() { ["toonie"] = 0d } @@ -2513,7 +2518,7 @@ public void TestDistanceBound() IDatabase db = GetCleanDatabase(); var ft = db.FT(); - ft.Create(index, new FTCreateParams(), new Schema().AddTextField("name").AddTextField("body")); + ft.Create(index, new(), new Schema().AddTextField("name").AddTextField("body")); // distance suppose to be between 1 and 4 Assert.Throws(() => ft.SpellCheck(index, "name", new FTSpellCheckParams().Distance(0))); } @@ -2524,7 +2529,7 @@ public async Task TestDistanceBoundAsync() IDatabase db = GetCleanDatabase(); var ft = db.FT(); - ft.Create(index, new FTCreateParams(), new Schema().AddTextField("name").AddTextField("body")); + ft.Create(index, new(), new Schema().AddTextField("name").AddTextField("body")); // distance suppose to be between 1 and 4 await Assert.ThrowsAsync(async () => await ft.SpellCheckAsync(index, "name", new FTSpellCheckParams().Distance(0))); } @@ -2535,7 +2540,7 @@ public void TestDialectBound() IDatabase db = GetCleanDatabase(); var ft = db.FT(); - ft.Create(index, new FTCreateParams(), new Schema().AddTextField("t")); + ft.Create(index, new(), new Schema().AddTextField("t")); // dialect 0 is not valid Assert.Throws(() => ft.SpellCheck(index, "name", new FTSpellCheckParams().Dialect(0))); } @@ -2546,7 +2551,7 @@ public async Task TestDialectBoundAsync() IDatabase db = GetCleanDatabase(); var ft = db.FT(); - ft.Create(index, new FTCreateParams(), new Schema().AddTextField("t")); + ft.Create(index, new(), new Schema().AddTextField("t")); // dialect 0 is not valid await Assert.ThrowsAsync(async () => await ft.SpellCheckAsync(index, "name", new FTSpellCheckParams().Dialect(0))); } @@ -2559,7 +2564,7 @@ public async Task TestQueryParamsWithParams_DefaultDialectAsync(string endpointI var ft = db.FT(2); var sc = new Schema().AddNumericField("numval"); - Assert.True(await ft.CreateAsync("idx", new FTCreateParams(), sc)); + Assert.True(await ft.CreateAsync("idx", new(), sc)); db.HashSet("1", "numval", 1); db.HashSet("2", "numval", 2); @@ -2574,16 +2579,12 @@ public async Task TestQueryParamsWithParams_DefaultDialectAsync(string endpointI ["min"] = 1, ["max"] = 2 }; - query = new Query("@numval:[$min $max]"); + query = new("@numval:[$min $max]"); res = await ft.SearchAsync("idx", query.Params(paramValue)); Assert.Equal(2, res.TotalResults); } - string key = "SugTestKey"; - - public SearchTests(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } + readonly string key = "SugTestKey"; [Fact] public void TestAddAndGetSuggestion() @@ -2791,7 +2792,7 @@ public async Task getSuggestionLengthAndDeleteSuggestionAsync() Assert.Equal(2L, await ft.SugLenAsync(key)); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.9")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.9")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestProfileSearch(string endpointId) { @@ -2799,22 +2800,23 @@ public void TestProfileSearch(string endpointId) var ft = db.FT(); Schema sc = new Schema().AddTextField("t1", 1.0).AddTextField("t2", 1.0); - Assert.True(ft.Create(index, new FTCreateParams(), sc)); + Assert.True(ft.Create(index, new(), sc)); - db.HashSet("doc1", new HashEntry[] { - new HashEntry("t1", "foo"), - new HashEntry("t2", "bar")}); + db.HashSet("doc1", [ + new("t1", "foo"), + new("t2", "bar") + ]); - var profile = ft.ProfileOnSearch(index, new Query("foo")); + var profile = ft.ProfileOnSearch(index, new("foo")); // Iterators profile={Type=TEXT, Time=0.0, Term=foo, Counter=1, Size=1} - var info = (RedisResult[])profile.Item2.Info; + var info = (RedisResult[])profile.Item2.Info!; int shardsIndex = Array.FindIndex(info, item => item.ToString() == "Shards"); int coordinatorIndex = Array.FindIndex(info, item => item.ToString() == "Coordinator"); CustomAssertions.GreaterThan(shardsIndex, -1); CustomAssertions.GreaterThan(coordinatorIndex, -1); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.9")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.9")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestProfileSearchAsync(string endpointId) { @@ -2822,21 +2824,22 @@ public async Task TestProfileSearchAsync(string endpointId) var ft = db.FT(); Schema sc = new Schema().AddTextField("t1", 1.0).AddTextField("t2", 1.0); - Assert.True(ft.Create(index, new FTCreateParams(), sc)); + Assert.True(ft.Create(index, new(), sc)); - db.HashSet("doc1", new HashEntry[] { - new HashEntry("t1", "foo"), - new HashEntry("t2", "bar")}); + db.HashSet("doc1", [ + new("t1", "foo"), + new("t2", "bar") + ]); - var profile = await ft.ProfileOnSearchAsync(index, new Query("foo")); - var info = (RedisResult[])profile.Item2.Info; + var profile = await ft.ProfileOnSearchAsync(index, new("foo")); + var info = (RedisResult[])profile.Item2.Info!; int shardsIndex = Array.FindIndex(info, item => item.ToString() == "Shards"); int coordinatorIndex = Array.FindIndex(info, item => item.ToString() == "Coordinator"); CustomAssertions.GreaterThan(shardsIndex, -1); CustomAssertions.GreaterThan(coordinatorIndex, -1); } - [SkipIfRedis(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.9")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.9")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestProfileSearch_WithoutCoordinator(string endpointId) { @@ -2844,18 +2847,19 @@ public void TestProfileSearch_WithoutCoordinator(string endpointId) var ft = db.FT(); Schema sc = new Schema().AddTextField("t1", 1.0).AddTextField("t2", 1.0); - Assert.True(ft.Create(index, new FTCreateParams(), sc)); + Assert.True(ft.Create(index, new(), sc)); - db.HashSet("doc1", new HashEntry[] { - new HashEntry("t1", "foo"), - new HashEntry("t2", "bar")}); + db.HashSet("doc1", [ + new("t1", "foo"), + new("t2", "bar") + ]); - var profile = ft.ProfileSearch(index, new Query("foo")); + var profile = ft.ProfileSearch(index, new("foo")); var info = profile.Item2; CustomAssertions.GreaterThan(info.Count, 4); } - [SkipIfRedis(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.9")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.9")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestProfileSearchAsync_WithoutCoordinator(string endpointId) { @@ -2863,18 +2867,19 @@ public async Task TestProfileSearchAsync_WithoutCoordinator(string endpointId) var ft = db.FT(); Schema sc = new Schema().AddTextField("t1", 1.0).AddTextField("t2", 1.0); - Assert.True(ft.Create(index, new FTCreateParams(), sc)); + Assert.True(ft.Create(index, new(), sc)); - db.HashSet("doc1", new HashEntry[] { - new HashEntry("t1", "foo"), - new HashEntry("t2", "bar")}); + db.HashSet("doc1", [ + new("t1", "foo"), + new("t2", "bar") + ]); - var profile = await ft.ProfileSearchAsync(index, new Query("foo")); + var profile = await ft.ProfileSearchAsync(index, new("foo")); var info = profile.Item2; CustomAssertions.GreaterThan(info.Count, 4); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.9")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.9")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestProfile(string endpointId) { @@ -2889,7 +2894,7 @@ public void TestProfile(string endpointId) var q = new Query("hello|world").SetNoContent(); var profileSearch = ft.ProfileOnSearch(index, q); var searchRes = profileSearch.Item1; - var searchDet = (RedisResult[])profileSearch.Item2.Info; + var searchDet = (RedisResult[])profileSearch.Item2.Info!; Assert.Equal(2, searchRes.Documents.Count); int shardsIndex = Array.FindIndex(searchDet, item => item.ToString() == "Shards"); @@ -2901,7 +2906,7 @@ public void TestProfile(string endpointId) var aggReq = new AggregationRequest("*").Load(FieldName.Of("t")).Apply("startswith(@t, 'hel')", "prefix"); var profileAggregate = ft.ProfileOnAggregate(index, aggReq); var aggregateRes = profileAggregate.Item1; - var aggregateDet = (RedisResult[])profileAggregate.Item2.Info; + var aggregateDet = (RedisResult[])profileAggregate.Item2.Info!; Assert.Equal(2, aggregateRes.TotalResults); shardsIndex = Array.FindIndex(aggregateDet, item => item.ToString() == "Shards"); @@ -2910,7 +2915,7 @@ public void TestProfile(string endpointId) CustomAssertions.GreaterThan(coordinatorIndex, -1); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.9")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.9")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestProfileAsync(string endpointId) { @@ -2925,7 +2930,7 @@ public async Task TestProfileAsync(string endpointId) var q = new Query("hello|world").SetNoContent(); var profileSearch = await ft.ProfileOnSearchAsync(index, q); var searchRes = profileSearch.Item1; - var searchDet = (RedisResult[])profileSearch.Item2.Info; + var searchDet = (RedisResult[])profileSearch.Item2.Info!; Assert.Equal(2, searchRes.Documents.Count); int shardsIndex = Array.FindIndex(searchDet, item => item.ToString() == "Shards"); @@ -2937,7 +2942,7 @@ public async Task TestProfileAsync(string endpointId) var aggReq = new AggregationRequest("*").Load(FieldName.Of("t")).Apply("startswith(@t, 'hel')", "prefix"); var profileAggregate = await ft.ProfileOnAggregateAsync(index, aggReq); var aggregateRes = profileAggregate.Item1; - var aggregateDet = (RedisResult[])profileAggregate.Item2.Info; + var aggregateDet = (RedisResult[])profileAggregate.Item2.Info!; Assert.Equal(2, aggregateRes.TotalResults); shardsIndex = Array.FindIndex(aggregateDet, item => item.ToString() == "Shards"); @@ -2946,7 +2951,7 @@ public async Task TestProfileAsync(string endpointId) CustomAssertions.GreaterThan(coordinatorIndex, -1); } - [SkipIfRedis(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.9")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.9")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestProfile_WithoutCoordinator(string endpointId) { @@ -2976,7 +2981,7 @@ public void TestProfile_WithoutCoordinator(string endpointId) CustomAssertions.GreaterThan(aggregateDet.Count, 4); } - [SkipIfRedis(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.9")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.GreaterThanOrEqual, "7.9")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestProfileAsync_WithoutCoordinator(string endpointId) { @@ -3006,7 +3011,7 @@ public async Task TestProfileAsync_WithoutCoordinator(string endpointId) CustomAssertions.GreaterThan(searchDet.Count, 4); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.3.240")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestProfileIssue306(string endpointId) { @@ -3021,7 +3026,7 @@ public void TestProfileIssue306(string endpointId) var q = new Query("hello|world").SetNoContent(); var profileSearch = ft.ProfileOnSearch(index, q); var searchRes = profileSearch.Item1; - var searchDet = (RedisResult[])profileSearch.Item2.Info; + var searchDet = (RedisResult[])profileSearch.Item2.Info!; CustomAssertions.GreaterThan(searchDet.Length, 3); Assert.Equal(2, searchRes.Documents.Count); @@ -3031,12 +3036,12 @@ public void TestProfileIssue306(string endpointId) var aggReq = new AggregationRequest("*").Load(FieldName.Of("t")).Apply("startswith(@t, 'hel')", "prefix"); var profileAggregate = ft.ProfileOnAggregate(index, aggReq); var aggregateRes = profileAggregate.Item1; - var aggregateDet = (RedisResult[])profileAggregate.Item2.Info; + var aggregateDet = (RedisResult[])profileAggregate.Item2.Info!; CustomAssertions.GreaterThan(aggregateDet.Length, 3); Assert.Equal(2, aggregateRes.TotalResults); } - [SkipIfRedis(Is.Enterprise, Comparison.LessThan, "7.3.240")] + [SkipIfRedisTheory(Is.Enterprise, Comparison.LessThan, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestProfileAsyncIssue306(string endpointId) { @@ -3051,7 +3056,7 @@ public async Task TestProfileAsyncIssue306(string endpointId) var q = new Query("hello|world").SetNoContent(); var profileSearch = await ft.ProfileOnSearchAsync(index, q); var searchRes = profileSearch.Item1; - var searchDet = (RedisResult[])profileSearch.Item2.Info; + var searchDet = (RedisResult[])profileSearch.Item2.Info!; CustomAssertions.GreaterThan(searchDet.Length, 3); Assert.Equal(2, searchRes.Documents.Count); @@ -3060,7 +3065,7 @@ public async Task TestProfileAsyncIssue306(string endpointId) var aggReq = new AggregationRequest("*").Load(FieldName.Of("t")).Apply("startswith(@t, 'hel')", "prefix"); var profileAggregate = await ft.ProfileOnAggregateAsync(index, aggReq); var aggregateRes = profileAggregate.Item1; - var aggregateDet = (RedisResult[])profileAggregate.Item2.Info; + var aggregateDet = (RedisResult[])profileAggregate.Item2.Info!; CustomAssertions.GreaterThan(aggregateDet.Length, 3); Assert.Equal(2, aggregateRes.TotalResults); } @@ -3068,13 +3073,13 @@ public async Task TestProfileAsyncIssue306(string endpointId) [Fact] public void TestProfileCommandBuilder() { - var search = SearchCommandBuilder.ProfileSearch("index", new Query(), true); - var aggregate = SearchCommandBuilder.ProfileAggregate("index", new AggregationRequest(), true); + var search = SearchCommandBuilder.ProfileSearch("index", new(), true); + var aggregate = SearchCommandBuilder.ProfileAggregate("index", new(), true); Assert.Equal("FT.PROFILE", search.Command); Assert.Equal("FT.PROFILE", aggregate.Command); - Assert.Equal(new object[] { "index", "SEARCH", "LIMITED", "QUERY", "*" }, search.Args); - Assert.Equal(new object[] { "index", "AGGREGATE", "LIMITED", "QUERY", "*" }, aggregate.Args); + Assert.Equal(["index", "SEARCH", "LIMITED", "QUERY", "*"], search.Args); + Assert.Equal(["index", "AGGREGATE", "LIMITED", "QUERY", "*"], aggregate.Args); } [SkippableTheory] @@ -3095,57 +3100,57 @@ public void Issue175(string endpointId) Assert.True(ft.Create("myIndex", ftParams, schema)); } - [SkipIfRedis(Comparison.LessThan, "7.2.1")] + [SkipIfRedisTheory(Comparison.LessThan, "7.2.1")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void GeoShapeFilterSpherical(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - WKTReader reader = new WKTReader(); - GeometryFactory factory = new GeometryFactory(); + WKTReader reader = new(); + GeometryFactory factory = new(); Assert.True(ft.Create(index, new Schema().AddGeoShapeField("geom", GeoShapeField.CoordinateSystem.SPHERICAL))); // Create polygons - Polygon small = factory.CreatePolygon(new Coordinate[] { - new Coordinate(34.9001, 29.7001), - new Coordinate(34.9001, 29.7100), - new Coordinate(34.9100, 29.7100), - new Coordinate(34.9100, 29.7001), - new Coordinate(34.9001, 29.7001) - }); + Polygon small = factory.CreatePolygon([ + new(34.9001, 29.7001), + new(34.9001, 29.7100), + new(34.9100, 29.7100), + new(34.9100, 29.7001), + new(34.9001, 29.7001) + ]); db.HashSet("small", "geom", small.ToString()); - Polygon large = factory.CreatePolygon(new Coordinate[] { - new Coordinate(34.9001, 29.7001), - new Coordinate(34.9001, 29.7200), - new Coordinate(34.9200, 29.7200), - new Coordinate(34.9200, 29.7001), - new Coordinate(34.9001, 29.7001) - }); + Polygon large = factory.CreatePolygon([ + new(34.9001, 29.7001), + new(34.9001, 29.7200), + new(34.9200, 29.7200), + new(34.9200, 29.7001), + new(34.9001, 29.7001) + ]); db.HashSet("large", "geom", large.ToString()); - Polygon within = factory.CreatePolygon(new Coordinate[] { - new Coordinate(34.9000, 29.7000), - new Coordinate(34.9000, 29.7150), - new Coordinate(34.9150, 29.7150), - new Coordinate(34.9150, 29.7000), - new Coordinate(34.9000, 29.7000) - }); + Polygon within = factory.CreatePolygon([ + new(34.9000, 29.7000), + new(34.9000, 29.7150), + new(34.9150, 29.7150), + new(34.9150, 29.7000), + new(34.9000, 29.7000) + ]); var res = ft.Search(index, new Query($"@geom:[within $poly]").AddParam("poly", within.ToString()).Dialect(3)); Assert.Equal(1, res.TotalResults); Assert.Single(res.Documents); Assert.Equal(small, reader.Read(res.Documents[0]["geom"].ToString())); - Polygon contains = factory.CreatePolygon(new Coordinate[] { - new Coordinate(34.9002, 29.7002), - new Coordinate(34.9002, 29.7050), - new Coordinate(34.9050, 29.7050), - new Coordinate(34.9050, 29.7002), - new Coordinate(34.9002, 29.7002) - }); + Polygon contains = factory.CreatePolygon([ + new(34.9002, 29.7002), + new(34.9002, 29.7050), + new(34.9050, 29.7050), + new(34.9050, 29.7002), + new(34.9002, 29.7002) + ]); res = ft.Search(index, new Query($"@geom:[contains $poly]").AddParam("poly", contains.ToString()).Dialect(3)); Assert.Equal(2, res.TotalResults); @@ -3160,57 +3165,57 @@ public void GeoShapeFilterSpherical(string endpointId) Assert.Equal(2, res.Documents.Count); } - [SkipIfRedis(Comparison.LessThan, "7.2.1")] + [SkipIfRedisTheory(Comparison.LessThan, "7.2.1")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task GeoShapeFilterSphericalAsync(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - WKTReader reader = new WKTReader(); - GeometryFactory factory = new GeometryFactory(); + WKTReader reader = new(); + GeometryFactory factory = new(); Assert.True(await ft.CreateAsync(index, new Schema().AddGeoShapeField("geom", GeoShapeField.CoordinateSystem.SPHERICAL))); // Create polygons - Polygon small = factory.CreatePolygon(new Coordinate[] { - new Coordinate(34.9001, 29.7001), - new Coordinate(34.9001, 29.7100), - new Coordinate(34.9100, 29.7100), - new Coordinate(34.9100, 29.7001), - new Coordinate(34.9001, 29.7001) - }); + Polygon small = factory.CreatePolygon([ + new(34.9001, 29.7001), + new(34.9001, 29.7100), + new(34.9100, 29.7100), + new(34.9100, 29.7001), + new(34.9001, 29.7001) + ]); db.HashSet("small", "geom", small.ToString()); - Polygon large = factory.CreatePolygon(new Coordinate[] { - new Coordinate(34.9001, 29.7001), - new Coordinate(34.9001, 29.7200), - new Coordinate(34.9200, 29.7200), - new Coordinate(34.9200, 29.7001), - new Coordinate(34.9001, 29.7001) - }); + Polygon large = factory.CreatePolygon([ + new(34.9001, 29.7001), + new(34.9001, 29.7200), + new(34.9200, 29.7200), + new(34.9200, 29.7001), + new(34.9001, 29.7001) + ]); db.HashSet("large", "geom", large.ToString()); - Polygon within = factory.CreatePolygon(new Coordinate[] { - new Coordinate(34.9000, 29.7000), - new Coordinate(34.9000, 29.7150), - new Coordinate(34.9150, 29.7150), - new Coordinate(34.9150, 29.7000), - new Coordinate(34.9000, 29.7000) - }); + Polygon within = factory.CreatePolygon([ + new(34.9000, 29.7000), + new(34.9000, 29.7150), + new(34.9150, 29.7150), + new(34.9150, 29.7000), + new(34.9000, 29.7000) + ]); var res = await ft.SearchAsync(index, new Query($"@geom:[within $poly]").AddParam("poly", within.ToString()).Dialect(3)); Assert.Equal(1, res.TotalResults); Assert.Single(res.Documents); Assert.Equal(small, reader.Read(res.Documents[0]["geom"].ToString())); - Polygon contains = factory.CreatePolygon(new Coordinate[] { - new Coordinate(34.9002, 29.7002), - new Coordinate(34.9002, 29.7050), - new Coordinate(34.9050, 29.7050), - new Coordinate(34.9050, 29.7002), - new Coordinate(34.9002, 29.7002) - }); + Polygon contains = factory.CreatePolygon([ + new(34.9002, 29.7002), + new(34.9002, 29.7050), + new(34.9050, 29.7050), + new(34.9050, 29.7002), + new(34.9002, 29.7002) + ]); res = await ft.SearchAsync(index, new Query($"@geom:[contains $poly]").AddParam("poly", contains.ToString()).Dialect(3)); Assert.Equal(2, res.TotalResults); @@ -3225,29 +3230,35 @@ public async Task GeoShapeFilterSphericalAsync(string endpointId) Assert.Equal(2, res.Documents.Count); } - [SkipIfRedis(Comparison.LessThan, "7.2.1")] + [SkipIfRedisTheory(Comparison.LessThan, "7.2.1")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void GeoShapeFilterFlat(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - WKTReader reader = new WKTReader(); - GeometryFactory factory = new GeometryFactory(); + WKTReader reader = new(); + GeometryFactory factory = new(); Assert.True(ft.Create(index, new Schema().AddGeoShapeField("geom", GeoShapeField.CoordinateSystem.FLAT))); // polygon type - Polygon small = factory.CreatePolygon(new Coordinate[]{new Coordinate(1, 1), - new Coordinate(1, 100), new Coordinate(100, 100), new Coordinate(100, 1), new Coordinate(1, 1)}); + Polygon small = factory.CreatePolygon([ + new(1, 1), + new(1, 100), new(100, 100), new(100, 1), new(1, 1) + ]); db.HashSet("small", "geom", small.ToString()); - Polygon large = factory.CreatePolygon(new Coordinate[]{new Coordinate(1, 1), - new Coordinate(1, 200), new Coordinate(200, 200), new Coordinate(200, 1), new Coordinate(1, 1)}); + Polygon large = factory.CreatePolygon([ + new(1, 1), + new(1, 200), new(200, 200), new(200, 1), new(1, 1) + ]); db.HashSet("large", "geom", large.ToString()); // within condition - Polygon within = factory.CreatePolygon(new Coordinate[]{new Coordinate(0, 0), - new Coordinate(0, 150), new Coordinate(150, 150), new Coordinate(150, 0), new Coordinate(0, 0)}); + Polygon within = factory.CreatePolygon([ + new(0, 0), + new(0, 150), new(150, 150), new(150, 0), new(0, 0) + ]); SearchResult res = ft.Search(index, new Query("@geom:[within $poly]").AddParam("poly", within.ToString()).Dialect(3)); Assert.Equal(1, res.TotalResults); @@ -3255,8 +3266,10 @@ public void GeoShapeFilterFlat(string endpointId) Assert.Equal(small, reader.Read(res.Documents[0]["geom"].ToString())); // contains condition - Polygon contains = factory.CreatePolygon(new Coordinate[]{new Coordinate(2, 2), - new Coordinate(2, 50), new Coordinate(50, 50), new Coordinate(50, 2), new Coordinate(2, 2)}); + Polygon contains = factory.CreatePolygon([ + new(2, 2), + new(2, 50), new(50, 50), new(50, 2), new(2, 2) + ]); res = ft.Search(index, new Query("@geom:[contains $poly]").AddParam("poly", contains.ToString()).Dialect(3)); Assert.Equal(2, res.TotalResults); @@ -3271,29 +3284,35 @@ public void GeoShapeFilterFlat(string endpointId) Assert.Equal(2, res.Documents.Count); } - [SkipIfRedis(Comparison.LessThan, "7.2.1")] + [SkipIfRedisTheory(Comparison.LessThan, "7.2.1")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task GeoShapeFilterFlatAsync(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); - WKTReader reader = new WKTReader(); - GeometryFactory factory = new GeometryFactory(); + WKTReader reader = new(); + GeometryFactory factory = new(); Assert.True(await ft.CreateAsync(index, new Schema().AddGeoShapeField("geom", GeoShapeField.CoordinateSystem.FLAT))); // polygon type - Polygon small = factory.CreatePolygon(new Coordinate[]{new Coordinate(1, 1), - new Coordinate(1, 100), new Coordinate(100, 100), new Coordinate(100, 1), new Coordinate(1, 1)}); + Polygon small = factory.CreatePolygon([ + new(1, 1), + new(1, 100), new(100, 100), new(100, 1), new(1, 1) + ]); db.HashSet("small", "geom", small.ToString()); - Polygon large = factory.CreatePolygon(new Coordinate[]{new Coordinate(1, 1), - new Coordinate(1, 200), new Coordinate(200, 200), new Coordinate(200, 1), new Coordinate(1, 1)}); + Polygon large = factory.CreatePolygon([ + new(1, 1), + new(1, 200), new(200, 200), new(200, 1), new(1, 1) + ]); db.HashSet("large", "geom", large.ToString()); // within condition - Polygon within = factory.CreatePolygon(new Coordinate[]{new Coordinate(0, 0), - new Coordinate(0, 150), new Coordinate(150, 150), new Coordinate(150, 0), new Coordinate(0, 0)}); + Polygon within = factory.CreatePolygon([ + new(0, 0), + new(0, 150), new(150, 150), new(150, 0), new(0, 0) + ]); SearchResult res = await ft.SearchAsync(index, new Query("@geom:[within $poly]").AddParam("poly", within.ToString()).Dialect(3)); Assert.Equal(1, res.TotalResults); @@ -3301,8 +3320,10 @@ public async Task GeoShapeFilterFlatAsync(string endpointId) Assert.Equal(small, reader.Read(res.Documents[0]["geom"].ToString())); // contains condition - Polygon contains = factory.CreatePolygon(new Coordinate[]{new Coordinate(2, 2), - new Coordinate(2, 50), new Coordinate(50, 50), new Coordinate(50, 2), new Coordinate(2, 2)}); + Polygon contains = factory.CreatePolygon([ + new(2, 2), + new(2, 50), new(50, 50), new(50, 2), new(2, 2) + ]); res = await ft.SearchAsync(index, new Query("@geom:[contains $poly]").AddParam("poly", contains.ToString()).Dialect(3)); Assert.Equal(2, res.TotalResults); @@ -3326,10 +3347,11 @@ public void Issue230() var buildCommand = SearchCommandBuilder.Aggregate("idx:users", request); // expected: FT.AGGREGATE idx:users * FILTER @StatusId==1 GROUPBY 1 @CreatedDay REDUCE COUNT_DISTINCT 1 @UserId REDUCE COUNT 0 AS count DIALECT 3 Assert.Equal("FT.AGGREGATE", buildCommand.Command); - Assert.Equal(new object[] { "idx:users", "*", "FILTER", "@StatusId==1", "GROUPBY", 1, "@CreatedDay", "REDUCE", "COUNT_DISTINCT", 1, "@UserId", "REDUCE", "COUNT", 0, "AS", "count", "DIALECT", 3 }, buildCommand.Args); + Assert.Equal(["idx:users", "*", "FILTER", "@StatusId==1", "GROUPBY", 1, "@CreatedDay", "REDUCE", "COUNT_DISTINCT", 1, "@UserId", "REDUCE", "COUNT", 0, "AS", "count", "DIALECT", 3 + ], buildCommand.Args); } - [SkipIfRedis(Comparison.LessThan, "7.3.240")] + [SkipIfRedisTheory(Comparison.LessThan, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestNumericInDialect4(string endpointId) { @@ -3341,18 +3363,18 @@ public void TestNumericInDialect4(string endpointId) .AddNumericField("version"); Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - Dictionary fields4 = new Dictionary + Dictionary fields4 = new() { { "title", "hello world" }, { "version", 123 } }; AddDocument(db, "qux", fields4); - Assert.Equal(1, ft.Search(index, new Query("@version:[123 123]")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@version:[123 123]")).TotalResults); Assert.Equal(1, ft.Search(index, new Query("@version:[123]").Dialect(4)).TotalResults); } - [SkipIfRedis(Comparison.LessThan, "7.3.240")] + [SkipIfRedisTheory(Comparison.LessThan, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestNumericOperatorsInDialect4(string endpointId) { @@ -3364,25 +3386,25 @@ public void TestNumericOperatorsInDialect4(string endpointId) .AddNumericField("version"); Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - Dictionary fields4 = new Dictionary + Dictionary fields4 = new() { { "title", "hello world" }, { "version", 123 } }; AddDocument(db, "qux", fields4); - Assert.Equal(1, ft.Search(index, new Query("@version:[123 123]")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@version:[123 123]")).TotalResults); Assert.Equal(1, ft.Search(index, new Query("@version==123").Dialect(4)).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("@version:[122 +inf]")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@version:[122 +inf]")).TotalResults); Assert.Equal(1, ft.Search(index, new Query("@version>=122").Dialect(4)).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("@version:[-inf 124]")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@version:[-inf 124]")).TotalResults); Assert.Equal(1, ft.Search(index, new Query("@version<=124").Dialect(4)).TotalResults); } - [SkipIfRedis(Comparison.LessThan, "7.3.240")] + [SkipIfRedisTheory(Comparison.LessThan, "7.3.240")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestNumericLogicalOperatorsInDialect4(string endpointId) { @@ -3395,7 +3417,7 @@ public void TestNumericLogicalOperatorsInDialect4(string endpointId) .AddNumericField("id"); Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - Dictionary fields4 = new Dictionary + Dictionary fields4 = new() { { "title", "hello world" }, { "version", 123 }, @@ -3405,13 +3427,13 @@ public void TestNumericLogicalOperatorsInDialect4(string endpointId) Assert.Equal(1, ft.Search(index, new Query("@version<=124").Dialect(4)).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("@version:[123 123]")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@version:[123 123]")).TotalResults); Assert.Equal(1, ft.Search(index, new Query("@version:[123] | @version:[124]").Dialect(4)).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("@version:[123 123] | @version:[7890 7890]")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@version:[123 123] | @version:[7890 7890]")).TotalResults); Assert.Equal(1, ft.Search(index, new Query("@version==123 | @version==7890").Dialect(4)).TotalResults); - Assert.Equal(1, ft.Search(index, new Query("@version:[123 123] | @id:[456 7890]")).TotalResults); + Assert.Equal(1, ft.Search(index, new("@version:[123 123] | @id:[456 7890]")).TotalResults); Assert.Equal(1, ft.Search(index, new Query("@version==123 @id==456").Dialect(4)).TotalResults); } @@ -3425,7 +3447,7 @@ public void TestNumericLogicalOperatorsInDialect4(string endpointId) [Fact] public void TestDocumentLoad_Issue352() { - Document d = Document.Load("1", 0.5, null, new RedisValue[] { RedisValue.Null }); + Document d = Document.Load("1", 0.5, null, [RedisValue.Null]); Assert.Empty(d.GetProperties().ToList()); } @@ -3438,7 +3460,7 @@ public void TestDocumentLoad_Issue352() /// [SkippableTheory] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async void TestDocumentLoadWithDB_Issue352(string endpointId) + public async Task TestDocumentLoadWithDB_Issue352(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); var ft = db.FT(); @@ -3446,7 +3468,7 @@ public async void TestDocumentLoadWithDB_Issue352(string endpointId) Schema sc = new Schema().AddTextField("firstText", 1.0).AddTextField("lastText", 1.0).AddNumericField("ageNumeric"); Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - Document droppedDocument = null; + Document? droppedDocument = null; int numberOfAttempts = 0; do { @@ -3454,7 +3476,7 @@ public async void TestDocumentLoadWithDB_Issue352(string endpointId) bool ttlRefreshed = false; do { - db.HashSet("student:22222", new HashEntry[] { new("firstText", "Joe"), new("lastText", "Dod"), new("ageNumeric", 18) }); + db.HashSet("student:22222", [new("firstText", "Joe"), new("lastText", "Dod"), new("ageNumeric", 18)]); ttlRefreshed = db.KeyExpire("student:22222", TimeSpan.FromMilliseconds(500)); } while (!ttlRefreshed); @@ -3464,7 +3486,7 @@ public async void TestDocumentLoadWithDB_Issue352(string endpointId) { for (int i = 0; i < 1000000; i++) { - SearchResult result = ft.Search(index, new Query()); + SearchResult result = ft.Search(index, new()); List docs = result.Documents; // check if doc is already dropped before search and load; @@ -3485,7 +3507,7 @@ public async void TestDocumentLoadWithDB_Issue352(string endpointId) } }; - List tasks = new List(); + List tasks = []; // try with 3 different tasks simultaneously to increase the chance of hitting it for (int i = 0; i < 3; i++) { tasks.Add(Task.Run(checker)); } Task checkTask = Task.WhenAll(tasks); diff --git a/tests/NRedisStack.Tests/SkipIfRedisAttribute.cs b/tests/NRedisStack.Tests/SkipIfRedisTheoryAttribute.cs similarity index 59% rename from tests/NRedisStack.Tests/SkipIfRedisAttribute.cs rename to tests/NRedisStack.Tests/SkipIfRedisTheoryAttribute.cs index acfebfe3..503a329b 100644 --- a/tests/NRedisStack.Tests/SkipIfRedisAttribute.cs +++ b/tests/NRedisStack.Tests/SkipIfRedisTheoryAttribute.cs @@ -14,15 +14,13 @@ public enum Is Enterprise } -[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] -[XunitTestCaseDiscoverer("NRedisStack.Tests.SkippableTheoryDiscoverer", "NRedisStack.Tests")] -public class SkipIfRedisAttribute : SkippableTheoryAttribute +internal readonly struct SkipIfRedisCore { private readonly string _targetVersion; private readonly Comparison _comparison; - private readonly List _environments = new List(); + private readonly List _environments = []; - public SkipIfRedisAttribute( + public SkipIfRedisCore( Is environment, Comparison comparison = Comparison.LessThan, string targetVersion = "0.0.0") @@ -32,19 +30,19 @@ public SkipIfRedisAttribute( _targetVersion = targetVersion; } - public SkipIfRedisAttribute(string targetVersion) // defaults to LessThan + public SkipIfRedisCore(string targetVersion) // defaults to LessThan { _comparison = Comparison.LessThan; _targetVersion = targetVersion; } - public SkipIfRedisAttribute(Comparison comparison, string targetVersion) + public SkipIfRedisCore(Comparison comparison, string targetVersion) { _comparison = comparison; _targetVersion = targetVersion; } - public override string? Skip + public string? Skip { get { @@ -97,4 +95,46 @@ public override string? Skip return null; } } +} + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] +[XunitTestCaseDiscoverer("NRedisStack.Tests.SkippableTheoryDiscoverer", "NRedisStack.Tests")] +public class SkipIfRedisTheoryAttribute : SkippableTheoryAttribute +{ + private readonly SkipIfRedisCore core; + + public SkipIfRedisTheoryAttribute( + Is environment, + Comparison comparison = Comparison.LessThan, + string targetVersion = "0.0.0") + => core = new(environment, comparison, targetVersion); + + public SkipIfRedisTheoryAttribute(string targetVersion) // defaults to LessThan + => core = new(targetVersion); + + public SkipIfRedisTheoryAttribute(Comparison comparison, string targetVersion) + => core = new(comparison, targetVersion); + + public override string? Skip => core.Skip; +} + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] +[XunitTestCaseDiscoverer("NRedisStack.Tests.SkippableTheoryDiscoverer", "NRedisStack.Tests")] +public class SkipIfRedisFactAttribute : SkippableFactAttribute +{ + private readonly SkipIfRedisCore core; + + public SkipIfRedisFactAttribute( + Is environment, + Comparison comparison = Comparison.LessThan, + string targetVersion = "0.0.0") + => core = new(environment, comparison, targetVersion); + + public SkipIfRedisFactAttribute(string targetVersion) // defaults to LessThan + => core = new(targetVersion); + + public SkipIfRedisFactAttribute(Comparison comparison, string targetVersion) + => core = new(comparison, targetVersion); + + public override string? Skip => core.Skip; } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/SkippableTheoryDiscoverer.cs b/tests/NRedisStack.Tests/SkippableTheoryDiscoverer.cs index 9f2261a3..a6bfe2b8 100644 --- a/tests/NRedisStack.Tests/SkippableTheoryDiscoverer.cs +++ b/tests/NRedisStack.Tests/SkippableTheoryDiscoverer.cs @@ -35,26 +35,26 @@ public class SkippableTheoryDiscoverer : IXunitTestCaseDiscoverer public SkippableTheoryDiscoverer(IMessageSink diagnosticMessageSink) { this.diagnosticMessageSink = diagnosticMessageSink; - this.theoryDiscoverer = new TheoryDiscoverer(diagnosticMessageSink); + theoryDiscoverer = new(diagnosticMessageSink); } /// public virtual IEnumerable Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute) { Requires.NotNull(factAttribute, nameof(factAttribute)); - string[] skippingExceptionNames = new[] { "Xunit.SkippableFact.SkipException", "Xunit.SkipException" }; + string[] skippingExceptionNames = ["Xunit.SkippableFact.SkipException", "Xunit.SkipException"]; TestMethodDisplay defaultMethodDisplay = discoveryOptions.MethodDisplayOrDefault(); - IEnumerable? basis = this.theoryDiscoverer.Discover(discoveryOptions, testMethod, factAttribute); + IEnumerable? basis = theoryDiscoverer.Discover(discoveryOptions, testMethod, factAttribute); foreach (IXunitTestCase? testCase in basis) { if (testCase is XunitTheoryTestCase) { - yield return new SkippableTheoryTestCase(skippingExceptionNames, this.diagnosticMessageSink, defaultMethodDisplay, discoveryOptions.MethodDisplayOptionsOrDefault(), testCase.TestMethod); + yield return new SkippableTheoryTestCase(skippingExceptionNames, diagnosticMessageSink, defaultMethodDisplay, discoveryOptions.MethodDisplayOptionsOrDefault(), testCase.TestMethod); } else { - yield return new SkippableFactTestCase(skippingExceptionNames, this.diagnosticMessageSink, defaultMethodDisplay, discoveryOptions.MethodDisplayOptionsOrDefault(), testCase.TestMethod, testCase.TestMethodArguments); + yield return new SkippableFactTestCase(skippingExceptionNames, diagnosticMessageSink, defaultMethodDisplay, discoveryOptions.MethodDisplayOptionsOrDefault(), testCase.TestMethod, testCase.TestMethodArguments); } } } diff --git a/tests/NRedisStack.Tests/Tdigest/TdigestTests.cs b/tests/NRedisStack.Tests/Tdigest/TdigestTests.cs index f81cce0d..1b49c559 100644 --- a/tests/NRedisStack.Tests/Tdigest/TdigestTests.cs +++ b/tests/NRedisStack.Tests/Tdigest/TdigestTests.cs @@ -211,7 +211,7 @@ public async Task TestAddAsync(string endpointId) AssertMergedUnmergedNodes(tdigest, "tdadd", 0, 5); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void TestMerge(string endpointId) { @@ -234,7 +234,7 @@ public void TestMerge(string endpointId) } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task TestMergeAsync(string endpointId) { @@ -257,7 +257,7 @@ public async Task TestMergeAsync(string endpointId) AssertMergedUnmergedNodes(tdigest, "td2", 3, 2); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public void MergeMultiAndParams(string endpointId) { @@ -271,14 +271,14 @@ public void MergeMultiAndParams(string endpointId) tdigest.Add("from1", 1d); tdigest.Add("from2", WeightedValue(1d, 10)); - Assert.True(tdigest.Merge("to", 2, sourceKeys: new RedisKey[] { "from1", "from2" })); + Assert.True(tdigest.Merge("to", 2, sourceKeys: ["from1", "from2"])); AssertTotalWeight(tdigest, "to", 11d); Assert.True(tdigest.Merge("to", 50, true, "from1", "from2")); Assert.Equal(50, tdigest.Info("to").Compression); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] public async Task MergeMultiAndParamsAsync(string endpointId) { @@ -292,7 +292,7 @@ public async Task MergeMultiAndParamsAsync(string endpointId) tdigest.Add("from1", 1d); tdigest.Add("from2", WeightedValue(1d, 10)); - Assert.True(await tdigest.MergeAsync("to", 2, sourceKeys: new RedisKey[] { "from1", "from2" })); + Assert.True(await tdigest.MergeAsync("to", 2, sourceKeys: ["from1", "from2"])); AssertTotalWeight(tdigest, "to", 11d); Assert.True(await tdigest.MergeAsync("to", 50, true, "from1", "from2")); @@ -317,7 +317,7 @@ public void TestCDF(string endpointId) tdigest.Add("tdcdf", 1, 1, 1); tdigest.Add("tdcdf", 100, 100); - Assert.Equal(new double[] { 0.6 }, tdigest.CDF("tdcdf", 50)); + Assert.Equal(new[] { 0.6 }, tdigest.CDF("tdcdf", 50)); tdigest.CDF("tdcdf", 25, 50, 75); // TODO: Why needed? } @@ -339,7 +339,7 @@ public async Task TestCDFAsync(string endpointId) tdigest.Add("tdcdf", 1, 1, 1); tdigest.Add("tdcdf", 100, 100); - Assert.Equal(new double[] { 0.6 }, await tdigest.CDFAsync("tdcdf", 50)); + Assert.Equal(new[] { 0.6 }, await tdigest.CDFAsync("tdcdf", 50)); await tdigest.CDFAsync("tdcdf", 25, 50, 75); // TODO: Why needed? } @@ -353,7 +353,7 @@ public void TestQuantile(string endpointId) tdigest.Create("tdqnt", 100); var resDelete = tdigest.Quantile("tdqnt", 0.5); - Assert.Equal(new double[] { double.NaN }, tdigest.Quantile("tdqnt", 0.5)); + Assert.Equal(new[] { double.NaN }, tdigest.Quantile("tdqnt", 0.5)); // tdigest.Add("tdqnt", DefinedValueWeight(1, 1), DefinedValueWeight(1, 1), DefinedValueWeight(1, 1)); // tdigest.Add("tdqnt", DefinedValueWeight(100, 1), DefinedValueWeight(100, 1)); @@ -371,7 +371,7 @@ public async Task TestQuantileAsync(string endpointId) tdigest.Create("tdqnt", 100); var resDelete = await tdigest.QuantileAsync("tdqnt", 0.5); - Assert.Equal(new double[] { double.NaN }, await tdigest.QuantileAsync("tdqnt", 0.5)); + Assert.Equal(new[] { double.NaN }, await tdigest.QuantileAsync("tdqnt", 0.5)); // await tdigest.AddAsync("tdqnt", DefinedValueWeight(1, 1), DefinedValueWeight(1, 1), DefinedValueWeight(1, 1)); // await tdigest.AddAsync("tdqnt", DefinedValueWeight(100, 1), DefinedValueWeight(100, 1)); @@ -477,15 +477,15 @@ public void TestModulePrefixs(string endpointId) private static double RandomValue() { - Random random = new Random(); + Random random = new(); return random.NextDouble() * 10000; } static Tuple RandomValueWeight() { - Random random = new Random(); + Random random = new(); - return new Tuple(random.NextDouble() * 10000, random.Next() + 1); + return new(random.NextDouble() * 10000, random.Next() + 1); } static Tuple[] RandomValueWeightArray(int count) @@ -500,7 +500,7 @@ static Tuple[] RandomValueWeightArray(int count) static Tuple DefinedValueWeight(double value, long weight) { - return new Tuple(value, weight); + return new(value, weight); } private static double[] WeightedValue(double value, int weight) diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAdd.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAdd.cs index 0794705f..fab1f57b 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAdd.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAdd.cs @@ -1,237 +1,235 @@ +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using StackExchange.Redis; using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; using NRedisStack.Literals.Enums; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestAdd(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable { - public class TestAdd : AbstractNRedisStackTest, IDisposable - { - private readonly string key = "ADD_TESTS"; - - public TestAdd(EndpointsFixture endpointsFixture) : base(endpointsFixture) { } - - - [Fact] - [Obsolete] - public void TestAddNotExistingTimeSeries() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, ts.Add(key, now, 1.1)); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(now, info.FirstTimeStamp); - Assert.Equal(now, info.LastTimeStamp); - } - - [Fact] - [Obsolete] - public void TestAddExistingTimeSeries() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - - ts.Create(key); - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, ts.Add(key, now, 1.1)); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(now, info.FirstTimeStamp); - Assert.Equal(now, info.LastTimeStamp); - } - - [Fact] - [Obsolete] - public void TestAddStar() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - - ts.Add(key, "*", 1.1); - TimeSeriesInformation info = ts.Info(key); - Assert.True(info.FirstTimeStamp! > 0); - Assert.Equal(info.FirstTimeStamp, info.LastTimeStamp); - } - - [Fact] - [Obsolete] - public void TestAddWithRetentionTime() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp now = DateTime.UtcNow; - long retentionTime = 5000; - Assert.Equal(now, ts.Add(key, now, 1.1, retentionTime: retentionTime)); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(now, info.FirstTimeStamp); - Assert.Equal(now, info.LastTimeStamp); - Assert.Equal(retentionTime, info.RetentionTime); - } - - [Fact] - [Obsolete] - public void TestAddWithLabels() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp now = DateTime.UtcNow; - TimeSeriesLabel label = new TimeSeriesLabel("key", "value"); - var labels = new List { label }; - Assert.Equal(now, ts.Add(key, now, 1.1, labels: labels)); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(now, info.FirstTimeStamp); - Assert.Equal(now, info.LastTimeStamp); - Assert.Equal(labels, info.Labels); - } - - [Fact] - [Obsolete] - public void TestAddWithUncompressed() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - ts.Create(key); - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, ts.Add(key, now, 1.1, uncompressed: true)); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(now, info.FirstTimeStamp); - Assert.Equal(now, info.LastTimeStamp); - } - - [Fact] - [Obsolete] - public void TestAddWithChunkSize() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, ts.Add(key, now, 1.1, chunkSizeBytes: 128)); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(now, info.FirstTimeStamp); - Assert.Equal(now, info.LastTimeStamp); - Assert.Equal(128, info.ChunkSize); - } - - [Fact] - public void TestAddWithDuplicatePolicyBlock() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, ts.Add(key, now, 1.1)); - Assert.Throws(() => ts.Add(key, now, 1.2)); - } - - [Fact] - public void TestAddWithDuplicatePolicyMin() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, ts.Add(key, now, 1.1)); - - // Insert a bigger number and check that it did not change the value. - Assert.Equal(now, ts.Add(key, now, 1.2, duplicatePolicy: TsDuplicatePolicy.MIN)); - Assert.Equal(1.1, ts.Range(key, now, now)[0].Val); - // Insert a smaller number and check that it changed. - Assert.Equal(now, ts.Add(key, now, 1.0, duplicatePolicy: TsDuplicatePolicy.MIN)); - Assert.Equal(1.0, ts.Range(key, now, now)[0].Val); - } - - [Fact] - public void TestAddWithDuplicatePolicyMax() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, ts.Add(key, now, 1.1)); - - // Insert a smaller number and check that it did not change the value. - Assert.Equal(now, ts.Add(key, now, 1.0, duplicatePolicy: TsDuplicatePolicy.MAX)); - Assert.Equal(1.1, ts.Range(key, now, now)[0].Val); - // Insert a bigger number and check that it changed. - Assert.Equal(now, ts.Add(key, now, 1.2, duplicatePolicy: TsDuplicatePolicy.MAX)); - Assert.Equal(1.2, ts.Range(key, now, now)[0].Val); - } - - [Fact] - public void TestAddWithDuplicatePolicySum() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, ts.Add(key, now, 1.1)); - Assert.Equal(now, ts.Add(key, now, 1.0, duplicatePolicy: TsDuplicatePolicy.SUM)); - Assert.Equal(2.1, ts.Range(key, now, now)[0].Val); - } - - [Fact] - public void TestAddWithDuplicatePolicyFirst() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, ts.Add(key, now, 1.1)); - Assert.Equal(now, ts.Add(key, now, 1.0, duplicatePolicy: TsDuplicatePolicy.FIRST)); - Assert.Equal(1.1, ts.Range(key, now, now)[0].Val); - } - - [Fact] - public void TestAddWithDuplicatePolicyLast() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp now = DateTime.UtcNow; - Assert.Equal(now, ts.Add(key, now, 1.1)); - Assert.Equal(now, ts.Add(key, now, 1.0, duplicatePolicy: TsDuplicatePolicy.LAST)); - Assert.Equal(1.0, ts.Range(key, now, now)[0].Val); - } - - [Fact] - public void TestOldAdd() - { - TimeStamp old_dt = DateTime.UtcNow; - Thread.Sleep(1000); - TimeStamp new_dt = DateTime.UtcNow; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - ts.Create(key); - ts.Add(key, new_dt, 1.1); - // Adding old event - var res = ts.Add(key, old_dt, 1.1); - Assert.Equal(old_dt.Value, res.Value); - } - - [Fact] - public void TestWrongParameters() - { - double value = 1.1; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var ex = Assert.Throws(() => ts.Add(key, "+", value)); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - ex = Assert.Throws(() => ts.Add(key, "-", value)); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - } - - [SkipIfRedis(Comparison.LessThan, "7.4.0")] - [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] - public void TestAddAndIgnoreValues(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var parameters = new TsAddParamsBuilder().AddTimestamp(101).AddValue(102).AddIgnoreValues(15, 16).build(); - ts.Add(key, parameters); - - int j = -1, k = -1; - RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); - Assert.NotNull(info); - Assert.True(info.Length > 0); - Assert.NotEqual(-1, j); - Assert.NotEqual(-1, k); - Assert.Equal(15, (long)info[j + 1]); - Assert.Equal(16, (long)info[k + 1]); - } - } -} + private readonly string key = "ADD_TESTS"; + + + [Fact] + [Obsolete] + public void TestAddNotExistingTimeSeries() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + + TimeStamp now = DateTime.UtcNow; + Assert.Equal(now, ts.Add(key, now, 1.1)); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(now, info.FirstTimeStamp); + Assert.Equal(now, info.LastTimeStamp); + } + + [Fact] + [Obsolete] + public void TestAddExistingTimeSeries() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + + ts.Create(key); + TimeStamp now = DateTime.UtcNow; + Assert.Equal(now, ts.Add(key, now, 1.1)); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(now, info.FirstTimeStamp); + Assert.Equal(now, info.LastTimeStamp); + } + + [Fact] + [Obsolete] + public void TestAddStar() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + + ts.Add(key, "*", 1.1); + TimeSeriesInformation info = ts.Info(key); + Assert.True(info.FirstTimeStamp! > 0); + Assert.Equal(info.FirstTimeStamp, info.LastTimeStamp); + } + + [Fact] + [Obsolete] + public void TestAddWithRetentionTime() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp now = DateTime.UtcNow; + long retentionTime = 5000; + Assert.Equal(now, ts.Add(key, now, 1.1, retentionTime: retentionTime)); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(now, info.FirstTimeStamp); + Assert.Equal(now, info.LastTimeStamp); + Assert.Equal(retentionTime, info.RetentionTime); + } + + [Fact] + [Obsolete] + public void TestAddWithLabels() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp now = DateTime.UtcNow; + TimeSeriesLabel label = new("key", "value"); + var labels = new List { label }; + Assert.Equal(now, ts.Add(key, now, 1.1, labels: labels)); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(now, info.FirstTimeStamp); + Assert.Equal(now, info.LastTimeStamp); + Assert.Equal(labels, info.Labels); + } + + [Fact] + [Obsolete] + public void TestAddWithUncompressed() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + ts.Create(key); + TimeStamp now = DateTime.UtcNow; + Assert.Equal(now, ts.Add(key, now, 1.1, uncompressed: true)); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(now, info.FirstTimeStamp); + Assert.Equal(now, info.LastTimeStamp); + } + + [Fact] + [Obsolete] + public void TestAddWithChunkSize() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp now = DateTime.UtcNow; + Assert.Equal(now, ts.Add(key, now, 1.1, chunkSizeBytes: 128)); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(now, info.FirstTimeStamp); + Assert.Equal(now, info.LastTimeStamp); + Assert.Equal(128, info.ChunkSize); + } + + [Fact] + public void TestAddWithDuplicatePolicyBlock() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp now = DateTime.UtcNow; + Assert.Equal(now, ts.Add(key, now, 1.1)); + Assert.Throws(() => ts.Add(key, now, 1.2)); + } + + [Fact] + public void TestAddWithDuplicatePolicyMin() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp now = DateTime.UtcNow; + Assert.Equal(now, ts.Add(key, now, 1.1)); + + // Insert a bigger number and check that it did not change the value. + Assert.Equal(now, ts.Add(key, now, 1.2, duplicatePolicy: TsDuplicatePolicy.MIN)); + Assert.Equal(1.1, ts.Range(key, now, now)[0].Val); + // Insert a smaller number and check that it changed. + Assert.Equal(now, ts.Add(key, now, 1.0, duplicatePolicy: TsDuplicatePolicy.MIN)); + Assert.Equal(1.0, ts.Range(key, now, now)[0].Val); + } + + [Fact] + public void TestAddWithDuplicatePolicyMax() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp now = DateTime.UtcNow; + Assert.Equal(now, ts.Add(key, now, 1.1)); + + // Insert a smaller number and check that it did not change the value. + Assert.Equal(now, ts.Add(key, now, 1.0, duplicatePolicy: TsDuplicatePolicy.MAX)); + Assert.Equal(1.1, ts.Range(key, now, now)[0].Val); + // Insert a bigger number and check that it changed. + Assert.Equal(now, ts.Add(key, now, 1.2, duplicatePolicy: TsDuplicatePolicy.MAX)); + Assert.Equal(1.2, ts.Range(key, now, now)[0].Val); + } + + [Fact] + public void TestAddWithDuplicatePolicySum() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp now = DateTime.UtcNow; + Assert.Equal(now, ts.Add(key, now, 1.1)); + Assert.Equal(now, ts.Add(key, now, 1.0, duplicatePolicy: TsDuplicatePolicy.SUM)); + Assert.Equal(2.1, ts.Range(key, now, now)[0].Val); + } + + [Fact] + public void TestAddWithDuplicatePolicyFirst() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp now = DateTime.UtcNow; + Assert.Equal(now, ts.Add(key, now, 1.1)); + Assert.Equal(now, ts.Add(key, now, 1.0, duplicatePolicy: TsDuplicatePolicy.FIRST)); + Assert.Equal(1.1, ts.Range(key, now, now)[0].Val); + } + + [Fact] + public void TestAddWithDuplicatePolicyLast() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp now = DateTime.UtcNow; + Assert.Equal(now, ts.Add(key, now, 1.1)); + Assert.Equal(now, ts.Add(key, now, 1.0, duplicatePolicy: TsDuplicatePolicy.LAST)); + Assert.Equal(1.0, ts.Range(key, now, now)[0].Val); + } + + [Fact] + public void TestOldAdd() + { + TimeStamp old_dt = DateTime.UtcNow; + Thread.Sleep(1000); + TimeStamp new_dt = DateTime.UtcNow; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + ts.Create(key); + ts.Add(key, new_dt, 1.1); + // Adding old event + var res = ts.Add(key, old_dt, 1.1); + Assert.Equal(old_dt.Value, res.Value); + } + + [Fact] + public void TestWrongParameters() + { + double value = 1.1; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var ex = Assert.Throws(() => ts.Add(key, "+", value)); + Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); + ex = Assert.Throws(() => ts.Add(key, "-", value)); + Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); + } + + [SkipIfRedisTheory(Comparison.LessThan, "7.4.0")] + [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] + public void TestAddAndIgnoreValues(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var parameters = new TsAddParamsBuilder().AddTimestamp(101).AddValue(102).AddIgnoreValues(15, 16).build(); + ts.Add(key, parameters); + + int j = -1, k = -1; + RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); + Assert.NotNull(info); + Assert.True(info.Length > 0); + Assert.NotEqual(-1, j); + Assert.NotEqual(-1, k); + Assert.Equal(15, (long)info[j + 1]); + Assert.Equal(16, (long)info[k + 1]); + } +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAddAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAddAsync.cs index f8a075b6..23714ae8 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAddAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAddAsync.cs @@ -1,242 +1,240 @@ +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using StackExchange.Redis; using NRedisStack.DataTypes; using NRedisStack.Literals.Enums; using NRedisStack.RedisStackCommands; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestAddAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestAddAsync : AbstractNRedisStackTest + [Fact] + [Obsolete] + public async Task TestAddNotExistingTimeSeries() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); + + var info = await ts.InfoAsync(key); + Assert.Equal(timeStamp, info.FirstTimeStamp); + Assert.Equal(timeStamp, info.LastTimeStamp); + } + + [Fact] + [Obsolete] + public async Task TestAddExistingTimeSeries() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + await ts.CreateAsync(key); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); + + var info = await ts.InfoAsync(key); + Assert.Equal(timeStamp, info.FirstTimeStamp); + Assert.Equal(timeStamp, info.LastTimeStamp); + } + + [Fact] + [Obsolete] + public async Task TestAddStar() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + await ts.AddAsync(key, "*", 1.1); + var info = await ts.InfoAsync(key); + Assert.True(info.FirstTimeStamp! > 0); + Assert.Equal(info.FirstTimeStamp, info.LastTimeStamp); + } + + [Fact] + [Obsolete] + public async Task TestAddWithRetentionTime() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + long retentionTime = 5000; + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1, retentionTime: retentionTime)); + + var info = await ts.InfoAsync(key); + Assert.Equal(timeStamp, info.FirstTimeStamp); + Assert.Equal(timeStamp, info.LastTimeStamp); + Assert.Equal(retentionTime, info.RetentionTime); + } + + [Fact] + [Obsolete] + public async Task TestAddWithLabels() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + var label = new TimeSeriesLabel("key", "value"); + var labels = new List { label }; + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1, labels: labels)); + + var info = await ts.InfoAsync(key); + Assert.Equal(timeStamp, info.FirstTimeStamp); + Assert.Equal(timeStamp, info.LastTimeStamp); + Assert.Equal(labels, info.Labels); + } + + [Fact] + [Obsolete] + public async Task TestAddWithChunkSize() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1, chunkSizeBytes: 128)); + var info = await ts.InfoAsync(key); + Assert.Equal(timeStamp, info.FirstTimeStamp); + Assert.Equal(timeStamp, info.LastTimeStamp); + Assert.Equal(128, info.ChunkSize); + } + + [Fact] + [Obsolete] + public async Task TestAddWithUncompressed() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + await ts.CreateAsync(key); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1, uncompressed: true)); + + var info = await ts.InfoAsync(key); + Assert.Equal(timeStamp, info.FirstTimeStamp); + Assert.Equal(timeStamp, info.LastTimeStamp); + } + + [Fact] + public async Task TestAddWithDuplicatePolicyBlock() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); + await Assert.ThrowsAsync(async () => await ts.AddAsync(key, timeStamp, 1.2)); + } + + [Fact] + public async Task TestAddWithDuplicatePolicyMin() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); + + // Insert a bigger number and check that it did not change the value. + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.2, duplicatePolicy: TsDuplicatePolicy.MIN)); + IReadOnlyList results = await ts.RangeAsync(key, timeStamp, timeStamp); + Assert.Equal(1.1, results[0].Val); + + // Insert a smaller number and check that it changed. + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.0, duplicatePolicy: TsDuplicatePolicy.MIN)); + results = await ts.RangeAsync(key, timeStamp, timeStamp); + Assert.Equal(1.0, results[0].Val); + } + + [Fact] + public async Task TestAddWithDuplicatePolicyMax() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); + + // Insert a smaller number and check that it did not change the value. + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.0, duplicatePolicy: TsDuplicatePolicy.MAX)); + IReadOnlyList results = await ts.RangeAsync(key, timeStamp, timeStamp); + Assert.Equal(1.1, results[0].Val); + // Insert a bigger number and check that it changed. + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.2, duplicatePolicy: TsDuplicatePolicy.MAX)); + results = await ts.RangeAsync(key, timeStamp, timeStamp); + Assert.Equal(1.2, results[0].Val); + } + + [Fact] + public async Task TestAddWithDuplicatePolicySum() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.0, duplicatePolicy: TsDuplicatePolicy.SUM)); + IReadOnlyList results = await ts.RangeAsync(key, timeStamp, timeStamp); + Assert.Equal(2.1, results[0].Val); + } + + [Fact] + public async Task TestAddWithDuplicatePolicyFirst() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.0, duplicatePolicy: TsDuplicatePolicy.FIRST)); + IReadOnlyList results = await ts.RangeAsync(key, timeStamp, timeStamp); + Assert.Equal(1.1, results[0].Val); + } + + [Fact] + public async Task TestAddWithDuplicatePolicyLast() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); + Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.0, duplicatePolicy: TsDuplicatePolicy.LAST)); + IReadOnlyList results = await ts.RangeAsync(key, timeStamp, timeStamp); + Assert.Equal(1.0, results[0].Val); + } + + [Fact] + public async Task TestOldAdd() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + var dateTime = DateTime.UtcNow; + TimeStamp oldTimeStamp = dateTime.AddSeconds(-1); + TimeStamp newTimeStamp = dateTime; + await ts.CreateAsync(key); + await ts.AddAsync(key, newTimeStamp, 1.1); + // Adding old event + var res = await ts.AddAsync(key, oldTimeStamp, 1.1); + Assert.Equal(oldTimeStamp.Value, res.Value); + } + + [Fact] + public async Task TestWrongParameters() { - public TestAddAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) { } - - [Fact] - [Obsolete] - public async Task TestAddNotExistingTimeSeries() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); - - var info = await ts.InfoAsync(key); - Assert.Equal(timeStamp, info.FirstTimeStamp); - Assert.Equal(timeStamp, info.LastTimeStamp); - } - - [Fact] - [Obsolete] - public async Task TestAddExistingTimeSeries() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - await ts.CreateAsync(key); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); - - var info = await ts.InfoAsync(key); - Assert.Equal(timeStamp, info.FirstTimeStamp); - Assert.Equal(timeStamp, info.LastTimeStamp); - } - - [Fact] - [Obsolete] - public async Task TestAddStar() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - await ts.AddAsync(key, "*", 1.1); - var info = await ts.InfoAsync(key); - Assert.True(info.FirstTimeStamp! > 0); - Assert.Equal(info.FirstTimeStamp, info.LastTimeStamp); - } - - [Fact] - [Obsolete] - public async Task TestAddWithRetentionTime() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - long retentionTime = 5000; - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1, retentionTime: retentionTime)); - - var info = await ts.InfoAsync(key); - Assert.Equal(timeStamp, info.FirstTimeStamp); - Assert.Equal(timeStamp, info.LastTimeStamp); - Assert.Equal(retentionTime, info.RetentionTime); - } - - [Fact] - [Obsolete] - public async Task TestAddWithLabels() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - var label = new TimeSeriesLabel("key", "value"); - var labels = new List { label }; - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1, labels: labels)); - - var info = await ts.InfoAsync(key); - Assert.Equal(timeStamp, info.FirstTimeStamp); - Assert.Equal(timeStamp, info.LastTimeStamp); - Assert.Equal(labels, info.Labels); - } - - [Fact] - [Obsolete] - public async Task TestAddWithChunkSize() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1, chunkSizeBytes: 128)); - var info = await ts.InfoAsync(key); - Assert.Equal(timeStamp, info.FirstTimeStamp); - Assert.Equal(timeStamp, info.LastTimeStamp); - Assert.Equal(128, info.ChunkSize); - } - - [Fact] - [Obsolete] - public async Task TestAddWithUncompressed() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - await ts.CreateAsync(key); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1, uncompressed: true)); - - var info = await ts.InfoAsync(key); - Assert.Equal(timeStamp, info.FirstTimeStamp); - Assert.Equal(timeStamp, info.LastTimeStamp); - } - - [Fact] - public async Task TestAddWithDuplicatePolicyBlock() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); - await Assert.ThrowsAsync(async () => await ts.AddAsync(key, timeStamp, 1.2)); - } - - [Fact] - public async Task TestAddWithDuplicatePolicyMin() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); - - // Insert a bigger number and check that it did not change the value. - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.2, duplicatePolicy: TsDuplicatePolicy.MIN)); - IReadOnlyList results = await ts.RangeAsync(key, timeStamp, timeStamp); - Assert.Equal(1.1, results[0].Val); - - // Insert a smaller number and check that it changed. - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.0, duplicatePolicy: TsDuplicatePolicy.MIN)); - results = await ts.RangeAsync(key, timeStamp, timeStamp); - Assert.Equal(1.0, results[0].Val); - } - - [Fact] - public async Task TestAddWithDuplicatePolicyMax() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); - - // Insert a smaller number and check that it did not change the value. - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.0, duplicatePolicy: TsDuplicatePolicy.MAX)); - IReadOnlyList results = await ts.RangeAsync(key, timeStamp, timeStamp); - Assert.Equal(1.1, results[0].Val); - // Insert a bigger number and check that it changed. - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.2, duplicatePolicy: TsDuplicatePolicy.MAX)); - results = await ts.RangeAsync(key, timeStamp, timeStamp); - Assert.Equal(1.2, results[0].Val); - } - - [Fact] - public async Task TestAddWithDuplicatePolicySum() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.0, duplicatePolicy: TsDuplicatePolicy.SUM)); - IReadOnlyList results = await ts.RangeAsync(key, timeStamp, timeStamp); - Assert.Equal(2.1, results[0].Val); - } - - [Fact] - public async Task TestAddWithDuplicatePolicyFirst() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.0, duplicatePolicy: TsDuplicatePolicy.FIRST)); - IReadOnlyList results = await ts.RangeAsync(key, timeStamp, timeStamp); - Assert.Equal(1.1, results[0].Val); - } - - [Fact] - public async Task TestAddWithDuplicatePolicyLast() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.1)); - Assert.Equal(timeStamp, await ts.AddAsync(key, timeStamp, 1.0, duplicatePolicy: TsDuplicatePolicy.LAST)); - IReadOnlyList results = await ts.RangeAsync(key, timeStamp, timeStamp); - Assert.Equal(1.0, results[0].Val); - } - - [Fact] - public async Task TestOldAdd() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - var dateTime = DateTime.UtcNow; - TimeStamp oldTimeStamp = dateTime.AddSeconds(-1); - TimeStamp newTimeStamp = dateTime; - await ts.CreateAsync(key); - await ts.AddAsync(key, newTimeStamp, 1.1); - // Adding old event - var res = await ts.AddAsync(key, oldTimeStamp, 1.1); - Assert.Equal(oldTimeStamp.Value, res.Value); - } - - [Fact] - public async Task TestWrongParameters() - { - var key = CreateKeyName(); - var value = 1.1; - var db = GetCleanDatabase(); - var ts = db.TS(); - var ex = await Assert.ThrowsAsync(async () => await ts.AddAsync(key, "+", value)); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - - ex = await Assert.ThrowsAsync(async () => await ts.AddAsync(key, "-", value)); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - } + var key = CreateKeyName(); + var value = 1.1; + var db = GetCleanDatabase(); + var ts = db.TS(); + var ex = await Assert.ThrowsAsync(async () => await ts.AddAsync(key, "+", value)); + Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); + + ex = await Assert.ThrowsAsync(async () => await ts.AddAsync(key, "-", value)); + Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAlter.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAlter.cs index 5177e5ca..3ea8ae72 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAlter.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAlter.cs @@ -4,79 +4,74 @@ using StackExchange.Redis; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI -{ - public class TestAlter : AbstractNRedisStackTest, IDisposable - { - private readonly string key = "ALTER_TESTS"; +namespace NRedisStack.Tests.TimeSeries.TestAPI; - public TestAlter(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } +public class TestAlter(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable +{ + private readonly string key = "ALTER_TESTS"; - [Fact] - [Obsolete] - public void TestAlterRetentionTime() - { - long retentionTime = 5000; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - ts.Create(key); - Assert.True(ts.Alter(key, retentionTime: retentionTime)); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(retentionTime, info.RetentionTime); - } + [Fact] + [Obsolete] + public void TestAlterRetentionTime() + { + long retentionTime = 5000; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + ts.Create(key); + Assert.True(ts.Alter(key, retentionTime: retentionTime)); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(retentionTime, info.RetentionTime); + } - [Fact] - [Obsolete] - public void TestAlterLabels() - { - TimeSeriesLabel label = new TimeSeriesLabel("key", "value"); - var labels = new List { label }; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - ts.Create(key); - Assert.True(ts.Alter(key, labels: labels)); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(labels, info.Labels); - labels.Clear(); - Assert.True(ts.Alter(key, labels: labels)); - info = ts.Info(key); - Assert.Equal(labels, info.Labels); - } + [Fact] + [Obsolete] + public void TestAlterLabels() + { + TimeSeriesLabel label = new("key", "value"); + var labels = new List { label }; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + ts.Create(key); + Assert.True(ts.Alter(key, labels: labels)); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(labels, info.Labels); + labels.Clear(); + Assert.True(ts.Alter(key, labels: labels)); + info = ts.Info(key); + Assert.Equal(labels, info.Labels); + } - [Fact] - [Obsolete] - public void TestAlterPolicyAndChunk() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - ts.Create(key); - Assert.True(ts.Alter(key, chunkSizeBytes: 128, duplicatePolicy: TsDuplicatePolicy.MIN)); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(128, info.ChunkSize); - Assert.Equal(TsDuplicatePolicy.MIN, info.DuplicatePolicy); - } + [Fact] + [Obsolete] + public void TestAlterPolicyAndChunk() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + ts.Create(key); + Assert.True(ts.Alter(key, chunkSizeBytes: 128, duplicatePolicy: TsDuplicatePolicy.MIN)); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(128, info.ChunkSize); + Assert.Equal(TsDuplicatePolicy.MIN, info.DuplicatePolicy); + } - [SkipIfRedis(Comparison.LessThan, "7.4.0")] - [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] - public void TestAlterAndIgnoreValues(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - ts.Create(key, new TsCreateParamsBuilder().build()); - var parameters = new TsAlterParamsBuilder().AddIgnoreValues(13, 14).build(); - Assert.True(ts.Alter(key, parameters)); + [SkipIfRedisTheory(Comparison.LessThan, "7.4.0")] + [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] + public void TestAlterAndIgnoreValues(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + ts.Create(key, new TsCreateParamsBuilder().build()); + var parameters = new TsAlterParamsBuilder().AddIgnoreValues(13, 14).build(); + Assert.True(ts.Alter(key, parameters)); - int j = -1, k = -1; - RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); - Assert.NotNull(info); - Assert.True(info.Length > 0); - Assert.NotEqual(-1, j); - Assert.NotEqual(-1, k); - Assert.Equal(13, (long)info[j + 1]); - Assert.Equal(14, (long)info[k + 1]); - } + int j = -1, k = -1; + RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); + Assert.NotNull(info); + Assert.True(info.Length > 0); + Assert.NotEqual(-1, j); + Assert.NotEqual(-1, k); + Assert.Equal(13, (long)info[j + 1]); + Assert.Equal(14, (long)info[k + 1]); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAlterAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAlterAsync.cs index a5199ef2..cee256f0 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAlterAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestAlterAsync.cs @@ -3,62 +3,59 @@ using NRedisStack.RedisStackCommands; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestAlterAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestAlterAsync : AbstractNRedisStackTest + [Fact] + [Obsolete] + public async Task TestAlterRetentionTime() { - public TestAlterAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) { } - - [Fact] - [Obsolete] - public async Task TestAlterRetentionTime() - { - var key = CreateKeyName(); - long retentionTime = 5000; - var db = GetCleanDatabase(); - var ts = db.TS(); - await ts.CreateAsync(key); - Assert.True(await ts.AlterAsync(key, retentionTime: retentionTime)); - - var info = await ts.InfoAsync(key); - Assert.Equal(retentionTime, info.RetentionTime); - } - - [Fact] - [Obsolete] - public async Task TestAlterLabels() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - var label = new TimeSeriesLabel("key", "value"); - var labels = new List { label }; - await ts.CreateAsync(key); - Assert.True(await ts.AlterAsync(key, labels: labels)); - - var info = await ts.InfoAsync(key); - Assert.Equal(labels, info.Labels); - - labels.Clear(); - Assert.True(await ts.AlterAsync(key, labels: labels)); - - info = await ts.InfoAsync(key); - Assert.Equal(labels, info.Labels); - } + var key = CreateKeyName(); + long retentionTime = 5000; + var db = GetCleanDatabase(); + var ts = db.TS(); + await ts.CreateAsync(key); + Assert.True(await ts.AlterAsync(key, retentionTime: retentionTime)); + + var info = await ts.InfoAsync(key); + Assert.Equal(retentionTime, info.RetentionTime); + } - [Fact] - [Obsolete] - public async Task TestAlterPolicyAndChunkAsync() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - ts.Create(key); - Assert.True(await ts.AlterAsync(key, chunkSizeBytes: 128, duplicatePolicy: TsDuplicatePolicy.MIN)); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(128, info.ChunkSize); - Assert.Equal(TsDuplicatePolicy.MIN, info.DuplicatePolicy); - } + [Fact] + [Obsolete] + public async Task TestAlterLabels() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + var label = new TimeSeriesLabel("key", "value"); + var labels = new List { label }; + await ts.CreateAsync(key); + Assert.True(await ts.AlterAsync(key, labels: labels)); + + var info = await ts.InfoAsync(key); + Assert.Equal(labels, info.Labels); + + labels.Clear(); + Assert.True(await ts.AlterAsync(key, labels: labels)); + + info = await ts.InfoAsync(key); + Assert.Equal(labels, info.Labels); + } + [Fact] + [Obsolete] + public async Task TestAlterPolicyAndChunkAsync() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + ts.Create(key); + Assert.True(await ts.AlterAsync(key, chunkSizeBytes: 128, duplicatePolicy: TsDuplicatePolicy.MIN)); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(128, info.ChunkSize); + Assert.Equal(TsDuplicatePolicy.MIN, info.DuplicatePolicy); } -} + +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreate.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreate.cs index 698f00bf..91fa05a8 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreate.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreate.cs @@ -1,159 +1,156 @@ +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using StackExchange.Redis; using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; using NRedisStack.Literals.Enums; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestCreate(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable { - public class TestCreate : AbstractNRedisStackTest, IDisposable + private readonly string key = "CREATE_TESTS"; + + + [Fact] + [Obsolete] + public void TestCreateOK() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.Create(key)); + TimeSeriesInformation info = ts.Info(key); + } + + [Fact] + [Obsolete] + public void TestCreateRetentionTime() + { + long retentionTime = 5000; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.Create(key, retentionTime: retentionTime)); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(retentionTime, info.RetentionTime); + } + + [Fact] + [Obsolete] + public void TestCreateLabels() + { + TimeSeriesLabel label = new("key", "value"); + var labels = new List { label }; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.Create(key, labels: labels)); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(labels, info.Labels); + } + + [Fact] + [Obsolete] + public void TestCreateEmptyLabels() + { + var labels = new List(); + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.Create(key, labels: labels)); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(labels, info.Labels); + } + + [Fact] + public void TestCreateUncompressed() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.Create(key, uncompressed: true)); + } + + [Fact] + public void TestCreatehDuplicatePolicyFirst() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.Create(key, duplicatePolicy: TsDuplicatePolicy.FIRST)); + } + + [Fact] + public void TestCreatehDuplicatePolicyLast() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.Create(key, duplicatePolicy: TsDuplicatePolicy.LAST)); + } + + [Fact] + public void TestCreatehDuplicatePolicyMin() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.Create(key, duplicatePolicy: TsDuplicatePolicy.MIN)); + } + + [Fact] + public void TestCreatehDuplicatePolicyMax() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.Create(key, duplicatePolicy: TsDuplicatePolicy.MAX)); + } + + [Fact] + public void TestCreatehDuplicatePolicySum() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.Create(key, duplicatePolicy: TsDuplicatePolicy.SUM)); + } + + [SkipIfRedisTheory(Comparison.LessThan, "7.4.0")] + [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] + public void TestCreateAndIgnoreValues(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var parameters = new TsCreateParamsBuilder().AddIgnoreValues(11, 12).build(); + Assert.True(ts.Create(key, parameters)); + + int j = -1, k = -1; + RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); + + Assert.NotEqual(-1, j); + Assert.NotEqual(-1, k); + Assert.Equal(11, (long)info[j + 1]); + Assert.Equal(12, (long)info[k + 1]); + } + + [Fact] + public void TestParamsBuilder() { - private readonly string key = "CREATE_TESTS"; - - public TestCreate(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } - - - [Fact] - [Obsolete] - public void TestCreateOK() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.Create(key)); - TimeSeriesInformation info = ts.Info(key); - } - - [Fact] - [Obsolete] - public void TestCreateRetentionTime() - { - long retentionTime = 5000; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.Create(key, retentionTime: retentionTime)); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(retentionTime, info.RetentionTime); - } - - [Fact] - [Obsolete] - public void TestCreateLabels() - { - TimeSeriesLabel label = new TimeSeriesLabel("key", "value"); - var labels = new List { label }; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.Create(key, labels: labels)); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(labels, info.Labels); - } - - [Fact] - [Obsolete] - public void TestCreateEmptyLabels() - { - var labels = new List(); - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.Create(key, labels: labels)); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(labels, info.Labels); - } - - [Fact] - public void TestCreateUncompressed() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.Create(key, uncompressed: true)); - } - - [Fact] - public void TestCreatehDuplicatePolicyFirst() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.Create(key, duplicatePolicy: TsDuplicatePolicy.FIRST)); - } - - [Fact] - public void TestCreatehDuplicatePolicyLast() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.Create(key, duplicatePolicy: TsDuplicatePolicy.LAST)); - } - - [Fact] - public void TestCreatehDuplicatePolicyMin() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.Create(key, duplicatePolicy: TsDuplicatePolicy.MIN)); - } - - [Fact] - public void TestCreatehDuplicatePolicyMax() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.Create(key, duplicatePolicy: TsDuplicatePolicy.MAX)); - } - - [Fact] - public void TestCreatehDuplicatePolicySum() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.Create(key, duplicatePolicy: TsDuplicatePolicy.SUM)); - } - - [SkipIfRedis(Comparison.LessThan, "7.4.0")] - [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] - public void TestCreateAndIgnoreValues(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var parameters = new TsCreateParamsBuilder().AddIgnoreValues(11, 12).build(); - Assert.True(ts.Create(key, parameters)); - - int j = -1, k = -1; - RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); - - Assert.NotEqual(-1, j); - Assert.NotEqual(-1, k); - Assert.Equal(11, (long)info[j + 1]); - Assert.Equal(12, (long)info[k + 1]); - } - - [Fact] - public void TestParamsBuilder() - { - TsCreateParams parameters = new TsCreateParamsBuilder() - .AddChunkSizeBytes(1000) - .AddDuplicatePolicy(TsDuplicatePolicy.FIRST) - .AddIgnoreValues(11, 12) - .AddLabels(new List() { new TimeSeriesLabel("key", "value") }) - .AddRetentionTime(5000) - .AddUncompressed(true).build(); - - var command = TimeSeriesCommandsBuilder.Create(key, parameters); - var expectedArgs = new object[] { key, "RETENTION", 5000L, "CHUNK_SIZE", 1000L, "LABELS", "key", "value", "UNCOMPRESSED", "DUPLICATE_POLICY", "FIRST", "IGNORE", 11L, 12L }; - Assert.Equal(expectedArgs, command.Args); - - parameters = new TsCreateParamsBuilder() - .AddChunkSizeBytes(1000) - .AddDuplicatePolicy(TsDuplicatePolicy.FIRST) - .AddIgnoreValues(11, 12) - .AddLabels(new List() { new TimeSeriesLabel("key", "value") }) - .AddRetentionTime(5000) - .AddUncompressed(false).build(); - - command = TimeSeriesCommandsBuilder.Create(key, parameters); - expectedArgs = new object[] { key, "RETENTION", 5000L, "CHUNK_SIZE", 1000L, "LABELS", "key", "value", "COMPRESSED", "DUPLICATE_POLICY", "FIRST", "IGNORE", 11L, 12L }; - Assert.Equal(expectedArgs, command.Args); - } + TsCreateParams parameters = new TsCreateParamsBuilder() + .AddChunkSizeBytes(1000) + .AddDuplicatePolicy(TsDuplicatePolicy.FIRST) + .AddIgnoreValues(11, 12) + .AddLabels(new List() { new("key", "value") }) + .AddRetentionTime(5000) + .AddUncompressed(true).build(); + + var command = TimeSeriesCommandsBuilder.Create(key, parameters); + var expectedArgs = new object[] { key, "RETENTION", 5000L, "CHUNK_SIZE", 1000L, "LABELS", "key", "value", "UNCOMPRESSED", "DUPLICATE_POLICY", "FIRST", "IGNORE", 11L, 12L }; + Assert.Equal(expectedArgs, command.Args); + + parameters = new TsCreateParamsBuilder() + .AddChunkSizeBytes(1000) + .AddDuplicatePolicy(TsDuplicatePolicy.FIRST) + .AddIgnoreValues(11, 12) + .AddLabels(new List() { new("key", "value") }) + .AddRetentionTime(5000) + .AddUncompressed(false).build(); + + command = TimeSeriesCommandsBuilder.Create(key, parameters); + expectedArgs = [key, "RETENTION", 5000L, "CHUNK_SIZE", 1000L, "LABELS", "key", "value", "COMPRESSED", "DUPLICATE_POLICY", "FIRST", "IGNORE", 11L, 12L + ]; + Assert.Equal(expectedArgs, command.Args); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreateAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreateAsync.cs index feb9562b..bba4864a 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreateAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestCreateAsync.cs @@ -1,118 +1,116 @@ +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using NRedisStack.DataTypes; using NRedisStack.Literals.Enums; using NRedisStack.RedisStackCommands; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestCreateAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestCreateAsync : AbstractNRedisStackTest + [Fact] + public async Task TestCreateOK() { - public TestCreateAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) { } - - [Fact] - public async Task TestCreateOK() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.CreateAsync(key)); - } + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.CreateAsync(key)); + } - [Fact] - [Obsolete] - public async Task TestCreateRetentionTime() - { - var key = CreateKeyName(); - long retentionTime = 5000; - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.CreateAsync(key, retentionTime: retentionTime)); + [Fact] + [Obsolete] + public async Task TestCreateRetentionTime() + { + var key = CreateKeyName(); + long retentionTime = 5000; + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.CreateAsync(key, retentionTime: retentionTime)); - var info = await ts.InfoAsync(key); - Assert.Equal(retentionTime, info.RetentionTime); - } + var info = await ts.InfoAsync(key); + Assert.Equal(retentionTime, info.RetentionTime); + } - [Fact] - [Obsolete] - public async Task TestCreateLabels() - { - var key = CreateKeyName(); - var label = new TimeSeriesLabel("key", "value"); - var labels = new List { label }; - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.CreateAsync(key, labels: labels)); + [Fact] + [Obsolete] + public async Task TestCreateLabels() + { + var key = CreateKeyName(); + var label = new TimeSeriesLabel("key", "value"); + var labels = new List { label }; + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.CreateAsync(key, labels: labels)); - var info = await ts.InfoAsync(key); - Assert.Equal(labels, info.Labels); - } + var info = await ts.InfoAsync(key); + Assert.Equal(labels, info.Labels); + } - [Fact] - [Obsolete] - public async Task TestCreateEmptyLabels() - { - var key = CreateKeyName(); - var labels = new List(); - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.CreateAsync(key, labels: labels)); + [Fact] + [Obsolete] + public async Task TestCreateEmptyLabels() + { + var key = CreateKeyName(); + var labels = new List(); + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.CreateAsync(key, labels: labels)); - var info = await ts.InfoAsync(key); - Assert.Equal(labels, info.Labels); - } + var info = await ts.InfoAsync(key); + Assert.Equal(labels, info.Labels); + } - [Fact] - public async Task TestCreateUncompressed() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.CreateAsync(key, uncompressed: true)); - } + [Fact] + public async Task TestCreateUncompressed() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.CreateAsync(key, uncompressed: true)); + } - [Fact] - public async Task TestCreatehDuplicatePolicyFirst() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.CreateAsync(key, duplicatePolicy: TsDuplicatePolicy.FIRST)); - } + [Fact] + public async Task TestCreatehDuplicatePolicyFirst() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.CreateAsync(key, duplicatePolicy: TsDuplicatePolicy.FIRST)); + } - [Fact] - public async Task TestCreatehDuplicatePolicyLast() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.CreateAsync(key, duplicatePolicy: TsDuplicatePolicy.LAST)); - } + [Fact] + public async Task TestCreatehDuplicatePolicyLast() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.CreateAsync(key, duplicatePolicy: TsDuplicatePolicy.LAST)); + } - [Fact] - public async Task TestCreatehDuplicatePolicyMin() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.CreateAsync(key, duplicatePolicy: TsDuplicatePolicy.MIN)); - } + [Fact] + public async Task TestCreatehDuplicatePolicyMin() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.CreateAsync(key, duplicatePolicy: TsDuplicatePolicy.MIN)); + } - [Fact] - public async Task TestCreatehDuplicatePolicyMax() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.CreateAsync(key, duplicatePolicy: TsDuplicatePolicy.MAX)); - } + [Fact] + public async Task TestCreatehDuplicatePolicyMax() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.CreateAsync(key, duplicatePolicy: TsDuplicatePolicy.MAX)); + } - [Fact] - public async Task TestCreatehDuplicatePolicySum() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.CreateAsync(key, duplicatePolicy: TsDuplicatePolicy.SUM)); - } + [Fact] + public async Task TestCreatehDuplicatePolicySum() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.CreateAsync(key, duplicatePolicy: TsDuplicatePolicy.SUM)); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrBy.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrBy.cs index b024015b..62bc4a1e 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrBy.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrBy.cs @@ -1,118 +1,114 @@ -using NRedisStack.DataTypes; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods +using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; using StackExchange.Redis; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI -{ - public class TestDecrBy : AbstractNRedisStackTest, IDisposable - { - private readonly string key = "DECRBY_TESTS"; +namespace NRedisStack.Tests.TimeSeries.TestAPI; - public TestDecrBy(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } +public class TestDecrBy(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable +{ + private readonly string key = "DECRBY_TESTS"; - [Fact] - public void TestDefaultDecrBy() - { - double value = 5.5; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.DecrBy(key, -value) > 0); - Assert.Equal(value, ts.Get(key)!.Val); - } + [Fact] + public void TestDefaultDecrBy() + { + double value = 5.5; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.DecrBy(key, -value) > 0); + Assert.Equal(value, ts.Get(key)!.Val); + } - [Fact] - public void TestStarDecrBy() - { - double value = 5.5; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.DecrBy(key, -value, timestamp: "*") > 0); - Assert.Equal(value, ts.Get(key)!.Val); - } + [Fact] + public void TestStarDecrBy() + { + double value = 5.5; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.DecrBy(key, -value, timestamp: "*") > 0); + Assert.Equal(value, ts.Get(key)!.Val); + } - [Fact] - public void TestDecrByTimeStamp() - { - double value = 5.5; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, ts.DecrBy(key, -value, timestamp: timeStamp)); - Assert.Equal(new TimeSeriesTuple(timeStamp, value), ts.Get(key)); - } + [Fact] + public void TestDecrByTimeStamp() + { + double value = 5.5; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, ts.DecrBy(key, -value, timestamp: timeStamp)); + Assert.Equal(new(timeStamp, value), ts.Get(key)); + } - [Fact] - [Obsolete] - public void TestDefaultDecrByWithRetentionTime() - { - double value = 5.5; - long retentionTime = 5000; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.DecrBy(key, -value, retentionTime: retentionTime) > 0); - Assert.Equal(value, ts.Get(key)!.Val); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(retentionTime, info.RetentionTime); - } + [Fact] + [Obsolete] + public void TestDefaultDecrByWithRetentionTime() + { + double value = 5.5; + long retentionTime = 5000; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.DecrBy(key, -value, retentionTime: retentionTime) > 0); + Assert.Equal(value, ts.Get(key)!.Val); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(retentionTime, info.RetentionTime); + } - [Fact] - [Obsolete] - public void TestDefaultDecrByWithLabels() - { - double value = 5.5; - TimeSeriesLabel label = new TimeSeriesLabel("key", "value"); - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var labels = new List { label }; - Assert.True(ts.DecrBy(key, -value, labels: labels) > 0); - Assert.Equal(value, ts.Get(key)!.Val); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(labels, info.Labels); - } + [Fact] + [Obsolete] + public void TestDefaultDecrByWithLabels() + { + double value = 5.5; + TimeSeriesLabel label = new("key", "value"); + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var labels = new List { label }; + Assert.True(ts.DecrBy(key, -value, labels: labels) > 0); + Assert.Equal(value, ts.Get(key)!.Val); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(labels, info.Labels); + } - [Fact] - public void TestDefaultDecrByWithUncompressed() - { - double value = 5.5; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.DecrBy(key, -value, uncompressed: true) > 0); - Assert.Equal(value, ts.Get(key)!.Val); - } + [Fact] + public void TestDefaultDecrByWithUncompressed() + { + double value = 5.5; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.DecrBy(key, -value, uncompressed: true) > 0); + Assert.Equal(value, ts.Get(key)!.Val); + } - [Fact] - public void TestWrongParameters() - { - double value = 5.5; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var ex = Assert.Throws(() => ts.DecrBy(key, value, timestamp: "+")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - ex = Assert.Throws(() => ts.DecrBy(key, value, timestamp: "-")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - } + [Fact] + public void TestWrongParameters() + { + double value = 5.5; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var ex = Assert.Throws(() => ts.DecrBy(key, value, timestamp: "+")); + Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); + ex = Assert.Throws(() => ts.DecrBy(key, value, timestamp: "-")); + Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); + } - [SkipIfRedis(Comparison.LessThan, "7.4.0")] - [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] - public async void TestIncrDecryByAndIgnoreValues(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var decrParameters = new TsDecrByParamsBuilder().AddValue(1).AddIgnoreValues(15, 16).build(); - ts.DecrBy(key, decrParameters); + [SkipIfRedisTheory(Comparison.LessThan, "7.4.0")] + [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] + public void TestIncrDecryByAndIgnoreValues(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var decrParameters = new TsDecrByParamsBuilder().AddValue(1).AddIgnoreValues(15, 16).build(); + ts.DecrBy(key, decrParameters); - int j = -1, k = -1; - RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); - Assert.NotNull(info); - Assert.True(info.Length > 0); - Assert.NotEqual(-1, j); - Assert.NotEqual(-1, k); - Assert.Equal(15, (long)info[j + 1]); - Assert.Equal(16, (long)info[k + 1]); - } + int j = -1, k = -1; + RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); + Assert.NotNull(info); + Assert.True(info.Length > 0); + Assert.NotEqual(-1, j); + Assert.NotEqual(-1, k); + Assert.Equal(15, (long)info[j + 1]); + Assert.Equal(16, (long)info[k + 1]); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrByAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrByAsync.cs index 67dc28eb..a272c3e9 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrByAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDecrByAsync.cs @@ -3,112 +3,109 @@ using StackExchange.Redis; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestDecrByAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestDecrByAsync : AbstractNRedisStackTest + [Fact] + public async Task TestDefaultDecrBy() + { + var key = CreateKeyName(); + var value = 5.5; + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.DecrByAsync(key, -value) > 0); + + var result = await ts.GetAsync(key); + Assert.Equal(value, result!.Val); + } + + [Fact] + public async Task TestStarDecrBy() + { + var key = CreateKeyName(); + var value = 5.5; + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.DecrByAsync(key, -value, timestamp: "*") > 0); + + var result = await ts.GetAsync(key); + Assert.Equal(value, result!.Val); + } + + [Fact] + public async Task TestDecrByTimeStamp() + { + var key = CreateKeyName(); + var value = 5.5; + var db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await ts.DecrByAsync(key, -value, timestamp: timeStamp)); + Assert.Equal(new(timeStamp, value), await ts.GetAsync(key)); + } + + [Fact] + [Obsolete] + public async Task TestDefaultDecrByWithRetentionTime() + { + var key = CreateKeyName(); + var value = 5.5; + long retentionTime = 5000; + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.DecrByAsync(key, -value, retentionTime: retentionTime) > 0); + + var result = await ts.GetAsync(key); + Assert.Equal(value, result!.Val); + + var info = await ts.InfoAsync(key); + Assert.Equal(retentionTime, info.RetentionTime); + } + + [Fact] + [Obsolete] + public async Task TestDefaultDecrByWithLabels() + { + var key = CreateKeyName(); + var value = 5.5; + var label = new TimeSeriesLabel("key", "value"); + var db = GetCleanDatabase(); + var ts = db.TS(); + var labels = new List { label }; + Assert.True(await ts.DecrByAsync(key, -value, labels: labels) > 0); + + var result = await ts.GetAsync(key); + Assert.Equal(value, result!.Val); + + var info = await ts.InfoAsync(key); + Assert.Equal(labels, info.Labels); + } + + [Fact] + public async Task TestDefaultDecrByWithUncompressed() + { + var key = CreateKeyName(); + var value = 5.5; + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.DecrByAsync(key, -value, uncompressed: true) > 0); + + var result = await ts.GetAsync(key); + Assert.Equal(value, result!.Val); + } + + [Fact] + public async Task TestWrongParameters() { - public TestDecrByAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) { } - - [Fact] - public async Task TestDefaultDecrBy() - { - var key = CreateKeyName(); - var value = 5.5; - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.DecrByAsync(key, -value) > 0); - - var result = await ts.GetAsync(key); - Assert.Equal(value, result!.Val); - } - - [Fact] - public async Task TestStarDecrBy() - { - var key = CreateKeyName(); - var value = 5.5; - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.DecrByAsync(key, -value, timestamp: "*") > 0); - - var result = await ts.GetAsync(key); - Assert.Equal(value, result!.Val); - } - - [Fact] - public async Task TestDecrByTimeStamp() - { - var key = CreateKeyName(); - var value = 5.5; - var db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await ts.DecrByAsync(key, -value, timestamp: timeStamp)); - Assert.Equal(new TimeSeriesTuple(timeStamp, value), await ts.GetAsync(key)); - } - - [Fact] - [Obsolete] - public async Task TestDefaultDecrByWithRetentionTime() - { - var key = CreateKeyName(); - var value = 5.5; - long retentionTime = 5000; - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.DecrByAsync(key, -value, retentionTime: retentionTime) > 0); - - var result = await ts.GetAsync(key); - Assert.Equal(value, result!.Val); - - var info = await ts.InfoAsync(key); - Assert.Equal(retentionTime, info.RetentionTime); - } - - [Fact] - [Obsolete] - public async Task TestDefaultDecrByWithLabels() - { - var key = CreateKeyName(); - var value = 5.5; - var label = new TimeSeriesLabel("key", "value"); - var db = GetCleanDatabase(); - var ts = db.TS(); - var labels = new List { label }; - Assert.True(await ts.DecrByAsync(key, -value, labels: labels) > 0); - - var result = await ts.GetAsync(key); - Assert.Equal(value, result!.Val); - - var info = await ts.InfoAsync(key); - Assert.Equal(labels, info.Labels); - } - - [Fact] - public async Task TestDefaultDecrByWithUncompressed() - { - var key = CreateKeyName(); - var value = 5.5; - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.DecrByAsync(key, -value, uncompressed: true) > 0); - - var result = await ts.GetAsync(key); - Assert.Equal(value, result!.Val); - } - - [Fact] - public async Task TestWrongParameters() - { - var key = CreateKeyName(); - var value = 5.5; - var db = GetCleanDatabase(); - var ts = db.TS(); - var ex = await Assert.ThrowsAsync(async () => await ts.DecrByAsync(key, value, timestamp: "+")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - - ex = await Assert.ThrowsAsync(async () => await ts.DecrByAsync(key, value, timestamp: "-")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - } + var key = CreateKeyName(); + var value = 5.5; + var db = GetCleanDatabase(); + var ts = db.TS(); + var ex = await Assert.ThrowsAsync(async () => await ts.DecrByAsync(key, value, timestamp: "+")); + Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); + + ex = await Assert.ThrowsAsync(async () => await ts.DecrByAsync(key, value, timestamp: "-")); + Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDel.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDel.cs index 609686c1..1ad443a9 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDel.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDel.cs @@ -4,49 +4,46 @@ using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI -{ - public class TestDel : AbstractNRedisStackTest, IDisposable - { - private readonly string key = "DEL_TESTS"; +namespace NRedisStack.Tests.TimeSeries.TestAPI; - public TestDel(EndpointsFixture endpointsFixture) : base(endpointsFixture) { } +public class TestDel(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable +{ + private readonly string key = "DEL_TESTS"; - private List CreateData(ITimeSeriesCommands ts, int timeBucket) //TODO: check this + private List CreateData(ITimeSeriesCommands ts, int timeBucket) //TODO: check this + { + var tuples = new List(); + for (int i = 0; i < 10; i++) { - var tuples = new List(); - for (int i = 0; i < 10; i++) - { - TimeStamp timeStamp = ts.Add(key, i * timeBucket, i); - tuples.Add(new TimeSeriesTuple(timeStamp, i)); - } - return tuples; + TimeStamp timeStamp = ts.Add(key, i * timeBucket, i); + tuples.Add(new(timeStamp, i)); } + return tuples; + } - [Fact] - public void TestDelNotExists() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var ex = Assert.Throws(() => ts.Del(key, "-", "+")); - Assert.Equal("ERR TSDB: the key does not exist", ex.Message); - } + [Fact] + public void TestDelNotExists() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var ex = Assert.Throws(() => ts.Del(key, "-", "+")); + Assert.Equal("ERR TSDB: the key does not exist", ex.Message); + } - [Fact] - public void TestDelRange() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var tuples = CreateData(ts, 50); - TimeStamp from = tuples[0].Time; - TimeStamp to = tuples[5].Time; - Assert.Equal(6, ts.Del(key, from, to)); - - // check that the operation deleted the timestamps - IReadOnlyList res = ts.Range(key, from, to); - Assert.Empty(res); - Assert.NotNull(ts.Get(key)); - } + [Fact] + public void TestDelRange() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var tuples = CreateData(ts, 50); + TimeStamp from = tuples[0].Time; + TimeStamp to = tuples[5].Time; + Assert.Equal(6, ts.Del(key, from, to)); + + // check that the operation deleted the timestamps + IReadOnlyList res = ts.Range(key, from, to); + Assert.Empty(res); + Assert.NotNull(ts.Get(key)); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDelAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDelAsync.cs index e71a2b9f..40b5b471 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDelAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestDelAsync.cs @@ -1,50 +1,48 @@ +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; using StackExchange.Redis; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestDelAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestDelAsync : AbstractNRedisStackTest + private async Task> CreateData(TimeSeriesCommands ts, string key, int timeBucket) { - public TestDelAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) { } - - private async Task> CreateData(TimeSeriesCommands ts, string key, int timeBucket) + var tuples = new List(); + for (var i = 0; i < 10; i++) { - var tuples = new List(); - for (var i = 0; i < 10; i++) - { - var timeStamp = await ts.AddAsync(key, i * timeBucket, i); - tuples.Add(new TimeSeriesTuple(timeStamp, i)); - } - return tuples; + var timeStamp = await ts.AddAsync(key, i * timeBucket, i); + tuples.Add(new(timeStamp, i)); } + return tuples; + } - [Fact] - public async Task TestDelNotExists() - { - var key = CreateKeyName(); - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var ex = await Assert.ThrowsAsync(async () => await ts.DelAsync(key, "-", "+")); - Assert.Equal("ERR TSDB: the key does not exist", ex.Message); - } + [Fact] + public async Task TestDelNotExists() + { + var key = CreateKeyName(); + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var ex = await Assert.ThrowsAsync(async () => await ts.DelAsync(key, "-", "+")); + Assert.Equal("ERR TSDB: the key does not exist", ex.Message); + } - [Fact] - public async Task TestDelRange() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var key = CreateKeyName(); - var tuples = await CreateData(ts, key, 50); - TimeStamp from = tuples[0].Time; - TimeStamp to = tuples[5].Time; - Assert.Equal(6, await ts.DelAsync(key, from, to)); + [Fact] + public async Task TestDelRange() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var key = CreateKeyName(); + var tuples = await CreateData(ts, key, 50); + TimeStamp from = tuples[0].Time; + TimeStamp to = tuples[5].Time; + Assert.Equal(6, await ts.DelAsync(key, from, to)); - // check that the operation deleted the timestamps - IReadOnlyList res = await ts.RangeAsync(key, from, to); - Assert.Empty(res); - Assert.NotNull(await ts.GetAsync(key)); - } + // check that the operation deleted the timestamps + IReadOnlyList res = await ts.RangeAsync(key, from, to); + Assert.Empty(res); + Assert.NotNull(await ts.GetAsync(key)); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestGet.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestGet.cs index b963e54c..21a4c18f 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestGet.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestGet.cs @@ -1,47 +1,45 @@ -using NRedisStack.DataTypes; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods +using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; using StackExchange.Redis; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI -{ - public class TestGet : AbstractNRedisStackTest, IDisposable - { +namespace NRedisStack.Tests.TimeSeries.TestAPI; - private readonly string key = "GET_TESTS"; +public class TestGet(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable +{ - public TestGet(EndpointsFixture endpointsFixture) : base(endpointsFixture) { } + private readonly string key = "GET_TESTS"; - [Fact] - public void TestGetNotExists() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var ex = Assert.Throws(() => ts.Get(key)); - Assert.Equal("ERR TSDB: the key does not exist", ex.Message); - } + [Fact] + public void TestGetNotExists() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var ex = Assert.Throws(() => ts.Get(key)); + Assert.Equal("ERR TSDB: the key does not exist", ex.Message); + } - [Fact] - public void TestEmptyGet() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - ts.Create(key); - Assert.Null(ts.Get(key)); - } + [Fact] + public void TestEmptyGet() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + ts.Create(key); + Assert.Null(ts.Get(key)); + } - [Fact] - public void TestAddAndGet() - { - DateTime now = DateTime.UtcNow; - TimeSeriesTuple expected = new TimeSeriesTuple(now, 1.1); - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - ts.Create(key); - ts.Add(key, now, 1.1); - TimeSeriesTuple actual = ts.Get(key)!; - Assert.Equal(expected, actual); - } + [Fact] + public void TestAddAndGet() + { + DateTime now = DateTime.UtcNow; + TimeSeriesTuple expected = new(now, 1.1); + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + ts.Create(key); + ts.Add(key, now, 1.1); + TimeSeriesTuple actual = ts.Get(key)!; + Assert.Equal(expected, actual); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestGetAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestGetAsync.cs index 2c7fd576..2dd0c1b2 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestGetAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestGetAsync.cs @@ -1,46 +1,44 @@ -using NRedisStack.DataTypes; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods +using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; using StackExchange.Redis; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestGetAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestGetAsync : AbstractNRedisStackTest + [Fact] + public async Task TestGetNotExists() { - public TestGetAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) { } - - [Fact] - public async Task TestGetNotExists() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - var ex = await Assert.ThrowsAsync(async () => await ts.GetAsync(key)); - Assert.Equal("ERR TSDB: the key does not exist", ex.Message); - } + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + var ex = await Assert.ThrowsAsync(async () => await ts.GetAsync(key)); + Assert.Equal("ERR TSDB: the key does not exist", ex.Message); + } - [Fact] - public async Task TestEmptyGet() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - await ts.CreateAsync(key); - Assert.Null(await ts.GetAsync(key)); - } + [Fact] + public async Task TestEmptyGet() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + await ts.CreateAsync(key); + Assert.Null(await ts.GetAsync(key)); + } - [Fact] - public async Task TestAddAndGet() - { - var key = CreateKeyName(); - var now = DateTime.UtcNow; - var expected = new TimeSeriesTuple(now, 1.1); - var db = GetCleanDatabase(); - var ts = db.TS(); - await ts.CreateAsync(key); - await ts.AddAsync(key, now, 1.1); - var actual = await ts.GetAsync(key); - Assert.Equal(expected, actual); - } + [Fact] + public async Task TestAddAndGet() + { + var key = CreateKeyName(); + var now = DateTime.UtcNow; + var expected = new TimeSeriesTuple(now, 1.1); + var db = GetCleanDatabase(); + var ts = db.TS(); + await ts.CreateAsync(key); + await ts.AddAsync(key, now, 1.1); + var actual = await ts.GetAsync(key); + Assert.Equal(expected, actual); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrBy.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrBy.cs index a9c519f6..ae557ff2 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrBy.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrBy.cs @@ -1,117 +1,113 @@ -using NRedisStack.RedisStackCommands; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods +using NRedisStack.RedisStackCommands; using NRedisStack.DataTypes; using StackExchange.Redis; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI -{ - public class TestIncrBy : AbstractNRedisStackTest, IDisposable - { - private readonly string key = "INCRBY_TESTS"; +namespace NRedisStack.Tests.TimeSeries.TestAPI; - public TestIncrBy(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } +public class TestIncrBy(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable +{ + private readonly string key = "INCRBY_TESTS"; - [Fact] - public void TestDefaultIncrBy() - { - double value = 5.5; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.IncrBy(key, value) > 0); - Assert.Equal(value, ts.Get(key)!.Val); - } + [Fact] + public void TestDefaultIncrBy() + { + double value = 5.5; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.IncrBy(key, value) > 0); + Assert.Equal(value, ts.Get(key)!.Val); + } - [Fact] - public void TestStarIncrBy() - { - double value = 5.5; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.IncrBy(key, value, timestamp: "*") > 0); - Assert.Equal(value, ts.Get(key)!.Val); - } + [Fact] + public void TestStarIncrBy() + { + double value = 5.5; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.IncrBy(key, value, timestamp: "*") > 0); + Assert.Equal(value, ts.Get(key)!.Val); + } - [Fact] - public void TestIncrByTimeStamp() - { - double value = 5.5; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, ts.IncrBy(key, value, timestamp: timeStamp)); - Assert.Equal(new TimeSeriesTuple(timeStamp, value), ts.Get(key)); - } + [Fact] + public void TestIncrByTimeStamp() + { + double value = 5.5; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, ts.IncrBy(key, value, timestamp: timeStamp)); + Assert.Equal(new(timeStamp, value), ts.Get(key)); + } - [Fact] - [Obsolete] - public void TestDefaultIncrByWithRetentionTime() - { - double value = 5.5; - long retentionTime = 5000; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.IncrBy(key, value, retentionTime: retentionTime) > 0); - Assert.Equal(value, ts.Get(key)!.Val); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(retentionTime, info.RetentionTime); - } + [Fact] + [Obsolete] + public void TestDefaultIncrByWithRetentionTime() + { + double value = 5.5; + long retentionTime = 5000; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.IncrBy(key, value, retentionTime: retentionTime) > 0); + Assert.Equal(value, ts.Get(key)!.Val); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(retentionTime, info.RetentionTime); + } - [Fact] - [Obsolete] - public void TestDefaultIncrByWithLabels() - { - double value = 5.5; - TimeSeriesLabel label = new TimeSeriesLabel("key", "value"); - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var labels = new List { label }; - Assert.True(ts.IncrBy(key, value, labels: labels) > 0); - Assert.Equal(value, ts.Get(key)!.Val); - TimeSeriesInformation info = ts.Info(key); - Assert.Equal(labels, info.Labels); - } + [Fact] + [Obsolete] + public void TestDefaultIncrByWithLabels() + { + double value = 5.5; + TimeSeriesLabel label = new("key", "value"); + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var labels = new List { label }; + Assert.True(ts.IncrBy(key, value, labels: labels) > 0); + Assert.Equal(value, ts.Get(key)!.Val); + TimeSeriesInformation info = ts.Info(key); + Assert.Equal(labels, info.Labels); + } - [Fact] - public void TestDefaultIncrByWithUncompressed() - { - double value = 5.5; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(ts.IncrBy(key, value, uncompressed: true) > 0); - Assert.Equal(value, ts.Get(key)!.Val); - } + [Fact] + public void TestDefaultIncrByWithUncompressed() + { + double value = 5.5; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(ts.IncrBy(key, value, uncompressed: true) > 0); + Assert.Equal(value, ts.Get(key)!.Val); + } - [Fact] - public void TestWrongParameters() - { - double value = 5.5; - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var ex = Assert.Throws(() => ts.IncrBy(key, value, timestamp: "+")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - ex = Assert.Throws(() => ts.IncrBy(key, value, timestamp: "-")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - } + [Fact] + public void TestWrongParameters() + { + double value = 5.5; + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var ex = Assert.Throws(() => ts.IncrBy(key, value, timestamp: "+")); + Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); + ex = Assert.Throws(() => ts.IncrBy(key, value, timestamp: "-")); + Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); + } - [SkipIfRedis(Comparison.LessThan, "7.4.0")] - [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] - public async void TestIncrByAndIgnoreValues(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var incrParameters = new TsIncrByParamsBuilder().AddValue(1).AddIgnoreValues(15, 16).build(); - ts.IncrBy(key, incrParameters); + [SkipIfRedisTheory(Comparison.LessThan, "7.4.0")] + [MemberData(nameof(EndpointsFixture.Env.AllEnvironments), MemberType = typeof(EndpointsFixture.Env))] + public void TestIncrByAndIgnoreValues(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var incrParameters = new TsIncrByParamsBuilder().AddValue(1).AddIgnoreValues(15, 16).build(); + ts.IncrBy(key, incrParameters); - int j = -1, k = -1; - RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); - Assert.NotNull(info); - Assert.True(info.Length > 0); - Assert.NotEqual(-1, j); - Assert.NotEqual(-1, k); - Assert.Equal(15, (long)info[j + 1]); - Assert.Equal(16, (long)info[k + 1]); - } + int j = -1, k = -1; + RedisResult info = TimeSeriesHelper.getInfo(db, key, out j, out k); + Assert.NotNull(info); + Assert.True(info.Length > 0); + Assert.NotEqual(-1, j); + Assert.NotEqual(-1, k); + Assert.Equal(15, (long)info[j + 1]); + Assert.Equal(16, (long)info[k + 1]); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrByAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrByAsync.cs index afdbbc03..eee0bb23 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrByAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestIncrByAsync.cs @@ -3,112 +3,109 @@ using StackExchange.Redis; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestIncrByAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestIncrByAsync : AbstractNRedisStackTest + [Fact] + public async Task TestDefaultIncrBy() + { + var key = CreateKeyName(); + var value = 5.5; + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.IncrByAsync(key, value) > 0); + + var result = await ts.GetAsync(key); + Assert.Equal(value, result!.Val); + } + + [Fact] + public async Task TestStarIncrBy() + { + var key = CreateKeyName(); + var value = 5.5; + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.IncrByAsync(key, value, timestamp: "*") > 0); + + var result = await ts.GetAsync(key); + Assert.Equal(value, result!.Val); + } + + [Fact] + public async Task TestIncrByTimeStamp() + { + var key = CreateKeyName(); + var value = 5.5; + var db = GetCleanDatabase(); + var ts = db.TS(); + TimeStamp timeStamp = DateTime.UtcNow; + Assert.Equal(timeStamp, await ts.IncrByAsync(key, value, timestamp: timeStamp)); + Assert.Equal(new(timeStamp, value), await ts.GetAsync(key)); + } + + [Fact] + [Obsolete] + public async Task TestDefaultIncrByWithRetentionTime() + { + var key = CreateKeyName(); + var value = 5.5; + long retentionTime = 5000; + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.IncrByAsync(key, value, retentionTime: retentionTime) > 0); + + var result = await ts.GetAsync(key); + Assert.Equal(value, result!.Val); + + var info = await ts.InfoAsync(key); + Assert.Equal(retentionTime, info.RetentionTime); + } + + [Fact] + [Obsolete] + public async Task TestDefaultIncrByWithLabels() + { + var key = CreateKeyName(); + var value = 5.5; + var label = new TimeSeriesLabel("key", "value"); + var db = GetCleanDatabase(); + var ts = db.TS(); + var labels = new List { label }; + Assert.True(await ts.IncrByAsync(key, value, labels: labels) > 0); + + var result = await ts.GetAsync(key); + Assert.Equal(value, result!.Val); + + var info = await ts.InfoAsync(key); + Assert.Equal(labels, info.Labels); + } + + [Fact] + public async Task TestDefaultIncrByWithUncompressed() + { + var key = CreateKeyName(); + var value = 5.5; + var db = GetCleanDatabase(); + var ts = db.TS(); + Assert.True(await ts.IncrByAsync(key, value, uncompressed: true) > 0); + + var result = await ts.GetAsync(key); + Assert.Equal(value, result!.Val); + } + + [Fact] + public async Task TestWrongParameters() { - public TestIncrByAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) { } - - [Fact] - public async Task TestDefaultIncrBy() - { - var key = CreateKeyName(); - var value = 5.5; - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.IncrByAsync(key, value) > 0); - - var result = await ts.GetAsync(key); - Assert.Equal(value, result!.Val); - } - - [Fact] - public async Task TestStarIncrBy() - { - var key = CreateKeyName(); - var value = 5.5; - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.IncrByAsync(key, value, timestamp: "*") > 0); - - var result = await ts.GetAsync(key); - Assert.Equal(value, result!.Val); - } - - [Fact] - public async Task TestIncrByTimeStamp() - { - var key = CreateKeyName(); - var value = 5.5; - var db = GetCleanDatabase(); - var ts = db.TS(); - TimeStamp timeStamp = DateTime.UtcNow; - Assert.Equal(timeStamp, await ts.IncrByAsync(key, value, timestamp: timeStamp)); - Assert.Equal(new TimeSeriesTuple(timeStamp, value), await ts.GetAsync(key)); - } - - [Fact] - [Obsolete] - public async Task TestDefaultIncrByWithRetentionTime() - { - var key = CreateKeyName(); - var value = 5.5; - long retentionTime = 5000; - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.IncrByAsync(key, value, retentionTime: retentionTime) > 0); - - var result = await ts.GetAsync(key); - Assert.Equal(value, result!.Val); - - var info = await ts.InfoAsync(key); - Assert.Equal(retentionTime, info.RetentionTime); - } - - [Fact] - [Obsolete] - public async Task TestDefaultIncrByWithLabels() - { - var key = CreateKeyName(); - var value = 5.5; - var label = new TimeSeriesLabel("key", "value"); - var db = GetCleanDatabase(); - var ts = db.TS(); - var labels = new List { label }; - Assert.True(await ts.IncrByAsync(key, value, labels: labels) > 0); - - var result = await ts.GetAsync(key); - Assert.Equal(value, result!.Val); - - var info = await ts.InfoAsync(key); - Assert.Equal(labels, info.Labels); - } - - [Fact] - public async Task TestDefaultIncrByWithUncompressed() - { - var key = CreateKeyName(); - var value = 5.5; - var db = GetCleanDatabase(); - var ts = db.TS(); - Assert.True(await ts.IncrByAsync(key, value, uncompressed: true) > 0); - - var result = await ts.GetAsync(key); - Assert.Equal(value, result!.Val); - } - - [Fact] - public async Task TestWrongParameters() - { - var key = CreateKeyName(); - var value = 5.5; - var db = GetCleanDatabase(); - var ts = db.TS(); - var ex = await Assert.ThrowsAsync(async () => await ts.IncrByAsync(key, value, timestamp: "+")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - - ex = await Assert.ThrowsAsync(async () => await ts.IncrByAsync(key, value, timestamp: "-")); - Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); - } + var key = CreateKeyName(); + var value = 5.5; + var db = GetCleanDatabase(); + var ts = db.TS(); + var ex = await Assert.ThrowsAsync(async () => await ts.IncrByAsync(key, value, timestamp: "+")); + Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); + + ex = await Assert.ThrowsAsync(async () => await ts.IncrByAsync(key, value, timestamp: "-")); + Assert.Equal("ERR TSDB: invalid timestamp", ex.Message); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMADD.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMADD.cs index 9072db06..ffc69cb2 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMADD.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMADD.cs @@ -1,119 +1,115 @@ -using NRedisStack.DataTypes; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods +using NRedisStack.DataTypes; using NRedisStack.Literals.Enums; using NRedisStack.RedisStackCommands; using StackExchange.Redis; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestMADD(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable { - public class TestMADD : AbstractNRedisStackTest, IDisposable + + private readonly string[] keys = ["MADD_TESTS_1", "MADD_TESTS_2"]; + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + [Obsolete] + public void TestStarMADD(string endpointId) + { + + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + + foreach (string key in keys) + { + ts.Create(key); + } + List<(string, TimeStamp, double)> sequence = new(keys.Length); + foreach (var keyname in keys) + { + sequence.Add((keyname, "*", 1.1)); + } + var response = ts.MAdd(sequence); + + Assert.Equal(keys.Length, response.Count); + + foreach (var key in keys) + { + TimeSeriesInformation info = ts.Info(key); + Assert.True(info.FirstTimeStamp! > 0); + Assert.Equal(info.FirstTimeStamp, info.LastTimeStamp); + } + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestSuccessfulMADD(string endpointId) { - private readonly string[] keys = { "MADD_TESTS_1", "MADD_TESTS_2" }; + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); - public TestMADD(EndpointsFixture endpointsFixture) : base(endpointsFixture) + foreach (string key in keys) { + ts.Create(key); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - [Obsolete] - public void TestStarMADD(string endpointId) + List<(string, TimeStamp, double)> sequence = new(keys.Length); + List timestamps = new(keys.Length); + foreach (var keyname in keys) { + DateTime now = DateTime.UtcNow; + timestamps.Add(now); + sequence.Add((keyname, now, 1.1)); + } + var response = ts.MAdd(sequence); - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - - foreach (string key in keys) - { - ts.Create(key); - } - List<(string, TimeStamp, double)> sequence = new List<(string, TimeStamp, double)>(keys.Length); - foreach (var keyname in keys) - { - sequence.Add((keyname, "*", 1.1)); - } - var response = ts.MAdd(sequence); - - Assert.Equal(keys.Length, response.Count); - - foreach (var key in keys) - { - TimeSeriesInformation info = ts.Info(key); - Assert.True(info.FirstTimeStamp! > 0); - Assert.Equal(info.FirstTimeStamp, info.LastTimeStamp); - } + Assert.Equal(timestamps.Count, response.Count); + for (int i = 0; i < response.Count; i++) + { + Assert.Equal(new DateTimeOffset(timestamps[i]).ToUnixTimeMilliseconds(), response[i].Value); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestSuccessfulMADD(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestOverrideMADD(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + + foreach (string key in keys) { + ts.Create(key, duplicatePolicy: TsDuplicatePolicy.MAX); + } - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - - foreach (string key in keys) - { - ts.Create(key); - } - - List<(string, TimeStamp, double)> sequence = new List<(string, TimeStamp, double)>(keys.Length); - List timestamps = new List(keys.Length); - foreach (var keyname in keys) - { - DateTime now = DateTime.UtcNow; - timestamps.Add(now); - sequence.Add((keyname, now, 1.1)); - } - var response = ts.MAdd(sequence); - - Assert.Equal(timestamps.Count, response.Count); - for (int i = 0; i < response.Count; i++) - { - Assert.Equal(new DateTimeOffset(timestamps[i]).ToUnixTimeMilliseconds(), response[i].Value); - } + List oldTimeStamps = []; + foreach (var keyname in keys) + { + oldTimeStamps.Add(DateTime.UtcNow); + } + + List<(string, TimeStamp, double)> sequence = new(keys.Length); + foreach (var keyname in keys) + { + sequence.Add((keyname, DateTime.UtcNow, 1.1)); + } + ts.MAdd(sequence); + + sequence.Clear(); + + // Override the same events should not throw an error + for (int i = 0; i < keys.Length; i++) + { + sequence.Add((keys[i], oldTimeStamps[i], 1.1)); } + var response = ts.MAdd(sequence); - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestOverrideMADD(string endpointId) + Assert.Equal(oldTimeStamps.Count, response.Count); + for (int i = 0; i < response.Count; i++) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - - foreach (string key in keys) - { - ts.Create(key, duplicatePolicy: TsDuplicatePolicy.MAX); - } - - List oldTimeStamps = new List(); - foreach (var keyname in keys) - { - oldTimeStamps.Add(DateTime.UtcNow); - } - - List<(string, TimeStamp, double)> sequence = new List<(string, TimeStamp, double)>(keys.Length); - foreach (var keyname in keys) - { - sequence.Add((keyname, DateTime.UtcNow, 1.1)); - } - ts.MAdd(sequence); - - sequence.Clear(); - - // Override the same events should not throw an error - for (int i = 0; i < keys.Length; i++) - { - sequence.Add((keys[i], oldTimeStamps[i], 1.1)); - } - var response = ts.MAdd(sequence); - - Assert.Equal(oldTimeStamps.Count, response.Count); - for (int i = 0; i < response.Count; i++) - { - Assert.Equal(new DateTimeOffset(oldTimeStamps[i]).ToUnixTimeMilliseconds(), response[i].Value); - } + Assert.Equal(new DateTimeOffset(oldTimeStamps[i]).ToUnixTimeMilliseconds(), response[i].Value); } } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMAddAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMAddAsync.cs index 8a13005d..7e235a80 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMAddAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMAddAsync.cs @@ -1,120 +1,117 @@ -using NRedisStack.DataTypes; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods +using NRedisStack.DataTypes; using NRedisStack.Literals.Enums; using NRedisStack.RedisStackCommands; using StackExchange.Redis; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestMAddAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestMAddAsync : AbstractNRedisStackTest + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + [Obsolete] + public async Task TestStarMADD(string endpointId) + { + var keys = CreateKeyNames(2); + + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + + foreach (string key in keys) + { + await ts.CreateAsync(key); + } + + List<(string, TimeStamp, double)> sequence = new(keys.Length); + foreach (var keyname in keys) + { + sequence.Add((keyname, "*", 1.1)); + } + var response = await ts.MAddAsync(sequence); + + Assert.Equal(keys.Length, response.Count); + + foreach (var key in keys) + { + TimeSeriesInformation info = await ts.InfoAsync(key); + Assert.True(info.FirstTimeStamp! > 0); + Assert.Equal(info.FirstTimeStamp, info.LastTimeStamp); + } + } + + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestSuccessfulMAdd(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + + foreach (var key in keys) + { + await ts.CreateAsync(key); + } + + var sequence = new List<(string, TimeStamp, double)>(keys.Length); + var timestamps = new List(keys.Length); + foreach (var keyname in keys) + { + var now = DateTime.UtcNow; + timestamps.Add(now); + sequence.Add((keyname, now, 1.1)); + } + + var response = await ts.MAddAsync(sequence); + Assert.Equal(timestamps.Count, response.Count); + for (var i = 0; i < response.Count; i++) + { + Assert.Equal(new DateTimeOffset(timestamps[i]).ToUnixTimeMilliseconds(), response[i].Value); + } + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestOverrideMAdd(string endpointId) { - public TestMAddAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) { } + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + + foreach (var key in keys) + { + await ts.CreateAsync(key, duplicatePolicy: TsDuplicatePolicy.MAX); + } + var oldTimeStamps = new List(); + foreach (var keyname in keys) + { + oldTimeStamps.Add(DateTime.UtcNow); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - [Obsolete] - public async Task TestStarMADD(string endpointId) + var sequence = new List<(string, TimeStamp, double)>(keys.Length); + foreach (var keyname in keys) { - var keys = CreateKeyNames(2); - - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - - foreach (string key in keys) - { - await ts.CreateAsync(key); - } - - List<(string, TimeStamp, double)> sequence = new List<(string, TimeStamp, double)>(keys.Length); - foreach (var keyname in keys) - { - sequence.Add((keyname, "*", 1.1)); - } - var response = await ts.MAddAsync(sequence); - - Assert.Equal(keys.Length, response.Count); - - foreach (var key in keys) - { - TimeSeriesInformation info = await ts.InfoAsync(key); - Assert.True(info.FirstTimeStamp! > 0); - Assert.Equal(info.FirstTimeStamp, info.LastTimeStamp); - } + sequence.Add((keyname, DateTime.UtcNow, 1.1)); } + await ts.MAddAsync(sequence); + sequence.Clear(); - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestSuccessfulMAdd(string endpointId) + // Override the same events should not throw an error + for (var i = 0; i < keys.Length; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - - foreach (var key in keys) - { - await ts.CreateAsync(key); - } - - var sequence = new List<(string, TimeStamp, double)>(keys.Length); - var timestamps = new List(keys.Length); - foreach (var keyname in keys) - { - var now = DateTime.UtcNow; - timestamps.Add(now); - sequence.Add((keyname, now, 1.1)); - } - - var response = await ts.MAddAsync(sequence); - Assert.Equal(timestamps.Count, response.Count); - for (var i = 0; i < response.Count; i++) - { - Assert.Equal(new DateTimeOffset(timestamps[i]).ToUnixTimeMilliseconds(), response[i].Value); - } + sequence.Add((keys[i], oldTimeStamps[i], 1.1)); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestOverrideMAdd(string endpointId) + var response = await ts.MAddAsync(sequence); + + Assert.Equal(oldTimeStamps.Count, response.Count); + for (int i = 0; i < response.Count; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - - foreach (var key in keys) - { - await ts.CreateAsync(key, duplicatePolicy: TsDuplicatePolicy.MAX); - } - - var oldTimeStamps = new List(); - foreach (var keyname in keys) - { - oldTimeStamps.Add(DateTime.UtcNow); - } - - var sequence = new List<(string, TimeStamp, double)>(keys.Length); - foreach (var keyname in keys) - { - sequence.Add((keyname, DateTime.UtcNow, 1.1)); - } - - await ts.MAddAsync(sequence); - sequence.Clear(); - - // Override the same events should not throw an error - for (var i = 0; i < keys.Length; i++) - { - sequence.Add((keys[i], oldTimeStamps[i], 1.1)); - } - - var response = await ts.MAddAsync(sequence); - - Assert.Equal(oldTimeStamps.Count, response.Count); - for (int i = 0; i < response.Count; i++) - { - Assert.Equal(new DateTimeOffset(oldTimeStamps[i]).ToUnixTimeMilliseconds(), response[i].Value); - } + Assert.Equal(new DateTimeOffset(oldTimeStamps[i]).ToUnixTimeMilliseconds(), response[i].Value); } } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMGet.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMGet.cs index 53a82cae..cabc43b5 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMGet.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMGet.cs @@ -1,98 +1,94 @@ -using NRedisStack.DataTypes; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods +using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; using StackExchange.Redis; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI -{ - public class TestMGet : AbstractNRedisStackTest, IDisposable - { +namespace NRedisStack.Tests.TimeSeries.TestAPI; - private readonly string[] keys = { "MGET_TESTS_1", "MGET_TESTS_2" }; +public class TestMGet(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable +{ - public TestMGet(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } + private readonly string[] keys = ["MGET_TESTS_1", "MGET_TESTS_2"]; - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMGetQuery(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMGetQuery(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); - var label1 = new TimeSeriesLabel("MGET_TESTS_1", "value"); - var label2 = new TimeSeriesLabel("MGET_TESTS_2", "value2"); - var labels1 = new List { label1, label2 }; - var labels2 = new List { label1 }; + var label1 = new TimeSeriesLabel("MGET_TESTS_1", "value"); + var label2 = new TimeSeriesLabel("MGET_TESTS_2", "value2"); + var labels1 = new List { label1, label2 }; + var labels2 = new List { label1 }; - TimeStamp ts1 = ts.Add(keys[0], "*", 1.1, labels: labels1); - TimeSeriesTuple tuple1 = new TimeSeriesTuple(ts1, 1.1); - TimeStamp ts2 = ts.Add(keys[1], "*", 2.2, labels: labels2); - TimeSeriesTuple tuple2 = new TimeSeriesTuple(ts2, 2.2); - var results = ts.MGet(new List { "MGET_TESTS_1=value" }); - Assert.Equal(2, results.Count); - Assert.Equal(keys[0], results[0].key); - Assert.Equal(tuple1, results[0].value); - Assert.Equal(new List(), results[0].labels); - Assert.Equal(keys[1], results[1].key); - Assert.Equal(tuple2, results[1].value); - Assert.Equal(new List(), results[1].labels); + TimeStamp ts1 = ts.Add(keys[0], "*", 1.1, labels: labels1); + TimeSeriesTuple tuple1 = new(ts1, 1.1); + TimeStamp ts2 = ts.Add(keys[1], "*", 2.2, labels: labels2); + TimeSeriesTuple tuple2 = new(ts2, 2.2); + var results = ts.MGet(new List { "MGET_TESTS_1=value" }); + Assert.Equal(2, results.Count); + Assert.Equal(keys[0], results[0].key); + Assert.Equal(tuple1, results[0].value); + Assert.Equal(new List(), results[0].labels); + Assert.Equal(keys[1], results[1].key); + Assert.Equal(tuple2, results[1].value); + Assert.Equal(new List(), results[1].labels); - } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMGetQueryWithLabels(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMGetQueryWithLabels(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); - var label1 = new TimeSeriesLabel("MGET_TESTS_1", "value"); - var label2 = new TimeSeriesLabel("MGET_TESTS_2", "value2"); - var labels1 = new List { label1, label2 }; - var labels2 = new List { label1 }; + var label1 = new TimeSeriesLabel("MGET_TESTS_1", "value"); + var label2 = new TimeSeriesLabel("MGET_TESTS_2", "value2"); + var labels1 = new List { label1, label2 }; + var labels2 = new List { label1 }; - TimeStamp ts1 = ts.Add(keys[0], "*", 1.1, labels: labels1); - TimeSeriesTuple tuple1 = new TimeSeriesTuple(ts1, 1.1); - TimeStamp ts2 = ts.Add(keys[1], "*", 2.2, labels: labels2); - TimeSeriesTuple tuple2 = new TimeSeriesTuple(ts2, 2.2); + TimeStamp ts1 = ts.Add(keys[0], "*", 1.1, labels: labels1); + TimeSeriesTuple tuple1 = new(ts1, 1.1); + TimeStamp ts2 = ts.Add(keys[1], "*", 2.2, labels: labels2); + TimeSeriesTuple tuple2 = new(ts2, 2.2); - var results = ts.MGet(new List { "MGET_TESTS_1=value" }, withLabels: true); - Assert.Equal(2, results.Count); - Assert.Equal(keys[0], results[0].key); - Assert.Equal(tuple1, results[0].value); - Assert.Equal(labels1, results[0].labels); - Assert.Equal(keys[1], results[1].key); - Assert.Equal(tuple2, results[1].value); - Assert.Equal(labels2, results[1].labels); - } + var results = ts.MGet(new List { "MGET_TESTS_1=value" }, withLabels: true); + Assert.Equal(2, results.Count); + Assert.Equal(keys[0], results[0].key); + Assert.Equal(tuple1, results[0].value); + Assert.Equal(labels1, results[0].labels); + Assert.Equal(keys[1], results[1].key); + Assert.Equal(tuple2, results[1].value); + Assert.Equal(labels2, results[1].labels); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMGetQuerySelectedLabels(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMGetQuerySelectedLabels(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); - var label1 = new TimeSeriesLabel("MGET_TESTS_1", "value"); - var label2 = new TimeSeriesLabel("MGET_TESTS_2", "value2"); - var labels1 = new List { label1, label2 }; - var labels2 = new List { label1 }; + var label1 = new TimeSeriesLabel("MGET_TESTS_1", "value"); + var label2 = new TimeSeriesLabel("MGET_TESTS_2", "value2"); + var labels1 = new List { label1, label2 }; + var labels2 = new List { label1 }; - TimeStamp ts1 = ts.Add(keys[0], "*", 1.1, labels: labels1); - TimeSeriesTuple tuple1 = new TimeSeriesTuple(ts1, 1.1); - TimeStamp ts2 = ts.Add(keys[1], "*", 2.2, labels: labels2); - TimeSeriesTuple tuple2 = new TimeSeriesTuple(ts2, 2.2); + TimeStamp ts1 = ts.Add(keys[0], "*", 1.1, labels: labels1); + TimeSeriesTuple tuple1 = new(ts1, 1.1); + TimeStamp ts2 = ts.Add(keys[1], "*", 2.2, labels: labels2); + TimeSeriesTuple tuple2 = new(ts2, 2.2); - var results = ts.MGet(new List { "MGET_TESTS_1=value" }, selectedLabels: new List { "MGET_TESTS_1" }); - Assert.Equal(2, results.Count); - Assert.Equal(keys[0], results[0].key); - Assert.Equal(tuple1, results[0].value); - Assert.Equal(labels2, results[0].labels); - Assert.Equal(keys[1], results[1].key); - Assert.Equal(tuple2, results[1].value); - Assert.Equal(labels2, results[1].labels); - } + var results = ts.MGet(new List { "MGET_TESTS_1=value" }, selectedLabels: new List { "MGET_TESTS_1" }); + Assert.Equal(2, results.Count); + Assert.Equal(keys[0], results[0].key); + Assert.Equal(tuple1, results[0].value); + Assert.Equal(labels2, results[0].labels); + Assert.Equal(keys[1], results[1].key); + Assert.Equal(tuple2, results[1].value); + Assert.Equal(labels2, results[1].labels); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMGetAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMGetAsync.cs index 308961f0..4c61b0dc 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMGetAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMGetAsync.cs @@ -1,97 +1,93 @@ -using NRedisStack.DataTypes; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods +using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestMGetAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestMGetAsync : AbstractNRedisStackTest + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMGetQuery(string endpointId) { - public TestMGetAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } - - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMGetQuery(string endpointId) - { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); - var label1 = new TimeSeriesLabel(keys[0], "value"); - var label2 = new TimeSeriesLabel(keys[1], "value2"); - var labels1 = new List { label1, label2 }; - var labels2 = new List { label1 }; + var label1 = new TimeSeriesLabel(keys[0], "value"); + var label2 = new TimeSeriesLabel(keys[1], "value2"); + var labels1 = new List { label1, label2 }; + var labels2 = new List { label1 }; - var ts1 = await ts.AddAsync(keys[0], "*", 1.1, labels: labels1); - var tuple1 = new TimeSeriesTuple(ts1, 1.1); - var ts2 = await ts.AddAsync(keys[1], "*", 2.2, labels: labels2); - var tuple2 = new TimeSeriesTuple(ts2, 2.2); + var ts1 = await ts.AddAsync(keys[0], "*", 1.1, labels: labels1); + var tuple1 = new TimeSeriesTuple(ts1, 1.1); + var ts2 = await ts.AddAsync(keys[1], "*", 2.2, labels: labels2); + var tuple2 = new TimeSeriesTuple(ts2, 2.2); - var results = await ts.MGetAsync(new List { $"{keys[0]}=value" }); - Assert.Equal(2, results.Count); - Assert.Equal(keys[0], results[0].key); - Assert.Equal(tuple1, results[0].value); - Assert.Equal(new List(), results[0].labels); - Assert.Equal(keys[1], results[1].key); - Assert.Equal(tuple2, results[1].value); - Assert.Equal(new List(), results[1].labels); - } + var results = await ts.MGetAsync(new List { $"{keys[0]}=value" }); + Assert.Equal(2, results.Count); + Assert.Equal(keys[0], results[0].key); + Assert.Equal(tuple1, results[0].value); + Assert.Equal(new List(), results[0].labels); + Assert.Equal(keys[1], results[1].key); + Assert.Equal(tuple2, results[1].value); + Assert.Equal(new List(), results[1].labels); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMGetQueryWithLabels(string endpointId) - { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMGetQueryWithLabels(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); - var label1 = new TimeSeriesLabel(keys[0], "value"); - var label2 = new TimeSeriesLabel(keys[1], "value2"); - var labels1 = new List { label1, label2 }; - var labels2 = new List { label1 }; + var label1 = new TimeSeriesLabel(keys[0], "value"); + var label2 = new TimeSeriesLabel(keys[1], "value2"); + var labels1 = new List { label1, label2 }; + var labels2 = new List { label1 }; - var ts1 = await ts.AddAsync(keys[0], "*", 1.1, labels: labels1); - var tuple1 = new TimeSeriesTuple(ts1, 1.1); - var ts2 = await ts.AddAsync(keys[1], "*", 2.2, labels: labels2); - var tuple2 = new TimeSeriesTuple(ts2, 2.2); + var ts1 = await ts.AddAsync(keys[0], "*", 1.1, labels: labels1); + var tuple1 = new TimeSeriesTuple(ts1, 1.1); + var ts2 = await ts.AddAsync(keys[1], "*", 2.2, labels: labels2); + var tuple2 = new TimeSeriesTuple(ts2, 2.2); - var results = await ts.MGetAsync(new List { $"{keys[0]}=value" }, withLabels: true); - Assert.Equal(2, results.Count); - Assert.Equal(keys[0], results[0].key); - Assert.Equal(tuple1, results[0].value); - Assert.Equal(labels1, results[0].labels); - Assert.Equal(keys[1], results[1].key); - Assert.Equal(tuple2, results[1].value); - Assert.Equal(labels2, results[1].labels); - } + var results = await ts.MGetAsync(new List { $"{keys[0]}=value" }, withLabels: true); + Assert.Equal(2, results.Count); + Assert.Equal(keys[0], results[0].key); + Assert.Equal(tuple1, results[0].value); + Assert.Equal(labels1, results[0].labels); + Assert.Equal(keys[1], results[1].key); + Assert.Equal(tuple2, results[1].value); + Assert.Equal(labels2, results[1].labels); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMGetQuerySelectedLabelsAsync(string endpointId) - { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMGetQuerySelectedLabelsAsync(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); - var label1 = new TimeSeriesLabel("MGET_TESTS_1", "value"); - var label2 = new TimeSeriesLabel("MGET_TESTS_2", "value2"); - var labels1 = new List { label1, label2 }; - var labels2 = new List { label1 }; + var label1 = new TimeSeriesLabel("MGET_TESTS_1", "value"); + var label2 = new TimeSeriesLabel("MGET_TESTS_2", "value2"); + var labels1 = new List { label1, label2 }; + var labels2 = new List { label1 }; - TimeStamp ts1 = await ts.AddAsync(keys[0], "*", 1.1, labels: labels1); - TimeSeriesTuple tuple1 = new TimeSeriesTuple(ts1, 1.1); - TimeStamp ts2 = await ts.AddAsync(keys[1], "*", 2.2, labels: labels2); - TimeSeriesTuple tuple2 = new TimeSeriesTuple(ts2, 2.2); + TimeStamp ts1 = await ts.AddAsync(keys[0], "*", 1.1, labels: labels1); + TimeSeriesTuple tuple1 = new(ts1, 1.1); + TimeStamp ts2 = await ts.AddAsync(keys[1], "*", 2.2, labels: labels2); + TimeSeriesTuple tuple2 = new(ts2, 2.2); - var results = await ts.MGetAsync(new List { "MGET_TESTS_1=value" }, selectedLabels: new List { "MGET_TESTS_1" }); - Assert.Equal(2, results.Count); - Assert.Equal(keys[0], results[0].key); - Assert.Equal(tuple1, results[0].value); - Assert.Equal(labels2, results[0].labels); - Assert.Equal(keys[1], results[1].key); - Assert.Equal(tuple2, results[1].value); - Assert.Equal(labels2, results[1].labels); - } + var results = await ts.MGetAsync(new List { "MGET_TESTS_1=value" }, selectedLabels: new List { "MGET_TESTS_1" }); + Assert.Equal(2, results.Count); + Assert.Equal(keys[0], results[0].key); + Assert.Equal(tuple1, results[0].value); + Assert.Equal(labels2, results[0].labels); + Assert.Equal(keys[1], results[1].key); + Assert.Equal(tuple2, results[1].value); + Assert.Equal(labels2, results[1].labels); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRange.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRange.cs index 7375f15a..99111ef0 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRange.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRange.cs @@ -1,517 +1,513 @@ +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; using StackExchange.Redis; using Xunit; using NRedisStack.RedisStackCommands; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestMRange(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable { - public class TestMRange : AbstractNRedisStackTest, IDisposable - { - private readonly string[] _keys = { "MRANGE_TESTS_1", "MRANGE_TESTS_2" }; + private readonly string[] _keys = ["MRANGE_TESTS_1", "MRANGE_TESTS_2"]; - public TestMRange(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } + private List CreateData(ITimeSeriesCommands ts, int timeBucket, string[]? keys = null) + { + keys ??= _keys; + var tuples = new List(); - private List CreateData(ITimeSeriesCommands ts, int timeBucket, string[]? keys = null) + for (int i = 0; i < 10; i++) { - keys ??= _keys; - var tuples = new List(); - - for (int i = 0; i < 10; i++) + TimeStamp timeStamp = new(i * timeBucket); + foreach (var key in keys) { - TimeStamp timeStamp = new TimeStamp(i * timeBucket); - foreach (var key in keys) - { - ts.Add(key, timeStamp, i); - } - tuples.Add(new TimeSeriesTuple(timeStamp, i)); + ts.Add(key, timeStamp, i); } - return tuples; + tuples.Add(new(timeStamp, i)); } + return tuples; + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestSimpleMRange(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestSimpleMRange(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + TimeSeriesLabel label = new("MRANGEkey", "MRANGEvalue"); + var labels = new List { label }; + foreach (string key in _keys) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - TimeSeriesLabel label = new TimeSeriesLabel("MRANGEkey", "MRANGEvalue"); - var labels = new List { label }; - foreach (string key in _keys) - { - ts.Create(key, labels: labels); - } + ts.Create(key, labels: labels); + } - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "MRANGEkey=MRANGEvalue" }); - Assert.Equal(_keys.Length, results.Count); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(_keys[i], results[i].key); - Assert.Empty(results[i].labels); - Assert.Equal(tuples, results[i].values); - } + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "MRANGEkey=MRANGEvalue" }); + Assert.Equal(_keys.Length, results.Count); + for (int i = 0; i < results.Count; i++) + { + Assert.Equal(_keys[i], results[i].key); + Assert.Empty(results[i].labels); + Assert.Equal(tuples, results[i].values); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeWithLabels(string endpointId) + } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeWithLabels(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + TimeSeriesLabel label = new("key", "MRangeWithLabels"); + var labels = new List { label }; + foreach (string key in _keys) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeWithLabels"); - var labels = new List { label }; - foreach (string key in _keys) - { - ts.Create(key, labels: labels); - } + ts.Create(key, labels: labels); + } - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "key=MRangeWithLabels" }, withLabels: true); - Assert.Equal(_keys.Length, results.Count); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(_keys[i], results[i].key); - Assert.Equal(labels, results[i].labels); - Assert.Equal(tuples, results[i].values); - } + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "key=MRangeWithLabels" }, withLabels: true); + Assert.Equal(_keys.Length, results.Count); + for (int i = 0; i < results.Count; i++) + { + Assert.Equal(_keys[i], results[i].key); + Assert.Equal(labels, results[i].labels); + Assert.Equal(tuples, results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeSelectLabels(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeSelectLabels(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + TimeSeriesLabel label1 = new("key", "MRangeSelectLabels"); + TimeSeriesLabel[] labels = [new("team", "CTO"), new("team", "AUT")]; + for (int i = 0; i < _keys.Length; i++) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - TimeSeriesLabel label1 = new TimeSeriesLabel("key", "MRangeSelectLabels"); - TimeSeriesLabel[] labels = new TimeSeriesLabel[] { new TimeSeriesLabel("team", "CTO"), new TimeSeriesLabel("team", "AUT") }; - for (int i = 0; i < _keys.Length; i++) - { - ts.Create(_keys[i], labels: new List { label1, labels[i] }); - } + ts.Create(_keys[i], labels: new List { label1, labels[i] }); + } - var tuples = CreateData(ts, 50); - // selectLabels and withlabels are mutualy exclusive. - var ex = Assert.Throws(() => ts.MRange("-", "+", new List { "key=MRangeSelectLabels" }, - withLabels: true, selectLabels: new List { "team" })); - Assert.Equal("withLabels and selectLabels cannot be specified together.", ex.Message); + var tuples = CreateData(ts, 50); + // selectLabels and withlabels are mutualy exclusive. + var ex = Assert.Throws(() => ts.MRange("-", "+", new List { "key=MRangeSelectLabels" }, + withLabels: true, selectLabels: new List { "team" })); + Assert.Equal("withLabels and selectLabels cannot be specified together.", ex.Message); - var results = ts.MRange("-", "+", new List { "key=MRangeSelectLabels" }, selectLabels: new List { "team" }); - Assert.Equal(_keys.Length, results.Count); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(_keys[i], results[i].key); - Assert.Equal(labels[i], results[i].labels[0]); - Assert.Equal(tuples, results[i].values); - } + var results = ts.MRange("-", "+", new List { "key=MRangeSelectLabels" }, selectLabels: new List { "team" }); + Assert.Equal(_keys.Length, results.Count); + for (int i = 0; i < results.Count; i++) + { + Assert.Equal(_keys[i], results[i].key); + Assert.Equal(labels[i], results[i].labels[0]); + Assert.Equal(tuples, results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeFilter(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeFilter"); - var labels = new List { label }; - ts.Create(_keys[0], labels: labels); - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "key=MRangeFilter" }); - Assert.Single(results); - Assert.Equal(_keys[0], results[0].key); - Assert.Empty(results[0].labels); - Assert.Equal(tuples, results[0].values); - } - - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeCount(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeCount"); - var labels = new List { label }; - foreach (string key in _keys) - { - ts.Create(key, labels: labels); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeFilter(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + TimeSeriesLabel label = new("key", "MRangeFilter"); + var labels = new List { label }; + ts.Create(_keys[0], labels: labels); + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "key=MRangeFilter" }); + Assert.Single(results); + Assert.Equal(_keys[0], results[0].key); + Assert.Empty(results[0].labels); + Assert.Equal(tuples, results[0].values); + } - var tuples = CreateData(ts, 50); - long count = 5; - var results = ts.MRange("-", "+", new List { "key=MRangeCount" }, count: count); - Assert.Equal(_keys.Length, results.Count); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(_keys[i], results[i].key); - Assert.Empty(results[i].labels); - Assert.Equal(tuples.GetRange(0, (int)count), results[i].values); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeCount(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + TimeSeriesLabel label = new("key", "MRangeCount"); + var labels = new List { label }; + foreach (string key in _keys) + { + ts.Create(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeAggregation(string endpointId) + var tuples = CreateData(ts, 50); + long count = 5; + var results = ts.MRange("-", "+", new List { "key=MRangeCount" }, count: count); + Assert.Equal(_keys.Length, results.Count); + for (int i = 0; i < results.Count; i++) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeAggregation"); - var labels = new List { label }; - foreach (string key in _keys) - { - ts.Create(key, labels: labels); - } - - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "key=MRangeAggregation" }, aggregation: TsAggregation.Min, timeBucket: 50); - Assert.Equal(_keys.Length, results.Count); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(_keys[i], results[i].key); - Assert.Empty(results[i].labels); - Assert.Equal(tuples, results[i].values); - } + Assert.Equal(_keys[i], results[i].key); + Assert.Empty(results[i].labels); + Assert.Equal(tuples.GetRange(0, (int)count), results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeAlign(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeAlign"); - var labels = new List { label }; - ts.Create(_keys[0], labels: labels); - CreateData(ts, 50); - var expected = new List { - new TimeSeriesTuple(0,1), - new TimeSeriesTuple(50,1), - new TimeSeriesTuple(100,1) - }; - var results = ts.MRange(0, "+", new List { "key=MRangeAlign" }, align: "-", aggregation: TsAggregation.Count, timeBucket: 10, count: 3); - Assert.Single(results); - Assert.Equal(_keys[0], results[0].key); - Assert.Equal(expected, results[0].values); - results = ts.MRange(1, 500, new List { "key=MRangeAlign" }, align: "+", aggregation: TsAggregation.Count, timeBucket: 10, count: 1); - Assert.Equal(expected[1], results[0].values[0]); - } - - [Fact] - public void TestMissingFilter() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - TimeSeriesLabel label = new TimeSeriesLabel("key", "MissingFilter"); - var labels = new List { label }; - foreach (string key in _keys) - { - ts.Create(key, labels: labels); - } - - var tuples = CreateData(ts, 50); - var ex = Assert.Throws(() => ts.MRange("-", "+", new List())); - Assert.Equal("There should be at least one filter on MRANGE/MREVRANGE", ex.Message); + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeAggregation(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + TimeSeriesLabel label = new("key", "MRangeAggregation"); + var labels = new List { label }; + foreach (string key in _keys) + { + ts.Create(key, labels: labels); } - [Fact] - public void TestMissingTimeBucket() + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "key=MRangeAggregation" }, aggregation: TsAggregation.Min, timeBucket: 50); + Assert.Equal(_keys.Length, results.Count); + for (int i = 0; i < results.Count; i++) { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - TimeSeriesLabel label = new TimeSeriesLabel("key", "MissingTimeBucket"); - var labels = new List { label }; - foreach (string key in _keys) - { - ts.Create(key, labels: labels); - } + Assert.Equal(_keys[i], results[i].key); + Assert.Empty(results[i].labels); + Assert.Equal(tuples, results[i].values); + } + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeAlign(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + TimeSeriesLabel label = new("key", "MRangeAlign"); + var labels = new List { label }; + ts.Create(_keys[0], labels: labels); + CreateData(ts, 50); + var expected = new List { + new(0,1), + new(50,1), + new(100,1) + }; + var results = ts.MRange(0, "+", new List { "key=MRangeAlign" }, align: "-", aggregation: TsAggregation.Count, timeBucket: 10, count: 3); + Assert.Single(results); + Assert.Equal(_keys[0], results[0].key); + Assert.Equal(expected, results[0].values); + results = ts.MRange(1, 500, new List { "key=MRangeAlign" }, align: "+", aggregation: TsAggregation.Count, timeBucket: 10, count: 1); + Assert.Equal(expected[1], results[0].values[0]); + } - var tuples = CreateData(ts, 50); - var ex = Assert.Throws(() => ts.MRange("-", "+", new List { "key=MissingTimeBucket" }, aggregation: TsAggregation.Avg)); - Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); + [Fact] + public void TestMissingFilter() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + TimeSeriesLabel label = new("key", "MissingFilter"); + var labels = new List { label }; + foreach (string key in _keys) + { + ts.Create(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeGroupby(string endpointId) + var tuples = CreateData(ts, 50); + var ex = Assert.Throws(() => ts.MRange("-", "+", new List())); + Assert.Equal("There should be at least one filter on MRANGE/MREVRANGE", ex.Message); + } + + [Fact] + public void TestMissingTimeBucket() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + TimeSeriesLabel label = new("key", "MissingTimeBucket"); + var labels = new List { label }; + foreach (string key in _keys) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - for (int i = 0; i < _keys.Length; i++) - { - var label1 = new TimeSeriesLabel("key", "MRangeGroupby"); - var label2 = new TimeSeriesLabel("group", i.ToString()); - ts.Create(_keys[i], labels: new List { label1, label2 }); - } + ts.Create(key, labels: labels); + } - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "key=MRangeGroupby" }, withLabels: true, groupbyTuple: ("group", TsReduce.Min)); - Assert.Equal(_keys.Length, results.Count); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal("group=" + i, results[i].key); - Assert.Equal(new TimeSeriesLabel("group", i.ToString()), results[i].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "min"), results[i].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", _keys[i]), results[i].labels[2]); - Assert.Equal(tuples, results[i].values); - } + var tuples = CreateData(ts, 50); + var ex = Assert.Throws(() => ts.MRange("-", "+", new List { "key=MissingTimeBucket" }, aggregation: TsAggregation.Avg)); + Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeGroupby(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + for (int i = 0; i < _keys.Length; i++) + { + var label1 = new TimeSeriesLabel("key", "MRangeGroupby"); + var label2 = new TimeSeriesLabel("group", i.ToString()); + ts.Create(_keys[i], labels: new List { label1, label2 }); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeReduceSum(string endpointId) + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "key=MRangeGroupby" }, withLabels: true, groupbyTuple: ("group", TsReduce.Min)); + Assert.Equal(_keys.Length, results.Count); + for (int i = 0; i < results.Count; i++) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - foreach (var key in _keys) - { - var label = new TimeSeriesLabel("key", "MRangeReduce"); - ts.Create(key, labels: new List { label }); - } + Assert.Equal("group=" + i, results[i].key); + Assert.Equal(new("group", i.ToString()), results[i].labels[0]); + Assert.Equal(new("__reducer__", "min"), results[i].labels[1]); + Assert.Equal(new("__source__", _keys[i]), results[i].labels[2]); + Assert.Equal(tuples, results[i].values); + } + } - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.Sum)); - Assert.Single(results); - Assert.Equal("key=MRangeReduce", results[0].key); - Assert.Equal(new TimeSeriesLabel("key", "MRangeReduce"), results[0].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "sum"), results[0].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", string.Join(",", _keys)), results[0].labels[2]); - for (int i = 0; i < results[0].values.Count; i++) - { - Assert.Equal(tuples[i].Val * 2, results[0].values[i].Val); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeReduceSum(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + foreach (var key in _keys) + { + var label = new TimeSeriesLabel("key", "MRangeReduce"); + ts.Create(key, labels: new List { label }); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeReduceAvg(string endpointId) + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.Sum)); + Assert.Single(results); + Assert.Equal("key=MRangeReduce", results[0].key); + Assert.Equal(new("key", "MRangeReduce"), results[0].labels[0]); + Assert.Equal(new("__reducer__", "sum"), results[0].labels[1]); + Assert.Equal(new("__source__", string.Join(",", _keys)), results[0].labels[2]); + for (int i = 0; i < results[0].values.Count; i++) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - foreach (var key in _keys) - { - var label = new TimeSeriesLabel("key", "MRangeReduce"); - ts.Create(key, labels: new List { label }); - } + Assert.Equal(tuples[i].Val * 2, results[0].values[i].Val); + } + } - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.Avg)); - Assert.Single(results); - Assert.Equal("key=MRangeReduce", results[0].key); - Assert.Equal(new TimeSeriesLabel("key", "MRangeReduce"), results[0].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "avg"), results[0].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", string.Join(",", _keys)), results[0].labels[2]); - for (int i = 0; i < results[0].values.Count; i++) - { - Assert.Equal(tuples[i].Val, results[0].values[i].Val); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeReduceAvg(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + foreach (var key in _keys) + { + var label = new TimeSeriesLabel("key", "MRangeReduce"); + ts.Create(key, labels: new List { label }); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeReduceRange(string endpointId) + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.Avg)); + Assert.Single(results); + Assert.Equal("key=MRangeReduce", results[0].key); + Assert.Equal(new("key", "MRangeReduce"), results[0].labels[0]); + Assert.Equal(new("__reducer__", "avg"), results[0].labels[1]); + Assert.Equal(new("__source__", string.Join(",", _keys)), results[0].labels[2]); + for (int i = 0; i < results[0].values.Count; i++) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - foreach (var key in _keys) - { - var label = new TimeSeriesLabel("key", "MRangeReduce"); - ts.Create(key, labels: new List { label }); - } + Assert.Equal(tuples[i].Val, results[0].values[i].Val); + } + } - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.Range)); - Assert.Single(results); - Assert.Equal("key=MRangeReduce", results[0].key); - Assert.Equal(new TimeSeriesLabel("key", "MRangeReduce"), results[0].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "range"), results[0].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", string.Join(",", _keys)), results[0].labels[2]); - for (int i = 0; i < results[0].values.Count; i++) - { - Assert.Equal(0, results[0].values[i].Val); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeReduceRange(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + foreach (var key in _keys) + { + var label = new TimeSeriesLabel("key", "MRangeReduce"); + ts.Create(key, labels: new List { label }); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeReduceCount(string endpointId) + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.Range)); + Assert.Single(results); + Assert.Equal("key=MRangeReduce", results[0].key); + Assert.Equal(new("key", "MRangeReduce"), results[0].labels[0]); + Assert.Equal(new("__reducer__", "range"), results[0].labels[1]); + Assert.Equal(new("__source__", string.Join(",", _keys)), results[0].labels[2]); + for (int i = 0; i < results[0].values.Count; i++) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - foreach (var key in _keys) - { - var label = new TimeSeriesLabel("key", "MRangeReduce"); - ts.Create(key, labels: new List { label }); - } + Assert.Equal(0, results[0].values[i].Val); + } + } - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.Count)); - Assert.Single(results); - Assert.Equal("key=MRangeReduce", results[0].key); - Assert.Equal(new TimeSeriesLabel("key", "MRangeReduce"), results[0].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "count"), results[0].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", string.Join(",", _keys)), results[0].labels[2]); - for (int i = 0; i < results[0].values.Count; i++) - { - Assert.Equal(2, results[0].values[i].Val); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeReduceCount(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + foreach (var key in _keys) + { + var label = new TimeSeriesLabel("key", "MRangeReduce"); + ts.Create(key, labels: new List { label }); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeReduceStdP(string endpointId) + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.Count)); + Assert.Single(results); + Assert.Equal("key=MRangeReduce", results[0].key); + Assert.Equal(new("key", "MRangeReduce"), results[0].labels[0]); + Assert.Equal(new("__reducer__", "count"), results[0].labels[1]); + Assert.Equal(new("__source__", string.Join(",", _keys)), results[0].labels[2]); + for (int i = 0; i < results[0].values.Count; i++) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - foreach (var key in _keys) - { - var label = new TimeSeriesLabel("key", "MRangeReduce"); - ts.Create(key, labels: new List { label }); - } + Assert.Equal(2, results[0].values[i].Val); + } + } - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.StdP)); - Assert.Single(results); - Assert.Equal("key=MRangeReduce", results[0].key); - Assert.Equal(new TimeSeriesLabel("key", "MRangeReduce"), results[0].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "std.p"), results[0].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", string.Join(",", _keys)), results[0].labels[2]); - for (int i = 0; i < results[0].values.Count; i++) - { - Assert.Equal(0, results[0].values[i].Val); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeReduceStdP(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + foreach (var key in _keys) + { + var label = new TimeSeriesLabel("key", "MRangeReduce"); + ts.Create(key, labels: new List { label }); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeReduceStdS(string endpointId) + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.StdP)); + Assert.Single(results); + Assert.Equal("key=MRangeReduce", results[0].key); + Assert.Equal(new("key", "MRangeReduce"), results[0].labels[0]); + Assert.Equal(new("__reducer__", "std.p"), results[0].labels[1]); + Assert.Equal(new("__source__", string.Join(",", _keys)), results[0].labels[2]); + for (int i = 0; i < results[0].values.Count; i++) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - foreach (var key in _keys) - { - var label = new TimeSeriesLabel("key", "MRangeReduce"); - ts.Create(key, labels: new List { label }); - } + Assert.Equal(0, results[0].values[i].Val); + } + } - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.StdS)); - Assert.Single(results); - Assert.Equal("key=MRangeReduce", results[0].key); - Assert.Equal(new TimeSeriesLabel("key", "MRangeReduce"), results[0].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "std.s"), results[0].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", string.Join(",", _keys)), results[0].labels[2]); - for (int i = 0; i < results[0].values.Count; i++) - { - Assert.Equal(0, results[0].values[i].Val); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeReduceStdS(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + foreach (var key in _keys) + { + var label = new TimeSeriesLabel("key", "MRangeReduce"); + ts.Create(key, labels: new List { label }); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeReduceVarP(string endpointId) + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.StdS)); + Assert.Single(results); + Assert.Equal("key=MRangeReduce", results[0].key); + Assert.Equal(new("key", "MRangeReduce"), results[0].labels[0]); + Assert.Equal(new("__reducer__", "std.s"), results[0].labels[1]); + Assert.Equal(new("__source__", string.Join(",", _keys)), results[0].labels[2]); + for (int i = 0; i < results[0].values.Count; i++) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - foreach (var key in _keys) - { - var label = new TimeSeriesLabel("key", "MRangeReduce"); - ts.Create(key, labels: new List { label }); - } + Assert.Equal(0, results[0].values[i].Val); + } + } - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.VarP)); - Assert.Single(results); - Assert.Equal("key=MRangeReduce", results[0].key); - Assert.Equal(new TimeSeriesLabel("key", "MRangeReduce"), results[0].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "var.p"), results[0].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", string.Join(",", _keys)), results[0].labels[2]); - for (int i = 0; i < results[0].values.Count; i++) - { - Assert.Equal(0, results[0].values[i].Val); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeReduceVarP(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + foreach (var key in _keys) + { + var label = new TimeSeriesLabel("key", "MRangeReduce"); + ts.Create(key, labels: new List { label }); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeReduceVarS(string endpointId) + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.VarP)); + Assert.Single(results); + Assert.Equal("key=MRangeReduce", results[0].key); + Assert.Equal(new("key", "MRangeReduce"), results[0].labels[0]); + Assert.Equal(new("__reducer__", "var.p"), results[0].labels[1]); + Assert.Equal(new("__source__", string.Join(",", _keys)), results[0].labels[2]); + for (int i = 0; i < results[0].values.Count; i++) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - foreach (var key in _keys) - { - var label = new TimeSeriesLabel("key", "MRangeReduce"); - ts.Create(key, labels: new List { label }); - } + Assert.Equal(0, results[0].values[i].Val); + } + } - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.VarS)); - Assert.Single(results); - Assert.Equal("key=MRangeReduce", results[0].key); - Assert.Equal(new TimeSeriesLabel("key", "MRangeReduce"), results[0].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "var.s"), results[0].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", string.Join(",", _keys)), results[0].labels[2]); - for (int i = 0; i < results[0].values.Count; i++) - { - Assert.Equal(0, results[0].values[i].Val); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeReduceVarS(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + foreach (var key in _keys) + { + var label = new TimeSeriesLabel("key", "MRangeReduce"); + ts.Create(key, labels: new List { label }); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeFilterBy(string endpointId) + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "key=MRangeReduce" }, withLabels: true, groupbyTuple: ("key", TsReduce.VarS)); + Assert.Single(results); + Assert.Equal("key=MRangeReduce", results[0].key); + Assert.Equal(new("key", "MRangeReduce"), results[0].labels[0]); + Assert.Equal(new("__reducer__", "var.s"), results[0].labels[1]); + Assert.Equal(new("__source__", string.Join(",", _keys)), results[0].labels[2]); + for (int i = 0; i < results[0].values.Count; i++) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - TimeSeriesLabel label = new TimeSeriesLabel("key", "MRangeFilterBy"); - var labels = new List { label }; - foreach (string key in _keys) - { - ts.Create(key, labels: labels); - } + Assert.Equal(0, results[0].values[i].Val); + } + } - var tuples = CreateData(ts, 50); - var results = ts.MRange("-", "+", new List { "key=MRangeFilterBy" }, filterByValue: (0, 2)); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(tuples.GetRange(0, 3), results[i].values); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeFilterBy(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + TimeSeriesLabel label = new("key", "MRangeFilterBy"); + var labels = new List { label }; + foreach (string key in _keys) + { + ts.Create(key, labels: labels); + } - results = ts.MRange("-", "+", new List { "key=MRangeFilterBy" }, filterByTs: new List { 0 }, filterByValue: (0, 2)); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(tuples.GetRange(0, 1), results[i].values); - } + var tuples = CreateData(ts, 50); + var results = ts.MRange("-", "+", new List { "key=MRangeFilterBy" }, filterByValue: (0, 2)); + for (int i = 0; i < results.Count; i++) + { + Assert.Equal(tuples.GetRange(0, 3), results[i].values); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRangeLatest(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel("key", "MRangeLatest"); - var compactedLabel = new TimeSeriesLabel("compact", "true"); - string primaryTsKey = _keys[0], compactedTsKey = _keys[1]; - var compactionRule = new TimeSeriesRule( - compactedTsKey, - (long)TimeSpan.FromHours(1).TotalMilliseconds, // 1h used to force partial bucket - TsAggregation.Sum); - - ts.Create(primaryTsKey, labels: new[] { label }); - ts.Create(compactedTsKey, labels: new[] { label, compactedLabel }); - ts.CreateRule(primaryTsKey, compactionRule); - var tuples = CreateData(ts, 50, new[] { primaryTsKey }); - - var results = ts.MRange("-", "+", new[] { "key=MRangeLatest", "compact=true" }, latest: true); - Assert.Single(results); - Assert.Equal(compactedTsKey, results[0].key); - Assert.NotEmpty(results[0].values); - Assert.Equal(tuples.Sum(x => x.Val), results[0].values.Sum(x => x.Val)); - - results = ts.MRange("-", "+", new[] { "key=MRangeLatest", "compact=true" }, latest: false); - Assert.Single(results); - Assert.Equal(compactedTsKey, results[0].key); - Assert.Empty(results[0].values); + results = ts.MRange("-", "+", new List { "key=MRangeFilterBy" }, filterByTs: new List { 0 }, filterByValue: (0, 2)); + for (int i = 0; i < results.Count; i++) + { + Assert.Equal(tuples.GetRange(0, 1), results[i].values); } } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRangeLatest(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel("key", "MRangeLatest"); + var compactedLabel = new TimeSeriesLabel("compact", "true"); + string primaryTsKey = _keys[0], compactedTsKey = _keys[1]; + var compactionRule = new TimeSeriesRule( + compactedTsKey, + (long)TimeSpan.FromHours(1).TotalMilliseconds, // 1h used to force partial bucket + TsAggregation.Sum); + + ts.Create(primaryTsKey, labels: [label]); + ts.Create(compactedTsKey, labels: [label, compactedLabel]); + ts.CreateRule(primaryTsKey, compactionRule); + var tuples = CreateData(ts, 50, [primaryTsKey]); + + var results = ts.MRange("-", "+", ["key=MRangeLatest", "compact=true"], latest: true); + Assert.Single(results); + Assert.Equal(compactedTsKey, results[0].key); + Assert.NotEmpty(results[0].values); + Assert.Equal(tuples.Sum(x => x.Val), results[0].values.Sum(x => x.Val)); + + results = ts.MRange("-", "+", ["key=MRangeLatest", "compact=true"], latest: false); + Assert.Single(results); + Assert.Equal(compactedTsKey, results[0].key); + Assert.Empty(results[0].values); + } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRangeAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRangeAsync.cs index 4c5018c1..65ee678a 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRangeAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRangeAsync.cs @@ -1,333 +1,329 @@ +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; using StackExchange.Redis; using Xunit; using NRedisStack.RedisStackCommands; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestMRangeAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestMRangeAsync : AbstractNRedisStackTest + private async Task> CreateData(TimeSeriesCommands ts, string[] keys, int timeBucket) { - public TestMRangeAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } + var tuples = new List(); - private async Task> CreateData(TimeSeriesCommands ts, string[] keys, int timeBucket) + for (var i = 0; i < 10; i++) { - var tuples = new List(); - - for (var i = 0; i < 10; i++) + var timeStamp = new TimeStamp(i * timeBucket); + foreach (var key in keys) { - var timeStamp = new TimeStamp(i * timeBucket); - foreach (var key in keys) - { - await ts.AddAsync(key, timeStamp, i); - } - tuples.Add(new TimeSeriesTuple(timeStamp, i)); + await ts.AddAsync(key, timeStamp, i); } - - return tuples; + tuples.Add(new(timeStamp, i)); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestSimpleMRange(string endpointId) + return tuples; + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestSimpleMRange(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - await ts.CreateAsync(key, labels: labels); - } + await ts.CreateAsync(key, labels: labels); + } - var tuples = await CreateData(ts, keys, 50); - var results = ts.MRange("-", "+", new List { $"{keys[0]}=value" }); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Empty(results[i].labels); - Assert.Equal(tuples, results[i].values); - } + var tuples = await CreateData(ts, keys, 50); + var results = ts.MRange("-", "+", new List { $"{keys[0]}=value" }); + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count; i++) + { + Assert.Equal(keys[i], results[i].key); + Assert.Empty(results[i].labels); + Assert.Equal(tuples, results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRangeWithLabels(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRangeWithLabels(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - await ts.CreateAsync(key, labels: labels); - } + await ts.CreateAsync(key, labels: labels); + } - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Equal(labels, results[i].labels); - Assert.Equal(tuples, results[i].values); - } + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true); + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count; i++) + { + Assert.Equal(keys[i], results[i].key); + Assert.Equal(labels, results[i].labels); + Assert.Equal(tuples, results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRangeSelectLabels(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRangeSelectLabels(string endpointId) + { + var keys = CreateKeyNames(2); + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + TimeSeriesLabel label1 = new(keys[0], "value"); + TimeSeriesLabel[] labels = [new("team", "CTO"), new("team", "AUT")]; + for (int i = 0; i < keys.Length; i++) { - var keys = CreateKeyNames(2); - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - TimeSeriesLabel label1 = new TimeSeriesLabel(keys[0], "value"); - TimeSeriesLabel[] labels = new TimeSeriesLabel[] { new TimeSeriesLabel("team", "CTO"), new TimeSeriesLabel("team", "AUT") }; - for (int i = 0; i < keys.Length; i++) - { - await ts.CreateAsync(keys[i], labels: new List { label1, labels[i] }); - } + await ts.CreateAsync(keys[i], labels: new List { label1, labels[i] }); + } - var tuples = await CreateData(ts, keys, 50); - // selectLabels and withlabels are mutualy exclusive. - var ex = await Assert.ThrowsAsync(async () => - { - await ts.MRangeAsync("-", "+", - new List { "key=MRangeSelectLabels" }, - withLabels: true, selectLabels: new List { "team" }); - }); - Assert.Equal("withLabels and selectLabels cannot be specified together.", ex.Message); + var tuples = await CreateData(ts, keys, 50); + // selectLabels and withlabels are mutualy exclusive. + var ex = await Assert.ThrowsAsync(async () => + { + await ts.MRangeAsync("-", "+", + new List { "key=MRangeSelectLabels" }, + withLabels: true, selectLabels: new List { "team" }); + }); + Assert.Equal("withLabels and selectLabels cannot be specified together.", ex.Message); - var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, selectLabels: new List { "team" }); - Assert.Equal(keys.Length, results.Count); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Equal(labels[i], results[i].labels[0]); - Assert.Equal(tuples, results[i].values); - } + var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, selectLabels: new List { "team" }); + Assert.Equal(keys.Length, results.Count); + for (int i = 0; i < results.Count; i++) + { + Assert.Equal(keys[i], results[i].key); + Assert.Equal(labels[i], results[i].labels[0]); + Assert.Equal(tuples, results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRangeFilter(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRangeFilter(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + await ts.CreateAsync(keys[0], labels: labels); + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }); + Assert.Single(results); + Assert.Equal(keys[0], results[0].key); + Assert.Empty(results[0].labels); + Assert.Equal(tuples, results[0].values); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRangeCount(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - await ts.CreateAsync(keys[0], labels: labels); - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }); - Assert.Single(results); - Assert.Equal(keys[0], results[0].key); - Assert.Empty(results[0].labels); - Assert.Equal(tuples, results[0].values); + await ts.CreateAsync(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRangeCount(string endpointId) + var tuples = await CreateData(ts, keys, 50); + var count = 5L; + var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, count: count); + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - await ts.CreateAsync(key, labels: labels); - } - - var tuples = await CreateData(ts, keys, 50); - var count = 5L; - var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, count: count); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Empty(results[i].labels); - Assert.Equal(tuples.GetRange(0, (int)count), results[i].values); - } + Assert.Equal(keys[i], results[i].key); + Assert.Empty(results[i].labels); + Assert.Equal(tuples.GetRange(0, (int)count), results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRangeAggregation(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRangeAggregation(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - await ts.CreateAsync(key, labels: labels); - } - - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, aggregation: TsAggregation.Min, timeBucket: 50); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Empty(results[i].labels); - Assert.Equal(tuples, results[i].values); - } + await ts.CreateAsync(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRangeAlign(string endpointId) + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, aggregation: TsAggregation.Min, timeBucket: 50); + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - ts.Create(keys[0], labels: labels); - await CreateData(ts, keys, 50); - var expected = new List { - new TimeSeriesTuple(0,1), - new TimeSeriesTuple(50,1), - new TimeSeriesTuple(100,1) - }; - var results = await ts.MRangeAsync(0, "+", new List { $"{keys[0]}=value" }, align: "-", aggregation: TsAggregation.Count, timeBucket: 10, count: 3); - Assert.Single(results); - Assert.Equal(keys[0], results[0].key); - Assert.Equal(expected, results[0].values); - results = await ts.MRangeAsync(0, 500, new List { $"{keys[0]}=value" }, align: "+", aggregation: TsAggregation.Count, timeBucket: 10, count: 1); - Assert.Equal(expected[0], results[0].values[0]); + Assert.Equal(keys[i], results[i].key); + Assert.Empty(results[i].labels); + Assert.Equal(tuples, results[i].values); } + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRangeAlign(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + ts.Create(keys[0], labels: labels); + await CreateData(ts, keys, 50); + var expected = new List { + new(0,1), + new(50,1), + new(100,1) + }; + var results = await ts.MRangeAsync(0, "+", new List { $"{keys[0]}=value" }, align: "-", aggregation: TsAggregation.Count, timeBucket: 10, count: 3); + Assert.Single(results); + Assert.Equal(keys[0], results[0].key); + Assert.Equal(expected, results[0].values); + results = await ts.MRangeAsync(0, 500, new List { $"{keys[0]}=value" }, align: "+", aggregation: TsAggregation.Count, timeBucket: 10, count: 1); + Assert.Equal(expected[0], results[0].values[0]); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMissingFilter(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMissingFilter(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - await ts.CreateAsync(key, labels: labels); - } + await ts.CreateAsync(key, labels: labels); + } + + var tuples = await CreateData(ts, keys, 50); + var ex = await Assert.ThrowsAsync(async () => await ts.MRangeAsync("-", "+", new List())); + Assert.Equal("There should be at least one filter on MRANGE/MREVRANGE", ex.Message); + } - var tuples = await CreateData(ts, keys, 50); - var ex = await Assert.ThrowsAsync(async () => await ts.MRangeAsync("-", "+", new List())); - Assert.Equal("There should be at least one filter on MRANGE/MREVRANGE", ex.Message); + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMissingTimeBucket(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) + { + await ts.CreateAsync(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMissingTimeBucket(string endpointId) + var tuples = await CreateData(ts, keys, 50); + var ex = await Assert.ThrowsAsync(async () => { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - await ts.CreateAsync(key, labels: labels); - } + await ts.MRangeAsync("-", "+", + filter: new List() { $"key=value" }, + aggregation: TsAggregation.Avg); + }); + Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); + } - var tuples = await CreateData(ts, keys, 50); - var ex = await Assert.ThrowsAsync(async () => - { - await ts.MRangeAsync("-", "+", - filter: new List() { $"key=value" }, - aggregation: TsAggregation.Avg); - }); - Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRangeGroupby(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + for (int i = 0; i < keys.Length; i++) + { + var label1 = new TimeSeriesLabel(keys[0], "value"); + var label2 = new TimeSeriesLabel("group", i.ToString()); + await ts.CreateAsync(keys[i], labels: new List { label1, label2 }); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRangeGroupby(string endpointId) + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true, groupbyTuple: ("group", TsReduce.Min)); + Assert.Equal(keys.Length, results.Count); + for (int i = 0; i < results.Count; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - for (int i = 0; i < keys.Length; i++) - { - var label1 = new TimeSeriesLabel(keys[0], "value"); - var label2 = new TimeSeriesLabel("group", i.ToString()); - await ts.CreateAsync(keys[i], labels: new List { label1, label2 }); - } - - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true, groupbyTuple: ("group", TsReduce.Min)); - Assert.Equal(keys.Length, results.Count); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal("group=" + i, results[i].key); - Assert.Equal(new TimeSeriesLabel("group", i.ToString()), results[i].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "min"), results[i].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", keys[i]), results[i].labels[2]); - Assert.Equal(tuples, results[i].values); - } + Assert.Equal("group=" + i, results[i].key); + Assert.Equal(new("group", i.ToString()), results[i].labels[0]); + Assert.Equal(new("__reducer__", "min"), results[i].labels[1]); + Assert.Equal(new("__source__", keys[i]), results[i].labels[2]); + Assert.Equal(tuples, results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRangeReduce(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRangeReduce(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + foreach (var key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - foreach (var key in keys) - { - var label = new TimeSeriesLabel(keys[0], "value"); - await ts.CreateAsync(key, labels: new List { label }); - } + var label = new TimeSeriesLabel(keys[0], "value"); + await ts.CreateAsync(key, labels: new List { label }); + } - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true, groupbyTuple: (keys[0], TsReduce.Sum)); - Assert.Single(results); - Assert.Equal($"{keys[0]}=value", results[0].key); - Assert.Equal(new TimeSeriesLabel(keys[0], "value"), results[0].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "sum"), results[0].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", string.Join(",", keys)), results[0].labels[2]); - for (int i = 0; i < results[0].values.Count; i++) - { - Assert.Equal(tuples[i].Val * 2, results[0].values[i].Val); - } + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true, groupbyTuple: (keys[0], TsReduce.Sum)); + Assert.Single(results); + Assert.Equal($"{keys[0]}=value", results[0].key); + Assert.Equal(new(keys[0], "value"), results[0].labels[0]); + Assert.Equal(new("__reducer__", "sum"), results[0].labels[1]); + Assert.Equal(new("__source__", string.Join(",", keys)), results[0].labels[2]); + for (int i = 0; i < results[0].values.Count; i++) + { + Assert.Equal(tuples[i].Val * 2, results[0].values[i].Val); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRangeFilterBy(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRangeFilterBy(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + TimeSeriesLabel label = new(keys[0], "value"); + var labels = new List { label }; + foreach (string key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - TimeSeriesLabel label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (string key in keys) - { - await ts.CreateAsync(key, labels: labels); - } + await ts.CreateAsync(key, labels: labels); + } - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, filterByValue: (0, 2)); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(tuples.GetRange(0, 3), results[i].values); - } + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, filterByValue: (0, 2)); + for (int i = 0; i < results.Count; i++) + { + Assert.Equal(tuples.GetRange(0, 3), results[i].values); + } - results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, filterByTs: new List { 0 }, filterByValue: (0, 2)); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(tuples.GetRange(0, 1), results[i].values); - } + results = await ts.MRangeAsync("-", "+", new List { $"{keys[0]}=value" }, filterByTs: new List { 0 }, filterByValue: (0, 2)); + for (int i = 0; i < results.Count; i++) + { + Assert.Equal(tuples.GetRange(0, 1), results[i].values); } } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRevRange.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRevRange.cs index 39186562..ddfd4bf2 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRevRange.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRevRange.cs @@ -1,320 +1,316 @@ +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; using StackExchange.Redis; using Xunit; using NRedisStack.RedisStackCommands; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestMRevRange(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestMRevRange : AbstractNRedisStackTest + private List CreateData(ITimeSeriesCommands ts, string[] keys, int timeBucket) { - public TestMRevRange(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } + var tuples = new List(); - private List CreateData(ITimeSeriesCommands ts, string[] keys, int timeBucket) + for (var i = 0; i < 10; i++) { - var tuples = new List(); - - for (var i = 0; i < 10; i++) + var timeStamp = new TimeStamp(i * timeBucket); + foreach (var key in keys) { - var timeStamp = new TimeStamp(i * timeBucket); - foreach (var key in keys) - { - ts.Add(key, timeStamp, i); - } - tuples.Add(new TimeSeriesTuple(timeStamp, i)); + ts.Add(key, timeStamp, i); } - return tuples; + tuples.Add(new(timeStamp, i)); } + return tuples; + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestSimpleMRevRange(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestSimpleMRevRange(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - ts.Create(key, labels: labels); - } + ts.Create(key, labels: labels); + } - var tuples = CreateData(ts, keys, 50); - var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Empty(results[i].labels); - Assert.Equal(ReverseData(tuples), results[i].values); - } + var tuples = CreateData(ts, keys, 50); + var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }); + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count; i++) + { + Assert.Equal(keys[i], results[i].key); + Assert.Empty(results[i].labels); + Assert.Equal(ReverseData(tuples), results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRevRangeWithLabels(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRevRangeWithLabels(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - ts.Create(key, labels: labels); - } + ts.Create(key, labels: labels); + } - var tuples = CreateData(ts, keys, 50); - var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }, withLabels: true); + var tuples = CreateData(ts, keys, 50); + var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }, withLabels: true); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Equal(labels, results[i].labels); - Assert.Equal(ReverseData(tuples), results[i].values); - } + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count; i++) + { + Assert.Equal(keys[i], results[i].key); + Assert.Equal(labels, results[i].labels); + Assert.Equal(ReverseData(tuples), results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRevRangeSelectLabels(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRevRangeSelectLabels(string endpointId) + { + var keys = CreateKeyNames(2); + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + TimeSeriesLabel label1 = new("key", "MRangeSelectLabels"); + TimeSeriesLabel[] labels = [new("team", "CTO"), new("team", "AUT")]; + for (int i = 0; i < keys.Length; i++) { - var keys = CreateKeyNames(2); - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - TimeSeriesLabel label1 = new TimeSeriesLabel("key", "MRangeSelectLabels"); - TimeSeriesLabel[] labels = new TimeSeriesLabel[] { new TimeSeriesLabel("team", "CTO"), new TimeSeriesLabel("team", "AUT") }; - for (int i = 0; i < keys.Length; i++) - { - ts.Create(keys[i], labels: new List { label1, labels[i] }); - } + ts.Create(keys[i], labels: new List { label1, labels[i] }); + } - var tuples = CreateData(ts, keys, 50); - var results = ts.MRevRange("-", "+", new List { "key=MRangeSelectLabels" }, selectLabels: new List { "team" }); - Assert.Equal(keys.Length, results.Count); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Equal(labels[i], results[i].labels[0]); - Assert.Equal(ReverseData(tuples), results[i].values); - } + var tuples = CreateData(ts, keys, 50); + var results = ts.MRevRange("-", "+", new List { "key=MRangeSelectLabels" }, selectLabels: new List { "team" }); + Assert.Equal(keys.Length, results.Count); + for (int i = 0; i < results.Count; i++) + { + Assert.Equal(keys[i], results[i].key); + Assert.Equal(labels[i], results[i].labels[0]); + Assert.Equal(ReverseData(tuples), results[i].values); } + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRevRangeFilter(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + ts.Create(keys[0], labels: labels); + var tuples = CreateData(ts, keys, 50); + var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }); + Assert.Single(results); + Assert.Equal(keys[0], results[0].key); + Assert.Empty(results[0].labels); + Assert.Equal(ReverseData(tuples), results[0].values); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRevRangeFilter(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRevRangeCount(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - ts.Create(keys[0], labels: labels); - var tuples = CreateData(ts, keys, 50); - var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }); - Assert.Single(results); - Assert.Equal(keys[0], results[0].key); - Assert.Empty(results[0].labels); - Assert.Equal(ReverseData(tuples), results[0].values); + ts.Create(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRevRangeCount(string endpointId) + var tuples = CreateData(ts, keys, 50); + var count = 5L; + var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }, count: count); + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - ts.Create(key, labels: labels); - } + Assert.Equal(keys[i], results[i].key); + Assert.Empty(results[i].labels); + Assert.Equal(ReverseData(tuples).GetRange(0, (int)count), results[i].values); + } + } - var tuples = CreateData(ts, keys, 50); - var count = 5L; - var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }, count: count); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Empty(results[i].labels); - Assert.Equal(ReverseData(tuples).GetRange(0, (int)count), results[i].values); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRevRangeAggregation(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) + { + ts.Create(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRevRangeAggregation(string endpointId) + var tuples = CreateData(ts, keys, 50); + var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }, aggregation: TsAggregation.Min, timeBucket: 50); + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - ts.Create(key, labels: labels); - } + Assert.Equal(keys[i], results[i].key); + Assert.Empty(results[i].labels); + Assert.Equal(ReverseData(tuples), results[i].values); + } + } - var tuples = CreateData(ts, keys, 50); - var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }, aggregation: TsAggregation.Min, timeBucket: 50); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Empty(results[i].labels); - Assert.Equal(ReverseData(tuples), results[i].values); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRevRangeAlign(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + ts.Create(keys[0], labels: labels); + CreateData(ts, keys, 50); + var expected = new List { + new(450,1), + new(400,1), + new(350,1) + }; + var results = ts.MRevRange(0, "+", new List { $"{keys[0]}=value" }, align: "-", aggregation: TsAggregation.Count, timeBucket: 10, count: 3); + Assert.Single(results); + Assert.Equal(keys[0], results[0].key); + Assert.Equal(expected, results[0].values); + results = ts.MRevRange(0, 500, new List { $"{keys[0]}=value" }, align: "+", aggregation: TsAggregation.Count, timeBucket: 10, count: 1); + Assert.Equal(expected[0], results[0].values[0]); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMissingFilter(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) + { + ts.Create(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRevRangeAlign(string endpointId) + var tuples = CreateData(ts, keys, 50); + var ex = Assert.Throws(() => ts.MRevRange("-", "+", new List())); + Assert.Equal("There should be at least one filter on MRANGE/MREVRANGE", ex.Message); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMissingTimeBucket(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - ts.Create(keys[0], labels: labels); - CreateData(ts, keys, 50); - var expected = new List { - new TimeSeriesTuple(450,1), - new TimeSeriesTuple(400,1), - new TimeSeriesTuple(350,1) - }; - var results = ts.MRevRange(0, "+", new List { $"{keys[0]}=value" }, align: "-", aggregation: TsAggregation.Count, timeBucket: 10, count: 3); - Assert.Single(results); - Assert.Equal(keys[0], results[0].key); - Assert.Equal(expected, results[0].values); - results = ts.MRevRange(0, 500, new List { $"{keys[0]}=value" }, align: "+", aggregation: TsAggregation.Count, timeBucket: 10, count: 1); - Assert.Equal(expected[0], results[0].values[0]); + ts.Create(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMissingFilter(string endpointId) + var tuples = CreateData(ts, keys, 50); + var ex = Assert.Throws(() => ts.MRevRange("-", "+", new List { "key=MissingTimeBucket" }, aggregation: TsAggregation.Avg)); + Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRevRangeGroupby(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + for (int i = 0; i < keys.Length; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - ts.Create(key, labels: labels); - } + var label1 = new TimeSeriesLabel(keys[0], "value"); + var label2 = new TimeSeriesLabel("group", i.ToString()); + ts.Create(keys[i], labels: new List { label1, label2 }); + } - var tuples = CreateData(ts, keys, 50); - var ex = Assert.Throws(() => ts.MRevRange("-", "+", new List())); - Assert.Equal("There should be at least one filter on MRANGE/MREVRANGE", ex.Message); + var tuples = CreateData(ts, keys, 50); + var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }, withLabels: true, groupbyTuple: ("group", TsReduce.Min)); + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count; i++) + { + Assert.Equal("group=" + i, results[i].key); + Assert.Equal(new("group", i.ToString()), results[i].labels[0]); + Assert.Equal(new("__reducer__", "min"), results[i].labels[1]); + Assert.Equal(new("__source__", keys[i]), results[i].labels[2]); + Assert.Equal(ReverseData(tuples), results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMissingTimeBucket(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRevRangeReduce(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + foreach (var key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - ts.Create(key, labels: labels); - } - - var tuples = CreateData(ts, keys, 50); - var ex = Assert.Throws(() => ts.MRevRange("-", "+", new List { "key=MissingTimeBucket" }, aggregation: TsAggregation.Avg)); - Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); + ts.Create(key, labels: new List { label }); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRevRangeGroupby(string endpointId) + var tuples = CreateData(ts, keys, 50); + var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }, withLabels: true, groupbyTuple: (keys[0], TsReduce.Sum)); + Assert.Single(results); + Assert.Equal($"{keys[0]}=value", results[0].key); + Assert.Equal(new(keys[0], "value"), results[0].labels[0]); + Assert.Equal(new("__reducer__", "sum"), results[0].labels[1]); + Assert.Equal(new("__source__", string.Join(",", keys)), results[0].labels[2]); + tuples = ReverseData(tuples); + for (int i = 0; i < results[0].values.Count; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - for (int i = 0; i < keys.Length; i++) - { - var label1 = new TimeSeriesLabel(keys[0], "value"); - var label2 = new TimeSeriesLabel("group", i.ToString()); - ts.Create(keys[i], labels: new List { label1, label2 }); - } - - var tuples = CreateData(ts, keys, 50); - var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }, withLabels: true, groupbyTuple: ("group", TsReduce.Min)); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count; i++) - { - Assert.Equal("group=" + i, results[i].key); - Assert.Equal(new TimeSeriesLabel("group", i.ToString()), results[i].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "min"), results[i].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", keys[i]), results[i].labels[2]); - Assert.Equal(ReverseData(tuples), results[i].values); - } + Assert.Equal(tuples[i].Val * 2, results[0].values[i].Val); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRevRangeReduce(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMRevRangeFilterBy(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (string key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - foreach (var key in keys) - { - var label = new TimeSeriesLabel(keys[0], "value"); - ts.Create(key, labels: new List { label }); - } - - var tuples = CreateData(ts, keys, 50); - var results = ts.MRevRange("-", "+", new List { $"{keys[0]}=value" }, withLabels: true, groupbyTuple: (keys[0], TsReduce.Sum)); - Assert.Single(results); - Assert.Equal($"{keys[0]}=value", results[0].key); - Assert.Equal(new TimeSeriesLabel(keys[0], "value"), results[0].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "sum"), results[0].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", string.Join(",", keys)), results[0].labels[2]); - tuples = ReverseData(tuples); - for (int i = 0; i < results[0].values.Count; i++) - { - Assert.Equal(tuples[i].Val * 2, results[0].values[i].Val); - } + ts.Create(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMRevRangeFilterBy(string endpointId) + var tuples = CreateData(ts, keys, 50); + var results = ts.MRevRange("-", "+", new List { "key=MRangeFilterBy" }, filterByValue: (0, 2)); + for (int i = 0; i < results.Count; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (string key in keys) - { - ts.Create(key, labels: labels); - } - - var tuples = CreateData(ts, keys, 50); - var results = ts.MRevRange("-", "+", new List { "key=MRangeFilterBy" }, filterByValue: (0, 2)); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(ReverseData(tuples.GetRange(0, 3)), results[i].values); - } + Assert.Equal(ReverseData(tuples.GetRange(0, 3)), results[i].values); + } - results = ts.MRevRange("-", "+", new List { "key=MRangeFilterBy" }, filterByTs: new List { 0 }, filterByValue: (0, 2)); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(ReverseData(tuples.GetRange(0, 1)), results[i].values); - } + results = ts.MRevRange("-", "+", new List { "key=MRangeFilterBy" }, filterByTs: new List { 0 }, filterByValue: (0, 2)); + for (int i = 0; i < results.Count; i++) + { + Assert.Equal(ReverseData(tuples.GetRange(0, 1)), results[i].values); } } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRevRangeAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRevRangeAsync.cs index 0ac01910..ea99dbbc 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRevRangeAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestMRevRangeAsync.cs @@ -1,325 +1,321 @@ +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using StackExchange.Redis; using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; using Xunit; using NRedisStack.RedisStackCommands; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestMRevRangeAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestMRevRangeAsync : AbstractNRedisStackTest + private async Task> CreateData(TimeSeriesCommands ts, string[] keys, int timeBucket) { - public TestMRevRangeAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } + var tuples = new List(); - private async Task> CreateData(TimeSeriesCommands ts, string[] keys, int timeBucket) + for (var i = 0; i < 10; i++) { - var tuples = new List(); - - for (var i = 0; i < 10; i++) + var timeStamp = new TimeStamp(i * timeBucket); + foreach (var key in keys) { - var timeStamp = new TimeStamp(i * timeBucket); - foreach (var key in keys) - { - await ts.AddAsync(key, timeStamp, i); - } - tuples.Add(new TimeSeriesTuple(timeStamp, i)); + await ts.AddAsync(key, timeStamp, i); } - - return tuples; + tuples.Add(new(timeStamp, i)); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestSimpleMRevRange(string endpointId) - { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - await ts.CreateAsync(key, labels: labels); - } + return tuples; + } - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Empty(results[i].labels); - Assert.Equal(ReverseData(tuples), results[i].values); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestSimpleMRevRange(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) + { + await ts.CreateAsync(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRevRangeWithLabels(string endpointId) + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }); + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - await ts.CreateAsync(key, labels: labels); - } - - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Equal(labels, results[i].labels); - Assert.Equal(ReverseData(tuples), results[i].values); - } + Assert.Equal(keys[i], results[i].key); + Assert.Empty(results[i].labels); + Assert.Equal(ReverseData(tuples), results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRevRangeSelectLabels(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRevRangeWithLabels(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) { - var keys = CreateKeyNames(2); - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - TimeSeriesLabel label1 = new TimeSeriesLabel(keys[0], "value"); - TimeSeriesLabel[] labels = new TimeSeriesLabel[] { new TimeSeriesLabel("team", "CTO"), new TimeSeriesLabel("team", "AUT") }; - for (int i = 0; i < keys.Length; i++) - { - await ts.CreateAsync(keys[i], labels: new List { label1, labels[i] }); - } + await ts.CreateAsync(key, labels: labels); + } - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, selectLabels: new List { "team" }); - Assert.Equal(keys.Length, results.Count); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Equal(labels[i], results[i].labels[0]); - Assert.Equal(ReverseData(tuples), results[i].values); - } + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true); + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count; i++) + { + Assert.Equal(keys[i], results[i].key); + Assert.Equal(labels, results[i].labels); + Assert.Equal(ReverseData(tuples), results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRevRangeFilter(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRevRangeSelectLabels(string endpointId) + { + var keys = CreateKeyNames(2); + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + TimeSeriesLabel label1 = new(keys[0], "value"); + TimeSeriesLabel[] labels = [new("team", "CTO"), new("team", "AUT")]; + for (int i = 0; i < keys.Length; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - await ts.CreateAsync(keys[0], labels: labels); - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }); - Assert.Single(results); - Assert.Equal(keys[0], results[0].key); - Assert.Empty(results[0].labels); - Assert.Equal(ReverseData(tuples), results[0].values); + await ts.CreateAsync(keys[i], labels: new List { label1, labels[i] }); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRevRangeCount(string endpointId) + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, selectLabels: new List { "team" }); + Assert.Equal(keys.Length, results.Count); + for (int i = 0; i < results.Count; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - await ts.CreateAsync(key, labels: labels); - } + Assert.Equal(keys[i], results[i].key); + Assert.Equal(labels[i], results[i].labels[0]); + Assert.Equal(ReverseData(tuples), results[i].values); + } + } - var tuples = await CreateData(ts, keys, 50); - var count = 5L; - var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, count: count); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Empty(results[i].labels); - Assert.Equal(ReverseData(tuples).GetRange(0, (int)count), results[i].values); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRevRangeFilter(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + await ts.CreateAsync(keys[0], labels: labels); + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }); + Assert.Single(results); + Assert.Equal(keys[0], results[0].key); + Assert.Empty(results[0].labels); + Assert.Equal(ReverseData(tuples), results[0].values); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRevRangeCount(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) + { + await ts.CreateAsync(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRangeAggregation(string endpointId) + var tuples = await CreateData(ts, keys, 50); + var count = 5L; + var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, count: count); + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - await ts.CreateAsync(key, labels: labels); - } + Assert.Equal(keys[i], results[i].key); + Assert.Empty(results[i].labels); + Assert.Equal(ReverseData(tuples).GetRange(0, (int)count), results[i].values); + } + } - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, aggregation: TsAggregation.Min, timeBucket: 50); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count; i++) - { - Assert.Equal(keys[i], results[i].key); - Assert.Empty(results[i].labels); - Assert.Equal(ReverseData(tuples), results[i].values); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRangeAggregation(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) + { + await ts.CreateAsync(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRevRangeAlign(string endpointId) + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, aggregation: TsAggregation.Min, timeBucket: 50); + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - ts.Create(keys[0], labels: labels); - await CreateData(ts, keys, 50); - var expected = new List { - new TimeSeriesTuple(450,1), - new TimeSeriesTuple(400,1), - new TimeSeriesTuple(350,1) - }; - var results = await ts.MRevRangeAsync(0, "+", new List { $"{keys[0]}=value" }, align: "-", aggregation: TsAggregation.Count, timeBucket: 10, count: 3); - Assert.Single(results); - Assert.Equal(keys[0], results[0].key); - Assert.Equal(expected, results[0].values); - results = await ts.MRevRangeAsync(0, 500, new List { $"{keys[0]}=value" }, align: "+", aggregation: TsAggregation.Count, timeBucket: 10, count: 1); - Assert.Equal(expected[0], results[0].values[0]); + Assert.Equal(keys[i], results[i].key); + Assert.Empty(results[i].labels); + Assert.Equal(ReverseData(tuples), results[i].values); } + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRevRangeAlign(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + ts.Create(keys[0], labels: labels); + await CreateData(ts, keys, 50); + var expected = new List { + new(450,1), + new(400,1), + new(350,1) + }; + var results = await ts.MRevRangeAsync(0, "+", new List { $"{keys[0]}=value" }, align: "-", aggregation: TsAggregation.Count, timeBucket: 10, count: 3); + Assert.Single(results); + Assert.Equal(keys[0], results[0].key); + Assert.Equal(expected, results[0].values); + results = await ts.MRevRangeAsync(0, 500, new List { $"{keys[0]}=value" }, align: "+", aggregation: TsAggregation.Count, timeBucket: 10, count: 1); + Assert.Equal(expected[0], results[0].values[0]); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMissingFilter(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMissingFilter(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - await ts.CreateAsync(key, labels: labels); - } + await ts.CreateAsync(key, labels: labels); + } - var tuples = await CreateData(ts, keys, 50); - var ex = await Assert.ThrowsAsync(async () => await ts.MRevRangeAsync("-", "+", new List())); - Assert.Equal("There should be at least one filter on MRANGE/MREVRANGE", ex.Message); + var tuples = await CreateData(ts, keys, 50); + var ex = await Assert.ThrowsAsync(async () => await ts.MRevRangeAsync("-", "+", new List())); + Assert.Equal("There should be at least one filter on MRANGE/MREVRANGE", ex.Message); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMissingTimeBucket(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label = new TimeSeriesLabel(keys[0], "value"); + var labels = new List { label }; + foreach (var key in keys) + { + await ts.CreateAsync(key, labels: labels); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMissingTimeBucket(string endpointId) + var tuples = await CreateData(ts, keys, 50); + var ex = await Assert.ThrowsAsync(async () => { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (var key in keys) - { - await ts.CreateAsync(key, labels: labels); - } + await ts.MRevRangeAsync("-", "+", + filter: new List() { $"key=value" }, + aggregation: TsAggregation.Avg); + }); + Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); + } - var tuples = await CreateData(ts, keys, 50); - var ex = await Assert.ThrowsAsync(async () => - { - await ts.MRevRangeAsync("-", "+", - filter: new List() { $"key=value" }, - aggregation: TsAggregation.Avg); - }); - Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRevRangeGroupby(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + for (int i = 0; i < keys.Length; i++) + { + var label1 = new TimeSeriesLabel(keys[0], "value"); + var label2 = new TimeSeriesLabel("group", i.ToString()); + await ts.CreateAsync(keys[i], labels: new List { label1, label2 }); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRevRangeGroupby(string endpointId) + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true, groupbyTuple: ("group", TsReduce.Min)); + Assert.Equal(keys.Length, results.Count); + for (var i = 0; i < results.Count && i < results[i].labels.Count; i++) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - for (int i = 0; i < keys.Length; i++) - { - var label1 = new TimeSeriesLabel(keys[0], "value"); - var label2 = new TimeSeriesLabel("group", i.ToString()); - await ts.CreateAsync(keys[i], labels: new List { label1, label2 }); - } - - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true, groupbyTuple: ("group", TsReduce.Min)); - Assert.Equal(keys.Length, results.Count); - for (var i = 0; i < results.Count && i < results[i].labels.Count; i++) - { - Assert.Equal("group=" + i, results[i].key); - Assert.Equal(new TimeSeriesLabel("group", i.ToString()), results[i].labels[0]); - Assert.Equal(new TimeSeriesLabel("__reducer__", "min"), results[i].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", keys[i]), results[i].labels[2]); - Assert.Equal(ReverseData(tuples), results[i].values); - } + Assert.Equal("group=" + i, results[i].key); + Assert.Equal(new("group", i.ToString()), results[i].labels[0]); + Assert.Equal(new("__reducer__", "min"), results[i].labels[1]); + Assert.Equal(new("__source__", keys[i]), results[i].labels[2]); + Assert.Equal(ReverseData(tuples), results[i].values); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRevRangeReduce(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRevRangeReduce(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + foreach (var key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - foreach (var key in keys) - { - var label = new TimeSeriesLabel(keys[0], "value"); - await ts.CreateAsync(key, labels: new List { label }); - } + var label = new TimeSeriesLabel(keys[0], "value"); + await ts.CreateAsync(key, labels: new List { label }); + } - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true, groupbyTuple: (keys[0], TsReduce.Sum)); - Assert.Single(results); - Assert.Equal($"{keys[0]}=value", results[0].key); - Assert.Equal(new TimeSeriesLabel(keys[0], "value"), results[0].labels.FirstOrDefault()); - Assert.Equal(new TimeSeriesLabel("__reducer__", "sum"), results[0].labels[1]); - Assert.Equal(new TimeSeriesLabel("__source__", string.Join(",", keys)), results[0].labels[2]); - tuples = ReverseData(tuples); - for (int i = 0; i < results[0].values.Count; i++) - { - Assert.Equal(tuples[i].Val * 2, results[0].values[i].Val); - } + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, withLabels: true, groupbyTuple: (keys[0], TsReduce.Sum)); + Assert.Single(results); + Assert.Equal($"{keys[0]}=value", results[0].key); + Assert.Equal(new(keys[0], "value"), results[0].labels.FirstOrDefault()); + Assert.Equal(new("__reducer__", "sum"), results[0].labels[1]); + Assert.Equal(new("__source__", string.Join(",", keys)), results[0].labels[2]); + tuples = ReverseData(tuples); + for (int i = 0; i < results[0].values.Count; i++) + { + Assert.Equal(tuples[i].Val * 2, results[0].values[i].Val); } + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMRevRangeFilterBy(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMRevRangeFilterBy(string endpointId) + { + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + TimeSeriesLabel label = new(keys[0], "value"); + var labels = new List { label }; + foreach (string key in keys) { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - TimeSeriesLabel label = new TimeSeriesLabel(keys[0], "value"); - var labels = new List { label }; - foreach (string key in keys) - { - await ts.CreateAsync(key, labels: labels); - } + await ts.CreateAsync(key, labels: labels); + } - var tuples = await CreateData(ts, keys, 50); - var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, filterByValue: (0, 2)); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(ReverseData(tuples.GetRange(0, 3)), results[i].values); - } + var tuples = await CreateData(ts, keys, 50); + var results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, filterByValue: (0, 2)); + for (int i = 0; i < results.Count; i++) + { + Assert.Equal(ReverseData(tuples.GetRange(0, 3)), results[i].values); + } - results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, filterByTs: new List { 0 }, filterByValue: (0, 2)); - for (int i = 0; i < results.Count; i++) - { - Assert.Equal(ReverseData(tuples.GetRange(0, 1)), results[i].values); - } + results = await ts.MRevRangeAsync("-", "+", new List { $"{keys[0]}=value" }, filterByTs: new List { 0 }, filterByValue: (0, 2)); + for (int i = 0; i < results.Count; i++) + { + Assert.Equal(ReverseData(tuples.GetRange(0, 1)), results[i].values); } } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestQueryIndex.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestQueryIndex.cs index b19dfea1..ec3413dd 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestQueryIndex.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestQueryIndex.cs @@ -1,32 +1,28 @@ -using NRedisStack.DataTypes; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods +using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI -{ - public class TestQueryIndex : AbstractNRedisStackTest, IDisposable - { - private readonly string[] keys = { "QUERYINDEX_TESTS_1", "QUERYINDEX_TESTS_2" }; +namespace NRedisStack.Tests.TimeSeries.TestAPI; - public TestQueryIndex(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } +public class TestQueryIndex(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable +{ + private readonly string[] keys = ["QUERYINDEX_TESTS_1", "QUERYINDEX_TESTS_2"]; - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestTSQueryIndex(string endpointId) - { - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label1 = new TimeSeriesLabel("QUERYINDEX_TESTS_1", "value"); - var label2 = new TimeSeriesLabel("QUERYINDEX_TESTS_2", "value2"); - var labels1 = new List { label1, label2 }; - var labels2 = new List { label1 }; + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestTSQueryIndex(string endpointId) + { + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label1 = new TimeSeriesLabel("QUERYINDEX_TESTS_1", "value"); + var label2 = new TimeSeriesLabel("QUERYINDEX_TESTS_2", "value2"); + var labels1 = new List { label1, label2 }; + var labels2 = new List { label1 }; - ts.Create(keys[0], labels: labels1); - ts.Create(keys[1], labels: labels2); - Assert.Equal(keys, ts.QueryIndex(new List { "QUERYINDEX_TESTS_1=value" })); - Assert.Equal(new List { keys[0] }, ts.QueryIndex(new List { "QUERYINDEX_TESTS_2=value2" })); - } + ts.Create(keys[0], labels: labels1); + ts.Create(keys[1], labels: labels2); + Assert.Equal(keys, ts.QueryIndex(new List { "QUERYINDEX_TESTS_1=value" })); + Assert.Equal(new List { keys[0] }, ts.QueryIndex(new List { "QUERYINDEX_TESTS_2=value2" })); } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestQueryIndexAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestQueryIndexAsync.cs index 8a4a7b30..b48079c3 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestQueryIndexAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestQueryIndexAsync.cs @@ -1,31 +1,27 @@ -using NRedisStack.DataTypes; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods +using NRedisStack.DataTypes; using NRedisStack.RedisStackCommands; using Xunit; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestQueryIndexAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestQueryIndexAsync : AbstractNRedisStackTest + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestTSQueryIndex(string endpointId) { - public TestQueryIndexAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } - - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestTSQueryIndex(string endpointId) - { - var keys = CreateKeyNames(2); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var label1 = new TimeSeriesLabel(keys[0], "value"); - var label2 = new TimeSeriesLabel(keys[1], "value2"); - var labels1 = new List { label1, label2 }; - var labels2 = new List { label1 }; + var keys = CreateKeyNames(2); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var label1 = new TimeSeriesLabel(keys[0], "value"); + var label2 = new TimeSeriesLabel(keys[1], "value2"); + var labels1 = new List { label1, label2 }; + var labels2 = new List { label1 }; - await ts.CreateAsync(keys[0], labels: labels1); - await ts.CreateAsync(keys[1], labels: labels2); - Assert.Equal(keys, ts.QueryIndex(new List { $"{keys[0]}=value" })); - Assert.Equal(new List { keys[0] }, ts.QueryIndex(new List { $"{keys[1]}=value2" })); - } + await ts.CreateAsync(keys[0], labels: labels1); + await ts.CreateAsync(keys[1], labels: labels2); + Assert.Equal(keys, ts.QueryIndex(new List { $"{keys[0]}=value" })); + Assert.Equal(new List { keys[0] }, ts.QueryIndex(new List { $"{keys[1]}=value2" })); } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRange.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRange.cs index 8531c6bf..8f1d27ac 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRange.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRange.cs @@ -1,284 +1,280 @@ -using NRedisStack.Literals.Enums; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods +using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; using StackExchange.Redis; using Xunit; using NRedisStack.RedisStackCommands; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestRange(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable { - public class TestRange : AbstractNRedisStackTest, IDisposable - { - private readonly string key = "RANGE_TESTS"; + private readonly string key = "RANGE_TESTS"; - public TestRange(EndpointsFixture endpointsFixture) : base(endpointsFixture) + private List CreateData(ITimeSeriesCommands ts, int timeBucket) + { + var tuples = new List(); + for (int i = 0; i < 10; i++) { + TimeStamp timeStamp = ts.Add(key, i * timeBucket, i); + tuples.Add(new(timeStamp, i)); } + return tuples; + } - private List CreateData(ITimeSeriesCommands ts, int timeBucket) - { - var tuples = new List(); - for (int i = 0; i < 10; i++) - { - TimeStamp timeStamp = ts.Add(key, i * timeBucket, i); - tuples.Add(new TimeSeriesTuple(timeStamp, i)); - } - return tuples; - } + [Fact] + public void TestSimpleRange() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var tuples = CreateData(ts, 50); + Assert.Equal(tuples, ts.Range(key, "-", "+")); + } - [Fact] - public void TestSimpleRange() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var tuples = CreateData(ts, 50); - Assert.Equal(tuples, ts.Range(key, "-", "+")); - } + [Fact] + public void TestRangeCount() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var tuples = CreateData(ts, 50); + Assert.Equal(tuples.GetRange(0, 5), ts.Range(key, "-", "+", count: 5)); + } - [Fact] - public void TestRangeCount() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var tuples = CreateData(ts, 50); - Assert.Equal(tuples.GetRange(0, 5), ts.Range(key, "-", "+", count: 5)); - } + [Fact] + public void TestRangeAggregation() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var tuples = CreateData(ts, 50); + Assert.Equal(tuples, ts.Range(key, "-", "+", aggregation: TsAggregation.Min, timeBucket: 50)); + } - [Fact] - public void TestRangeAggregation() + [Fact] + public void TestRangeAlign() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var tuples = new List() { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var tuples = CreateData(ts, 50); - Assert.Equal(tuples, ts.Range(key, "-", "+", aggregation: TsAggregation.Min, timeBucket: 50)); - } + new(1, 10), + new(3, 5), + new(11, 10), + new(21, 11) + }; - [Fact] - public void TestRangeAlign() + foreach (var tuple in tuples) { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var tuples = new List() - { - new TimeSeriesTuple(1, 10), - new TimeSeriesTuple(3, 5), - new TimeSeriesTuple(11, 10), - new TimeSeriesTuple(21, 11) - }; - - foreach (var tuple in tuples) - { - ts.Add(key, tuple.Time, tuple.Val); - } - - // Aligh start - var resStart = new List() - { - new TimeSeriesTuple(1, 2), - new TimeSeriesTuple(11, 1), - new TimeSeriesTuple(21, 1) - }; - Assert.Equal(resStart, ts.Range(key, 1, 30, align: "-", aggregation: TsAggregation.Count, timeBucket: 10)); - - // Aligh end - var resEnd = new List() - { - new TimeSeriesTuple(0, 2), - new TimeSeriesTuple(10, 1), - new TimeSeriesTuple(20, 1) - }; - Assert.Equal(resEnd, ts.Range(key, 1, 30, align: "+", aggregation: TsAggregation.Count, timeBucket: 10)); - - // Align 1 - Assert.Equal(resStart, ts.Range(key, 1, 30, align: 1, aggregation: TsAggregation.Count, timeBucket: 10)); + ts.Add(key, tuple.Time, tuple.Val); } - [Fact] - public void TestMissingTimeBucket() + // Aligh start + var resStart = new List() { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var tuples = CreateData(ts, 50); - var ex = Assert.Throws(() => ts.Range(key, "-", "+", aggregation: TsAggregation.Avg)); - Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); - } - - [Fact] - public void TestFilterBy() + new(1, 2), + new(11, 1), + new(21, 1) + }; + Assert.Equal(resStart, ts.Range(key, 1, 30, align: "-", aggregation: TsAggregation.Count, timeBucket: 10)); + + // Aligh end + var resEnd = new List() { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var tuples = CreateData(ts, 50); + new(0, 2), + new(10, 1), + new(20, 1) + }; + Assert.Equal(resEnd, ts.Range(key, 1, 30, align: "+", aggregation: TsAggregation.Count, timeBucket: 10)); + + // Align 1 + Assert.Equal(resStart, ts.Range(key, 1, 30, align: 1, aggregation: TsAggregation.Count, timeBucket: 10)); + } - var res = ts.Range(key, "-", "+", filterByValue: (0, 2)); // The first 3 tuples - Assert.Equal(3, res.Count); - Assert.Equal(tuples.GetRange(0, 3), res); + [Fact] + public void TestMissingTimeBucket() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var tuples = CreateData(ts, 50); + var ex = Assert.Throws(() => ts.Range(key, "-", "+", aggregation: TsAggregation.Avg)); + Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); + } - var filterTs = new List { 0, 50, 100 }; // Also the first 3 tuples - res = ts.Range(key, "-", "+", filterByTs: filterTs); - Assert.Equal(tuples.GetRange(0, 3), res); + [Fact] + public void TestFilterBy() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var tuples = CreateData(ts, 50); - res = ts.Range(key, "-", "+", filterByTs: filterTs, filterByValue: (2, 5)); // The third tuple - Assert.Equal(tuples.GetRange(2, 1), res); - } + var res = ts.Range(key, "-", "+", filterByValue: (0, 2)); // The first 3 tuples + Assert.Equal(3, res.Count); + Assert.Equal(tuples.GetRange(0, 3), res); - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void latest(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - ts.Create("ts1"); - ts.Create("ts2"); - ts.CreateRule("ts1", new TimeSeriesRule("ts2", 10, TsAggregation.Sum)); - ts.Add("ts1", 1, 1); - ts.Add("ts1", 2, 3); - ts.Add("ts1", 11, 7); - ts.Add("ts1", 13, 1); - var range = ts.Range("ts1", 0, 20); - Assert.Equal(4, range.Count); + var filterTs = new List { 0, 50, 100 }; // Also the first 3 tuples + res = ts.Range(key, "-", "+", filterByTs: filterTs); + Assert.Equal(tuples.GetRange(0, 3), res); - var compact = new TimeSeriesTuple(0, 4); - var latest = new TimeSeriesTuple(10, 8); + res = ts.Range(key, "-", "+", filterByTs: filterTs, filterByValue: (2, 5)); // The third tuple + Assert.Equal(tuples.GetRange(2, 1), res); + } - // get - Assert.Equal(compact, ts.Get("ts2")); + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void latest(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + ts.Create("ts1"); + ts.Create("ts2"); + ts.CreateRule("ts1", new("ts2", 10, TsAggregation.Sum)); + ts.Add("ts1", 1, 1); + ts.Add("ts1", 2, 3); + ts.Add("ts1", 11, 7); + ts.Add("ts1", 13, 1); + var range = ts.Range("ts1", 0, 20); + Assert.Equal(4, range.Count); - Assert.Equal(latest, ts.Get("ts2", true)); + var compact = new TimeSeriesTuple(0, 4); + var latest = new TimeSeriesTuple(10, 8); - // range - Assert.Equal(new List() { compact }, ts.Range("ts2", 0, 10)); + // get + Assert.Equal(compact, ts.Get("ts2")); - Assert.Equal(new List() { compact, latest }, ts.Range("ts2", 0, 10, true)); + Assert.Equal(latest, ts.Get("ts2", true)); - // revrange - Assert.Equal(new List() { compact }, ts.RevRange("ts2", 0, 10)); + // range + Assert.Equal(new List() { compact }, ts.Range("ts2", 0, 10)); - Assert.Equal(new List() { latest, compact }, ts.RevRange("ts2", 0, 10, true)); - } + Assert.Equal(new List() { compact, latest }, ts.Range("ts2", 0, 10, true)); - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestAlignTimestamp(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - ts.Create("ts1"); - ts.Create("ts2"); - ts.Create("ts3"); - ts.CreateRule("ts1", new TimeSeriesRule("ts2", 10, TsAggregation.Count), 0); - ts.CreateRule("ts1", new TimeSeriesRule("ts3", 10, TsAggregation.Count), 1); - ts.Add("ts1", 1, 1); - ts.Add("ts1", 10, 3); - ts.Add("ts1", 21, 7); - Assert.Equal(2, ts.Range("ts2", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10).Count); - Assert.Single(ts.Range("ts3", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10)); - } + // revrange + Assert.Equal(new List() { compact }, ts.RevRange("ts2", 0, 10)); - [Fact] - public void TestBucketTimestamp() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - - ts.Create("t1"); - - ts.Add("t1", 15, 1); - ts.Add("t1", 17, 4); - ts.Add("t1", 51, 3); - ts.Add("t1", 73, 5); - ts.Add("t1", 75, 3); - - var rangeHigh = ts.Range("t1", 0, 100, - align: 0, - aggregation: TsAggregation.Max, - timeBucket: 10); - - var expected = new List(); - expected.Add(new TimeSeriesTuple(10, 4.0)); - expected.Add(new TimeSeriesTuple(50, 3.0)); - expected.Add(new TimeSeriesTuple(70, 5.0)); - Assert.Equal(rangeHigh, expected); - - rangeHigh = ts.Range("t1", 0, 100, - align: 0, - aggregation: TsAggregation.Max, - timeBucket: 10, - bt: TsBucketTimestamps.high); - expected.Clear(); - expected.Add(new TimeSeriesTuple(20, 4.0)); - expected.Add(new TimeSeriesTuple(60, 3.0)); - expected.Add(new TimeSeriesTuple(80, 5.0)); - Assert.Equal(rangeHigh, expected); - - var rangeLow = ts.Range("t1", 0, 100, - align: 0, - aggregation: TsAggregation.Max, - timeBucket: 10, - bt: TsBucketTimestamps.low); - expected.Clear(); - expected.Add(new TimeSeriesTuple(10, 4.0)); - expected.Add(new TimeSeriesTuple(50, 3.0)); - expected.Add(new TimeSeriesTuple(70, 5.0)); - Assert.Equal(rangeLow, expected); - - var rangeMid = ts.Range("t1", 0, 100, - align: 0, - aggregation: TsAggregation.Max, - timeBucket: 10, - bt: TsBucketTimestamps.mid); - expected.Clear(); - expected.Add(new TimeSeriesTuple(15, 4.0)); - expected.Add(new TimeSeriesTuple(55, 3.0)); - expected.Add(new TimeSeriesTuple(75, 5.0)); - Assert.Equal(rangeMid, expected); - } + Assert.Equal(new List() { latest, compact }, ts.RevRange("ts2", 0, 10, true)); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestAlignTimestamp(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + ts.Create("ts1"); + ts.Create("ts2"); + ts.Create("ts3"); + ts.CreateRule("ts1", new("ts2", 10, TsAggregation.Count), 0); + ts.CreateRule("ts1", new("ts3", 10, TsAggregation.Count), 1); + ts.Add("ts1", 1, 1); + ts.Add("ts1", 10, 3); + ts.Add("ts1", 21, 7); + Assert.Equal(2, ts.Range("ts2", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10).Count); + Assert.Single(ts.Range("ts3", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10)); + } - [Fact] - public void TestEmpty() + [Fact] + public void TestBucketTimestamp() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + + ts.Create("t1"); + + ts.Add("t1", 15, 1); + ts.Add("t1", 17, 4); + ts.Add("t1", 51, 3); + ts.Add("t1", 73, 5); + ts.Add("t1", 75, 3); + + var rangeHigh = ts.Range("t1", 0, 100, + align: 0, + aggregation: TsAggregation.Max, + timeBucket: 10); + + var expected = new List(); + expected.Add(new(10, 4.0)); + expected.Add(new(50, 3.0)); + expected.Add(new(70, 5.0)); + Assert.Equal(rangeHigh, expected); + + rangeHigh = ts.Range("t1", 0, 100, + align: 0, + aggregation: TsAggregation.Max, + timeBucket: 10, + bt: TsBucketTimestamps.high); + expected.Clear(); + expected.Add(new(20, 4.0)); + expected.Add(new(60, 3.0)); + expected.Add(new(80, 5.0)); + Assert.Equal(rangeHigh, expected); + + var rangeLow = ts.Range("t1", 0, 100, + align: 0, + aggregation: TsAggregation.Max, + timeBucket: 10, + bt: TsBucketTimestamps.low); + expected.Clear(); + expected.Add(new(10, 4.0)); + expected.Add(new(50, 3.0)); + expected.Add(new(70, 5.0)); + Assert.Equal(rangeLow, expected); + + var rangeMid = ts.Range("t1", 0, 100, + align: 0, + aggregation: TsAggregation.Max, + timeBucket: 10, + bt: TsBucketTimestamps.mid); + expected.Clear(); + expected.Add(new(15, 4.0)); + expected.Add(new(55, 3.0)); + expected.Add(new(75, 5.0)); + Assert.Equal(rangeMid, expected); + } + + [Fact] + public void TestEmpty() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + + ts.Create("t1"); + + ts.Add("t1", 15, 1); + ts.Add("t1", 17, 4); + ts.Add("t1", 51, 3); + ts.Add("t1", 73, 5); + ts.Add("t1", 75, 3); + + var range = ts.Range("t1", 0, 100, + align: 0, + aggregation: TsAggregation.Max, + timeBucket: 10); + + var expected = new List(); + expected.Add(new(10, 4.0)); + expected.Add(new(50, 3.0)); + expected.Add(new(70, 5.0)); + Assert.Equal(range, expected); + + range = ts.Range("t1", 0, 100, + align: 0, + aggregation: TsAggregation.Max, + timeBucket: 10, + empty: true); + + expected.Clear(); + + expected.Add(new(10, 4.0)); + expected.Add(new(20, double.NaN)); + expected.Add(new(30, double.NaN)); + expected.Add(new(40, double.NaN)); + expected.Add(new(50, 3.0)); + expected.Add(new(60, double.NaN)); + expected.Add(new(70, 5.0)); + + for (int i = 0; i < range.Count(); i++) { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - - ts.Create("t1"); - - ts.Add("t1", 15, 1); - ts.Add("t1", 17, 4); - ts.Add("t1", 51, 3); - ts.Add("t1", 73, 5); - ts.Add("t1", 75, 3); - - var range = ts.Range("t1", 0, 100, - align: 0, - aggregation: TsAggregation.Max, - timeBucket: 10); - - var expected = new List(); - expected.Add(new TimeSeriesTuple(10, 4.0)); - expected.Add(new TimeSeriesTuple(50, 3.0)); - expected.Add(new TimeSeriesTuple(70, 5.0)); - Assert.Equal(range, expected); - - range = ts.Range("t1", 0, 100, - align: 0, - aggregation: TsAggregation.Max, - timeBucket: 10, - empty: true); - - expected.Clear(); - - expected.Add(new TimeSeriesTuple(10, 4.0)); - expected.Add(new TimeSeriesTuple(20, double.NaN)); - expected.Add(new TimeSeriesTuple(30, double.NaN)); - expected.Add(new TimeSeriesTuple(40, double.NaN)); - expected.Add(new TimeSeriesTuple(50, 3.0)); - expected.Add(new TimeSeriesTuple(60, double.NaN)); - expected.Add(new TimeSeriesTuple(70, 5.0)); - - for (int i = 0; i < range.Count(); i++) - { - Assert.Equal(range[i].Time.Value, expected[i].Time.Value); - Assert.Equal(range[i].Val, expected[i].Val); - } + Assert.Equal(range[i].Time.Value, expected[i].Time.Value); + Assert.Equal(range[i].Val, expected[i].Val); } } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRangeAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRangeAsync.cs index b7dc2ca9..880ad648 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRangeAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRangeAsync.cs @@ -1,290 +1,286 @@ -using NRedisStack.Literals.Enums; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods +using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; using StackExchange.Redis; using Xunit; using NRedisStack.RedisStackCommands; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestRangeAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestRangeAsync : AbstractNRedisStackTest + private async Task> CreateData(TimeSeriesCommands ts, string key, int timeBucket) { - public TestRangeAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) + var tuples = new List(); + for (var i = 0; i < 10; i++) { + var timeStamp = await ts.AddAsync(key, i * timeBucket, i); + tuples.Add(new(timeStamp, i)); } + return tuples; + } - private async Task> CreateData(TimeSeriesCommands ts, string key, int timeBucket) - { - var tuples = new List(); - for (var i = 0; i < 10; i++) - { - var timeStamp = await ts.AddAsync(key, i * timeBucket, i); - tuples.Add(new TimeSeriesTuple(timeStamp, i)); - } - return tuples; - } + [Fact] + public async Task TestSimpleRange() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + var tuples = await CreateData(ts, key, 50); + Assert.Equal(tuples, await ts.RangeAsync(key, "-", "+")); + } - [Fact] - public async Task TestSimpleRange() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - var tuples = await CreateData(ts, key, 50); - Assert.Equal(tuples, await ts.RangeAsync(key, "-", "+")); - } + [Fact] + public async Task TestRangeCount() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + var tuples = await CreateData(ts, key, 50); + Assert.Equal(tuples.GetRange(0, 5), await ts.RangeAsync(key, "-", "+", count: 5)); + } - [Fact] - public async Task TestRangeCount() - { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - var tuples = await CreateData(ts, key, 50); - Assert.Equal(tuples.GetRange(0, 5), await ts.RangeAsync(key, "-", "+", count: 5)); - } + [Fact] + public async Task TestRangeAggregation() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + var tuples = await CreateData(ts, key, 50); + Assert.Equal(tuples, await ts.RangeAsync(key, "-", "+", aggregation: TsAggregation.Min, timeBucket: 50)); + } - [Fact] - public async Task TestRangeAggregation() + [Fact] + public async Task TestRangeAlign() + { + var key = CreateKeyName(); + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + var tuples = new List() { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - var tuples = await CreateData(ts, key, 50); - Assert.Equal(tuples, await ts.RangeAsync(key, "-", "+", aggregation: TsAggregation.Min, timeBucket: 50)); - } + new(1, 10), + new(3, 5), + new(11, 10), + new(21, 11) + }; - [Fact] - public async Task TestRangeAlign() + foreach (var tuple in tuples) { - var key = CreateKeyName(); - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - var tuples = new List() - { - new TimeSeriesTuple(1, 10), - new TimeSeriesTuple(3, 5), - new TimeSeriesTuple(11, 10), - new TimeSeriesTuple(21, 11) - }; - - foreach (var tuple in tuples) - { - await ts.AddAsync(key, tuple.Time, tuple.Val); - } - - // Aligh start - var resStart = new List() - { - new TimeSeriesTuple(1, 2), - new TimeSeriesTuple(11, 1), - new TimeSeriesTuple(21, 1) - }; - Assert.Equal(resStart, await ts.RangeAsync(key, 1, 30, align: "-", aggregation: TsAggregation.Count, timeBucket: 10)); - - // Aligh end - var resEnd = new List() - { - new TimeSeriesTuple(0, 2), - new TimeSeriesTuple(10, 1), - new TimeSeriesTuple(20, 1) - }; - Assert.Equal(resEnd, await ts.RangeAsync(key, 1, 30, align: "+", aggregation: TsAggregation.Count, timeBucket: 10)); - - // Align 1 - Assert.Equal(resStart, await ts.RangeAsync(key, 1, 30, align: 1, aggregation: TsAggregation.Count, timeBucket: 10)); + await ts.AddAsync(key, tuple.Time, tuple.Val); } - [Fact] - public async Task TestMissingTimeBucket() + // Aligh start + var resStart = new List() { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - var tuples = await CreateData(ts, key, 50); - var ex = await Assert.ThrowsAsync(async () => await ts.RangeAsync(key, "-", "+", aggregation: TsAggregation.Avg)); - Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); - } - - [Fact] - public async Task TestFilterBy() + new(1, 2), + new(11, 1), + new(21, 1) + }; + Assert.Equal(resStart, await ts.RangeAsync(key, 1, 30, align: "-", aggregation: TsAggregation.Count, timeBucket: 10)); + + // Aligh end + var resEnd = new List() { - var key = CreateKeyName(); - var db = GetCleanDatabase(); - var ts = db.TS(); - var tuples = await CreateData(ts, key, 50); + new(0, 2), + new(10, 1), + new(20, 1) + }; + Assert.Equal(resEnd, await ts.RangeAsync(key, 1, 30, align: "+", aggregation: TsAggregation.Count, timeBucket: 10)); + + // Align 1 + Assert.Equal(resStart, await ts.RangeAsync(key, 1, 30, align: 1, aggregation: TsAggregation.Count, timeBucket: 10)); + } - var res = await ts.RangeAsync(key, "-", "+", filterByValue: (0, 2)); // The first 3 tuples - Assert.Equal(3, res.Count); - Assert.Equal(tuples.GetRange(0, 3), res); + [Fact] + public async Task TestMissingTimeBucket() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + var tuples = await CreateData(ts, key, 50); + var ex = await Assert.ThrowsAsync(async () => await ts.RangeAsync(key, "-", "+", aggregation: TsAggregation.Avg)); + Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); + } - var filterTs = new List { 0, 50, 100 }; // Also the first 3 tuples - res = await ts.RangeAsync(key, "-", "+", filterByTs: filterTs); - Assert.Equal(tuples.GetRange(0, 3), res); + [Fact] + public async Task TestFilterBy() + { + var key = CreateKeyName(); + var db = GetCleanDatabase(); + var ts = db.TS(); + var tuples = await CreateData(ts, key, 50); - res = await ts.RangeAsync(key, "-", "+", filterByTs: filterTs, filterByValue: (2, 5)); // The third tuple - Assert.Equal(tuples.GetRange(2, 1), res); - } + var res = await ts.RangeAsync(key, "-", "+", filterByValue: (0, 2)); // The first 3 tuples + Assert.Equal(3, res.Count); + Assert.Equal(tuples.GetRange(0, 3), res); - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestLatestAsync(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - await ts.CreateAsync("ts1"); - await ts.CreateAsync("ts2"); - await ts.CreateRuleAsync("ts1", new TimeSeriesRule("ts2", 10, TsAggregation.Sum)); - await ts.AddAsync("ts1", 1, 1); - await ts.AddAsync("ts1", 2, 3); - await ts.AddAsync("ts1", 11, 7); - await ts.AddAsync("ts1", 13, 1); - var range = await ts.RangeAsync("ts1", 0, 20); - Assert.Equal(4, range.Count); + var filterTs = new List { 0, 50, 100 }; // Also the first 3 tuples + res = await ts.RangeAsync(key, "-", "+", filterByTs: filterTs); + Assert.Equal(tuples.GetRange(0, 3), res); - var compact = new TimeSeriesTuple(0, 4); - var latest = new TimeSeriesTuple(10, 8); + res = await ts.RangeAsync(key, "-", "+", filterByTs: filterTs, filterByValue: (2, 5)); // The third tuple + Assert.Equal(tuples.GetRange(2, 1), res); + } - // get - Assert.Equal(compact, await ts.GetAsync("ts2")); + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestLatestAsync(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + await ts.CreateAsync("ts1"); + await ts.CreateAsync("ts2"); + await ts.CreateRuleAsync("ts1", new("ts2", 10, TsAggregation.Sum)); + await ts.AddAsync("ts1", 1, 1); + await ts.AddAsync("ts1", 2, 3); + await ts.AddAsync("ts1", 11, 7); + await ts.AddAsync("ts1", 13, 1); + var range = await ts.RangeAsync("ts1", 0, 20); + Assert.Equal(4, range.Count); - Assert.Equal(latest, await ts.GetAsync("ts2", true)); + var compact = new TimeSeriesTuple(0, 4); + var latest = new TimeSeriesTuple(10, 8); - // range - Assert.Equal(new List() { compact }, await ts.RangeAsync("ts2", 0, 10)); + // get + Assert.Equal(compact, await ts.GetAsync("ts2")); - Assert.Equal(new List() { compact, latest }, await ts.RangeAsync("ts2", 0, 10, true)); + Assert.Equal(latest, await ts.GetAsync("ts2", true)); - // revrange - Assert.Equal(new List() { compact }, await ts.RevRangeAsync("ts2", 0, 10)); + // range + Assert.Equal(new List() { compact }, await ts.RangeAsync("ts2", 0, 10)); - Assert.Equal(new List() { latest, compact }, await ts.RevRangeAsync("ts2", 0, 10, true)); - } + Assert.Equal(new List() { compact, latest }, await ts.RangeAsync("ts2", 0, 10, true)); - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestAlignTimestampAsync(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - ts.Create("ts1"); - ts.Create("ts2"); - ts.Create("ts3"); - ts.CreateRule("ts1", new TimeSeriesRule("ts2", 10, TsAggregation.Count), 0); - ts.CreateRule("ts1", new TimeSeriesRule("ts3", 10, TsAggregation.Count), 1); - ts.Add("ts1", 1, 1); - ts.Add("ts1", 10, 3); - ts.Add("ts1", 21, 7); - Assert.Equal(2, (await ts.RangeAsync("ts2", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10)).Count); - Assert.Single((await ts.RangeAsync("ts3", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10))); - } + // revrange + Assert.Equal(new List() { compact }, await ts.RevRangeAsync("ts2", 0, 10)); - [Fact] - public async Task TestBucketTimestampAsync() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - - ts.Create("t1"); - - ts.Add("t1", 15, 1); - ts.Add("t1", 17, 4); - ts.Add("t1", 51, 3); - ts.Add("t1", 73, 5); - ts.Add("t1", 75, 3); - - var rangeHigh = await ts.RangeAsync("t1", 0, 100, - align: 0, - aggregation: TsAggregation.Max, - timeBucket: 10); - - var expected = new List(); - expected.Add(new TimeSeriesTuple(10, 4.0)); - expected.Add(new TimeSeriesTuple(50, 3.0)); - expected.Add(new TimeSeriesTuple(70, 5.0)); - Assert.Equal(rangeHigh, expected); - - rangeHigh = await ts.RangeAsync("t1", 0, 100, - align: 0, - aggregation: TsAggregation.Max, - timeBucket: 10, - bt: TsBucketTimestamps.high); - - expected.Clear(); - expected.Add(new TimeSeriesTuple(20, 4.0)); - expected.Add(new TimeSeriesTuple(60, 3.0)); - expected.Add(new TimeSeriesTuple(80, 5.0)); - Assert.Equal(rangeHigh, expected); - - var rangeLow = await ts.RangeAsync("t1", 0, 100, - align: 0, - aggregation: TsAggregation.Max, - timeBucket: 10, - bt: TsBucketTimestamps.low); - expected.Clear(); - expected.Add(new TimeSeriesTuple(10, 4.0)); - expected.Add(new TimeSeriesTuple(50, 3.0)); - expected.Add(new TimeSeriesTuple(70, 5.0)); - Assert.Equal(rangeLow, expected); - - var rangeMid = await ts.RangeAsync("t1", 0, 100, - align: 0, - aggregation: TsAggregation.Max, - timeBucket: 10, - bt: TsBucketTimestamps.mid); - expected.Clear(); - expected.Add(new TimeSeriesTuple(15, 4.0)); - expected.Add(new TimeSeriesTuple(55, 3.0)); - expected.Add(new TimeSeriesTuple(75, 5.0)); - Assert.Equal(rangeMid, expected); + Assert.Equal(new List() { latest, compact }, await ts.RevRangeAsync("ts2", 0, 10, true)); + } - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestAlignTimestampAsync(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + ts.Create("ts1"); + ts.Create("ts2"); + ts.Create("ts3"); + ts.CreateRule("ts1", new("ts2", 10, TsAggregation.Count), 0); + ts.CreateRule("ts1", new("ts3", 10, TsAggregation.Count), 1); + ts.Add("ts1", 1, 1); + ts.Add("ts1", 10, 3); + ts.Add("ts1", 21, 7); + Assert.Equal(2, (await ts.RangeAsync("ts2", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10)).Count); + Assert.Single((await ts.RangeAsync("ts3", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10))); + } - [Fact] - public async Task TestEmptyAsync() + [Fact] + public async Task TestBucketTimestampAsync() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + + ts.Create("t1"); + + ts.Add("t1", 15, 1); + ts.Add("t1", 17, 4); + ts.Add("t1", 51, 3); + ts.Add("t1", 73, 5); + ts.Add("t1", 75, 3); + + var rangeHigh = await ts.RangeAsync("t1", 0, 100, + align: 0, + aggregation: TsAggregation.Max, + timeBucket: 10); + + var expected = new List(); + expected.Add(new(10, 4.0)); + expected.Add(new(50, 3.0)); + expected.Add(new(70, 5.0)); + Assert.Equal(rangeHigh, expected); + + rangeHigh = await ts.RangeAsync("t1", 0, 100, + align: 0, + aggregation: TsAggregation.Max, + timeBucket: 10, + bt: TsBucketTimestamps.high); + + expected.Clear(); + expected.Add(new(20, 4.0)); + expected.Add(new(60, 3.0)); + expected.Add(new(80, 5.0)); + Assert.Equal(rangeHigh, expected); + + var rangeLow = await ts.RangeAsync("t1", 0, 100, + align: 0, + aggregation: TsAggregation.Max, + timeBucket: 10, + bt: TsBucketTimestamps.low); + expected.Clear(); + expected.Add(new(10, 4.0)); + expected.Add(new(50, 3.0)); + expected.Add(new(70, 5.0)); + Assert.Equal(rangeLow, expected); + + var rangeMid = await ts.RangeAsync("t1", 0, 100, + align: 0, + aggregation: TsAggregation.Max, + timeBucket: 10, + bt: TsBucketTimestamps.mid); + expected.Clear(); + expected.Add(new(15, 4.0)); + expected.Add(new(55, 3.0)); + expected.Add(new(75, 5.0)); + Assert.Equal(rangeMid, expected); + + } + + [Fact] + public async Task TestEmptyAsync() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + + ts.Create("t1"); + + ts.Add("t1", 15, 1); + ts.Add("t1", 17, 4); + ts.Add("t1", 51, 3); + ts.Add("t1", 73, 5); + ts.Add("t1", 75, 3); + + var range = await ts.RangeAsync("t1", 0, 100, + align: 0, + aggregation: TsAggregation.Max, + timeBucket: 10); + + var expected = new List(); + expected.Add(new(10, 4.0)); + expected.Add(new(50, 3.0)); + expected.Add(new(70, 5.0)); + Assert.Equal(range, expected); + + range = await ts.RangeAsync("t1", 0, 100, + align: 0, + aggregation: TsAggregation.Max, + timeBucket: 10, + empty: true); + + expected.Clear(); + + expected.Add(new(10, 4.0)); + expected.Add(new(20, double.NaN)); + expected.Add(new(30, double.NaN)); + expected.Add(new(40, double.NaN)); + expected.Add(new(50, 3.0)); + expected.Add(new(60, double.NaN)); + expected.Add(new(70, 5.0)); + + for (int i = 0; i < range.Count(); i++) { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - - ts.Create("t1"); - - ts.Add("t1", 15, 1); - ts.Add("t1", 17, 4); - ts.Add("t1", 51, 3); - ts.Add("t1", 73, 5); - ts.Add("t1", 75, 3); - - var range = await ts.RangeAsync("t1", 0, 100, - align: 0, - aggregation: TsAggregation.Max, - timeBucket: 10); - - var expected = new List(); - expected.Add(new TimeSeriesTuple(10, 4.0)); - expected.Add(new TimeSeriesTuple(50, 3.0)); - expected.Add(new TimeSeriesTuple(70, 5.0)); - Assert.Equal(range, expected); - - range = await ts.RangeAsync("t1", 0, 100, - align: 0, - aggregation: TsAggregation.Max, - timeBucket: 10, - empty: true); - - expected.Clear(); - - expected.Add(new TimeSeriesTuple(10, 4.0)); - expected.Add(new TimeSeriesTuple(20, double.NaN)); - expected.Add(new TimeSeriesTuple(30, double.NaN)); - expected.Add(new TimeSeriesTuple(40, double.NaN)); - expected.Add(new TimeSeriesTuple(50, 3.0)); - expected.Add(new TimeSeriesTuple(60, double.NaN)); - expected.Add(new TimeSeriesTuple(70, 5.0)); - - for (int i = 0; i < range.Count(); i++) - { - Assert.Equal(range[i].Time.Value, expected[i].Time.Value); - Assert.Equal(range[i].Val, expected[i].Val); - } + Assert.Equal(range[i].Time.Value, expected[i].Time.Value); + Assert.Equal(range[i].Val, expected[i].Val); } } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRevRange.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRevRange.cs index b9ae7eb8..fcf5f604 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRevRange.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRevRange.cs @@ -1,133 +1,129 @@ -using NRedisStack.Literals.Enums; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods +using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; using Xunit; using NRedisStack.RedisStackCommands; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestRevRange(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestRevRange : AbstractNRedisStackTest + private List CreateData(ITimeSeriesCommands ts, string key, int timeBucket) { - public TestRevRange(EndpointsFixture endpointsFixture) : base(endpointsFixture) + var tuples = new List(); + for (var i = 0; i < 10; i++) { + var timeStamp = ts.Add(key, i * timeBucket, i); + tuples.Add(new(timeStamp, i)); } + return tuples; + } - private List CreateData(ITimeSeriesCommands ts, string key, int timeBucket) - { - var tuples = new List(); - for (var i = 0; i < 10; i++) - { - var timeStamp = ts.Add(key, i * timeBucket, i); - tuples.Add(new TimeSeriesTuple(timeStamp, i)); - } - return tuples; - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestSimpleRevRange(string endpointId) + { + var key = CreateKeyName(); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var tuples = CreateData(ts, key, 50); + Assert.Equal(ReverseData(tuples), ts.RevRange(key, "-", "+")); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestSimpleRevRange(string endpointId) - { - var key = CreateKeyName(); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var tuples = CreateData(ts, key, 50); - Assert.Equal(ReverseData(tuples), ts.RevRange(key, "-", "+")); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestRevRangeCount(string endpointId) + { + var key = CreateKeyName(); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var tuples = CreateData(ts, key, 50); + Assert.Equal(ReverseData(tuples).GetRange(0, 5), ts.RevRange(key, "-", "+", count: 5)); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestRevRangeCount(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestRevRangeAggregation(string endpointId) + { + var key = CreateKeyName(); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var tuples = CreateData(ts, key, 50); + Assert.Equal(ReverseData(tuples), ts.RevRange(key, "-", "+", aggregation: TsAggregation.Min, timeBucket: 50)); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestRevRangeAlign(string endpointId) + { + var key = CreateKeyName(); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var tuples = new List() { - var key = CreateKeyName(); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var tuples = CreateData(ts, key, 50); - Assert.Equal(ReverseData(tuples).GetRange(0, 5), ts.RevRange(key, "-", "+", count: 5)); - } + new(1, 10), + new(3, 5), + new(11, 10), + new(21, 11) + }; - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestRevRangeAggregation(string endpointId) + foreach (var tuple in tuples) { - var key = CreateKeyName(); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var tuples = CreateData(ts, key, 50); - Assert.Equal(ReverseData(tuples), ts.RevRange(key, "-", "+", aggregation: TsAggregation.Min, timeBucket: 50)); + ts.Add(key, tuple.Time, tuple.Val); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestRevRangeAlign(string endpointId) + // Aligh start + var resStart = new List() { - var key = CreateKeyName(); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var tuples = new List() - { - new TimeSeriesTuple(1, 10), - new TimeSeriesTuple(3, 5), - new TimeSeriesTuple(11, 10), - new TimeSeriesTuple(21, 11) - }; - - foreach (var tuple in tuples) - { - ts.Add(key, tuple.Time, tuple.Val); - } + new(21, 1), + new(11, 1), + new(1, 2) + }; + Assert.Equal(resStart, ts.RevRange(key, 1, 30, align: "-", aggregation: TsAggregation.Count, timeBucket: 10)); - // Aligh start - var resStart = new List() - { - new TimeSeriesTuple(21, 1), - new TimeSeriesTuple(11, 1), - new TimeSeriesTuple(1, 2) - }; - Assert.Equal(resStart, ts.RevRange(key, 1, 30, align: "-", aggregation: TsAggregation.Count, timeBucket: 10)); - - // Aligh end - var resEnd = new List() - { - new TimeSeriesTuple(20, 1), - new TimeSeriesTuple(10, 1), - new TimeSeriesTuple(0, 2) - }; - Assert.Equal(resEnd, ts.RevRange(key, 1, 30, align: "+", aggregation: TsAggregation.Count, timeBucket: 10)); + // Aligh end + var resEnd = new List() + { + new(20, 1), + new(10, 1), + new(0, 2) + }; + Assert.Equal(resEnd, ts.RevRange(key, 1, 30, align: "+", aggregation: TsAggregation.Count, timeBucket: 10)); - // Align 1 - Assert.Equal(resStart, ts.RevRange(key, 1, 30, align: 1, aggregation: TsAggregation.Count, timeBucket: 10)); - } + // Align 1 + Assert.Equal(resStart, ts.RevRange(key, 1, 30, align: 1, aggregation: TsAggregation.Count, timeBucket: 10)); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestMissingTimeBucket(string endpointId) - { - var key = CreateKeyName(); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var tuples = CreateData(ts, key, 50); - var ex = Assert.Throws(() => ts.RevRange(key, "-", "+", aggregation: TsAggregation.Avg)); - Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestMissingTimeBucket(string endpointId) + { + var key = CreateKeyName(); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var tuples = CreateData(ts, key, 50); + var ex = Assert.Throws(() => ts.RevRange(key, "-", "+", aggregation: TsAggregation.Avg)); + Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestFilterBy(string endpointId) - { - var key = CreateKeyName(); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var tuples = CreateData(ts, key, 50); + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestFilterBy(string endpointId) + { + var key = CreateKeyName(); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var tuples = CreateData(ts, key, 50); - var res = ts.RevRange(key, "-", "+", filterByValue: (0, 2)); - Assert.Equal(3, res.Count); - Assert.Equal(ReverseData(tuples.GetRange(0, 3)), res); + var res = ts.RevRange(key, "-", "+", filterByValue: (0, 2)); + Assert.Equal(3, res.Count); + Assert.Equal(ReverseData(tuples.GetRange(0, 3)), res); - var filterTs = new List { 0, 50, 100 }; - res = ts.RevRange(key, "-", "+", filterByTs: filterTs); - Assert.Equal(ReverseData(tuples.GetRange(0, 3)), res); + var filterTs = new List { 0, 50, 100 }; + res = ts.RevRange(key, "-", "+", filterByTs: filterTs); + Assert.Equal(ReverseData(tuples.GetRange(0, 3)), res); - res = ts.RevRange(key, "-", "+", filterByTs: filterTs, filterByValue: (2, 5)); - Assert.Equal(tuples.GetRange(2, 1), res); - } + res = ts.RevRange(key, "-", "+", filterByTs: filterTs, filterByValue: (2, 5)); + Assert.Equal(tuples.GetRange(2, 1), res); } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRevRangeAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRevRangeAsync.cs index 9be16f3f..a18154dc 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRevRangeAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRevRangeAsync.cs @@ -1,134 +1,129 @@ -using StackExchange.Redis; +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; using Xunit; using NRedisStack.RedisStackCommands; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestRevRangeAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestRevRangeAsync : AbstractNRedisStackTest + private async Task> CreateData(TimeSeriesCommands ts, string key, int timeBucket) { - public TestRevRangeAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) + var tuples = new List(); + for (var i = 0; i < 10; i++) { + var timeStamp = await ts.AddAsync(key, i * timeBucket, i); + tuples.Add(new(timeStamp, i)); } + return tuples; + } - private async Task> CreateData(TimeSeriesCommands ts, string key, int timeBucket) - { - var tuples = new List(); - for (var i = 0; i < 10; i++) - { - var timeStamp = await ts.AddAsync(key, i * timeBucket, i); - tuples.Add(new TimeSeriesTuple(timeStamp, i)); - } - return tuples; - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestSimpleRevRange(string endpointId) + { + var key = CreateKeyName(); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var tuples = await CreateData(ts, key, 50); + Assert.Equal(ReverseData(tuples), await ts.RevRangeAsync(key, "-", "+")); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestSimpleRevRange(string endpointId) - { - var key = CreateKeyName(); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var tuples = await CreateData(ts, key, 50); - Assert.Equal(ReverseData(tuples), await ts.RevRangeAsync(key, "-", "+")); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestRevRangeCount(string endpointId) + { + var key = CreateKeyName(); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var tuples = await CreateData(ts, key, 50); + Assert.Equal(ReverseData(tuples).GetRange(0, 5), await ts.RevRangeAsync(key, "-", "+", count: 5)); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestRevRangeCount(string endpointId) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestRevRangeAggregation(string endpointId) + { + var key = CreateKeyName(); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var tuples = await CreateData(ts, key, 50); + Assert.Equal(ReverseData(tuples), await ts.RevRangeAsync(key, "-", "+", aggregation: TsAggregation.Min, timeBucket: 50)); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestRevRangeAlign(string endpointId) + { + var key = CreateKeyName(); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var tuples = new List() { - var key = CreateKeyName(); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var tuples = await CreateData(ts, key, 50); - Assert.Equal(ReverseData(tuples).GetRange(0, 5), await ts.RevRangeAsync(key, "-", "+", count: 5)); - } + new(1, 10), + new(3, 5), + new(11, 10), + new(21, 11) + }; - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestRevRangeAggregation(string endpointId) + foreach (var tuple in tuples) { - var key = CreateKeyName(); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var tuples = await CreateData(ts, key, 50); - Assert.Equal(ReverseData(tuples), await ts.RevRangeAsync(key, "-", "+", aggregation: TsAggregation.Min, timeBucket: 50)); + await ts.AddAsync(key, tuple.Time, tuple.Val); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestRevRangeAlign(string endpointId) + // Aligh start + var resStart = new List() { - var key = CreateKeyName(); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var tuples = new List() - { - new TimeSeriesTuple(1, 10), - new TimeSeriesTuple(3, 5), - new TimeSeriesTuple(11, 10), - new TimeSeriesTuple(21, 11) - }; - - foreach (var tuple in tuples) - { - await ts.AddAsync(key, tuple.Time, tuple.Val); - } + new(21, 1), + new(11, 1), + new(1, 2) + }; + Assert.Equal(resStart, await ts.RevRangeAsync(key, 1, 30, align: "-", aggregation: TsAggregation.Count, timeBucket: 10)); - // Aligh start - var resStart = new List() - { - new TimeSeriesTuple(21, 1), - new TimeSeriesTuple(11, 1), - new TimeSeriesTuple(1, 2) - }; - Assert.Equal(resStart, await ts.RevRangeAsync(key, 1, 30, align: "-", aggregation: TsAggregation.Count, timeBucket: 10)); - - // Aligh end - var resEnd = new List() - { - new TimeSeriesTuple(20, 1), - new TimeSeriesTuple(10, 1), - new TimeSeriesTuple(0, 2) - }; - Assert.Equal(resEnd, await ts.RevRangeAsync(key, 1, 30, align: "+", aggregation: TsAggregation.Count, timeBucket: 10)); + // Aligh end + var resEnd = new List() + { + new(20, 1), + new(10, 1), + new(0, 2) + }; + Assert.Equal(resEnd, await ts.RevRangeAsync(key, 1, 30, align: "+", aggregation: TsAggregation.Count, timeBucket: 10)); - // Align 1 - Assert.Equal(resStart, await ts.RevRangeAsync(key, 1, 30, align: 1, aggregation: TsAggregation.Count, timeBucket: 10)); - } + // Align 1 + Assert.Equal(resStart, await ts.RevRangeAsync(key, 1, 30, align: 1, aggregation: TsAggregation.Count, timeBucket: 10)); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestMissingTimeBucket(string endpointId) - { - var key = CreateKeyName(); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var tuples = await CreateData(ts, key, 50); - var ex = await Assert.ThrowsAsync(async () => await ts.RevRangeAsync(key, "-", "+", aggregation: TsAggregation.Avg)); - Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); - } + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestMissingTimeBucket(string endpointId) + { + var key = CreateKeyName(); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var tuples = await CreateData(ts, key, 50); + var ex = await Assert.ThrowsAsync(async () => await ts.RevRangeAsync(key, "-", "+", aggregation: TsAggregation.Avg)); + Assert.Equal("RANGE Aggregation should have timeBucket value", ex.Message); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestFilterBy(string endpointId) - { - var key = CreateKeyName(); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - var tuples = await CreateData(ts, key, 50); + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestFilterBy(string endpointId) + { + var key = CreateKeyName(); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + var tuples = await CreateData(ts, key, 50); - var res = await ts.RevRangeAsync(key, "-", "+", filterByValue: (0, 2)); - Assert.Equal(3, res.Count); - Assert.Equal(ReverseData(tuples.GetRange(0, 3)), res); + var res = await ts.RevRangeAsync(key, "-", "+", filterByValue: (0, 2)); + Assert.Equal(3, res.Count); + Assert.Equal(ReverseData(tuples.GetRange(0, 3)), res); - var filterTs = new List { 0, 50, 100 }; - res = await ts.RevRangeAsync(key, "-", "+", filterByTs: filterTs); - Assert.Equal(ReverseData(tuples.GetRange(0, 3)), res); + var filterTs = new List { 0, 50, 100 }; + res = await ts.RevRangeAsync(key, "-", "+", filterByTs: filterTs); + Assert.Equal(ReverseData(tuples.GetRange(0, 3)), res); - res = await ts.RevRangeAsync(key, "-", "+", filterByTs: filterTs, filterByValue: (2, 5)); - Assert.Equal(tuples.GetRange(2, 1), res); - } + res = await ts.RevRangeAsync(key, "-", "+", filterByTs: filterTs, filterByValue: (2, 5)); + Assert.Equal(tuples.GetRange(2, 1), res); } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRules.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRules.cs index 5c115812..25227758 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRules.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRules.cs @@ -1,120 +1,115 @@ -using NRedisStack.Literals.Enums; +#pragma warning disable CS0618 // allow testing obsolete methods +using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; using StackExchange.Redis; using Xunit; using NRedisStack.RedisStackCommands; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestRules(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable { - public class TestRules : AbstractNRedisStackTest, IDisposable - { - private string srcKey = "RULES_TEST_SRC"; + private readonly string srcKey = "RULES_TEST_SRC"; - private Dictionary destKeys; + private readonly Dictionary destKeys = new() + { + { TsAggregation.Avg, "RULES_DEST_" + TsAggregation.Avg }, + { TsAggregation.Count, "RULES_DEST_" + TsAggregation.Count }, + { TsAggregation.First, "RULES_DEST_" + TsAggregation.First }, + { TsAggregation.Last, "RULES_DEST_" + TsAggregation.Last }, + { TsAggregation.Max, "RULES_DEST_" + TsAggregation.Max }, + { TsAggregation.Min, "RULES_DEST_" + TsAggregation.Min }, + { TsAggregation.Range, "RULES_DEST_" + TsAggregation.Range }, + { TsAggregation.StdP, "RULES_DEST_" + TsAggregation.StdP }, + { TsAggregation.StdS, "RULES_DEST_" + TsAggregation.StdS }, + { TsAggregation.Sum, "RULES_DEST_" + TsAggregation.Sum }, + { TsAggregation.VarP, "RULES_DEST_" + TsAggregation.VarP }, + { TsAggregation.VarS, "RULES_DEST_" + TsAggregation.VarS } + }; - public TestRules(EndpointsFixture endpointsFixture) : base(endpointsFixture) + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + [Obsolete] + public void TestRulesAdditionDeletion(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + ts.Create(srcKey); + foreach (var destKey in destKeys.Values) { - destKeys = new Dictionary - { - { TsAggregation.Avg, "RULES_DEST_" + TsAggregation.Avg }, - { TsAggregation.Count, "RULES_DEST_" + TsAggregation.Count }, - { TsAggregation.First, "RULES_DEST_" + TsAggregation.First }, - { TsAggregation.Last, "RULES_DEST_" + TsAggregation.Last }, - { TsAggregation.Max, "RULES_DEST_" + TsAggregation.Max }, - { TsAggregation.Min, "RULES_DEST_" + TsAggregation.Min }, - { TsAggregation.Range, "RULES_DEST_" + TsAggregation.Range }, - { TsAggregation.StdP, "RULES_DEST_" + TsAggregation.StdP }, - { TsAggregation.StdS, "RULES_DEST_" + TsAggregation.StdS }, - { TsAggregation.Sum, "RULES_DEST_" + TsAggregation.Sum }, - { TsAggregation.VarP, "RULES_DEST_" + TsAggregation.VarP }, - { TsAggregation.VarS, "RULES_DEST_" + TsAggregation.VarS } - }; + ts.Create(destKey); } - - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - [Obsolete] - public void TestRulesAdditionDeletion(string endpointId) + long timeBucket = 50; + var rules = new List(); + var rulesMap = new Dictionary(); + foreach (var aggregation in destKeys.Keys) { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - ts.Create(srcKey); - foreach (var destKey in destKeys.Values) - { - ts.Create(destKey); - } - long timeBucket = 50; - var rules = new List(); - var rulesMap = new Dictionary(); - foreach (var aggregation in destKeys.Keys) - { - var rule = new TimeSeriesRule(destKeys[aggregation], timeBucket, aggregation); - rules.Add(rule); - rulesMap[aggregation] = rule; - Assert.True(ts.CreateRule(srcKey, rule)); - TimeSeriesInformation info = ts.Info(srcKey); - Assert.Equal(rules, info.Rules); - } - foreach (var aggregation in destKeys.Keys) - { - var rule = rulesMap[aggregation]; - rules.Remove(rule); - Assert.True(ts.DeleteRule(srcKey, rule.DestKey)); - TimeSeriesInformation info = ts.Info(srcKey); - Assert.Equal(rules, info.Rules); - } + var rule = new TimeSeriesRule(destKeys[aggregation], timeBucket, aggregation); + rules.Add(rule); + rulesMap[aggregation] = rule; + Assert.True(ts.CreateRule(srcKey, rule)); + TimeSeriesInformation info = ts.Info(srcKey); + Assert.Equal(rules, info.Rules); } - - [Fact] - public void TestNonExistingSrc() + foreach (var aggregation in destKeys.Keys) { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - string destKey = "RULES_DEST_" + TsAggregation.Avg; - ts.Create(destKey); - TimeSeriesRule rule = new TimeSeriesRule(destKey, 50, TsAggregation.Avg); - var ex = Assert.Throws(() => ts.CreateRule(srcKey, rule)); - Assert.Equal("ERR TSDB: the key does not exist", ex.Message); - ex = Assert.Throws(() => ts.DeleteRule(srcKey, destKey)); - Assert.Equal("ERR TSDB: the key does not exist", ex.Message); + var rule = rulesMap[aggregation]; + rules.Remove(rule); + Assert.True(ts.DeleteRule(srcKey, rule.DestKey)); + TimeSeriesInformation info = ts.Info(srcKey); + Assert.Equal(rules, info.Rules); } + } - [Fact] - public void TestNonExisitingDestinaion() - { - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - string destKey = "RULES_DEST_" + TsAggregation.Avg; - ts.Create(srcKey); - TimeSeriesRule rule = new TimeSeriesRule(destKey, 50, TsAggregation.Avg); - var ex = Assert.Throws(() => ts.CreateRule(srcKey, rule)); - Assert.Equal("ERR TSDB: the key does not exist", ex.Message); - ex = Assert.Throws(() => ts.DeleteRule(srcKey, destKey)); - Assert.Equal("ERR TSDB: compaction rule does not exist", ex.Message); - } + [Fact] + public void TestNonExistingSrc() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + string destKey = "RULES_DEST_" + TsAggregation.Avg; + ts.Create(destKey); + TimeSeriesRule rule = new(destKey, 50, TsAggregation.Avg); + var ex = Assert.Throws(() => ts.CreateRule(srcKey, rule)); + Assert.Equal("ERR TSDB: the key does not exist", ex.Message); + ex = Assert.Throws(() => ts.DeleteRule(srcKey, destKey)); + Assert.Equal("ERR TSDB: the key does not exist", ex.Message); + } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public void TestAlignTimestamp(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - ts.Create("ts1"); - ts.Create("ts2"); - ts.Create("ts3"); + [Fact] + public void TestNonExisitingDestinaion() + { + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + string destKey = "RULES_DEST_" + TsAggregation.Avg; + ts.Create(srcKey); + TimeSeriesRule rule = new(destKey, 50, TsAggregation.Avg); + var ex = Assert.Throws(() => ts.CreateRule(srcKey, rule)); + Assert.Equal("ERR TSDB: the key does not exist", ex.Message); + ex = Assert.Throws(() => ts.DeleteRule(srcKey, destKey)); + Assert.Equal("ERR TSDB: compaction rule does not exist", ex.Message); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestAlignTimestamp(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + ts.Create("ts1"); + ts.Create("ts2"); + ts.Create("ts3"); - TimeSeriesRule rule1 = new TimeSeriesRule("ts2", 10, TsAggregation.Count); - ts.CreateRule("ts1", rule1, 0); + TimeSeriesRule rule1 = new("ts2", 10, TsAggregation.Count); + ts.CreateRule("ts1", rule1, 0); - TimeSeriesRule rule2 = new TimeSeriesRule("ts3", 10, TsAggregation.Count); - ts.CreateRule("ts1", rule2, 1); + TimeSeriesRule rule2 = new("ts3", 10, TsAggregation.Count); + ts.CreateRule("ts1", rule2, 1); - ts.Add("ts1", 1, 1); - ts.Add("ts1", 10, 3); - ts.Add("ts1", 21, 7); + ts.Add("ts1", 1, 1); + ts.Add("ts1", 10, 3); + ts.Add("ts1", 21, 7); - Assert.Equal(2, ts.Range("ts2", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10).Count); - Assert.Single(ts.Range("ts3", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10)); - } + Assert.Equal(2, ts.Range("ts2", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10).Count); + Assert.Single(ts.Range("ts3", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10)); } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRulesAsync.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRulesAsync.cs index 21b07234..4df57d54 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRulesAsync.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TestRulesAsync.cs @@ -1,118 +1,114 @@ -using StackExchange.Redis; +#pragma warning disable CS0618 // allow testing obsolete methods +using StackExchange.Redis; using NRedisStack.Literals.Enums; using NRedisStack.DataTypes; using Xunit; using NRedisStack.RedisStackCommands; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TestRulesAsync(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture) { - public class TestRulesAsync : AbstractNRedisStackTest + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + [Obsolete] + public async Task TestRulesAdditionDeletion(string endpointId) { - public TestRulesAsync(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } + var key = CreateKeyName(); + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + await ts.CreateAsync(key); + var aggregations = (TsAggregation[])Enum.GetValues(typeof(TsAggregation)); - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - [Obsolete] - public async Task TestRulesAdditionDeletion(string endpointId) + foreach (var aggregation in aggregations) { - var key = CreateKeyName(); - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - await ts.CreateAsync(key); - var aggregations = (TsAggregation[])Enum.GetValues(typeof(TsAggregation)); - - foreach (var aggregation in aggregations) - { - await ts.CreateAsync($"{key}:{aggregation}"); - } - - var timeBucket = 50L; - var rules = new List(); - var rulesMap = new Dictionary(); - foreach (var aggregation in aggregations) - { - var rule = new TimeSeriesRule($"{key}:{aggregation}", timeBucket, aggregation); - rules.Add(rule); - rulesMap[aggregation] = rule; - Assert.True(await ts.CreateRuleAsync(key, rule)); - - var info = await ts.InfoAsync(key); - Assert.Equal(rules, info.Rules); - } - - foreach (var aggregation in aggregations) - { - var rule = rulesMap[aggregation]; - rules.Remove(rule); - Assert.True(await ts.DeleteRuleAsync(key, rule.DestKey)); - - var info = await ts.InfoAsync(key); - Assert.Equal(rules, info.Rules); - } - - await db.KeyDeleteAsync(aggregations.Select(i => (RedisKey)$"{key}:{i}").ToArray()); + await ts.CreateAsync($"{key}:{aggregation}"); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestNonExistingSrc(string endpointId) + var timeBucket = 50L; + var rules = new List(); + var rulesMap = new Dictionary(); + foreach (var aggregation in aggregations) { - var key = CreateKeyName(); - var aggKey = $"{key}:{TsAggregation.Avg}"; - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - await ts.CreateAsync(aggKey); - var rule = new TimeSeriesRule(aggKey, 50, TsAggregation.Avg); - var ex = await Assert.ThrowsAsync(async () => await ts.CreateRuleAsync(key, rule)); - Assert.Equal("ERR TSDB: the key does not exist", ex.Message); - - ex = await Assert.ThrowsAsync(async () => await ts.DeleteRuleAsync(key, aggKey)); - Assert.Equal("ERR TSDB: the key does not exist", ex.Message); - - await db.KeyDeleteAsync(aggKey); + var rule = new TimeSeriesRule($"{key}:{aggregation}", timeBucket, aggregation); + rules.Add(rule); + rulesMap[aggregation] = rule; + Assert.True(await ts.CreateRuleAsync(key, rule)); + + var info = await ts.InfoAsync(key); + Assert.Equal(rules, info.Rules); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestNonExisitingDestinaion(string endpointId) + foreach (var aggregation in aggregations) { - var key = CreateKeyName(); - var aggKey = $"{key}:{TsAggregation.Avg}"; - var db = GetCleanDatabase(endpointId); - var ts = db.TS(); - await ts.CreateAsync(key); - var rule = new TimeSeriesRule(aggKey, 50, TsAggregation.Avg); - var ex = await Assert.ThrowsAsync(async () => await ts.CreateRuleAsync(key, rule)); - Assert.Equal("ERR TSDB: the key does not exist", ex.Message); - - ex = await Assert.ThrowsAsync(async () => await ts.DeleteRuleAsync(key, aggKey)); - Assert.Equal("ERR TSDB: compaction rule does not exist", ex.Message); + var rule = rulesMap[aggregation]; + rules.Remove(rule); + Assert.True(await ts.DeleteRuleAsync(key, rule.DestKey)); + + var info = await ts.InfoAsync(key); + Assert.Equal(rules, info.Rules); } - [SkipIfRedis(Is.Enterprise)] - [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] - public async Task TestAlignTimestampAsync(string endpointId) - { - IDatabase db = GetCleanDatabase(endpointId); - var ts = db.TS(); - await ts.CreateAsync("ts1"); - await ts.CreateAsync("ts2"); - await ts.CreateAsync("ts3"); + await db.KeyDeleteAsync(aggregations.Select(i => (RedisKey)$"{key}:{i}").ToArray()); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestNonExistingSrc(string endpointId) + { + var key = CreateKeyName(); + var aggKey = $"{key}:{TsAggregation.Avg}"; + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + await ts.CreateAsync(aggKey); + var rule = new TimeSeriesRule(aggKey, 50, TsAggregation.Avg); + var ex = await Assert.ThrowsAsync(async () => await ts.CreateRuleAsync(key, rule)); + Assert.Equal("ERR TSDB: the key does not exist", ex.Message); + + ex = await Assert.ThrowsAsync(async () => await ts.DeleteRuleAsync(key, aggKey)); + Assert.Equal("ERR TSDB: the key does not exist", ex.Message); + + await db.KeyDeleteAsync(aggKey); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestNonExisitingDestinaion(string endpointId) + { + var key = CreateKeyName(); + var aggKey = $"{key}:{TsAggregation.Avg}"; + var db = GetCleanDatabase(endpointId); + var ts = db.TS(); + await ts.CreateAsync(key); + var rule = new TimeSeriesRule(aggKey, 50, TsAggregation.Avg); + var ex = await Assert.ThrowsAsync(async () => await ts.CreateRuleAsync(key, rule)); + Assert.Equal("ERR TSDB: the key does not exist", ex.Message); + + ex = await Assert.ThrowsAsync(async () => await ts.DeleteRuleAsync(key, aggKey)); + Assert.Equal("ERR TSDB: compaction rule does not exist", ex.Message); + } + + [SkipIfRedisTheory(Is.Enterprise)] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public async Task TestAlignTimestampAsync(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + var ts = db.TS(); + await ts.CreateAsync("ts1"); + await ts.CreateAsync("ts2"); + await ts.CreateAsync("ts3"); - TimeSeriesRule rule1 = new TimeSeriesRule("ts2", 10, TsAggregation.Count); - await ts.CreateRuleAsync("ts1", rule1, 0); + TimeSeriesRule rule1 = new("ts2", 10, TsAggregation.Count); + await ts.CreateRuleAsync("ts1", rule1, 0); - TimeSeriesRule rule2 = new TimeSeriesRule("ts3", 10, TsAggregation.Count); - await ts.CreateRuleAsync("ts1", rule2, 1); + TimeSeriesRule rule2 = new("ts3", 10, TsAggregation.Count); + await ts.CreateRuleAsync("ts1", rule2, 1); - await ts.AddAsync("ts1", 1, 1); - await ts.AddAsync("ts1", 10, 3); - await ts.AddAsync("ts1", 21, 7); + await ts.AddAsync("ts1", 1, 1); + await ts.AddAsync("ts1", 10, 3); + await ts.AddAsync("ts1", 21, 7); - Assert.Equal(2, (await ts.RangeAsync("ts2", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10)).Count); - Assert.Single((await ts.RangeAsync("ts3", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10))); - } + Assert.Equal(2, (await ts.RangeAsync("ts2", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10)).Count); + Assert.Single((await ts.RangeAsync("ts3", "-", "+", aggregation: TsAggregation.Count, timeBucket: 10))); } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TimeSeriesHelper.cs b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TimeSeriesHelper.cs index 4cef7208..2bc6c4f0 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestAPI/TimeSeriesHelper.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestAPI/TimeSeriesHelper.cs @@ -1,23 +1,22 @@ using StackExchange.Redis; using NRedisStack.RedisStackCommands; -namespace NRedisStack.Tests.TimeSeries.TestAPI +namespace NRedisStack.Tests.TimeSeries.TestAPI; + +public class TimeSeriesHelper { - public class TimeSeriesHelper + public static RedisResult getInfo(IDatabase db, string key, out int j, out int k) { - public static RedisResult getInfo(IDatabase db, string key, out int j, out int k) - { - var cmd = new SerializedCommand("TS.INFO", key); - RedisResult info = db.Execute(cmd); + var cmd = new SerializedCommand("TS.INFO", key); + RedisResult info = db.Execute(cmd); - j = -1; - k = -1; - for (int i = 0; i < info.Length; i++) - { - if (info[i].ToString().Equals("ignoreMaxTimeDiff")) j = i; - if (info[i].ToString().Equals("ignoreMaxValDiff")) k = i; - } - return info; + j = -1; + k = -1; + for (int i = 0; i < info.Length; i++) + { + if (info[i].ToString().Equals("ignoreMaxTimeDiff")) j = i; + if (info[i].ToString().Equals("ignoreMaxValDiff")) k = i; } + return info; } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesInformation.cs b/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesInformation.cs index c528c45b..b4a4ab6a 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesInformation.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesInformation.cs @@ -1,3 +1,4 @@ +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using StackExchange.Redis; using NRedisStack.DataTypes; using NRedisStack.Literals.Enums; @@ -6,116 +7,108 @@ using NRedisStack.Tests; -namespace NRedisTimeSeries.Test.TestDataTypes +namespace NRedisTimeSeries.Test.TestDataTypes; + +public class TestInformation(EndpointsFixture endpointsFixture) + : AbstractNRedisStackTest(endpointsFixture) { - public class TestInformation : AbstractNRedisStackTest + [SkipIfRedisFact(Comparison.GreaterThanOrEqual, "7.9.240")] + public void TestInformationSync() + { + string key = CreateKeyName(); + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + ts.Add(key, "*", 1.1); + ts.Add(key, "*", 1.3, duplicatePolicy: TsDuplicatePolicy.LAST); + + TimeSeriesInformation info = ts.Info(key); + TimeSeriesInformation infoDebug = ts.Info(key, debug: true); + + Assert.Equal(0, info.RetentionTime); + Assert.Equal(1, info.ChunkCount); + Assert.Null(info.DuplicatePolicy); + Assert.Null(info.KeySelfName); + Assert.Null(info.Chunks); + + Assert.Equal(0, infoDebug.RetentionTime); + Assert.Equal(1, infoDebug.ChunkCount); + Assert.Null(infoDebug.DuplicatePolicy); + Assert.Equal(infoDebug.KeySelfName, key); + Assert.Single(infoDebug.Chunks!); + } + + [SkipIfRedisFact(Comparison.GreaterThanOrEqual, "7.9.240")] + public async Task TestInformationAsync() + { + string key = CreateKeyName(); + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + await ts.AddAsync(key, "*", 1.1); + await ts.AddAsync(key, "*", 1.3, duplicatePolicy: TsDuplicatePolicy.LAST); + + TimeSeriesInformation info = await ts.InfoAsync(key); + TimeSeriesInformation infoDebug = await ts.InfoAsync(key, debug: true); + + Assert.Equal(0, info.RetentionTime); + Assert.Equal(1, info.ChunkCount); + Assert.Null(info.DuplicatePolicy); + Assert.Null(info.KeySelfName); + Assert.Null(info.Chunks); + + Assert.Equal(0, infoDebug.RetentionTime); + Assert.Equal(1, infoDebug.ChunkCount); + Assert.Null(infoDebug.DuplicatePolicy); + Assert.Equal(infoDebug.KeySelfName, key); + Assert.Single(infoDebug.Chunks!); + } + + [SkipIfRedisFact(Comparison.LessThan, "7.9.240")] + public void TestInformationSync_CE80() + { + string key = CreateKeyName(); + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + ts.Add(key, "*", 1.1); + ts.Add(key, "*", 1.3, duplicatePolicy: TsDuplicatePolicy.LAST); + + TimeSeriesInformation info = ts.Info(key); + TimeSeriesInformation infoDebug = ts.Info(key, debug: true); + + Assert.Equal(0, info.RetentionTime); + Assert.Equal(1, info.ChunkCount); + Assert.Equal(TsDuplicatePolicy.BLOCK, info.DuplicatePolicy); + Assert.Null(info.KeySelfName); + Assert.Null(info.Chunks); + + Assert.Equal(0, infoDebug.RetentionTime); + Assert.Equal(1, infoDebug.ChunkCount); + Assert.Equal(TsDuplicatePolicy.BLOCK, infoDebug.DuplicatePolicy); + Assert.Equal(infoDebug.KeySelfName, key); + Assert.Single(infoDebug.Chunks!); + } + + [SkipIfRedisFact(Comparison.LessThan, "7.9.240")] + public async Task TestInformationAsync_CE80() { - public TestInformation(NRedisStack.Tests.EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } - - [SkipIfRedis(Comparison.GreaterThanOrEqual, "7.9.240")] - [InlineData] - public void TestInformationSync() - { - string key = CreateKeyName(); - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - ts.Add(key, "*", 1.1); - ts.Add(key, "*", 1.3, duplicatePolicy: TsDuplicatePolicy.LAST); - - TimeSeriesInformation info = ts.Info(key); - TimeSeriesInformation infoDebug = ts.Info(key, debug: true); - - Assert.Equal(0, info.RetentionTime); - Assert.Equal(1, info.ChunkCount); - Assert.Null(info.DuplicatePolicy); - Assert.Null(info.KeySelfName); - Assert.Null(info.Chunks); - - Assert.Equal(0, infoDebug.RetentionTime); - Assert.Equal(1, infoDebug.ChunkCount); - Assert.Null(infoDebug.DuplicatePolicy); - Assert.Equal(infoDebug.KeySelfName, key); - Assert.Single(infoDebug.Chunks!); - } - - [SkipIfRedis(Comparison.GreaterThanOrEqual, "7.9.240")] - [InlineData] - public async Task TestInformationAsync() - { - string key = CreateKeyName(); - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - await ts.AddAsync(key, "*", 1.1); - await ts.AddAsync(key, "*", 1.3, duplicatePolicy: TsDuplicatePolicy.LAST); - - TimeSeriesInformation info = await ts.InfoAsync(key); - TimeSeriesInformation infoDebug = await ts.InfoAsync(key, debug: true); - - Assert.Equal(0, info.RetentionTime); - Assert.Equal(1, info.ChunkCount); - Assert.Null(info.DuplicatePolicy); - Assert.Null(info.KeySelfName); - Assert.Null(info.Chunks); - - Assert.Equal(0, infoDebug.RetentionTime); - Assert.Equal(1, infoDebug.ChunkCount); - Assert.Null(infoDebug.DuplicatePolicy); - Assert.Equal(infoDebug.KeySelfName, key); - Assert.Single(infoDebug.Chunks!); - } - - [SkipIfRedis(Comparison.LessThan, "7.9.240")] - [InlineData] - public void TestInformationSync_CE80() - { - string key = CreateKeyName(); - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - ts.Add(key, "*", 1.1); - ts.Add(key, "*", 1.3, duplicatePolicy: TsDuplicatePolicy.LAST); - - TimeSeriesInformation info = ts.Info(key); - TimeSeriesInformation infoDebug = ts.Info(key, debug: true); - - Assert.Equal(0, info.RetentionTime); - Assert.Equal(1, info.ChunkCount); - Assert.Equal(TsDuplicatePolicy.BLOCK, info.DuplicatePolicy); - Assert.Null(info.KeySelfName); - Assert.Null(info.Chunks); - - Assert.Equal(0, infoDebug.RetentionTime); - Assert.Equal(1, infoDebug.ChunkCount); - Assert.Equal(TsDuplicatePolicy.BLOCK, infoDebug.DuplicatePolicy); - Assert.Equal(infoDebug.KeySelfName, key); - Assert.Single(infoDebug.Chunks!); - } - - [SkipIfRedis(Comparison.LessThan, "7.9.240")] - [InlineData] - public async Task TestInformationAsync_CE80() - { - string key = CreateKeyName(); - IDatabase db = GetCleanDatabase(); - var ts = db.TS(); - await ts.AddAsync(key, "*", 1.1); - await ts.AddAsync(key, "*", 1.3, duplicatePolicy: TsDuplicatePolicy.LAST); - - TimeSeriesInformation info = await ts.InfoAsync(key); - TimeSeriesInformation infoDebug = await ts.InfoAsync(key, debug: true); - - Assert.Equal(0, info.RetentionTime); - Assert.Equal(1, info.ChunkCount); - Assert.Equal(TsDuplicatePolicy.BLOCK, info.DuplicatePolicy); - Assert.Null(info.KeySelfName); - Assert.Null(info.Chunks); - - Assert.Equal(0, infoDebug.RetentionTime); - Assert.Equal(1, infoDebug.ChunkCount); - Assert.Equal(TsDuplicatePolicy.BLOCK, infoDebug.DuplicatePolicy); - Assert.Equal(infoDebug.KeySelfName, key); - Assert.Single(infoDebug.Chunks!); - } + string key = CreateKeyName(); + IDatabase db = GetCleanDatabase(); + var ts = db.TS(); + await ts.AddAsync(key, "*", 1.1); + await ts.AddAsync(key, "*", 1.3, duplicatePolicy: TsDuplicatePolicy.LAST); + + TimeSeriesInformation info = await ts.InfoAsync(key); + TimeSeriesInformation infoDebug = await ts.InfoAsync(key, debug: true); + + Assert.Equal(0, info.RetentionTime); + Assert.Equal(1, info.ChunkCount); + Assert.Equal(TsDuplicatePolicy.BLOCK, info.DuplicatePolicy); + Assert.Null(info.KeySelfName); + Assert.Null(info.Chunks); + + Assert.Equal(0, infoDebug.RetentionTime); + Assert.Equal(1, infoDebug.ChunkCount); + Assert.Equal(TsDuplicatePolicy.BLOCK, infoDebug.DuplicatePolicy); + Assert.Equal(infoDebug.KeySelfName, key); + Assert.Single(infoDebug.Chunks!); } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesLabel.cs b/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesLabel.cs index 092a85ac..7d85c272 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesLabel.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesLabel.cs @@ -1,50 +1,49 @@ using NRedisStack.DataTypes; using Xunit; -namespace NRedisTimeSeries.Test.TestDataTypes +namespace NRedisTimeSeries.Test.TestDataTypes; + +public class TestLabel { - public class TestLabel + [Fact] + public void TestLabelConstructor() + { + TimeSeriesLabel label = new("a", "b"); + Assert.Equal("a", label.Key); + Assert.Equal("b", label.Value); + } + + + [Fact] + public void TestLbaelEquals() + { + TimeSeriesLabel label_ab = new("a", "b"); + TimeSeriesLabel label1 = new("a", "b"); + TimeSeriesLabel label2 = new("a", "c"); + TimeSeriesLabel label3 = new("c", "b"); + + Assert.Equal(label_ab, label1); + Assert.NotEqual(label_ab, label2); + Assert.NotEqual(label_ab, label3); + } + + [Fact] + public void TestLabelHashCode() + { + TimeSeriesLabel label_ab = new("a", "b"); + TimeSeriesLabel label1 = new("a", "b"); + TimeSeriesLabel label2 = new("a", "c"); + TimeSeriesLabel label3 = new("c", "b"); + + Assert.Equal(label_ab.GetHashCode(), label1.GetHashCode()); + Assert.NotEqual(label_ab.GetHashCode(), label2.GetHashCode()); + Assert.NotEqual(label_ab.GetHashCode(), label3.GetHashCode()); + } + + [Fact] + public void TestLabelToString() { - [Fact] - public void TestLabelConstructor() - { - TimeSeriesLabel label = new TimeSeriesLabel("a", "b"); - Assert.Equal("a", label.Key); - Assert.Equal("b", label.Value); - } - - - [Fact] - public void TestLbaelEquals() - { - TimeSeriesLabel label_ab = new TimeSeriesLabel("a", "b"); - TimeSeriesLabel label1 = new TimeSeriesLabel("a", "b"); - TimeSeriesLabel label2 = new TimeSeriesLabel("a", "c"); - TimeSeriesLabel label3 = new TimeSeriesLabel("c", "b"); - - Assert.Equal(label_ab, label1); - Assert.NotEqual(label_ab, label2); - Assert.NotEqual(label_ab, label3); - } - - [Fact] - public void TestLabelHashCode() - { - TimeSeriesLabel label_ab = new TimeSeriesLabel("a", "b"); - TimeSeriesLabel label1 = new TimeSeriesLabel("a", "b"); - TimeSeriesLabel label2 = new TimeSeriesLabel("a", "c"); - TimeSeriesLabel label3 = new TimeSeriesLabel("c", "b"); - - Assert.Equal(label_ab.GetHashCode(), label1.GetHashCode()); - Assert.NotEqual(label_ab.GetHashCode(), label2.GetHashCode()); - Assert.NotEqual(label_ab.GetHashCode(), label3.GetHashCode()); - } - - [Fact] - public void TestLabelToString() - { - TimeSeriesLabel label = new TimeSeriesLabel("a", "b"); - Assert.Equal("Key: a, Val:b", (string)label); - } + TimeSeriesLabel label = new("a", "b"); + Assert.Equal("Key: a, Val:b", (string)label); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesRule.cs b/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesRule.cs index a4eac165..64fedb08 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesRule.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesRule.cs @@ -2,58 +2,57 @@ using NRedisStack.DataTypes; using Xunit; -namespace NRedisTimeSeries.Test.TestDataTypes +namespace NRedisTimeSeries.Test.TestDataTypes; + +public class TestTimeSeriesRule { - public class TestTimeSeriesRule + public TestTimeSeriesRule() { } + + [Fact] + public void TestRuleConstructor() + { + TimeSeriesRule rule = new("key", 50, TsAggregation.Avg); + Assert.Equal("key", rule.DestKey); + Assert.Equal(TsAggregation.Avg, rule.Aggregation); + Assert.Equal(50, rule.TimeBucket); + } + + [Fact] + public void TestRuleEquals() + { + TimeSeriesRule rule = new("key", 50, TsAggregation.Avg); + + TimeSeriesRule rule1 = new("key", 50, TsAggregation.Avg); + TimeSeriesRule rule2 = new("key2", 50, TsAggregation.Avg); + TimeSeriesRule rule3 = new("key", 51, TsAggregation.Avg); + TimeSeriesRule rule4 = new("key", 50, TsAggregation.Count); + + Assert.Equal(rule, rule1); + Assert.NotEqual(rule, rule2); + Assert.NotEqual(rule, rule3); + Assert.NotEqual(rule, rule4); + } + + [Fact] + public void TestRuleHashCode() + { + TimeSeriesRule rule = new("key", 50, TsAggregation.Avg); + + TimeSeriesRule rule1 = new("key", 50, TsAggregation.Avg); + TimeSeriesRule rule2 = new("key2", 50, TsAggregation.Avg); + TimeSeriesRule rule3 = new("key", 51, TsAggregation.Avg); + TimeSeriesRule rule4 = new("key", 50, TsAggregation.Count); + + Assert.Equal(rule.GetHashCode(), rule1.GetHashCode()); + Assert.NotEqual(rule.GetHashCode(), rule2.GetHashCode()); + Assert.NotEqual(rule.GetHashCode(), rule3.GetHashCode()); + Assert.NotEqual(rule.GetHashCode(), rule4.GetHashCode()); + } + + [Fact] + public void TestRuleToString() { - public TestTimeSeriesRule() { } - - [Fact] - public void TestRuleConstructor() - { - TimeSeriesRule rule = new TimeSeriesRule("key", 50, TsAggregation.Avg); - Assert.Equal("key", rule.DestKey); - Assert.Equal(TsAggregation.Avg, rule.Aggregation); - Assert.Equal(50, rule.TimeBucket); - } - - [Fact] - public void TestRuleEquals() - { - TimeSeriesRule rule = new TimeSeriesRule("key", 50, TsAggregation.Avg); - - TimeSeriesRule rule1 = new TimeSeriesRule("key", 50, TsAggregation.Avg); - TimeSeriesRule rule2 = new TimeSeriesRule("key2", 50, TsAggregation.Avg); - TimeSeriesRule rule3 = new TimeSeriesRule("key", 51, TsAggregation.Avg); - TimeSeriesRule rule4 = new TimeSeriesRule("key", 50, TsAggregation.Count); - - Assert.Equal(rule, rule1); - Assert.NotEqual(rule, rule2); - Assert.NotEqual(rule, rule3); - Assert.NotEqual(rule, rule4); - } - - [Fact] - public void TestRuleHashCode() - { - TimeSeriesRule rule = new TimeSeriesRule("key", 50, TsAggregation.Avg); - - TimeSeriesRule rule1 = new TimeSeriesRule("key", 50, TsAggregation.Avg); - TimeSeriesRule rule2 = new TimeSeriesRule("key2", 50, TsAggregation.Avg); - TimeSeriesRule rule3 = new TimeSeriesRule("key", 51, TsAggregation.Avg); - TimeSeriesRule rule4 = new TimeSeriesRule("key", 50, TsAggregation.Count); - - Assert.Equal(rule.GetHashCode(), rule1.GetHashCode()); - Assert.NotEqual(rule.GetHashCode(), rule2.GetHashCode()); - Assert.NotEqual(rule.GetHashCode(), rule3.GetHashCode()); - Assert.NotEqual(rule.GetHashCode(), rule4.GetHashCode()); - } - - [Fact] - public void TestRuleToString() - { - TimeSeriesRule rule = new TimeSeriesRule("key", 50, TsAggregation.Avg); - Assert.Equal("DestinationKey: key, TimeBucket: 50, Aggregation: avg", (string)rule); - } + TimeSeriesRule rule = new("key", 50, TsAggregation.Avg); + Assert.Equal("DestinationKey: key, TimeBucket: 50, Aggregation: avg", (string)rule); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesTuple.cs b/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesTuple.cs index 1d6de180..3b070376 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesTuple.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeSeriesTuple.cs @@ -1,43 +1,42 @@ using NRedisStack.DataTypes; using Xunit; -namespace NRedisTimeSeries.Test +namespace NRedisTimeSeries.Test; + +public class TestTimeSeriesTuple { - public class TestTimeSeriesTuple + [Fact] + public void TestTupleConstructor() { - [Fact] - public void TestTupleConstructor() - { - TimeSeriesTuple tuple = new TimeSeriesTuple(1, 1.1); - Assert.Equal(1, tuple.Time); - Assert.Equal(1.1, tuple.Val); - } + TimeSeriesTuple tuple = new(1, 1.1); + Assert.Equal(1, tuple.Time); + Assert.Equal(1.1, tuple.Val); + } - [Fact] - public void TestTupleEqual() - { - TimeSeriesTuple tuple1 = new TimeSeriesTuple(1, 1.1); - TimeSeriesTuple tuple1_1 = new TimeSeriesTuple(1, 1.1); - TimeSeriesTuple tuple1_2 = new TimeSeriesTuple(2, 2.2); - Assert.Equal(tuple1, tuple1_1); - Assert.NotEqual(tuple1, tuple1_2); - } + [Fact] + public void TestTupleEqual() + { + TimeSeriesTuple tuple1 = new(1, 1.1); + TimeSeriesTuple tuple1_1 = new(1, 1.1); + TimeSeriesTuple tuple1_2 = new(2, 2.2); + Assert.Equal(tuple1, tuple1_1); + Assert.NotEqual(tuple1, tuple1_2); + } - [Fact] - public void TestTupleHashCode() - { - TimeSeriesTuple tuple1 = new TimeSeriesTuple(1, 1.1); - TimeSeriesTuple tuple1_1 = new TimeSeriesTuple(1, 1.1); - TimeSeriesTuple tuple1_2 = new TimeSeriesTuple(2, 2.2); - Assert.Equal(tuple1.GetHashCode(), tuple1_1.GetHashCode()); - Assert.NotEqual(tuple1.GetHashCode(), tuple1_2.GetHashCode()); - } + [Fact] + public void TestTupleHashCode() + { + TimeSeriesTuple tuple1 = new(1, 1.1); + TimeSeriesTuple tuple1_1 = new(1, 1.1); + TimeSeriesTuple tuple1_2 = new(2, 2.2); + Assert.Equal(tuple1.GetHashCode(), tuple1_1.GetHashCode()); + Assert.NotEqual(tuple1.GetHashCode(), tuple1_2.GetHashCode()); + } - [Fact] - public void TestTupleToString() - { - TimeSeriesTuple tuple = new TimeSeriesTuple(1, 1.1); - Assert.Equal("Time: 1, Val:1.1", (string)tuple); - } + [Fact] + public void TestTupleToString() + { + TimeSeriesTuple tuple = new(1, 1.1); + Assert.Equal("Time: 1, Val:1.1", (string)tuple); } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeStamp.cs b/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeStamp.cs index d083166c..7926c8c4 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeStamp.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TestDataTypes/TestTimeStamp.cs @@ -1,32 +1,31 @@ using NRedisStack.DataTypes; using Xunit; -namespace NRedisTimeSeries.Test +namespace NRedisTimeSeries.Test; + +public class TestTimeStamp { - public class TestTimeStamp - { - [Fact] - public void TestTimeStampImplicitCast() - { - TimeStamp ts = 1; - Assert.Equal(1, ts); + [Fact] + public void TestTimeStampImplicitCast() + { + TimeStamp ts = 1; + Assert.Equal(1, ts); - ts = "+"; - Assert.Equal("+", ts); + ts = "+"; + Assert.Equal("+", ts); - ts = "*"; - Assert.Equal("*", ts); + ts = "*"; + Assert.Equal("*", ts); - ts = "-"; - Assert.Equal("-", ts); + ts = "-"; + Assert.Equal("-", ts); - var ex = Assert.Throws(() => ts = "hi"); - Assert.Equal("The string hi cannot be used", ex.Message); + var ex = Assert.Throws(() => ts = "hi"); + Assert.Equal("The string hi cannot be used", ex.Message); - DateTime now = DateTime.UtcNow; - ts = now; - Assert.Equal(new DateTimeOffset(now).ToUnixTimeMilliseconds(), ts.Value); + DateTime now = DateTime.UtcNow; + ts = now; + Assert.Equal(new DateTimeOffset(now).ToUnixTimeMilliseconds(), ts.Value); - } } -} +} \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TimeSeries/TimeSeriesTests.cs b/tests/NRedisStack.Tests/TimeSeries/TimeSeriesTests.cs index c8027588..46651651 100644 --- a/tests/NRedisStack.Tests/TimeSeries/TimeSeriesTests.cs +++ b/tests/NRedisStack.Tests/TimeSeries/TimeSeriesTests.cs @@ -5,12 +5,8 @@ namespace NRedisStack.Tests.TimeSeries; -public class TimeSeriesTests : AbstractNRedisStackTest, IDisposable +public class TimeSeriesTests(EndpointsFixture endpointsFixture) : AbstractNRedisStackTest(endpointsFixture), IDisposable { - public TimeSeriesTests(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } - [Fact] public void TestModulePrefixs() { diff --git a/tests/NRedisStack.Tests/TokenBasedAuthentication/AuthenticationTests.cs b/tests/NRedisStack.Tests/TokenBasedAuthentication/AuthenticationTests.cs index ef8e9fcc..cd43ee1f 100644 --- a/tests/NRedisStack.Tests/TokenBasedAuthentication/AuthenticationTests.cs +++ b/tests/NRedisStack.Tests/TokenBasedAuthentication/AuthenticationTests.cs @@ -1,58 +1,58 @@ +#pragma warning disable CS0618, CS0612 // allow testing obsolete methods using Xunit; using StackExchange.Redis; using Azure.Identity; using NRedisStack.RedisStackCommands; using NRedisStack.Search; -namespace NRedisStack.Tests.TokenBasedAuthentication +namespace NRedisStack.Tests.TokenBasedAuthentication; + +public class AuthenticationTests : AbstractNRedisStackTest { - public class AuthenticationTests : AbstractNRedisStackTest + public AuthenticationTests(EndpointsFixture endpointsFixture) : base(endpointsFixture) { - public AuthenticationTests(EndpointsFixture endpointsFixture) : base(endpointsFixture) - { - } + } - static readonly string key = "myKey"; - static readonly string value = "myValue"; - static readonly string index = "myIndex"; - static readonly string field = "myField"; - static readonly string alias = "myAlias"; + static readonly string key = "myKey"; + static readonly string value = "myValue"; + static readonly string index = "myIndex"; + static readonly string field = "myField"; + static readonly string alias = "myAlias"; - [SkippableFact] - public void TestTokenBasedAuthentication() - { - // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection - SkipIfTargetConnectionDoesNotExist(EndpointsFixture.Env.StandaloneEntraId); + [SkippableFact] + public void TestTokenBasedAuthentication() + { + // This is needed because we're constructing ConfigurationOptions in the test before calling GetConnection + SkipIfTargetConnectionDoesNotExist(EndpointsFixture.Env.StandaloneEntraId); - var configurationOptions = new ConfigurationOptions().ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential()).Result!; - configurationOptions.Ssl = false; - configurationOptions.AbortOnConnectFail = true; // Fail fast for the purposes of this sample. In production code, this should remain false to retry connections on startup + var configurationOptions = new ConfigurationOptions().ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential()).Result; + configurationOptions.Ssl = false; + configurationOptions.AbortOnConnectFail = true; // Fail fast for the purposes of this sample. In production code, this should remain false to retry connections on startup - ConnectionMultiplexer? connectionMultiplexer = GetConnection(configurationOptions, EndpointsFixture.Env.StandaloneEntraId); + ConnectionMultiplexer? connectionMultiplexer = GetConnection(configurationOptions, EndpointsFixture.Env.StandaloneEntraId); - IDatabase db = connectionMultiplexer.GetDatabase(); + IDatabase db = connectionMultiplexer.GetDatabase(); - db.KeyDelete(key); - try - { - db.FT().DropIndex(index); - } - catch { } + db.KeyDelete(key); + try + { + db.FT().DropIndex(index); + } + catch { } - db.StringSet(key, value); - string result = db.StringGet(key); - Assert.Equal(value, result); + db.StringSet(key, value); + string result = db.StringGet(key)!; + Assert.Equal(value, result); - var ft = db.FT(); - Schema sc = new Schema().AddTextField(field); - Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); + var ft = db.FT(); + Schema sc = new Schema().AddTextField(field); + Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc)); - db.HashSet(index, new HashEntry[] { new HashEntry(field, value) }); + db.HashSet(index, [new(field, value)]); - Assert.True(ft.AliasAdd(alias, index)); - SearchResult res1 = ft.Search(alias, new Query("*").ReturnFields(field)); - Assert.Equal(1, res1.TotalResults); - Assert.Equal(value, res1.Documents[0][field]); - } + Assert.True(ft.AliasAdd(alias, index)); + SearchResult res1 = ft.Search(alias, new Query("*").ReturnFields(field)); + Assert.Equal(1, res1.TotalResults); + Assert.Equal(value, res1.Documents[0][field]); } } \ No newline at end of file diff --git a/tests/NRedisStack.Tests/TokenBasedAuthentication/FaultInjectorClient.cs b/tests/NRedisStack.Tests/TokenBasedAuthentication/FaultInjectorClient.cs index cf319cf1..920d0ee5 100644 --- a/tests/NRedisStack.Tests/TokenBasedAuthentication/FaultInjectorClient.cs +++ b/tests/NRedisStack.Tests/TokenBasedAuthentication/FaultInjectorClient.cs @@ -1,6 +1,7 @@ +using System.Diagnostics; +using System.Net.Http; using System.Text; using System.Text.Json; -using System.Net.Http; public class FaultInjectorClient { @@ -61,7 +62,7 @@ public async Task IsCompletedAsync(TimeSpan checkInterval, TimeSpan delayA } catch (HttpRequestException e) { - throw new Exception("Fault injection proxy error", e); + throw new("Fault injection proxy error", e); } } return false; @@ -103,10 +104,11 @@ public async Task TriggerActionAsync(string actionType, D return JsonSerializer.Deserialize(result, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }); + })!; } catch (HttpRequestException e) { + Debug.WriteLine(e); throw; } } diff --git a/tests/NRedisStack.Tests/TopK/TopKTests.cs b/tests/NRedisStack.Tests/TopK/TopKTests.cs index 574b425d..027b6a66 100644 --- a/tests/NRedisStack.Tests/TopK/TopKTests.cs +++ b/tests/NRedisStack.Tests/TopK/TopKTests.cs @@ -25,10 +25,10 @@ public void CreateTopKFilter(string endpointId) var res = topk.Add(key, "bb", "cc"); Assert.True(res![0].IsNull && res[1].IsNull); - Assert.Equal(topk.Query(key, "bb", "gg", "cc"), new bool[] { true, false, true }); + Assert.Equal(topk.Query(key, "bb", "gg", "cc"), new[] { true, false, true }); Assert.False(topk.Query(key, "notExists")); - Assert.Equal(topk.Count(key, "bb", "gg", "cc"), new long[] { 1, 0, 1 }); + Assert.Equal(topk.Count(key, "bb", "gg", "cc"), [1, 0, 1]); var res2 = topk.List(key); Assert.Equal("bb", res2[0].ToString()); @@ -62,10 +62,10 @@ public async Task CreateTopKFilterAsync(string endpointId) var res = await topk.AddAsync(key, "bb", "cc"); Assert.True(res![0].IsNull && res[1].IsNull); - Assert.Equal(await topk.QueryAsync(key, "bb", "gg", "cc"), new bool[] { true, false, true }); + Assert.Equal(await topk.QueryAsync(key, "bb", "gg", "cc"), new[] { true, false, true }); Assert.False(await topk.QueryAsync(key, "notExists")); - Assert.Equal(await topk.CountAsync(key, "bb", "gg", "cc"), new long[] { 1, 0, 1 }); + Assert.Equal(await topk.CountAsync(key, "bb", "gg", "cc"), [1, 0, 1]); var res2 = await topk.ListAsync(key); Assert.Equal("bb", res2[0].ToString()); diff --git a/tests/NRedisStack.Tests/TransactionsTests.cs b/tests/NRedisStack.Tests/TransactionsTests.cs index 62f1a086..ca7dabe1 100644 --- a/tests/NRedisStack.Tests/TransactionsTests.cs +++ b/tests/NRedisStack.Tests/TransactionsTests.cs @@ -33,7 +33,7 @@ public void TestJsonTransaction(string endpointId) Assert.Equal("{\"Name\":\"Shachar\",\"Age\":23}", getResponse.Result.ToString()); } - [SkipIfRedis(Comparison.GreaterThanOrEqual, "7.1.242")] + [SkipIfRedisTheory(Comparison.GreaterThanOrEqual, "7.1.242")] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] [Obsolete] public void TestModulesTransaction(string endpointId) @@ -46,7 +46,7 @@ public void TestModulesTransaction(string endpointId) _ = tran.Cms.InitByDimAsync("cms-key", 100, 5); _ = tran.Cf.ReserveAsync("cf-key", 100); _ = tran.Json.SetAsync("json-key", "$", "{}"); - _ = tran.Ft.CreateAsync("ft-key", new FTCreateParams(), new Schema().AddTextField("txt")); + _ = tran.Ft.CreateAsync("ft-key", new(), new Schema().AddTextField("txt")); _ = tran.Tdigest.CreateAsync("tdigest-key", 100); _ = tran.Ts.CreateAsync("ts-key", 100); _ = tran.TopK.ReserveAsync("topk-key", 100, 100, 100); @@ -81,7 +81,7 @@ public void TestModulesTransaction(string endpointId) Assert.NotNull(db.TOPK().Info("topk-key")); } - [SkipIfRedis(Is.Enterprise)] + [SkipIfRedisTheory(Is.Enterprise)] [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] [Obsolete] public void TestModulesTransactionWithoutGraph(string endpointId) @@ -94,7 +94,7 @@ public void TestModulesTransactionWithoutGraph(string endpointId) _ = tran.Cms.InitByDimAsync("cms-key", 100, 5); _ = tran.Cf.ReserveAsync("cf-key", 100); _ = tran.Json.SetAsync("json-key", "$", "{}"); - _ = tran.Ft.CreateAsync("ft-key", new FTCreateParams(), new Schema().AddTextField("txt")); + _ = tran.Ft.CreateAsync("ft-key", new(), new Schema().AddTextField("txt")); _ = tran.Tdigest.CreateAsync("tdigest-key", 100); _ = tran.Ts.CreateAsync("ts-key", 100); _ = tran.TopK.ReserveAsync("topk-key", 100, 100, 100); From 44a475876dd6308a3ccc483602b54f566b5015d0 Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Tue, 5 Aug 2025 13:26:26 +0300 Subject: [PATCH 06/10] missed merge --- src/NRedisStack/Search/FieldName.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/NRedisStack/Search/FieldName.cs b/src/NRedisStack/Search/FieldName.cs index eee3ca7e..8977588f 100644 --- a/src/NRedisStack/Search/FieldName.cs +++ b/src/NRedisStack/Search/FieldName.cs @@ -26,15 +26,14 @@ public int AddCommandArguments(List args) return 3; } - public static FieldName Of(string name) - { - return new FieldName(name); - } + public static FieldName Of(string name) => new(name); public FieldName As(string attribute) { this.Alias = attribute; return this; } + + public static implicit operator FieldName(string name) => new(name); } } \ No newline at end of file From 4e5e54643bd06097f203b8255f2bf8a3e24ece2a Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Tue, 5 Aug 2025 13:40:14 +0300 Subject: [PATCH 07/10] add missing 0 from test; enable net9 --- tests/NRedisStack.Tests/NRedisStack.Tests.csproj | 2 +- tests/NRedisStack.Tests/Search/IndexCreationTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/NRedisStack.Tests/NRedisStack.Tests.csproj b/tests/NRedisStack.Tests/NRedisStack.Tests.csproj index 465b3fbf..5d756454 100644 --- a/tests/NRedisStack.Tests/NRedisStack.Tests.csproj +++ b/tests/NRedisStack.Tests/NRedisStack.Tests.csproj @@ -1,6 +1,6 @@ - net6.0;net7.0;net8.0;net481 + net6.0;net7.0;net8.0;net9.0;net481 false true diff --git a/tests/NRedisStack.Tests/Search/IndexCreationTests.cs b/tests/NRedisStack.Tests/Search/IndexCreationTests.cs index bcaff246..8e0f2036 100644 --- a/tests/NRedisStack.Tests/Search/IndexCreationTests.cs +++ b/tests/NRedisStack.Tests/Search/IndexCreationTests.cs @@ -35,7 +35,7 @@ public void TestMissingEmptyFieldCommandArgs() "numeric1","NUMERIC", INDEXMISSING, "geo1","GEO", INDEXMISSING, "geoshape1","GEOSHAPE", "FLAT", INDEXMISSING, - "vector1","VECTOR","FLAT", INDEXMISSING}; + "vector1","VECTOR","FLAT", 0, INDEXMISSING}; Assert.Equal(expectedArgs, cmd.Args); } From 785cf1fd4f019b90b11222255cb5acd85cf91fac Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Tue, 5 Aug 2025 14:11:16 +0300 Subject: [PATCH 08/10] migrate upstream tests --- NRedisStack.sln.DotSettings | 7 + .../Search/IndexCreationTests.cs | 244 +++++++++++++++--- 2 files changed, 212 insertions(+), 39 deletions(-) create mode 100644 NRedisStack.sln.DotSettings diff --git a/NRedisStack.sln.DotSettings b/NRedisStack.sln.DotSettings new file mode 100644 index 00000000..a53aa8e9 --- /dev/null +++ b/NRedisStack.sln.DotSettings @@ -0,0 +1,7 @@ + + True + True + True + True + True + True \ No newline at end of file diff --git a/tests/NRedisStack.Tests/Search/IndexCreationTests.cs b/tests/NRedisStack.Tests/Search/IndexCreationTests.cs index 8e0f2036..3a8ec19b 100644 --- a/tests/NRedisStack.Tests/Search/IndexCreationTests.cs +++ b/tests/NRedisStack.Tests/Search/IndexCreationTests.cs @@ -1,3 +1,4 @@ +using System.Runtime.InteropServices; using StackExchange.Redis; using NRedisStack.Search; using NRedisStack.RedisStackCommands; @@ -11,31 +12,40 @@ public class IndexCreationTests(EndpointsFixture endpointsFixture) { private readonly string index = "MISSING_EMPTY_INDEX"; + // ReSharper disable once InconsistentNaming private static readonly string INDEXMISSING = "INDEXMISSING"; + + // ReSharper disable once InconsistentNaming private static readonly string INDEXEMPTY = "INDEXEMPTY"; + + // ReSharper disable once InconsistentNaming private static readonly string SORTABLE = "SORTABLE"; [Fact] public void TestMissingEmptyFieldCommandArgs() { Schema sc = new Schema() - .AddTextField("text1", 1.0, missingIndex: true, emptyIndex: true) - .AddTagField("tag1", missingIndex: true, emptyIndex: true) - .AddNumericField("numeric1", missingIndex: true) - .AddGeoField("geo1", missingIndex: true) - .AddGeoShapeField("geoshape1", Schema.GeoShapeField.CoordinateSystem.FLAT, missingIndex: true) - .AddVectorField("vector1", Schema.VectorField.VectorAlgo.FLAT, missingIndex: true); + // ReSharper disable once RedundantArgumentDefaultValue + .AddTextField("text1", 1.0, missingIndex: true, emptyIndex: true) + .AddTagField("tag1", missingIndex: true, emptyIndex: true) + .AddNumericField("numeric1", missingIndex: true) + .AddGeoField("geo1", missingIndex: true) + .AddGeoShapeField("geoshape1", Schema.GeoShapeField.CoordinateSystem.FLAT, missingIndex: true) + .AddVectorField("vector1", Schema.VectorField.VectorAlgo.FLAT, missingIndex: true); var ftCreateParams = FTCreateParams.CreateParams(); var cmd = SearchCommandBuilder.Create(index, ftCreateParams, sc); - var expectedArgs = new object[] { "MISSING_EMPTY_INDEX", "SCHEMA", - "text1","TEXT",INDEXMISSING,INDEXEMPTY, - "tag1","TAG", INDEXMISSING,INDEXEMPTY, - "numeric1","NUMERIC", INDEXMISSING, - "geo1","GEO", INDEXMISSING, - "geoshape1","GEOSHAPE", "FLAT", INDEXMISSING, - "vector1","VECTOR","FLAT", 0, INDEXMISSING}; + var expectedArgs = new object[] + { + "MISSING_EMPTY_INDEX", "SCHEMA", + "text1", "TEXT", INDEXMISSING, INDEXEMPTY, + "tag1", "TAG", INDEXMISSING, INDEXEMPTY, + "numeric1", "NUMERIC", INDEXMISSING, + "geo1", "GEO", INDEXMISSING, + "geoshape1", "GEOSHAPE", "FLAT", INDEXMISSING, + "vector1", "VECTOR", "FLAT", 0, INDEXMISSING + }; Assert.Equal(expectedArgs, cmd.Args); } @@ -44,6 +54,7 @@ public void TestMissingEmptyFieldCommandArgs() public void TestMissingFields(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); + // ReSharper disable once RedundantArgumentDefaultValue var ft = db.FT(2); var vectorAttrs = new Dictionary() { @@ -52,12 +63,13 @@ public void TestMissingFields(string endpointId) ["DISTANCE_METRIC"] = "L2", }; Schema sc = new Schema() - .AddTextField("text1", 1.0, missingIndex: true) - .AddTagField("tag1", missingIndex: true) - .AddNumericField("numeric1", missingIndex: true) - .AddGeoField("geo1", missingIndex: true) - .AddGeoShapeField("geoshape1", Schema.GeoShapeField.CoordinateSystem.FLAT, missingIndex: true) - .AddVectorField("vector1", Schema.VectorField.VectorAlgo.FLAT, vectorAttrs, missingIndex: true); + // ReSharper disable once RedundantArgumentDefaultValue + .AddTextField("text1", 1.0, missingIndex: true) + .AddTagField("tag1", missingIndex: true) + .AddNumericField("numeric1", missingIndex: true) + .AddGeoField("geo1", missingIndex: true) + .AddGeoShapeField("geoshape1", Schema.GeoShapeField.CoordinateSystem.FLAT, missingIndex: true) + .AddVectorField("vector1", Schema.VectorField.VectorAlgo.FLAT, vectorAttrs, missingIndex: true); var ftCreateParams = FTCreateParams.CreateParams(); Assert.True(ft.Create(index, ftCreateParams, sc)); @@ -67,7 +79,11 @@ public void TestMissingFields(string endpointId) Polygon polygon = new GeometryFactory().CreatePolygon([new(1, 1), new(10, 10), new(100, 100), new(1, 1)]); - var hashWithAllFields = new HashEntry[] { new("text1", "value1"), new("tag1", "value2"), new("numeric1", "3.141"), new("geo1", "-0.441,51.458"), new("geoshape1", polygon.ToString()), new("vector1", "aaaaaaaa") }; + var hashWithAllFields = new HashEntry[] + { + new("text1", "value1"), new("tag1", "value2"), new("numeric1", "3.141"), new("geo1", "-0.441,51.458"), + new("geoshape1", polygon.ToString()), new("vector1", "aaaaaaaa") + }; db.HashSet("hashWithAllFields", hashWithAllFields); var result = ft.Search(index, new("ismissing(@text1)")); @@ -100,10 +116,12 @@ public void TestMissingFields(string endpointId) public void TestEmptyFields(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); + // ReSharper disable once RedundantArgumentDefaultValue var ft = db.FT(2); Schema sc = new Schema() - .AddTextField("text1", 1.0, emptyIndex: true) - .AddTagField("tag1", emptyIndex: true); + // ReSharper disable once RedundantArgumentDefaultValue + .AddTextField("text1", 1.0, emptyIndex: true) + .AddTagField("tag1", emptyIndex: true); var ftCreateParams = FTCreateParams.CreateParams(); Assert.True(ft.Create(index, ftCreateParams, sc)); @@ -121,7 +139,6 @@ public void TestEmptyFields(string endpointId) result = ft.Search(index, new("@tag1:{''}")); Assert.Equal(1, result.TotalResults); Assert.Equal("hashWithEmptyFields", result.Documents[0].Id); - } [SkipIfRedisTheory(Comparison.LessThan, "7.3.240")] @@ -129,6 +146,7 @@ public void TestEmptyFields(string endpointId) public void TestCreateFloat16VectorField(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); + // ReSharper disable once RedundantArgumentDefaultValue var ft = db.FT(2); var schema = new Schema().AddVectorField("v", Schema.VectorField.VectorAlgo.FLAT, new() { @@ -170,6 +188,7 @@ public void TestCreateFloat16VectorField(string endpointId) public void TestCreateInt8VectorField(string endpointId) { IDatabase db = GetCleanDatabase(endpointId); + // ReSharper disable once RedundantArgumentDefaultValue var ft = db.FT(2); var schema = new Schema().AddVectorField("v", Schema.VectorField.VectorAlgo.FLAT, new() { @@ -206,19 +225,23 @@ public void TestMissingSortableFieldCommandArgs() { string idx = "MISSING_EMPTY_SORTABLE_INDEX"; Schema sc = new Schema() - .AddTextField("text1", 1.0, missingIndex: true, emptyIndex: true, sortable: true) - .AddTagField("tag1", missingIndex: true, emptyIndex: true, sortable: true) - .AddNumericField("numeric1", missingIndex: true, sortable: true) - .AddGeoField("geo1", missingIndex: true, sortable: true); + // ReSharper disable once RedundantArgumentDefaultValue + .AddTextField("text1", 1.0, missingIndex: true, emptyIndex: true, sortable: true) + .AddTagField("tag1", missingIndex: true, emptyIndex: true, sortable: true) + .AddNumericField("numeric1", missingIndex: true, sortable: true) + .AddGeoField("geo1", missingIndex: true, sortable: true); var ftCreateParams = FTCreateParams.CreateParams(); var cmd = SearchCommandBuilder.Create(idx, ftCreateParams, sc); - var expectedArgs = new object[] { idx, "SCHEMA", - "text1","TEXT",INDEXMISSING,INDEXEMPTY,SORTABLE, - "tag1","TAG", INDEXMISSING,INDEXEMPTY,SORTABLE, - "numeric1","NUMERIC", INDEXMISSING,SORTABLE, - "geo1","GEO", INDEXMISSING, SORTABLE}; + var expectedArgs = new object[] + { + idx, "SCHEMA", + "text1", "TEXT", INDEXMISSING, INDEXEMPTY, SORTABLE, + "tag1", "TAG", INDEXMISSING, INDEXEMPTY, SORTABLE, + "numeric1", "NUMERIC", INDEXMISSING, SORTABLE, + "geo1", "GEO", INDEXMISSING, SORTABLE + }; Assert.Equal(expectedArgs, cmd.Args); } @@ -228,6 +251,7 @@ public void TestCombiningMissingEmptySortableFields(string endpointId) { string idx = "MISSING_EMPTY_SORTABLE_INDEX"; IDatabase db = GetCleanDatabase(endpointId); + // ReSharper disable once RedundantArgumentDefaultValue var ft = db.FT(2); var vectorAttrs = new Dictionary() { @@ -236,12 +260,13 @@ public void TestCombiningMissingEmptySortableFields(string endpointId) ["DISTANCE_METRIC"] = "L2", }; Schema sc = new Schema() - .AddTextField("text1", 1.0, missingIndex: true, emptyIndex: true, sortable: true) - .AddTagField("tag1", missingIndex: true, emptyIndex: true, sortable: true) - .AddNumericField("numeric1", missingIndex: true, sortable: true) - .AddGeoField("geo1", missingIndex: true, sortable: true) - .AddGeoShapeField("geoshape1", Schema.GeoShapeField.CoordinateSystem.FLAT, missingIndex: true) - .AddVectorField("vector1", Schema.VectorField.VectorAlgo.FLAT, vectorAttrs, missingIndex: true); + // ReSharper disable once RedundantArgumentDefaultValue + .AddTextField("text1", 1.0, missingIndex: true, emptyIndex: true, sortable: true) + .AddTagField("tag1", missingIndex: true, emptyIndex: true, sortable: true) + .AddNumericField("numeric1", missingIndex: true, sortable: true) + .AddGeoField("geo1", missingIndex: true, sortable: true) + .AddGeoShapeField("geoshape1", Schema.GeoShapeField.CoordinateSystem.FLAT, missingIndex: true) + .AddVectorField("vector1", Schema.VectorField.VectorAlgo.FLAT, vectorAttrs, missingIndex: true); var ftCreateParams = FTCreateParams.CreateParams(); Assert.True(ft.Create(idx, ftCreateParams, sc)); @@ -251,7 +276,11 @@ public void TestCombiningMissingEmptySortableFields(string endpointId) Polygon polygon = new GeometryFactory().CreatePolygon([new(1, 1), new(10, 10), new(100, 100), new(1, 1)]); - var hashWithAllFields = new HashEntry[] { new("text1", "value1"), new("tag1", "value2"), new("numeric1", "3.141"), new("geo1", "-0.441,51.458"), new("geoshape1", polygon.ToString()), new("vector1", "aaaaaaaa") }; + var hashWithAllFields = new HashEntry[] + { + new("text1", "value1"), new("tag1", "value2"), new("numeric1", "3.141"), new("geo1", "-0.441,51.458"), + new("geoshape1", polygon.ToString()), new("vector1", "aaaaaaaa") + }; db.HashSet("hashWithAllFields", hashWithAllFields); var result = ft.Search(idx, new("ismissing(@text1)")); @@ -279,5 +308,142 @@ public void TestCombiningMissingEmptySortableFields(string endpointId) Assert.Equal("hashWithMissingFields", result.Documents[0].Id); } + [SkipIfRedisTheory(Comparison.LessThan, "8.1.240")] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestCreate_Float16_Int32_VectorField_Svs(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + // ReSharper disable once RedundantArgumentDefaultValue + var ft = db.FT(2); + var schema = new Schema().AddSvsVanamaVectorField("v", Schema.VectorField.VectorType.FLOAT16, 5, + Schema.VectorField.VectorDistanceMetric.EuclideanDistance) + .AddSvsVanamaVectorField("v2", Schema.VectorField.VectorType.FLOAT32, 4, + Schema.VectorField.VectorDistanceMetric.EuclideanDistance); + + var cmd = SearchCommandBuilder.Create("idx", FTCreateParams.CreateParams(), schema).ToString(); + Log(cmd); + + Assert.True(ft.Create("idx", new FTCreateParams(), schema)); + + byte[] vec1ToBytes = MemoryMarshal.AsBytes(stackalloc short[] { 2, 1, 2, 2, 2 }).ToArray(); + byte[] vec2ToBytes = MemoryMarshal.AsBytes(stackalloc int[] { 1, 2, 2, 2 }).ToArray(); + + HashEntry[] entries = [new("v", vec1ToBytes), new("v2", vec2ToBytes)]; + db.HashSet("a", entries); + db.HashSet("b", entries); + db.HashSet("c", entries); + + var q = new Query("*=>[KNN 2 @v $vec]").ReturnFields("__v_score"); + var res = ft.Search("idx", q.AddParam("vec", vec1ToBytes)); + Assert.Equal(2, res.TotalResults); + + q = new Query("*=>[KNN 2 @v2 $vec]").ReturnFields("__v_score"); + res = ft.Search("idx", q.AddParam("vec", vec2ToBytes)); + Assert.Equal(2, res.TotalResults); + } + + [SkipIfRedisTheory(Comparison.LessThan, "8.1.240")] + [MemberData(nameof(EndpointsFixture.Env.StandaloneOnly), MemberType = typeof(EndpointsFixture.Env))] + public void TestCreate_Float16_Int32_VectorField_Svs_WithCompression(string endpointId) + { + IDatabase db = GetCleanDatabase(endpointId); + // ReSharper disable once RedundantArgumentDefaultValue + var ft = db.FT(2); + var schema = new Schema().AddSvsVanamaVectorField("v", Schema.VectorField.VectorType.FLOAT16, 5, + Schema.VectorField.VectorDistanceMetric.EuclideanDistance, + reducedDimensions: 2, compressionAlgorithm: Schema.VectorField.VectorCompressionAlgorithm.LeanVec4x8) + .AddSvsVanamaVectorField("v2", Schema.VectorField.VectorType.FLOAT32, 4, + Schema.VectorField.VectorDistanceMetric.EuclideanDistance, + compressionAlgorithm: Schema.VectorField.VectorCompressionAlgorithm.LVQ4); + + var cmd = SearchCommandBuilder.Create("idx", FTCreateParams.CreateParams(), schema).ToString(); + Log(cmd); + + Assert.True(ft.Create("idx", new FTCreateParams(), schema)); + byte[] vec1ToBytes = MemoryMarshal.AsBytes(stackalloc short[] { 2, 1, 2, 2, 2 }).ToArray(); + byte[] vec2ToBytes = MemoryMarshal.AsBytes(stackalloc int[] { 1, 2, 2, 2 }).ToArray(); + + HashEntry[] entries = [new("v", vec1ToBytes), new("v2", vec2ToBytes)]; + db.HashSet("a", entries); + db.HashSet("b", entries); + db.HashSet("c", entries); + + var q = new Query("*=>[KNN 2 @v $vec]").ReturnFields("__v_score"); + var res = ft.Search("idx", q.AddParam("vec", vec1ToBytes)); + Assert.Equal(2, res.TotalResults); + + q = new Query("*=>[KNN 2 @v2 $vec]").ReturnFields("__v_score"); + res = ft.Search("idx", q.AddParam("vec", vec2ToBytes)); + Assert.Equal(2, res.TotalResults); + } + + [Fact] + public void TestIndexingCreation_Default() + { + Schema sc = new Schema() + .AddFlatVectorField("vector1", Schema.VectorField.VectorType.FLOAT32, 2, + Schema.VectorField.VectorDistanceMetric.EuclideanDistance, missingIndex: true) + .AddHnswVectorField("vector2", Schema.VectorField.VectorType.FLOAT64, 3, + Schema.VectorField.VectorDistanceMetric.CosineDistance, missingIndex: false) + .AddSvsVanamaVectorField("vector3", Schema.VectorField.VectorType.FLOAT16, 4, + Schema.VectorField.VectorDistanceMetric.InnerProduct, missingIndex: true); + + var ftCreateParams = FTCreateParams.CreateParams(); + var cmd = SearchCommandBuilder.Create("IDX_NAME", ftCreateParams, sc).ToString(); + + Assert.Equal( + "FT.CREATE IDX_NAME SCHEMA vector1 VECTOR FLAT 6 DIM 2 TYPE FLOAT32 DISTANCE_METRIC L2 INDEXMISSING vector2 VECTOR HNSW 6 DIM 3 TYPE FLOAT64 DISTANCE_METRIC COSINE vector3 VECTOR SVS-VAMANA 6 DIM 4 TYPE FLOAT16 DISTANCE_METRIC IP INDEXMISSING", + cmd); + } + + [Fact] + public void TestIndexingCreation_WithAttribs() + { + Schema sc = new Schema() + .AddFlatVectorField("vector1", Schema.VectorField.VectorType.NotSpecified, 0, + Schema.VectorField.VectorDistanceMetric.NotSpecified, missingIndex: true, + attributes: new Dictionary() + { + ["TYPE"] = "FUT1", // some values not representable in the old API + ["DIM"] = "FUT2", + ["DISTANCE_METRIC"] = "FUT3", + ["NEW_FIELD"] = "NEW_VALUE", + }); + + var ftCreateParams = FTCreateParams.CreateParams(); + var cmd = SearchCommandBuilder.Create("IDX_NAME", ftCreateParams, sc).ToString(); + + Assert.Equal( + "FT.CREATE IDX_NAME SCHEMA vector1 VECTOR FLAT 8 TYPE FUT1 DIM FUT2 DISTANCE_METRIC FUT3 NEW_FIELD NEW_VALUE INDEXMISSING", + cmd); + } + + [Fact] + public void TestIndexingCreation_Custom_Everything() + { + Schema sc = new Schema() + .AddFlatVectorField("vector1", Schema.VectorField.VectorType.FLOAT32, 2, + Schema.VectorField.VectorDistanceMetric.EuclideanDistance, missingIndex: true) + .AddHnswVectorField("vector2", Schema.VectorField.VectorType.FLOAT64, 3, + Schema.VectorField.VectorDistanceMetric.CosineDistance, + maxOutgoingConnections: 10, maxConnectedNeighbors: 20, maxTopCandidates: 30, boundaryFactor: 0.7, + missingIndex: false) + .AddSvsVanamaVectorField("vector3", Schema.VectorField.VectorType.FLOAT16, 4, + Schema.VectorField.VectorDistanceMetric.InnerProduct, + compressionAlgorithm: Schema.VectorField.VectorCompressionAlgorithm.LeanVec4x8, + constructionWindowSize: 35, graphMaxDegree: 17, searchWindowSize: 30, + rangeSearchApproximationFactor: 0.5, + trainingThreshold: 100, reducedDimensions: 50, + missingIndex: true); + + var ftCreateParams = FTCreateParams.CreateParams(); + var cmd = SearchCommandBuilder.Create("IDX_NAME", ftCreateParams, sc).ToString(); + + Assert.Equal( + "FT.CREATE IDX_NAME SCHEMA vector1 VECTOR FLAT 6 DIM 2 TYPE FLOAT32 DISTANCE_METRIC L2 INDEXMISSING " + + "vector2 VECTOR HNSW 14 DIM 3 TYPE FLOAT64 DISTANCE_METRIC COSINE M 10 EF_CONSTRUCTION 20 EF_RUNTIME 30 EPSILON 0.7 " + + "vector3 VECTOR SVS-VAMANA 20 COMPRESSION LeanVec4x8 DIM 4 TYPE FLOAT16 DISTANCE_METRIC IP CONSTRUCTION_WINDOW_SIZE 35 GRAPH_MAX_DEGREE 17 SEARCH_WINDOW_SIZE 30 EPSILON 0.5 TRAINING_THRESHOLD 100 REDUCE 50 INDEXMISSING", + cmd); + } } \ No newline at end of file From 2dfe3d9506313333dfd5bbb032e74628a8a5183f Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Tue, 5 Aug 2025 14:13:32 +0300 Subject: [PATCH 09/10] mark API changes as shipped --- .../PublicAPI/PublicAPI.Shipped.txt | 64 +++++++++++++++++++ .../PublicAPI/PublicAPI.Unshipped.txt | 64 ------------------- 2 files changed, 64 insertions(+), 64 deletions(-) diff --git a/src/NRedisStack/PublicAPI/PublicAPI.Shipped.txt b/src/NRedisStack/PublicAPI/PublicAPI.Shipped.txt index 12d7f4c3..e3cae9d9 100644 --- a/src/NRedisStack/PublicAPI/PublicAPI.Shipped.txt +++ b/src/NRedisStack/PublicAPI/PublicAPI.Shipped.txt @@ -1350,3 +1350,67 @@ static readonly NRedisStack.Search.Query.GeoFilter.METERS -> string! static readonly NRedisStack.Search.Query.GeoFilter.MILES -> string! virtual NRedisStack.Search.Aggregation.Reducer.AddOwnArgs(System.Collections.Generic.List! args) -> void virtual NRedisStack.Search.Aggregation.Reducer.GetOwnArgsCount() -> int +NRedisStack.Search.Schema.AddFlatVectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorType type, int dimensions, NRedisStack.Search.Schema.VectorField.VectorDistanceMetric distanceMetric, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddHnswVectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorType type, int dimensions, NRedisStack.Search.Schema.VectorField.VectorDistanceMetric distanceMetric, int maxOutgoingConnections = 16, int maxConnectedNeighbors = 200, int maxTopCandidates = 10, double boundaryFactor = 0.01, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.AddSvsVanamaVectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorType type, int dimensions, NRedisStack.Search.Schema.VectorField.VectorDistanceMetric distanceMetric, NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm compressionAlgorithm = NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.NotSpecified, int constructionWindowSize = 200, int graphMaxDegree = 32, int searchWindowSize = 10, double rangeSearchApproximationFactor = 0.01, int trainingThreshold = 0, int reducedDimensions = 0, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> NRedisStack.Search.Schema! +NRedisStack.Search.Schema.FlatVectorField +NRedisStack.Search.Schema.FlatVectorField.FlatVectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorType type, int dimensions, NRedisStack.Search.Schema.VectorField.VectorDistanceMetric distanceMetric, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> void +NRedisStack.Search.Schema.HnswVectorField +NRedisStack.Search.Schema.HnswVectorField.BoundaryFactor.get -> double +NRedisStack.Search.Schema.HnswVectorField.BoundaryFactor.set -> void +NRedisStack.Search.Schema.HnswVectorField.HnswVectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorType type, int dimensions, NRedisStack.Search.Schema.VectorField.VectorDistanceMetric distanceMetric, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> void +NRedisStack.Search.Schema.HnswVectorField.MaxConnectedNeighbors.get -> int +NRedisStack.Search.Schema.HnswVectorField.MaxConnectedNeighbors.set -> void +NRedisStack.Search.Schema.HnswVectorField.MaxOutgoingConnections.get -> int +NRedisStack.Search.Schema.HnswVectorField.MaxOutgoingConnections.set -> void +NRedisStack.Search.Schema.HnswVectorField.MaxTopCandidates.get -> int +NRedisStack.Search.Schema.HnswVectorField.MaxTopCandidates.set -> void +NRedisStack.Search.Schema.SvsVanamaVectorField +NRedisStack.Search.Schema.SvsVanamaVectorField.CompressionAlgorithm.get -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm +NRedisStack.Search.Schema.SvsVanamaVectorField.CompressionAlgorithm.set -> void +NRedisStack.Search.Schema.SvsVanamaVectorField.ConstructionWindowSize.get -> int +NRedisStack.Search.Schema.SvsVanamaVectorField.ConstructionWindowSize.set -> void +NRedisStack.Search.Schema.SvsVanamaVectorField.GraphMaxDegree.get -> int +NRedisStack.Search.Schema.SvsVanamaVectorField.GraphMaxDegree.set -> void +NRedisStack.Search.Schema.SvsVanamaVectorField.RangeSearchApproximationFactor.get -> double +NRedisStack.Search.Schema.SvsVanamaVectorField.RangeSearchApproximationFactor.set -> void +NRedisStack.Search.Schema.SvsVanamaVectorField.ReducedDimensions.get -> int +NRedisStack.Search.Schema.SvsVanamaVectorField.ReducedDimensions.set -> void +NRedisStack.Search.Schema.SvsVanamaVectorField.SearchWindowSize.get -> int +NRedisStack.Search.Schema.SvsVanamaVectorField.SearchWindowSize.set -> void +NRedisStack.Search.Schema.SvsVanamaVectorField.SvsVanamaVectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorType type, int dimensions, NRedisStack.Search.Schema.VectorField.VectorDistanceMetric distanceMetric, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> void +NRedisStack.Search.Schema.SvsVanamaVectorField.TrainingThreshold.get -> int +NRedisStack.Search.Schema.SvsVanamaVectorField.TrainingThreshold.set -> void +NRedisStack.Search.Schema.VectorField.Dimensions.get -> int +NRedisStack.Search.Schema.VectorField.Dimensions.set -> void +NRedisStack.Search.Schema.VectorField.DistanceMetric.get -> NRedisStack.Search.Schema.VectorField.VectorDistanceMetric +NRedisStack.Search.Schema.VectorField.DistanceMetric.set -> void +NRedisStack.Search.Schema.VectorField.Type.get -> NRedisStack.Search.Schema.VectorField.VectorType +NRedisStack.Search.Schema.VectorField.Type.set -> void +NRedisStack.Search.Schema.VectorField.VectorAlgo.SVS_VAMANA = 2 -> NRedisStack.Search.Schema.VectorField.VectorAlgo +NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm +NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.LeanVec4x8 = 5 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm +NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.LeanVec8x8 = 6 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm +NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.LVQ4 = 2 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm +NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.LVQ4x4 = 3 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm +NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.LVQ4x8 = 4 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm +NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.LVQ8 = 1 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm +NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.NotSpecified = 0 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm +NRedisStack.Search.Schema.VectorField.VectorDistanceMetric +NRedisStack.Search.Schema.VectorField.VectorDistanceMetric.CosineDistance = 3 -> NRedisStack.Search.Schema.VectorField.VectorDistanceMetric +NRedisStack.Search.Schema.VectorField.VectorDistanceMetric.EuclideanDistance = 1 -> NRedisStack.Search.Schema.VectorField.VectorDistanceMetric +NRedisStack.Search.Schema.VectorField.VectorDistanceMetric.InnerProduct = 2 -> NRedisStack.Search.Schema.VectorField.VectorDistanceMetric +NRedisStack.Search.Schema.VectorField.VectorDistanceMetric.NotSpecified = 0 -> NRedisStack.Search.Schema.VectorField.VectorDistanceMetric +NRedisStack.Search.Schema.VectorField.VectorType +NRedisStack.Search.Schema.VectorField.VectorType.BFLOAT16 = 3 -> NRedisStack.Search.Schema.VectorField.VectorType +NRedisStack.Search.Schema.VectorField.VectorType.FLOAT16 = 4 -> NRedisStack.Search.Schema.VectorField.VectorType +NRedisStack.Search.Schema.VectorField.VectorType.FLOAT32 = 1 -> NRedisStack.Search.Schema.VectorField.VectorType +NRedisStack.Search.Schema.VectorField.VectorType.FLOAT64 = 2 -> NRedisStack.Search.Schema.VectorField.VectorType +NRedisStack.Search.Schema.VectorField.VectorType.NotSpecified = 0 -> NRedisStack.Search.Schema.VectorField.VectorType +override NRedisStack.RedisStackCommands.SerializedCommand.ToString() -> string! +static NRedisStack.Search.FieldName.implicit operator NRedisStack.Search.FieldName!(string! name) -> NRedisStack.Search.FieldName! +~override NRedisStack.DataTypes.TimeStamp.ToString() -> string +~override NRedisStack.DataTypes.TimeStamp.Equals(object obj) -> bool +NRedisStack.DataTypes.TimeStamp.Equals(NRedisStack.DataTypes.TimeStamp other) -> bool +static NRedisStack.DataTypes.TimeStamp.operator ==(NRedisStack.DataTypes.TimeStamp left, NRedisStack.DataTypes.TimeStamp right) -> bool +static NRedisStack.DataTypes.TimeStamp.operator !=(NRedisStack.DataTypes.TimeStamp left, NRedisStack.DataTypes.TimeStamp right) -> bool diff --git a/src/NRedisStack/PublicAPI/PublicAPI.Unshipped.txt b/src/NRedisStack/PublicAPI/PublicAPI.Unshipped.txt index 45b12d1c..7dc5c581 100644 --- a/src/NRedisStack/PublicAPI/PublicAPI.Unshipped.txt +++ b/src/NRedisStack/PublicAPI/PublicAPI.Unshipped.txt @@ -1,65 +1 @@ #nullable enable -NRedisStack.Search.Schema.AddFlatVectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorType type, int dimensions, NRedisStack.Search.Schema.VectorField.VectorDistanceMetric distanceMetric, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> NRedisStack.Search.Schema! -NRedisStack.Search.Schema.AddHnswVectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorType type, int dimensions, NRedisStack.Search.Schema.VectorField.VectorDistanceMetric distanceMetric, int maxOutgoingConnections = 16, int maxConnectedNeighbors = 200, int maxTopCandidates = 10, double boundaryFactor = 0.01, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> NRedisStack.Search.Schema! -NRedisStack.Search.Schema.AddSvsVanamaVectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorType type, int dimensions, NRedisStack.Search.Schema.VectorField.VectorDistanceMetric distanceMetric, NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm compressionAlgorithm = NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.NotSpecified, int constructionWindowSize = 200, int graphMaxDegree = 32, int searchWindowSize = 10, double rangeSearchApproximationFactor = 0.01, int trainingThreshold = 0, int reducedDimensions = 0, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> NRedisStack.Search.Schema! -NRedisStack.Search.Schema.FlatVectorField -NRedisStack.Search.Schema.FlatVectorField.FlatVectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorType type, int dimensions, NRedisStack.Search.Schema.VectorField.VectorDistanceMetric distanceMetric, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> void -NRedisStack.Search.Schema.HnswVectorField -NRedisStack.Search.Schema.HnswVectorField.BoundaryFactor.get -> double -NRedisStack.Search.Schema.HnswVectorField.BoundaryFactor.set -> void -NRedisStack.Search.Schema.HnswVectorField.HnswVectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorType type, int dimensions, NRedisStack.Search.Schema.VectorField.VectorDistanceMetric distanceMetric, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> void -NRedisStack.Search.Schema.HnswVectorField.MaxConnectedNeighbors.get -> int -NRedisStack.Search.Schema.HnswVectorField.MaxConnectedNeighbors.set -> void -NRedisStack.Search.Schema.HnswVectorField.MaxOutgoingConnections.get -> int -NRedisStack.Search.Schema.HnswVectorField.MaxOutgoingConnections.set -> void -NRedisStack.Search.Schema.HnswVectorField.MaxTopCandidates.get -> int -NRedisStack.Search.Schema.HnswVectorField.MaxTopCandidates.set -> void -NRedisStack.Search.Schema.SvsVanamaVectorField -NRedisStack.Search.Schema.SvsVanamaVectorField.CompressionAlgorithm.get -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm -NRedisStack.Search.Schema.SvsVanamaVectorField.CompressionAlgorithm.set -> void -NRedisStack.Search.Schema.SvsVanamaVectorField.ConstructionWindowSize.get -> int -NRedisStack.Search.Schema.SvsVanamaVectorField.ConstructionWindowSize.set -> void -NRedisStack.Search.Schema.SvsVanamaVectorField.GraphMaxDegree.get -> int -NRedisStack.Search.Schema.SvsVanamaVectorField.GraphMaxDegree.set -> void -NRedisStack.Search.Schema.SvsVanamaVectorField.RangeSearchApproximationFactor.get -> double -NRedisStack.Search.Schema.SvsVanamaVectorField.RangeSearchApproximationFactor.set -> void -NRedisStack.Search.Schema.SvsVanamaVectorField.ReducedDimensions.get -> int -NRedisStack.Search.Schema.SvsVanamaVectorField.ReducedDimensions.set -> void -NRedisStack.Search.Schema.SvsVanamaVectorField.SearchWindowSize.get -> int -NRedisStack.Search.Schema.SvsVanamaVectorField.SearchWindowSize.set -> void -NRedisStack.Search.Schema.SvsVanamaVectorField.SvsVanamaVectorField(NRedisStack.Search.FieldName! name, NRedisStack.Search.Schema.VectorField.VectorType type, int dimensions, NRedisStack.Search.Schema.VectorField.VectorDistanceMetric distanceMetric, System.Collections.Generic.Dictionary? attributes = null, bool missingIndex = false) -> void -NRedisStack.Search.Schema.SvsVanamaVectorField.TrainingThreshold.get -> int -NRedisStack.Search.Schema.SvsVanamaVectorField.TrainingThreshold.set -> void -NRedisStack.Search.Schema.VectorField.Dimensions.get -> int -NRedisStack.Search.Schema.VectorField.Dimensions.set -> void -NRedisStack.Search.Schema.VectorField.DistanceMetric.get -> NRedisStack.Search.Schema.VectorField.VectorDistanceMetric -NRedisStack.Search.Schema.VectorField.DistanceMetric.set -> void -NRedisStack.Search.Schema.VectorField.Type.get -> NRedisStack.Search.Schema.VectorField.VectorType -NRedisStack.Search.Schema.VectorField.Type.set -> void -NRedisStack.Search.Schema.VectorField.VectorAlgo.SVS_VAMANA = 2 -> NRedisStack.Search.Schema.VectorField.VectorAlgo -NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm -NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.LeanVec4x8 = 5 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm -NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.LeanVec8x8 = 6 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm -NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.LVQ4 = 2 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm -NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.LVQ4x4 = 3 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm -NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.LVQ4x8 = 4 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm -NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.LVQ8 = 1 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm -NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm.NotSpecified = 0 -> NRedisStack.Search.Schema.VectorField.VectorCompressionAlgorithm -NRedisStack.Search.Schema.VectorField.VectorDistanceMetric -NRedisStack.Search.Schema.VectorField.VectorDistanceMetric.CosineDistance = 3 -> NRedisStack.Search.Schema.VectorField.VectorDistanceMetric -NRedisStack.Search.Schema.VectorField.VectorDistanceMetric.EuclideanDistance = 1 -> NRedisStack.Search.Schema.VectorField.VectorDistanceMetric -NRedisStack.Search.Schema.VectorField.VectorDistanceMetric.InnerProduct = 2 -> NRedisStack.Search.Schema.VectorField.VectorDistanceMetric -NRedisStack.Search.Schema.VectorField.VectorDistanceMetric.NotSpecified = 0 -> NRedisStack.Search.Schema.VectorField.VectorDistanceMetric -NRedisStack.Search.Schema.VectorField.VectorType -NRedisStack.Search.Schema.VectorField.VectorType.BFLOAT16 = 3 -> NRedisStack.Search.Schema.VectorField.VectorType -NRedisStack.Search.Schema.VectorField.VectorType.FLOAT16 = 4 -> NRedisStack.Search.Schema.VectorField.VectorType -NRedisStack.Search.Schema.VectorField.VectorType.FLOAT32 = 1 -> NRedisStack.Search.Schema.VectorField.VectorType -NRedisStack.Search.Schema.VectorField.VectorType.FLOAT64 = 2 -> NRedisStack.Search.Schema.VectorField.VectorType -NRedisStack.Search.Schema.VectorField.VectorType.NotSpecified = 0 -> NRedisStack.Search.Schema.VectorField.VectorType -override NRedisStack.RedisStackCommands.SerializedCommand.ToString() -> string! -static NRedisStack.Search.FieldName.implicit operator NRedisStack.Search.FieldName!(string! name) -> NRedisStack.Search.FieldName! -~override NRedisStack.DataTypes.TimeStamp.ToString() -> string -~override NRedisStack.DataTypes.TimeStamp.Equals(object obj) -> bool -NRedisStack.DataTypes.TimeStamp.Equals(NRedisStack.DataTypes.TimeStamp other) -> bool -static NRedisStack.DataTypes.TimeStamp.operator ==(NRedisStack.DataTypes.TimeStamp left, NRedisStack.DataTypes.TimeStamp right) -> bool -static NRedisStack.DataTypes.TimeStamp.operator !=(NRedisStack.DataTypes.TimeStamp left, NRedisStack.DataTypes.TimeStamp right) -> bool \ No newline at end of file From cd28663eff9f2b61cadb1691eb2d967da977791f Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Tue, 5 Aug 2025 14:34:42 +0300 Subject: [PATCH 10/10] re-establish log fixture, and ensure it can't be overlooked in the future --- tests/NRedisStack.Tests/AbstractNRedisStackTest.cs | 8 ++++++-- tests/NRedisStack.Tests/Search/IndexCreationTests.cs | 5 +++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/NRedisStack.Tests/AbstractNRedisStackTest.cs b/tests/NRedisStack.Tests/AbstractNRedisStackTest.cs index 5bad605a..5f2063db 100644 --- a/tests/NRedisStack.Tests/AbstractNRedisStackTest.cs +++ b/tests/NRedisStack.Tests/AbstractNRedisStackTest.cs @@ -9,10 +9,14 @@ namespace NRedisStack.Tests; public abstract class AbstractNRedisStackTest : IClassFixture, IAsyncLifetime { - protected internal EndpointsFixture EndpointsFixture; + private protected EndpointsFixture EndpointsFixture { get; } private readonly ITestOutputHelper? log; - protected void Log(string message) => log?.WriteLine(message); // TODO: DISH overload in net9? net10? + protected void Log(string message) + { + if (log is null) throw new InvalidOperationException("Log is not initialized"); + log.WriteLine(message); + } protected readonly ConfigurationOptions DefaultConnectionConfig = new() { diff --git a/tests/NRedisStack.Tests/Search/IndexCreationTests.cs b/tests/NRedisStack.Tests/Search/IndexCreationTests.cs index 3a8ec19b..a9475b5a 100644 --- a/tests/NRedisStack.Tests/Search/IndexCreationTests.cs +++ b/tests/NRedisStack.Tests/Search/IndexCreationTests.cs @@ -4,11 +4,12 @@ using NRedisStack.RedisStackCommands; using Xunit; using NetTopologySuite.Geometries; +using Xunit.Abstractions; namespace NRedisStack.Tests.Search; -public class IndexCreationTests(EndpointsFixture endpointsFixture) - : AbstractNRedisStackTest(endpointsFixture), IDisposable +public class IndexCreationTests(EndpointsFixture endpointsFixture, ITestOutputHelper log) + : AbstractNRedisStackTest(endpointsFixture, log), IDisposable { private readonly string index = "MISSING_EMPTY_INDEX";