Add TimestampedSetRepository #2

Merged
on.nemtina merged 8 commits from TimestampedSetRepository into master 2024-11-26 12:59:05 +05:00
4 changed files with 104 additions and 24 deletions
Showing only changes of commit 3bb5fc4411 - Show all commits

View File

@ -2,11 +2,14 @@
using Microsoft.AspNetCore.Mvc;
using Persistence.Models;
using Persistence.Repositories;
using Persistence.Repository.Repositories;
using System.Net;
namespace Persistence.API.Controllers;
/// <summary>
/// Хранение наборов данных с отметкой времени.
/// Не оптимизировано под большие данные.
/// </summary>
[ApiController]
[Authorize]
[Route("api/[controller]/{idDiscriminator}")]
@ -19,6 +22,14 @@ public class TimestampedSetController : ControllerBase
this.repository = repository;
}
/// <summary>
/// Записать новые данные
/// Предполагается что данные с одним дискриминатором имеют одинаковую структуру
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="sets"></param>
/// <param name="token"></param>
/// <returns>кол-во затронутых записей</returns>
[HttpPost]
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
public async Task<IActionResult> InsertRange([FromRoute]Guid idDiscriminator, [FromBody]IEnumerable<TimestampedSetDto> sets, CancellationToken token)
@ -27,22 +38,46 @@ public class TimestampedSetController : ControllerBase
return Ok(result);
}
/// <summary>
/// Получение данных с фильтрацией. Значение фильтра null - отключен
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="geTimestamp">Фильтр позднее даты</param>
/// <param name="columnNames">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param>
/// <param name="skip"></param>
/// <param name="take"></param>
/// <param name="token"></param>
/// <returns>Фильтрованный набор данных с сортировкой по отметке времени</returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<TimestampedSetDto>), (int)HttpStatusCode.OK)]
public async Task<IActionResult> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, [FromQuery]IEnumerable<string>? props, int skip, int take, CancellationToken token)
public async Task<IActionResult> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, [FromQuery]IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
{
var result = await repository.Get(idDiscriminator, geTimestamp, props, skip, take, token);
var result = await repository.Get(idDiscriminator, geTimestamp, columnNames, skip, take, token);
return Ok(result);
}
/// <summary>
/// Получить последние данные
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="columnNames">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param>
/// <param name="take"></param>
/// <param name="token"></param>
/// <returns>Фильтрованный набор данных с сортировкой по отметке времени</returns>
[HttpGet("last")]
[ProducesResponseType(typeof(IEnumerable<TimestampedSetDto>), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetLast(Guid idDiscriminator, [FromQuery]IEnumerable<string>? props, int take, CancellationToken token)
public async Task<IActionResult> GetLast(Guid idDiscriminator, [FromQuery]IEnumerable<string>? columnNames, int take, CancellationToken token)
{
var result = await repository.GetLast(idDiscriminator, props, take, token);
var result = await repository.GetLast(idDiscriminator, columnNames, take, token);
return Ok(result);
}
/// <summary>
/// Диапазон дат за которые есть данные
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="token"></param>
/// <returns>Дата первой и последней записи</returns>
[HttpGet("datesRange")]
[ProducesResponseType(typeof(DatesRangeDto), (int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.NoContent)]
@ -52,8 +87,14 @@ public class TimestampedSetController : ControllerBase
return Ok(result);
}
/// <summary>
/// Количество записей по указанному набору в БД. Для пагинации.
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet("count")]
[ProducesResponseType(typeof(DatesRangeDto), (int)HttpStatusCode.OK)]
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.NoContent)]
public async Task<IActionResult> Count(Guid idDiscriminator, CancellationToken token)
{

View File

@ -2,22 +2,61 @@
using Refit;
namespace Persistence.Client.Clients;
/// <summary>
/// Клиент для работы с репозиторием для хранения разных наборов данных рядов.
/// idDiscriminator - идентифицирует конкретный набор данных, прим.: циклы измерения АСИБР, или отчет о DrillTest.
/// idDiscriminator формируют клиенты и только им известно что они обозначают.
/// Так как данные приходят редко, то их прореживания для построения графиков не предусмотрено.
/// </summary>
public interface ITimestampedSetClient
{
private const string baseUrl = "/api/TimestampedSet/{idDiscriminator}";
/// <summary>
/// Добавление новых данных
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="sets"></param>
/// <returns></returns>
[Post(baseUrl)]
Task<IApiResponse<int>> InsertRange(Guid idDiscriminator, IEnumerable<TimestampedSetDto> sets);
/// <summary>
/// Получение данных с фильтрацией. Значение фильтра null - отключен
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="geTimestamp">Фильтр позднее даты</param>
/// <param name="columnNames">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param>
/// <param name="skip"></param>
/// <param name="take"></param>
/// <returns></returns>
[Get(baseUrl)]
Task<IApiResponse<IEnumerable<TimestampedSetDto>>> Get(Guid idDiscriminator, [Query] DateTimeOffset? geTimestamp, [Query] IEnumerable<string>? props, int skip, int take);
Task<IApiResponse<IEnumerable<TimestampedSetDto>>> Get(Guid idDiscriminator, [Query] DateTimeOffset? geTimestamp, [Query] IEnumerable<string>? columnNames, int skip, int take);
/// <summary>
/// Получить последние данные
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="columnNames">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param>
/// <param name="take"></param>
/// <returns></returns>
[Get($"{baseUrl}/last")]
Task<IApiResponse<IEnumerable<TimestampedSetDto>>> GetLast(Guid idDiscriminator, [Query] IEnumerable<string>? props, int take);
Task<IApiResponse<IEnumerable<TimestampedSetDto>>> GetLast(Guid idDiscriminator, [Query] IEnumerable<string>? columnNames, int take);
/// <summary>
/// Количество записей по указанному набору в БД. Для пагинации.
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <returns></returns>
[Get($"{baseUrl}/count")]
Task<IApiResponse<int>> Count(Guid idDiscriminator);
/// <summary>
/// Диапазон дат за которые есть данные
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <returns></returns>
[Get($"{baseUrl}/datesRange")]
Task<IApiResponse<DatesRangeDto?>> GetDatesRange(Guid idDiscriminator);
}

View File

@ -28,7 +28,7 @@ public class TimestampedSetRepository : ITimestampedSetRepository
return db.SaveChangesAsync(token);
}
public async Task<IEnumerable<TimestampedSetDto>> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable<string>? props, int skip, int take, CancellationToken token)
public async Task<IEnumerable<TimestampedSetDto>> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
{
var dbSet = db.Set<TimestampedSet>();
var query = dbSet.Where(entity => entity.IdDiscriminator == idDiscriminator);
@ -43,13 +43,13 @@ public class TimestampedSetRepository : ITimestampedSetRepository
var data = await Materialize(query, token);
if (props is not null && props.Any())
data = ApplyPropsFilter(data, props);
if (columnNames is not null && columnNames.Any())
data = ReduceSetColumnsByNames(data, columnNames);
return data;
}
public async Task<IEnumerable<TimestampedSetDto>> GetLast(Guid idDiscriminator, IEnumerable<string>? props, int take, CancellationToken token)
public async Task<IEnumerable<TimestampedSetDto>> GetLast(Guid idDiscriminator, IEnumerable<string>? columnNames, int take, CancellationToken token)
{
var dbSet = db.Set<TimestampedSet>();
var query = dbSet.Where(entity => entity.IdDiscriminator == idDiscriminator);
@ -60,8 +60,8 @@ public class TimestampedSetRepository : ITimestampedSetRepository
var data = await Materialize(query, token);
if (props is not null && props.Any())
data = ApplyPropsFilter(data, props);
if (columnNames is not null && columnNames.Any())

Фильтр применился после материализации, а материализовывается только take элементов. А вдруг именно в этой порции ничего не найдено?

Фильтр применился после материализации, а материализовывается только take элементов. А вдруг именно в этой порции ничего не найдено?
data = ReduceSetColumnsByNames(data, columnNames);
return data;
}
@ -107,13 +107,13 @@ public class TimestampedSetRepository : ITimestampedSetRepository
return query.Where(entity => entity.Timestamp >= geTimestampUtc);
}
private static IEnumerable<TimestampedSetDto> ApplyPropsFilter(IEnumerable<TimestampedSetDto> query, IEnumerable<string> props)
private static IEnumerable<TimestampedSetDto> ReduceSetColumnsByNames(IEnumerable<TimestampedSetDto> query, IEnumerable<string> columnNames)

