149 lines
6.1 KiB
C#
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();
|
|
} |