Skip to content

Commit

Permalink
fix: sorting and properties
Browse files Browse the repository at this point in the history
  • Loading branch information
cguckes committed Dec 11, 2023
1 parent b93840a commit 5e574e4
Show file tree
Hide file tree
Showing 14 changed files with 292 additions and 42 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ jobs:
sed -i "s@#AZURE_CLIENT_ID#@${{ secrets.AZURE_CLIENT_ID }}@g" ./build/app/appsettings.Production.json
sed -i "s@#AZURE_TENANT_ID#@${{ secrets.AZURE_TENANT_ID }}@g" ./build/app/appsettings.Production.json
sed -i "s@#AZURE_AUDIENCE#@${{ secrets.AZURE_AUDIENCE }}@g" ./build/app/appsettings.Production.json
sed -i "s@#AZURE_INSTANCE#@${{ env.AZURE_INSTANCE }}@g" ./build/app/appsettings.Production.json
sed -i "s@#AZURE_INSTANCE#@https://login.microsoftonline.com/@g" ./build/app/appsettings.Production.json
- name: Docker build
run: |
cd build
Expand Down
10 changes: 7 additions & 3 deletions src/WebIO/WebIO.Elastic/Data/IndexedDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

using System.Collections.Immutable;
using Management;
using Nest;

public record IndexedDevice : IIndexedEntity<Guid>
{
public Guid Id { get; init; } = Guid.NewGuid();
public string Name { get; init; } = string.Empty;
public string DeviceType { get; init; } = string.Empty;
[Keyword] public string Name { get; init; } = string.Empty;
[Keyword] public string DeviceType { get; init; } = string.Empty;
public string Comment { get; init; } = string.Empty;

[Nested]
public IReadOnlyDictionary<string, string> Properties { get; init; } = ImmutableDictionary<string, string>.Empty;

public int InterfaceCount { get; init; }
}
}
12 changes: 11 additions & 1 deletion src/WebIO/WebIO.Elastic/Data/IndexedInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,35 @@ namespace WebIO.Elastic.Data;

using System.Collections.Immutable;
using Management;
using Nest;

public record IndexedInterface : IIndexedEntity<Guid>
{
public Guid Id { get; init; } = Guid.NewGuid();
[Keyword]
public Guid DeviceId { get; init; }
[Keyword]
public string Name { get; init; } = string.Empty;
public int Index { get; init; }
[Keyword]
public string InterfaceTemplate { get; init; } = string.Empty;
public string Comment { get; init; } = string.Empty;
[Keyword]
public string DeviceType { get; init; } = string.Empty;
[Keyword]
public string DeviceName { get; init; } = string.Empty;

[Nested]
public IReadOnlyDictionary<string, string> Properties { get; init; } = ImmutableDictionary<string, string>.Empty;

public int StreamsCountVideoSend { get; init; }
public int StreamsCountAudioSend { get; init; }
public int StreamsCountAncillarySend { get; init; }
public int StreamsCountVideoReceive { get; init; }
public int StreamsCountAudioReceive { get; init; }
public int StreamsCountAncillaryReceive { get; init; }

[Nested]
public IReadOnlyDictionary<string, string> DeviceProperties { get; init; } =
ImmutableDictionary<string, string>.Empty;
}
}
22 changes: 14 additions & 8 deletions src/WebIO/WebIO.Elastic/Data/IndexedStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,30 @@ namespace WebIO.Elastic.Data;

using System.Collections.Immutable;
using Management;
using Nest;