Переименовать (убрать слово Filter)

Переименовать (убрать слово Filter)
{
var newQuery = query
.Select(entity => new TimestampedSetDto(
entity.Timestamp,
entity.Set
.Where(prop => props.Contains(prop.Key))
.Where(prop => columnNames.Contains(prop.Key))
.ToDictionary(prop => prop.Key, prop => prop.Value)
));
return newQuery;

View File

@ -3,7 +3,7 @@
namespace Persistence.Repositories;
/// <summary>
/// Репозиторий для хранения разных наборов данных временных рядов.
/// Репозиторий для хранения разных наборов данных рядов.
/// idDiscriminator - идентифицирует конкретный набор данных, прим.: циклы измерения АСИБР, или отчет о DrillTest.
/// idDiscriminator формируют клиенты и только им известно что они обозначают.
/// Так как данные приходят редко, то их прореживания для построения графиков не предусмотрено.
@ -13,7 +13,7 @@ public interface ITimestampedSetRepository
/// <summary>
/// Количество записей по указанному набору в БД. Для пагинации.
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> Count(Guid idDiscriminator, CancellationToken token);
@ -23,17 +23,17 @@ public interface ITimestampedSetRepository
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="geTimestamp">Фильтр позднее даты</param>
/// <param name="props">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param>
/// <param name="columnNames">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param>
/// <param name="skip"></param>
/// <param name="take"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<TimestampedSetDto>> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable<string>? props, int skip, int take, CancellationToken token);
Task<IEnumerable<TimestampedSetDto>> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token);
/// <summary>
/// Диапазон дат за которые есть данные
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="token"></param>
/// <returns></returns>
Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token);
@ -42,11 +42,11 @@ public interface ITimestampedSetRepository
/// Получить последние данные
/// </summary>
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
/// <param name="props">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param>
/// <param name="columnNames">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param>
/// <param name="take"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<TimestampedSetDto>> GetLast(Guid idDiscriminator, IEnumerable<string>? props, int take, CancellationToken token);
Task<IEnumerable<TimestampedSetDto>> GetLast(Guid idDiscriminator, IEnumerable<string>? columnNames, int take, CancellationToken token);
/// <summary>
/// Добавление новых данных