Доработать схему данных по части хранения типов полей в соответствии с индексацией
This commit is contained in:
parent
f955aab218
commit
1d0921c3e8
@ -13,7 +13,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace DD.Persistence.Database.Postgres.Migrations
|
||||
{
|
||||
[DbContext(typeof(PersistencePostgresContext))]
|
||||
[Migration("20250203061429_Init")]
|
||||
[Migration("20250204044050_Init")]
|
||||
partial class Init
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@ -79,6 +79,11 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
||||
.HasColumnType("jsonb")
|
||||
.HasComment("Наименования полей в порядке индексации");
|
||||
|
||||
b.PrimitiveCollection<int[]>("PropTypes")
|
||||
.IsRequired()
|
||||
.HasColumnType("integer[]")
|
||||
.HasComment("Типы полей в порядке индексации");
|
||||
|
||||
b.HasKey("DiscriminatorId");
|
||||
|
||||
b.ToTable("data_scheme");
|
@ -35,7 +35,8 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
||||
columns: table => new
|
||||
{
|
||||
DiscriminatorId = table.Column<Guid>(type: "uuid", nullable: false, comment: "Идентификатор схемы данных"),
|
||||
PropNames = table.Column<string>(type: "jsonb", nullable: false, comment: "Наименования полей в порядке индексации")
|
||||
PropNames = table.Column<string>(type: "jsonb", nullable: false, comment: "Наименования полей в порядке индексации"),
|
||||
PropTypes = table.Column<int[]>(type: "integer[]", nullable: false, comment: "Типы полей в порядке индексации")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
@ -76,6 +76,11 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
||||
.HasColumnType("jsonb")
|
||||
.HasComment("Наименования полей в порядке индексации");
|
||||
|
||||
b.PrimitiveCollection<int[]>("PropTypes")
|
||||
.IsRequired()
|
||||
.HasColumnType("integer[]")
|
||||
.HasComment("Типы полей в порядке индексации");
|
||||
|
||||
b.HasKey("DiscriminatorId");
|
||||
|
||||
b.ToTable("data_scheme");
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DD.Persistence.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
@ -12,4 +13,7 @@ public class DataScheme
|
||||
|
||||
[Comment("Наименования полей в порядке индексации"), Column(TypeName = "jsonb")]
|
||||
public string[] PropNames { get; set; } = [];
|
||||
|
||||
[Comment("Типы полей в порядке индексации")]
|
||||
public PropTypeEnum[] PropTypes { get; set; } = [];
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ using DD.Persistence.Client.Clients;
|
||||
using DD.Persistence.Client.Clients.Interfaces;
|
||||
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||
using DD.Persistence.Database.Entity;
|
||||
using DD.Persistence.Extensions;
|
||||
using DD.Persistence.Models;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@ -267,7 +266,7 @@ public class TimestampedValuesControllerTest : BaseIntegrationTest
|
||||
var count = 2048;
|
||||
var timestampBegin = DateTimeOffset.UtcNow;
|
||||
var dtos = await AddRange(discriminatorId, count);
|
||||
|
||||
|
||||
|
||||
//act
|
||||
var response = await timestampedValuesClient.GetResampledData(discriminatorId, timestampBegin, count);
|
||||
|
@ -14,4 +14,9 @@ public class DataSchemeDto
|
||||
/// Наименования полей
|
||||
/// </summary>
|
||||
public string[] PropNames { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Типы полей
|
||||
/// </summary>
|
||||
public PropTypeEnum[] PropTypes { get; set; } = [];
|
||||
}
|
||||
|
14
DD.Persistence.Models/Enumerations/PropTypeEnum.cs
Normal file
14
DD.Persistence.Models/Enumerations/PropTypeEnum.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace DD.Persistence.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Типы для набора данных
|
||||
/// </summary>
|
||||
public enum PropTypeEnum
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
String = 0,
|
||||
/// <inheritdoc/>
|
||||
Double = 1,
|
||||
/// <inheritdoc/>
|
||||
DateTime = 2
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
using DD.Persistence.Extensions;
|
||||
using DD.Persistence.Models;
|
||||
using DD.Persistence.Models.Common;
|
||||
using DD.Persistence.Repositories;
|
||||
using DD.Persistence.Services.Interfaces;
|
||||
|
||||
@ -25,8 +24,7 @@ public class TimestampedValuesService : ITimestampedValuesService
|
||||
// ToDo: реализовать без foreach
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
var keys = dto.Values.Keys.ToArray();
|
||||
await CreateSystemSpecificationIfNotExist(discriminatorId, keys, token);
|
||||
await CreateDataSchemeIfNotExist(discriminatorId, dto, token);
|
||||
}
|
||||
|
||||
var result = await timestampedValuesRepository.AddRange(discriminatorId, dtos, token);
|
||||
@ -94,7 +92,7 @@ public class TimestampedValuesService : ITimestampedValuesService
|
||||
public async Task<IEnumerable<TimestampedValuesDto>> GetGtDate(Guid discriminatorId, DateTimeOffset beginTimestamp, CancellationToken token)
|
||||
{
|
||||
var result = await timestampedValuesRepository.GetGtDate(discriminatorId, beginTimestamp, token);
|
||||
|
||||
|
||||
var resultToMaterialize = new[] { KeyValuePair.Create(discriminatorId, result) }
|
||||
.ToDictionary();
|
||||
var dtos = await Materialize(resultToMaterialize, token);
|
||||
@ -140,37 +138,69 @@ public class TimestampedValuesService : ITimestampedValuesService
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создать спецификацию, при отсутствии таковой
|
||||
/// Создать схему данных, при отсутствии таковой
|
||||
/// </summary>
|
||||
/// <param name="discriminatorId">Дискриминатор системы</param>
|
||||
/// <param name="fieldNames">Набор наименований полей</param>
|
||||
/// <param name="discriminatorId">Дискриминатор схемы</param>
|
||||
/// <param name="dto">Набор данных, по образу которого будет создана соответствующая схема</param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="InvalidOperationException">Некорректный набор наименований полей</exception>
|
||||
private async Task CreateSystemSpecificationIfNotExist(Guid discriminatorId, string[] fieldNames, CancellationToken token)
|
||||
private async Task CreateDataSchemeIfNotExist(Guid discriminatorId, TimestampedValuesDto dto, CancellationToken token)
|
||||
{
|
||||
var systemSpecification = await dataSchemeRepository.Get(discriminatorId, token);
|
||||
if (systemSpecification is null)
|
||||
var propNames = dto.Values.Keys.ToArray();
|
||||
var propTypes = GetPropTypes(dto);
|
||||
|
||||
var dataScheme = await dataSchemeRepository.Get(discriminatorId, token);
|
||||
if (dataScheme is null)
|
||||
{
|
||||
systemSpecification = new DataSchemeDto()
|
||||
dataScheme = new DataSchemeDto()
|
||||
{
|
||||
DiscriminatorId = discriminatorId,
|
||||
PropNames = fieldNames
|
||||
PropNames = propNames,
|
||||
PropTypes = propTypes
|
||||
};
|
||||
await dataSchemeRepository.Add(systemSpecification, token);
|
||||
await dataSchemeRepository.Add(dataScheme, token);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!systemSpecification.PropNames.SequenceEqual(fieldNames))
|
||||
if (!dataScheme.PropNames.SequenceEqual(propNames))
|
||||
{
|
||||
var expectedFieldNames = string.Join(", ", systemSpecification.PropNames);
|
||||
var actualFieldNames = string.Join(", ", fieldNames);
|
||||
var expectedFieldNames = string.Join(", ", dataScheme.PropNames);
|
||||
var actualFieldNames = string.Join(", ", propNames);
|
||||
throw new InvalidOperationException($"Для системы {discriminatorId.ToString()} " +
|
||||
$"характерен набор данных: [{expectedFieldNames}], однако был передан набор: [{actualFieldNames}]");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получить типы для набора данных в соответствии с индексацией
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
private PropTypeEnum[] GetPropTypes(TimestampedValuesDto dto)
|
||||
{
|
||||
var types = dto.Values.Select(e =>
|
||||
{
|
||||
var valueString = e.Value.ToString();
|
||||
|
||||
if (valueString is null)
|
||||
throw new ArgumentNullException("Переданный набор данных содержит null, в следствии чего не удаётся определить типы полей");
|
||||
|
||||
if (DateTimeOffset.TryParse(valueString, out _))
|
||||
return PropTypeEnum.DateTime;
|
||||
|
||||
var doubleString = valueString.Replace('.', ',');
|
||||
if (double.TryParse(doubleString, out _))
|
||||
return PropTypeEnum.Double;
|
||||
|
||||
return PropTypeEnum.String;
|
||||
});
|
||||
|
||||
return types.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отсеить лишние поля в соответствии с заданным фильтром
|
||||
/// </summary>
|
||||
|
Loading…
Reference in New Issue
Block a user