public record IndexedStream : IIndexedEntity<Guid>
{
public Guid Id { get; init; } = Guid.NewGuid();
public Guid InterfaceId { get; init; }
public string DeviceName { get; init; } = string.Empty;
public string InterfaceName { get; init; } = string.Empty;
public string Name { get; init; } = string.Empty;
[Keyword] public Guid InterfaceId { get; init; }
[Keyword] public string DeviceName { get; init; } = string.Empty;
[Keyword] public string InterfaceName { get; init; } = string.Empty;
[Keyword] public string Name { get; init; } = string.Empty;
public string Comment { get; init; } = string.Empty;
public StreamType Type { get; init; }
public StreamDirection Direction { get; init; }
[Keyword] public StreamType Type { get; init; }
[Keyword] public StreamDirection Direction { get; init; }

[Nested]
public IReadOnlyDictionary<string, string> Properties { get; init; } = ImmutableDictionary<string, string>.Empty;
public Guid DeviceId { get; init; }
public string DeviceType { get; init; } = string.Empty;

[Keyword] public Guid DeviceId { get; init; }
[Keyword] public string DeviceType { get; init; } = string.Empty;

[Nested]
public IReadOnlyDictionary<string, string> InterfaceProperties { get; init; } =
ImmutableDictionary<string, string>.Empty;

[Nested]
public IReadOnlyDictionary<string, string> DeviceProperties { get; init; } =
ImmutableDictionary<string, string>.Empty;
}
2 changes: 1 addition & 1 deletion src/WebIO/WebIO.Elastic/Hosting/HostingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static IServiceCollection RegisterElastic(
builder.AddSingleton(config);

var connectionSettings = new ConnectionSettings(config.Url);
// connectionSettings.EnableDebugMode();
connectionSettings.EnableDebugMode();
if (config.Proxy != null)
{
connectionSettings.Proxy(config.Proxy, config.ProxyUser, config.ProxyPassword);
Expand Down
1 change: 1 addition & 0 deletions src/WebIO/WebIO.Elastic/Management/Search/SearchRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ public record SearchRequest
{
public int? Take { get; init; }
public string? Fulltext { get; init; }
public IEnumerable<KeyValuePair<string, string>> Sorting { get; init; } = Enumerable.Empty<KeyValuePair<string, string>>();
}
24 changes: 20 additions & 4 deletions src/WebIO/WebIO.Elastic/Management/Search/Searcher.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace WebIO.Elastic.Management.Search;

using System.Runtime.CompilerServices;
using System.Text;
using Elasticsearch.Net;
using IndexManagement;
using Microsoft.Extensions.Logging;
using Nest;
Expand Down Expand Up @@ -28,12 +30,12 @@ protected Searcher(
public async Task<SearchResult<TEntity>> FindAllAsync(TSearchRequest request, CancellationToken ct)
{
var searchResponse = await _client.SearchAsync<TEntity>(sd => PrepareQuery(request, sd), ct);
// var json = Encoding.UTF8.GetString(searchResponse.ApiCall.RequestBodyInBytes);
var json = Encoding.UTF8.GetString(searchResponse.ApiCall.RequestBodyInBytes);
return new(Documents: IterateResultsAsync(searchResponse, request, ct), Total: searchResponse.Total);
}

public async Task<TEntity?> GetAsync(TId id, CancellationToken ct)
=> (await GetAllAsync(new[] {id}, ct)).FirstOrDefault();
=> (await GetAllAsync(new[] { id }, ct)).FirstOrDefault();

public async Task<IEnumerable<TEntity>> GetAllAsync(IEnumerable<TId> ids, CancellationToken ct)
=> (await _client.GetManyAsync<TEntity>(ids.Select(id => $"{id}"), _indexManager.GetAliasName(), ct)).Select(hit
Expand Down Expand Up @@ -70,11 +72,13 @@ private SearchDescriptor<TEntity> PrepareQuery(
TSearchRequest request,
SearchDescriptor<TEntity> sd,
int currentPosition = 0)
=> UseIndex(_indexManager.GetAliasName(),
=> UseIndex(
_indexManager.GetAliasName(),
Sort(request,
SkipTake(
currentPosition,
request.Take ?? _config.BatchSize,
ToQuery(request)(sd)));
ToQuery(request)(sd))));

private static SearchDescriptor<TEntity> UseIndex(string index, SearchDescriptor<TEntity> sd)
{
Expand All @@ -91,4 +95,16 @@ private static SearchDescriptor<TEntity> SkipTake(
sd.Take(take);
return sd;
}

private static SearchDescriptor<TEntity> Sort(
SearchRequest request,
SearchDescriptor<TEntity> sd)
{
sd.Sort(d => request.Sorting.Aggregate(d,
(sort, kv) => sort.Field(f
=> f.Field(kv.Key)
.Order(kv.Value == "asc" ? SortOrder.Ascending : SortOrder.Descending)
.UnmappedType(FieldType.Keyword))));
return sd;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ namespace WebIO.Elastic.Management.Search;

public record TextFieldSelector<TIndexEntity>
{
public Expression<Func<TIndexEntity, object>> Selector { get; init; } = null!;
public string Name { get; init; } = string.Empty;
public Expression<Func<TIndexEntity, object>>? Selector { get; init; }
public double Boost { get; init; }
public TextFieldType Type { get; init; }
}
5 changes: 4 additions & 1 deletion src/WebIO/WebIO.Elastic/Management/Util.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,10 @@ private static Func<FieldsDescriptor<TIndexedEntity>, FieldsDescriptor<TIndexedE
{
foreach (var field in selectors)
{
f.Field(field.Selector, field.Boost);
if(field.Selector != null)
f.Field(field.Selector, field.Boost);
else
f.Field(field.Name, field.Boost);
}

return f;
Expand Down
16 changes: 9 additions & 7 deletions src/WebIO/WebIO.Tests/IntegrationTests/ElasticTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ public class ElasticTest
DeviceType = "testDeviceType",
Comment = "test comment",
Properties = new(new()),
Interfaces = new()
{
Interfaces =
[
new()
{
Name = "testInterface",
Index = 1,
InterfaceTemplate = "sender",
Comment = "test comment",
Properties = new(new()),
Streams = new()
{
Streams =
[
new()
{
Name = "audio send stream",
Expand All @@ -40,10 +40,12 @@ public class ElasticTest
Modification = new("testUser", DateTime.Now, "test modifier", DateTime.Now, "test comment"),
Properties = new(new()),
},
},

],
Modification = new("testUser", DateTime.Now, "test modifier", DateTime.Now, "test comment"),
},
},

],
Modification = new("testUser", DateTime.Now, "test modifier", DateTime.Now, "test comment"),
};

Expand All @@ -56,7 +58,7 @@ public ElasticTest()
_app.Services.GetRequiredService<AppDbContext>().Database.EnsureCreated();
}

[Fact(Skip = "Broken atm")]
[Fact]
public void WriteAndLoadEntity()
{
var repo = _app.Services.GetRequiredService<IDeviceRepository>();
Expand Down
28 changes: 28 additions & 0 deletions src/WebIO/WebIO/DataAccess/Elastic/DeviceSearcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,34 @@ protected override Func<SearchDescriptor<IndexedDevice>, SearchDescriptor<Indexe
mustFilters.Add(mf => Util.ToTextQuery<IndexedDevice, Guid>(mf, request.DeviceName, fields));
}

foreach (var (key, value) in request.Properties)
{
if (!string.IsNullOrWhiteSpace(value))
{
var fields = new[]
{
new TextFieldSelector<IndexedDevice>
{
Name = $"properties.{key}",
Boost = 10,
Type = TextFieldType.Exact,
},
new TextFieldSelector<IndexedDevice>
{
Name = $"properties.{key}",
Boost = 8,
Type = TextFieldType.PrefixWildcard,
},
};

mustFilters.Add(mf
=> mf.Nested(nqd
=> nqd
.Path(d => d.Properties)
.Query(q => Util.ToTextQuery<IndexedDevice, Guid>(q, value, fields))));
}
}

return sd
=> sd
.MinScore(mustFilters.Any() ? 8 : 0)
Expand Down
17 changes: 17 additions & 0 deletions src/WebIO/WebIO/DataAccess/Elastic/ElasticDeviceRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ private SearchResult<IndexedDevice> FindDeviceByQuery(Query query)
DeviceName = query.Filter.FirstOrDefault(f => f.Key == "Name")?.Value ??
string.Empty,
Properties = query.Filter.ToDictionary(i => i.Key, i => i.Value),
Sorting = ToSortDictionary(query),
}, default).GetAwaiter().GetResult();

private SearchResult<IndexedInterface> FindInterfaceByQuery(Query query)
Expand All @@ -162,6 +163,7 @@ private SearchResult<IndexedInterface> FindInterfaceByQuery(Query query)
string.Empty,
DeviceName = query.Filter.FirstOrDefault(f => f.Key == nameof(InterfaceSearchRequest.DeviceName))?.Value ??
string.Empty,
Sorting = ToSortDictionary(query),
Properties = query.Filter.ToDictionary(i => i.Key, i => i.Value),
}, default).GetAwaiter().GetResult();
}
Expand All @@ -177,6 +179,7 @@ private SearchResult<IndexedStream> FindStreamByQuery(Query query)
string.Empty,
DeviceName = query.Filter.FirstOrDefault(f => f.Key == nameof(StreamSearchRequest.DeviceName))?.Value ??
string.Empty,
Sorting = ToSortDictionary(query),
Properties = query.Filter.ToDictionary(i => i.Key, i => i.Value),
}, default).GetAwaiter().GetResult();

Expand Down Expand Up @@ -314,6 +317,20 @@ private static StreamInfo ToStreamInfo(IndexedStream stream)
stream.DeviceProperties.ToImmutableDictionary(),
stream.InterfaceProperties.ToImmutableDictionary(),
null);

private static IEnumerable<KeyValuePair<string, string>> ToSortDictionary(Query query)
=> query.Sort?.Split(',').Select(LcFirstIfBaseObjectMember)
.Zip(query.Order?.Split(',') ?? Enumerable.Empty<string>(), KeyValuePair.Create)
?? ImmutableArray<KeyValuePair<string, string>>.Empty;

private static string LcFirstIfBaseObjectMember(string field)
=> field switch {
"Name" => "name",
"DeviceName" => "deviceName",
"InterfaceName" => "interfaceName",
"StreamName" => "streamName",
_ => $"properties.{field}",
};
}

public record DeviceSearchRequest : SearchRequest
Expand Down
Loading

0 comments on commit 5e574e4

Please sign in to comment.