From 31d2f81e54105b97338bfd4a9ca493f086acfc21 Mon Sep 17 00:00:00 2001 From: shacharPash Date: Mon, 24 Apr 2023 14:03:32 +0300 Subject: [PATCH] starting --- .vscode/settings.json | 2 +- Examples/AdvancedQueryOperations.md | 97 +++++++++++++++++++------ src/NRedisStack/Graph/DataTypes/Edge.cs | 4 +- src/NRedisStack/Graph/GraphCommands.cs | 2 +- 4 files changed, 80 insertions(+), 25 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index b26a2359..d20a1ad7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,4 @@ { "dotnet-test-explorer.testArguments": "/p:CollectCoverage=true /p:CoverletOutputFormat=lcov /p:CoverletOutput=./lcov.info", - "dotnet-test-explorer.testProjectPath": "**/*NRedisStack.Tests.csproj" + "dotnet-test-explorer.testProjectPath": "**/*NRedisStack.Tests.csproj", } \ No newline at end of file diff --git a/Examples/AdvancedQueryOperations.md b/Examples/AdvancedQueryOperations.md index 1ced1dac..9094a362 100644 --- a/Examples/AdvancedQueryOperations.md +++ b/Examples/AdvancedQueryOperations.md @@ -1,32 +1,38 @@ # Advanced Querying + Aggregation and other more complex RediSearch queries + ## Contents -1. [Business Value Statement](#value) -2. [Modules Needed](#modules) -3. [Vector Similarity Search](#vss) - 1. [Data Load](#vss_dataload) - 2. [Index Creation](#vss_index) - 3. [Search](#vss_search) -4. [Advanced Search Queries](#adv_search) - 1. [Data Set](#advs_dataset) - 2. [Data Load](#advs_dataload) - 3. [Index Creation](#advs_index) - 4. [Search w/JSON Filtering - Example 1](#advs_ex1) - 5. [Search w/JSON Filtering - Example 2](#advs_ex2) -5. [Aggregation](#aggr) - 1. [Data Set](#aggr_dataset) - 2. [Data Load](#aggr_dataload) - 3. [Index Creation](#aggr_index) - 4. [Aggregation - Count](#aggr_count) - 5. [Aggregation - Sum](#aggr_sum) - -## Business Value Statement + +1. [Business Value Statement](#value) +2. [Modules Needed](#modules) +3. [Vector Similarity Search](#vss) + 1. [Data Load](#vss_dataload) + 2. [Index Creation](#vss_index) + 3. [Search](#vss_search) +4. [Advanced Search Queries](#adv_search) + 1. [Data Set](#advs_dataset) + 2. [Data Load](#advs_dataload) + 3. [Index Creation](#advs_index) + 4. [Search w/JSON Filtering - Example 1](#advs_ex1) + 5. [Search w/JSON Filtering - Example 2](#advs_ex2) +5. [Aggregation](#aggr) + 1. [Data Set](#aggr_dataset) + 2. [Data Load](#aggr_dataload) + 3. [Index Creation](#aggr_index) + 4. [Aggregation - Count](#aggr_count) + 5. [Aggregation - Sum](#aggr_sum) + +## Business Value Statement + Redis provides the following additional advanced search capabilities to derive further value of Redis-held data: + * Vector Similarity Search - Store and search by ML-generated encodings of text and images * Search + JSON Filtering - Combine the power of search with JSONPath filtering of search results * Aggregation - Create processing pipelines of search results to extract analytic insights. ## Modules Needed + ```c# using StackExchange.Redis; using NRedisStack; @@ -35,19 +41,26 @@ using NRedisStack.Search; using NRedisStack.Search.Literals.Enums; using NRedisStack.Search.Aggregation; ``` + ## Vector Similarity Search (VSS) + ### Syntax + [VSS](https://redis.io/docs/stack/search/reference/vectors/) ### Data Load + ```c# db.HashSet("vec:1", "vector", (new float[] { 1f, 1f, 1f, 1f }).SelectMany(BitConverter.GetBytes).ToArray()); db.HashSet("vec:2", "vector", (new float[] { 2f, 2f, 2f, 2f }).SelectMany(BitConverter.GetBytes).ToArray()); db.HashSet("vec:3", "vector", (new float[] { 3f, 3f, 3f, 3f }).SelectMany(BitConverter.GetBytes).ToArray()); db.HashSet("vec:5", "vector", (new float[] { 4f, 4f, 4f, 4f }).SelectMany(BitConverter.GetBytes).ToArray()); ``` + ### Index Creation + #### Command + ```c# ISearchCommands ft = db.FT(); try {ft.DropIndex("vss_idx");} catch {}; @@ -62,13 +75,17 @@ Console.WriteLine(ft.Create("vss_idx", new FTCreateParams().On(IndexDataType.HAS } ))); ``` + #### Result + ```bash True ``` ### Search + #### Command + ```c# float[] vec = new[] { 2f, 2f, 3f, 3f}; var res = ft.Search("vss_idx", @@ -84,14 +101,18 @@ foreach (var doc in res.Documents) { } } ``` + #### Result + ```bash id: vec:2, score: 2 id: vec:3, score: 2 ``` ## Advanced Search Queries + ### Data Set + ```json { "city": "Boston", @@ -150,6 +171,7 @@ id: vec:3, score: 2 ``` ### Data Load + ```c# IJsonCommands json = db.JSON(); json.Set("warehouse:1", "$", new { @@ -209,7 +231,9 @@ json.Set("warehouse:2", "$", new { ``` ### Index Creation + #### Command + ```c# ISearchCommands ft = db.FT(); try {ft.DropIndex("wh_idx");} catch {}; @@ -218,14 +242,19 @@ Console.WriteLine(ft.Create("wh_idx", new FTCreateParams() .Prefix("warehouse:"), new Schema().AddTextField(new FieldName("$.city", "city")))); ``` + #### Result + ```bash True ``` ### Search w/JSON Filtering - Example 1 + Find all inventory ids from all the Boston warehouse that have a price > $50. + #### Command + ```c# foreach (var doc in ft.Search("wh_idx", new Query("@city:Boston") @@ -236,14 +265,19 @@ foreach (var doc in ft.Search("wh_idx", Console.WriteLine(doc); } ``` + #### Result + ```json [59263] ``` ### Search w/JSON Filtering - Example 2 + Find all inventory items in Dallas that are for Women or Girls + #### Command + ```c# foreach (var doc in ft.Search("wh_idx", new Query("@city:(Dallas)") @@ -254,16 +288,21 @@ foreach (var doc in ft.Search("wh_idx", Console.WriteLine(doc); } ``` + #### Result + ```json [{"id":51919,"gender":"Women","season":["Summer"],"description":"Nyk Black Horado Handbag","price":52.49},{"id":37561,"gender":"Girls","season":["Spring","Summer"],"description":"Madagascar3 Infant Pink Snapsuit Romper","price":23.95}] ``` ## Aggregation + ### Syntax + [FT.AGGREGATE](https://redis.io/commands/ft.aggregate/) ### Data Set + ```JSON { "title": "System Design Interview", @@ -286,7 +325,9 @@ foreach (var doc in ft.Search("wh_idx", "price": 14.36 } ``` + ### Data Load + ```c# json.Set("book:1", "$", new { title = "System Design Interview", @@ -311,7 +352,9 @@ json.Set("book:4", "$", new { ``` ### Index Creation + #### Command + ```c# Console.WriteLine(ft.Create("book_idx", new FTCreateParams() .On(IndexDataType.JSON) @@ -320,14 +363,19 @@ Console.WriteLine(ft.Create("book_idx", new FTCreateParams() .AddNumericField(new FieldName("$.year", "year")) .AddNumericField(new FieldName("$.price", "price")))); ``` + #### Result + ```bash True ``` ### Aggregation - Count + Find the total number of books per year + #### Command + ```c# var request = new AggregationRequest("*").GroupBy("@year", Reducers.Count().As("count")); var result = ft.Aggregate("book_idx", request); @@ -337,7 +385,9 @@ for (var i=0; i + Sum of inventory dollar value by year + #### Command + ```c# request = new AggregationRequest("*").GroupBy("@year", Reducers.Sum("@price").As("sum")); result = ft.Aggregate("book_idx", request); @@ -356,9 +409,11 @@ for (var i=0; i /// - public string RelationshipType { get; set; } + public string? RelationshipType { get; set; } /// /// The ID of the source node. @@ -66,7 +66,7 @@ public override int GetHashCode() int hash = 17; hash = hash * 31 + base.GetHashCode(); - hash = hash * 31 + RelationshipType.GetHashCode(); + hash = hash * 31 + (RelationshipType ?? "").GetHashCode(); hash = hash * 31 + Source.GetHashCode(); hash = hash * 31 + Destination.GetHashCode(); diff --git a/src/NRedisStack/Graph/GraphCommands.cs b/src/NRedisStack/Graph/GraphCommands.cs index 4f0481c2..393f974e 100644 --- a/src/NRedisStack/Graph/GraphCommands.cs +++ b/src/NRedisStack/Graph/GraphCommands.cs @@ -55,7 +55,7 @@ public ResultSet RO_Query(string graphName, string query, long? timeout = null) return new ResultSet(_db.Execute(GraphCommandBuilder.RO_Query(graphName, query, timeout)), _graphCaches[graphName]); } - internal static readonly Dictionary> EmptyKwargsDictionary = + internal static new readonly Dictionary> EmptyKwargsDictionary = new Dictionary>(); // TODO: Check if this is needed: