MyBookmark/Modules.Rating.Api/Repositories/RateRepository.cs
THE_KONDRAT 7b16d72329 ui and login
mongo => postgres
2024-11-03 16:08:39 +03:00

149 lines
6.1 KiB
C#

using Microsoft.EntityFrameworkCore;
using Modules.Rating.Api.Database;
using Modules.Rating.Api.Database.Entities;
using System.Linq.Expressions;
namespace Modules.Rating.Api.Repositories;
public class RateRepository(RatingDbContext context)
{
private readonly RatingDbContext _context = context;
public async Task AddAsync(Rate entity)
{
if (await IsRateExists(entity.ObjectId, entity.SubjectId)) throw new Exception("Object is already rated by subject");
_context.Rates.Add(entity);
await _context.SaveChangesAsync();
}
public async Task<bool> UpdateAsync(Rate entity)
{
var rate = await _context.Rates
.FirstOrDefaultAsync(q => q.ObjectId == entity.ObjectId && q.SubjectId == entity.SubjectId)
?? throw new Exception("Rate not found");
rate.RatePercentage = entity.RatePercentage;
await _context.SaveChangesAsync();
return rate != null;
}
public async Task<bool> DeleteAsync(Guid objectId, Guid subjectId)
{
var rate = await _context.Rates.FirstOrDefaultAsync(q => q.ObjectId == objectId && q.SubjectId == subjectId);
if (rate != null) _context.Rates?.Remove(rate);
return rate != null;
}
public async Task<Rate?> GetFirstOrDefaultWhere(Expression<Func<Rate, bool>> predicate) =>
await _context.Rates.Where(predicate).SingleOrDefaultAsync();
public async Task<List<Rate>> GetWhere(Expression<Func<Rate, bool>> predicate) =>
await _context.Rates.Where(predicate).ToListAsync();
internal async Task<List<RateItem>> GetRates(IEnumerable<Guid> objectIds, Guid? subjectId)
{
var query = _context.Rates.AsQueryable();
return await query
.Where(q => objectIds.Contains(q.ObjectId))
.GroupBy(q => q.ObjectId, (o, r) => new { ObjectId = o, Rate = r.Average(q => q.RatePercentage) })
.GroupJoin(query.Where(q => q.SubjectId == subjectId),
q => q.ObjectId,
q => q.ObjectId,
(g, r) => new { g.ObjectId, g.Rate, SubjecrRates = r })
.SelectMany(q => q.SubjecrRates.DefaultIfEmpty(), (r, s) =>
new RateItem { ObjectId = r.ObjectId, Rate = r.Rate, SubjectRate = s != null ? s.RatePercentage : null })
.ToListAsync().ConfigureAwait(false);
//var builder = Builders<BsonDocument>.SetFields
//await _collection
//.Aggregate()
//.Match(q => objectIds.Contains(q.Key.ObjectId))
//.Group(q => q.Key.ObjectId, q => new { ObjectId = q.Key, Rate = q.Average(q => q.RatePercentage) })
//.Lookup<Rate, RateItem>(nameof(Rate), q => q.ObjectId, q)
//.FirstOrDefaultAsync().ConfigureAwait(false);
}
//internal async Task<List<RateItem>> GetRates(IEnumerable<Guid> objectIds, Guid? subjectId)
//{
// var matchStage = new BsonDocument("$match", new BsonDocument("Key.ObjectId", new BsonDocument("$in", new BsonArray(objectIds))));
// var groupStage = new BsonDocument("$group", new BsonDocument
// {
// { "_id", "$Key.ObjectId" },
// { "AverageRate", new BsonDocument("$avg", "$RatePercentage") }
// });
// var lookupStage = new BsonDocument("$lookup", new BsonDocument
// {
// { "from", _collection.CollectionNamespace.CollectionName },
// { "let", new BsonDocument("objectId", "$_id") },
// { "pipeline", new BsonArray
// {
// new BsonDocument("$match", new BsonDocument("$expr", new BsonDocument("$and", new BsonArray
// {
// new BsonDocument("$eq", new BsonArray { "$Key.ObjectId", "$$objectId" }),
// //new BsonDocument("$eq", new BsonArray { "$Key.SubjectId", subjectId.ToString() ?? "" })
// new BsonDocument("$eq", new BsonArray { "$Key.SubjectId", subjectId.ToString() ?? "" })
// })))
// }
// },
// { "as", "SubjectRates" }
// });
// var projectStage = new BsonDocument("$project", new BsonDocument
// {
// { "ObjectId", "$_id" },
// { "Rate", "$AverageRate" },
// { "SubjectRate", new BsonDocument("$arrayElemAt", new BsonArray { "$SubjectRates.RatePercentage", 0 }) }
// });
// var pipeline = new[] { matchStage, groupStage, lookupStage, projectStage };
// var result = await _collection.AggregateAsync<BsonDocument>(pipeline).ConfigureAwait(false);
// var rateItems = new List<RateItem>();
// //await result.ForEachAsync(doc =>
// //{
// // rateItems.Add(new RateItem
// // {
// // ObjectId = doc["ObjectId"].AsGuid,
// // Rate = doc["Rate"].AsDouble,
// // SubjectRate = doc["SubjectRate"].IsBsonNull ? (ushort?)null : doc["SubjectRate"].AsNullableInt32
// // });
// //}).ConfigureAwait(false);
// await result.ForEachAsync(doc =>
// {
// var subjectRate = doc.GetValue("SubjectRate", BsonNull.Value);
// rateItems.Add(new RateItem
// {
// ObjectId = doc.GetValue("ObjectId").AsGuid,
// Rate = doc.GetValue("Rate").AsDouble,
// SubjectRate = subjectRate.IsBsonNull ? null : subjectRate.AsNullableInt32
// });
// }).ConfigureAwait(false);
// return rateItems;
//}
internal class RateItem
{
internal Guid ObjectId { get; set; } = default!;
internal double Rate { get; set; }
internal int? SubjectRate { get; set; }
}
public async Task<double?> GetAverageObjectRate(Guid objectId)
{
if (!await _context.Rates.AnyAsync(q => q.ObjectId == objectId)) return null;
return await _context.Rates
.Where(q => q.ObjectId == objectId)
.GroupBy(q => q.ObjectId)
.Select(q => q.Average(q => q.RatePercentage))
.FirstOrDefaultAsync().ConfigureAwait(false);
}
public async Task<bool> IsRateExists(Guid objectId, Guid subjectId) =>
await _context.Rates.Where(q => q.ObjectId == objectId && q.SubjectId == subjectId).AnyAsync();
}