Creado apartir del commit b888de6c92056de294456f581a56e25e734d4ab7 de develop
This commit is contained in:
@@ -0,0 +1,297 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.Pumps;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories
|
||||
{
|
||||
public class PumpObservationRepository : MongoRepository<PumpObservation>, IPumpObservationRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
|
||||
|
||||
public PumpObservationRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.PumpObservations ?? "pump_observations";
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var indexModels = new List<CreateIndexModel<PumpObservation>>
|
||||
{
|
||||
// Timeline por bomba (consulta más frecuente)
|
||||
new CreateIndexModel<PumpObservation>(
|
||||
Builders<PumpObservation>.IndexKeys
|
||||
.Ascending(x => x.DeviceId)
|
||||
.Descending(x => x.Time),
|
||||
new CreateIndexOptions { Name = "ix_deviceId_time" }),
|
||||
|
||||
// consultas por paciente
|
||||
new CreateIndexModel<PumpObservation>(
|
||||
Builders<PumpObservation>.IndexKeys.Ascending(x => x.PatientId),
|
||||
new CreateIndexOptions { Name = "ix_patientId" }),
|
||||
|
||||
|
||||
// TTL por antigüedad (si aplica retención directa en Mongo)
|
||||
// new CreateIndexModel<PumpObservation>(
|
||||
// Builders<PumpObservation>.IndexKeys.Ascending(x => x.Time),
|
||||
// new CreateIndexOptions { Name = "ttl_time", ExpireAfter = TimeSpan.FromDays(180) })
|
||||
};
|
||||
|
||||
await Collection.Indexes.CreateManyAsync(indexModels);
|
||||
}
|
||||
|
||||
public async Task InsertAsync(PumpObservation obs)
|
||||
{
|
||||
await Collection.InsertOneAsync(obs);
|
||||
}
|
||||
|
||||
public async Task InsertManyAsync(IEnumerable<PumpObservation>? observations)
|
||||
{
|
||||
if (observations == null) return;
|
||||
|
||||
var list = observations as IList<PumpObservation> ?? observations.ToList();
|
||||
if (list.Count == 0) return;
|
||||
|
||||
await Collection.InsertManyAsync(list);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PumpObservation>> FindByDeviceIdAsync(
|
||||
string deviceId,
|
||||
DateTime? from = null,
|
||||
DateTime? to = null,
|
||||
int? limit = null)
|
||||
{
|
||||
var filter = Builders<PumpObservation>.Filter.Eq(x => x.DeviceId, deviceId);
|
||||
|
||||
if (from.HasValue)
|
||||
filter &= Builders<PumpObservation>.Filter.Gte(x => x.Time, from.Value);
|
||||
|
||||
if (to.HasValue)
|
||||
filter &= Builders<PumpObservation>.Filter.Lte(x => x.Time, to.Value);
|
||||
|
||||
var query = Collection.Find(filter)
|
||||
.SortByDescending(x => x.Time);
|
||||
|
||||
if (limit.HasValue)
|
||||
query = query.Limit(limit.Value) as IOrderedFindFluent<PumpObservation, PumpObservation>;
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
|
||||
// histórico por paciente
|
||||
public async Task<IEnumerable<PumpObservation>> FindByPatientAsync(
|
||||
ObjectId patientId,
|
||||
DateTime? from = null,
|
||||
DateTime? to = null,
|
||||
int? limit = null)
|
||||
{
|
||||
var filter = Builders<PumpObservation>.Filter.Eq(x => x.PatientId, patientId);
|
||||
|
||||
if (from.HasValue)
|
||||
filter &= Builders<PumpObservation>.Filter.Gte(x => x.Time, from.Value);
|
||||
|
||||
if (to.HasValue)
|
||||
filter &= Builders<PumpObservation>.Filter.Lte(x => x.Time, to.Value);
|
||||
|
||||
var query = Collection.Find(filter)
|
||||
.SortByDescending(x => x.Time);
|
||||
|
||||
if (limit.HasValue)
|
||||
query = query.Limit(limit.Value) as IOrderedFindFluent<PumpObservation, PumpObservation>;
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<Dictionary<ObjectId, DateTime>> FindAllLastPatientObservationTimeAsync()
|
||||
{
|
||||
// Pipeline:
|
||||
// 1) Filtrar observaciones con PatientId no nulo
|
||||
// 2) Agrupar por PatientId
|
||||
// 3) Obtener el máximo Time
|
||||
// 4) Devolver diccionario
|
||||
|
||||
var pipeline = new[]
|
||||
{
|
||||
new BsonDocument("$match", new BsonDocument
|
||||
{
|
||||
{ "patientid", new BsonDocument("$ne", BsonNull.Value) }
|
||||
}),
|
||||
new BsonDocument("$group", new BsonDocument
|
||||
{
|
||||
{ "_id", "$patientid" },
|
||||
{ "LastTime", new BsonDocument("$max", "$time") }
|
||||
})
|
||||
};
|
||||
|
||||
var docs = await Collection.Aggregate<BsonDocument>(pipeline).ToListAsync();
|
||||
|
||||
var result = new Dictionary<ObjectId, DateTime>();
|
||||
|
||||
foreach (var doc in docs.Where(doc =>
|
||||
doc["_id"].IsObjectId && doc["LastTime"].IsValidDateTime
|
||||
))
|
||||
{
|
||||
result[doc["_id"].AsObjectId] = doc["LastTime"].ToUniversalTime();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<PumpObservation?> FindLastByDeviceIdAsync(string deviceId)
|
||||
{
|
||||
return await Collection
|
||||
.Find(x => x.DeviceId == deviceId)
|
||||
.SortByDescending(x => x.Time)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PumpObservation>> FindByPatientId(ObjectId? patientId)
|
||||
{
|
||||
return await Collection.Find(x => x.PatientId == patientId).ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<PumpObservation>> AggregatedPatientLastObservations(ObjectId patientId, int num = 100)
|
||||
{
|
||||
var filterBuilder = Builders<PumpObservation>.Filter;
|
||||
var sortBuilder = Builders<PumpObservation>.Sort;
|
||||
|
||||
var filter = filterBuilder.Eq(o => o.PatientId, patientId);
|
||||
var sort = sortBuilder.Descending("time");
|
||||
var options = new FindOptions<PumpObservation> { Sort = sort, Limit = num };
|
||||
|
||||
var result = await Collection.FindAsync(filter, options);
|
||||
var observations = await result.ToListAsync();
|
||||
|
||||
var distinctObservations = observations.DistinctBy(m => new { m.Code, m.Name }).ToList();
|
||||
var sortedObservations = distinctObservations.OrderByDescending(x => x.Time).ToList();
|
||||
|
||||
return sortedObservations;
|
||||
}
|
||||
|
||||
public async Task DeleteByPatientId(ObjectId? patientId)
|
||||
{
|
||||
await Collection.DeleteManyAsync(x => x.PatientId == patientId);
|
||||
}
|
||||
public async Task<long> DeleteOlderThanDaysAsync(int days, string? name = null)
|
||||
{
|
||||
var limitDate = DateTime.UtcNow.AddDays(-days);
|
||||
|
||||
var filter = Builders<PumpObservation>.Filter.Lt(x => x.Time, limitDate);
|
||||
if(!string.IsNullOrEmpty(name))
|
||||
filter &= Builders<PumpObservation>.Filter.Eq(x=> x.Name, name);
|
||||
|
||||
return (await Collection.DeleteManyAsync(filter)).DeletedCount;
|
||||
}
|
||||
|
||||
public async Task<long> DeleteKeepLastNAsync(int maxCount)
|
||||
{
|
||||
// Para cada DeviceId:
|
||||
var deviceIds = await Collection
|
||||
.Distinct<string>("DeviceId", FilterDefinition<PumpObservation>.Empty)
|
||||
.ToListAsync();
|
||||
|
||||
long totalDeleted = 0;
|
||||
|
||||
foreach (var filter in deviceIds.Select(deviceId =>
|
||||
Builders<PumpObservation>.Filter.Eq(x => x.DeviceId, deviceId)
|
||||
))
|
||||
{
|
||||
var all = await Collection.Find(filter)
|
||||
.SortByDescending(x => x.Time)
|
||||
.ToListAsync();
|
||||
|
||||
if (all.Count <= maxCount)
|
||||
continue;
|
||||
|
||||
var toDelete = all.Skip(maxCount).Select(x => x.Id).ToList();
|
||||
|
||||
var deleteFilter = Builders<PumpObservation>.Filter.In(x => x.Id, toDelete);
|
||||
var result = await Collection.DeleteManyAsync(deleteFilter);
|
||||
|
||||
totalDeleted += result.DeletedCount;
|
||||
}
|
||||
|
||||
return totalDeleted;
|
||||
}
|
||||
|
||||
public async Task<long> UpdateManyObjectIdByFieldAsync(string fieldName, ObjectId newId, ObjectId? oldId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(fieldName))
|
||||
throw new ArgumentException("fieldName can't be null or empty.", nameof(fieldName));
|
||||
|
||||
// Normalize casing (Mongo is case-sensitive)
|
||||
// if (fieldName.Equals("patientid", StringComparison.OrdinalIgnoreCase))
|
||||
// fieldName = nameof(PumpObservation.PatientId);
|
||||
|
||||
var filter = Builders<PumpObservation>.Filter.Eq(fieldName, oldId);
|
||||
var update = Builders<PumpObservation>.Update.Set(fieldName, newId);
|
||||
|
||||
var result = await Collection.UpdateManyAsync(filter, update);
|
||||
return result.ModifiedCount;
|
||||
}
|
||||
|
||||
|
||||
public async Task<long> DeleteOlderNumberAsync(string name, int maxCount)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
return 0;
|
||||
|
||||
// 1. Filtrar todas las observaciones con ese Name
|
||||
var filter = Builders<PumpObservation>.Filter.Eq(x => x.Name, name);
|
||||
|
||||
// 2. Obtenerlas ordenadas por Time DESC (las más recientes primero)
|
||||
var all = await Collection
|
||||
.Find(filter)
|
||||
.SortByDescending(x => x.Time)
|
||||
.ToListAsync();
|
||||
|
||||
// 3. Si hay menos o igual al número permitido → no borrar nada
|
||||
if (all.Count <= maxCount)
|
||||
return 0;
|
||||
|
||||
// 4. Seleccionar TODAS excepto las maxCount más recientes
|
||||
var toDeleteIds = all
|
||||
.Skip(maxCount)
|
||||
.Select(x => x.Id)
|
||||
.ToList();
|
||||
|
||||
if (toDeleteIds.Count == 0)
|
||||
return 0;
|
||||
|
||||
// 5. Borrar las seleccionadas
|
||||
var deleteFilter = Builders<PumpObservation>.Filter.In(x => x.Id, toDeleteIds);
|
||||
var result = await Collection.DeleteManyAsync(deleteFilter);
|
||||
|
||||
return result.DeletedCount;
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<PumpObservation>> FindLastObservations(ObjectId patientId, string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
return [];
|
||||
|
||||
var filter = Builders<PumpObservation>.Filter.And(
|
||||
Builders<PumpObservation>.Filter.Eq(x => x.PatientId, patientId),
|
||||
Builders<PumpObservation>.Filter.Eq(x => x.Name, name)
|
||||
);
|
||||
|
||||
return await Collection
|
||||
.Find(filter)
|
||||
.SortByDescending(x => x.Time)
|
||||
.Limit(2)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user