Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Redis Search Commands #32

Merged
merged 29 commits into from
Oct 12, 2022
Merged
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1ba2ff3
Add Alias command
shacharPash Sep 6, 2022
6edac52
Start FT.CERATE Command
shacharPash Sep 7, 2022
8d01781
Start FTCreateParams class for FT.CERATE
shacharPash Sep 8, 2022
45975c2
Add FT.CERATE command
shacharPash Sep 12, 2022
03d6f1f
Fixing Schema and FieldName Classes
shacharPash Sep 13, 2022
6bf4e42
Work on Schema class
shacharPash Sep 18, 2022
90de6ae
Add FT.SEARCH command
shacharPash Sep 22, 2022
845196b
Add FT.ALTER command
shacharPash Sep 22, 2022
5e55a8c
Linking to the latest pre-release (#30)
chayim Sep 6, 2022
083adb5
Updading the version to v0.2.1 (#31)
shacharPash Sep 6, 2022
71f264d
adding JSON commands (#29)
slorello89 Sep 7, 2022
2648aad
Implement new TDIGEST commands and TDIGEST.CREATE compression (#33)
shacharPash Oct 2, 2022
a8846bc
Test Commit
shacharPash Oct 2, 2022
c344d58
Merge branch 'master' into SearchCommands
shacharPash Oct 2, 2022
b7bd388
Add Async Commands & tests
shacharPash Oct 2, 2022
f77ca6f
Working on FT.INFO Command
shacharPash Oct 2, 2022
6475a3d
Finish FT.INFO Command
shacharPash Oct 3, 2022
66491b1
Add AggregationRequest Class for FT.AGGREGATE Command
shacharPash Oct 3, 2022
0368e23
Add FT.AGGREGATE Command + Tests
shacharPash Oct 9, 2022
cba57f0
Adding TODOs to commands that have not yet been implemented
shacharPash Oct 9, 2022
fc5c9a3
Add FT.CONFIG GET/SET Commands + Tests
shacharPash Oct 9, 2022
dac3fa4
Add FT.CURSOR READ/DEL Commands
shacharPash Oct 11, 2022
49ba5bb
Add FT.DICT(ADD/DEL/DUMP) Commands
shacharPash Oct 11, 2022
45309c3
Add FT.DICT(ADD/DEL/DUMP) Async Commands + Tests
shacharPash Oct 11, 2022
eeb870f
Add FT.DROPINDEX Sync/Async Commands + Tests
shacharPash Oct 11, 2022
d8da602
Fix Aggregate & Add more Commands
shacharPash Oct 11, 2022
30330b4
Add FT.TAGVALS Sync/Async Command + Tests
shacharPash Oct 12, 2022
2360158
Add Sync/Async Tests for FT.ALIAS
shacharPash Oct 12, 2022
c3ab0ef
Fixing Tdigest.Add Command and Tests
shacharPash Oct 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Working on FT.INFO Command
shacharPash committed Oct 2, 2022

Verified

This commit was signed with the committer’s verified signature.
ChrisDenton Chris Denton
commit f77ca6f4203e6f0ba9bc3f9c2ef5f71bd2738ab1
15 changes: 15 additions & 0 deletions src/NRedisStack/ResponseParser.cs
Original file line number Diff line number Diff line change
@@ -485,6 +485,21 @@ public static TimeSeriesInformation ToTimeSeriesInfo(this RedisResult result)
lastTimestamp, retentionTime, chunkCount, chunkSize, labels, sourceKey, rules, duplicatePolicy, keySelfName, chunks);
}

public static Dictionary<string, RedisValue> ToFtInfoAsDictionary(this RedisResult value)
{
var res = (RedisResult[])value;
var info = new Dictionary<string, RedisValue>();
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 IReadOnlyList<TimeSeriesChunck> ToTimeSeriesChunkArray(this RedisResult result)
{
RedisResult[] redisResults = (RedisResult[])result;
142 changes: 142 additions & 0 deletions src/NRedisStack/Search/DataTypes/InfoResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
using System.Collections.Generic;
using StackExchange.Redis;

namespace NRedisStack.Search.DataTypes
{
public class InfoResult
{
private readonly Dictionary<string, RedisResult> _all = new Dictionary<string, RedisResult>();

public string IndexName => GetString("index_name");
public Dictionary<string, RedisResult> IndexOption => GetRedisResultDictionary("index_options");
public Dictionary<string, RedisResult[]> IndexDefinition => GetRedisResultsDictionary("index_definition");

public Dictionary<string, RedisResult[]> Attributes => GetRedisResultsDictionary("attributes"); // TODO: check if this is correct

public long NumDocs => GetLong("num_docs");

public string MaxDocId => GetString("max_doc_id");

public long NumTerms => GetLong("num_terms");

public long NumRecords => GetLong("num_records");

public double InvertedSzMebibytes => GetDouble("inverted_sz_mb");

public double VectorIndexSzMebibytes => GetDouble("vector_index_sz_mb"); // TODO: check if double or long

public double TotalInvertedIndexBlocks => GetDouble("total_inverted_index_blocks");

// public double InvertedCapOvh => GetDouble("inverted_cap_ovh");

public double OffsetVectorsSzMebibytes => GetDouble("offset_vectors_sz_mb");

public double DocTableSizeMebibytes => GetDouble("doc_table_size_mb");

public double SortableValueSizeMebibytes => GetDouble("sortable_value_size_mb");

public double KeyTableSizeMebibytes => GetDouble("key_table_size_mb");

// public double SkipIndexSizeMebibytes => GetDouble("skip_index_size_mb");

// public double ScoreIndexSizeMebibytes => GetDouble("score_index_size_mb");

public double RecordsPerDocAvg => GetDouble("records_per_doc_avg");

public double BytesPerRecordAvg => GetDouble("bytes_per_record_avg");

public double OffsetsPerTermAvg => GetDouble("offsets_per_term_avg");

public double OffsetBitsPerRecordAvg => GetDouble("offset_bits_per_record_avg");

public long HashIndexingFailures => GetLong("hash_indexing_failures");

public double TotalIndexingTime => GetDouble("total_indexing_time");

public long Indexing => GetLong("indexing");

public double PercentIndexed => GetDouble("percent_indexed");

public long NumberOfUses => GetLong("number_of_uses");


public Dictionary<string, RedisResult> GcStats => GetRedisResultDictionary("gc_stats");

public Dictionary<string, RedisResult> CursorStats => GetRedisResultDictionary("cursor_stats");

public InfoResult(RedisResult result)
{
var results = (RedisResult[])result;

for (var i = 0; i < results.Length; i += 2)
{
var key = (string)results[i];
var value = results[i + 1];

_all.Add(key, value);
}
}

private string GetString(string key) => _all.TryGetValue(key, out var value) ? (string)value : default;

private long GetLong(string key) => _all.TryGetValue(key, out var value) ? (long)value : default;

private double GetDouble(string key)
{
if (_all.TryGetValue(key, out var value))
{
if ((string)value == "-nan")
{
return default;
}
else
{
return (double)value;
}
}
else
{
return default;
}
}

private Dictionary<string, RedisResult> GetRedisResultDictionary(string key)
{
if (_all.TryGetValue(key, out var value))
{
var values = (RedisResult[])value;
var result = new Dictionary<string, RedisResult>();

for (var ii = 0; ii < values.Length; ii += 2)
{
result.Add((string)values[ii], values[ii + 1]);
}

return result;
}
else
{
return default;
}
}

private Dictionary<string, RedisResult[]> GetRedisResultsDictionary(string key)
{
if (_all.TryGetValue(key, out var value))
{
var result = new Dictionary<string, RedisResult[]>();

foreach (RedisResult[] fv in (RedisResult[])value)
{
result.Add((string)fv[0], fv);
}

return result;
}
else
{
return default;
}
}
}
}
60 changes: 30 additions & 30 deletions src/NRedisStack/Search/DataTypes/SearchInformation.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
namespace NRedisStack.Search.DataTypes
{
/// <summary>
/// This class represents the response for SEARCH.INFO command.
/// This object has Read-only properties and cannot be generated outside a SEARCH.INFO response.
/// </summary>
public class SearchInformation
{
// TODO: work on it with someone from Search team
// public string IndexName { get; private set; }
// public string[] IndexOptions { get; private set; }
// public long IndexDefinition { get; private set; }
// public long UnmergedNodes { get; private set; }
// public double MergedWeight { get; private set; }
// public double UnmergedWeight { get; private set; }
// namespace NRedisStack.Search.DataTypes
// {
// /// <summary>
// /// This class represents the response for SEARCH.INFO command.
// /// This object has Read-only properties and cannot be generated outside a SEARCH.INFO response.
// /// </summary>
// public class SearchInformation
// {
// // TODO: work on it with someone from Search team
// // public string IndexName { get; private set; }
// // public string[] IndexOptions { get; private set; }
// // public long IndexDefinition { get; private set; }
// // public long UnmergedNodes { get; private set; }
// // public double MergedWeight { get; private set; }
// // public double UnmergedWeight { get; private set; }

// public long TotalCompressions { get; private set; }
// // public long TotalCompressions { get; private set; }


// internal SearchInformation(long compression, long capacity, long mergedNodes,
// long unmergedNodes, double mergedWeight,
// double unmergedWeight, long totalCompressions)
// // internal SearchInformation(long compression, long capacity, long mergedNodes,
// // long unmergedNodes, double mergedWeight,
// // double unmergedWeight, long totalCompressions)

// {
// Compression = compression;
// Capacity = capacity;
// MergedNodes = mergedNodes;
// UnmergedNodes = unmergedNodes;
// MergedWeight = mergedWeight;
// UnmergedWeight = unmergedWeight;
// TotalCompressions = totalCompressions;
// }
}
}
// // {
// // Compression = compression;
// // Capacity = capacity;
// // MergedNodes = mergedNodes;
// // UnmergedNodes = unmergedNodes;
// // MergedWeight = mergedWeight;
// // UnmergedWeight = unmergedWeight;
// // TotalCompressions = totalCompressions;
// // }
// }
// }
26 changes: 21 additions & 5 deletions src/NRedisStack/Search/SearchCommands.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using NRedisStack.Literals;
using NRedisStack.Search;
using NRedisStack.Search.DataTypes;
using NRedisStack.Search.FT.CREATE;
using StackExchange.Redis;
namespace NRedisStack
@@ -148,11 +149,26 @@ public async Task<bool> AlterAsync(string index, Schema schema, bool skipInitial
return (await _db.ExecuteAsync(FT.ALTER, args)).OKtoBoolean();
}

// TODO: finish this & add summary
public RedisResult Info(RedisValue index)
{
return _db.Execute(FT.INFO, index);
}
// /// <summary>
// /// Return information and statistics on the index.
// /// </summary>
// /// <param name="key">The name of the index.</param>
// /// <returns>Dictionary of key and value with information about the index</returns>
// /// <remarks><seealso href="https://redis.io/commands/ft.info"/></remarks>
// public Dictionary<string, RedisValue> Info(RedisValue index)
// {
// return _db.Execute(FT.INFO, index).ToFtInfoAsDictionary();
// }

/// <summary>
/// Return information and statistics on the index.
/// </summary>
/// <param name="key">The name of the index.</param>
/// <returns>Dictionary of key and value with information about the index</returns>
/// <remarks><seealso href="https://redis.io/commands/ft.info"/></remarks>
public InfoResult Info(RedisValue index) =>
new InfoResult(_db.Execute("FT.INFO", index));


/// <summary>
/// Create an index with the given specification.
15 changes: 8 additions & 7 deletions tests/NRedisStack.Tests/Search/SearchTests.cs
Original file line number Diff line number Diff line change
@@ -227,11 +227,12 @@ public void AlterAdd()
SearchResult res2 = ft.Search(index, new Query("@tags:{tagA}"));
Assert.Equal(100, res2.TotalResults);

//TODO: complete this test when I finish the command FT.INFO
// var info = ft.Info(index);
// Assert.Equal(index, info.get("index_name"));
// Assert.Equal("identifier", ((List)((List)info.get("attributes")).get(1)).get(0));
// Assert.Equal("attribute", ((List)((List)info.get("attributes")).get(1)).get(2));
//TODO: complete this test
var info = ft.Info(index);
Assert.Equal(index, info.IndexName);
//var result = info["attributes"];
// Assert.Equal("identifier", (info.Attributes[]);
// Assert.Equal("attribute", ((RedisValue[])((RedisValue[])info["attributes"])[1])[2]);
}

[Fact]
@@ -266,8 +267,8 @@ public async Task AlterAddAsync()
//TODO: complete this test when I finish the command FT.INFO
// var info = ft.Info(index);
// Assert.Equal(index, info.get("index_name"));
// Assert.Equal("identifier", ((List)((List)info.get("attributes")).get(1)).get(0));
// Assert.Equal("attribute", ((List)((List)info.get("attributes")).get(1)).get(2));
// Assert.Equal("identifier", ((RedisValue[])((RedisValue[])info.get("attributes"))[1])[0]);
// Assert.Equal("attribute", ((RedisValue[])((RedisValue[])info.get("attributes"))[1])[2]);
}

[Fact]