초기커밋

This commit is contained in:
2025-05-01 07:20:41 +09:00
commit 98bb2e3c5c
2747 changed files with 646947 additions and 0 deletions

View File

@@ -0,0 +1,285 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using SharpCompress.Common;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using ServerCommon.UGQ;
using System.Drawing;
using UGQDataAccess.Repository.Models;
using UGQDataAccess.Repository.Query;
namespace UGQDataAccess.Repository;
public enum AccountSortType
{
CreatedAtAsc,
CreatedAtDesc,
}
public class AccountRepository : BaseRepository<AccountEntity>
{
private const string CollectionName = "Account";
public AccountRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task<AccountEntity?> getByAccountId(string accountId)
{
var filter = Builders<AccountEntity>.Filter
.Eq(x => x.AccountId, accountId);
return await Collection.Find(filter).FirstOrDefaultAsync();
}
public async Task<AccountEntity?> get(string userGuid)
{
var filter = Builders<AccountEntity>.Filter
.Eq(x => x.UserGuid, userGuid);
return await Collection.Find(filter).FirstOrDefaultAsync();
}
public async Task<long> getAllCount()
{
var builder = Builders<AccountEntity>.Filter;
var filter = builder.Empty;
var result = await Collection.Find(filter).CountDocumentsAsync();
return result;
}
public async Task<AccountEntity> getOrInsertForGameUser(string userGuid)
{
var filter = Builders<AccountEntity>.Filter
.Eq(x => x.UserGuid, userGuid);
var update = Builders<AccountEntity>.Update
.SetOnInsert(x => x.UserGuid, userGuid)
.SetOnInsert(x => x.Nickname, "")
.SetOnInsert(x => x.GradeType, UgqGradeType.Amature)
.SetOnInsert(x => x.AdditionalSlotCount, 0)
.SetOnInsert(x => x.UpdatedAt, DateTime.UtcNow)
.SetOnInsert(x => x.CreatedAt, DateTime.UtcNow);
var option = new FindOneAndUpdateOptions<AccountEntity>
{
IsUpsert = true,
ReturnDocument = ReturnDocument.After
};
return await Collection.FindOneAndUpdateAsync(filter, update, option);
}
public async Task<AccountEntity> getOrInsert(string userGuid, string nickname, string accountId)
{
var filter = Builders<AccountEntity>.Filter
.Eq(x => x.UserGuid, userGuid);
var update = Builders<AccountEntity>.Update
.SetOnInsert(x => x.UserGuid, userGuid)
.Set(x => x.Nickname, nickname)
.Set(x => x.AccountId, accountId)
.SetOnInsert(x => x.AdditionalSlotCount, 0)
.SetOnInsert(x => x.GradeType, UgqGradeType.Amature)
.SetOnInsert(x => x.UpdatedAt, DateTime.UtcNow)
.SetOnInsert(x => x.CreatedAt, DateTime.UtcNow);
var option = new FindOneAndUpdateOptions<AccountEntity>
{
IsUpsert = true,
ReturnDocument = ReturnDocument.After
};
return await Collection.FindOneAndUpdateAsync(filter, update, option);
}
public async Task<AccountEntity?> modifyAccountGrade(string userGuid, UgqGradeType grade)
{
var filter = Builders<AccountEntity>.Filter
.Eq(x => x.UserGuid, userGuid);
var update = Builders<AccountEntity>.Update
.Set(x => x.UpdatedAt, DateTime.UtcNow)
.Set(x => x.GradeType, grade);
var options = new FindOneAndUpdateOptions<AccountEntity>
{
ReturnDocument = ReturnDocument.After,
};
return await Collection.FindOneAndUpdateAsync(filter, update, options);
}
public async Task<AccountEntity?> promoteAccountGrade(string userGuid, UgqGradeType before, UgqGradeType after)
{
var filterBuilder = Builders<AccountEntity>.Filter;
var filter = filterBuilder.Eq(x => x.UserGuid, userGuid) &
(filterBuilder.Exists(x => x.GradeType, false) | filterBuilder.Eq(x => x.GradeType, before));
var update = Builders<AccountEntity>.Update
.Set(x => x.UpdatedAt, DateTime.UtcNow)
.Set(x => x.GradeType, after);
var options = new FindOneAndUpdateOptions<AccountEntity>
{
ReturnDocument = ReturnDocument.After,
};
return await Collection.FindOneAndUpdateAsync(filter, update, options);
}
public async Task<AccountEntity?> addSlotCount(string userGuid, int? slotCountVersion, int addCount)
{
var filterBuilder = Builders<AccountEntity>.Filter;
var filter = filterBuilder.Eq(x => x.UserGuid, userGuid) &
filterBuilder.Eq(x => x.SlotCountVersion, slotCountVersion);
var update = Builders<AccountEntity>.Update
.Set(x => x.UpdatedAt, DateTime.UtcNow)
.Inc(x => x.AdditionalSlotCount, addCount)
.Inc(x => x.SlotCountVersion, 1);
var options = new FindOneAndUpdateOptions<AccountEntity>
{
ReturnDocument = ReturnDocument.After,
};
return await Collection.FindOneAndUpdateAsync(filter, update, options);
}
public async Task<AccountEntity?> incCreatorPoint(string userGuid, int? creatorPointVersion, double amount)
{
var filterBuilder = Builders<AccountEntity>.Filter;
var filter = filterBuilder.Eq(x => x.UserGuid, userGuid) &
filterBuilder.Eq(x => x.CreatorPointVersion, creatorPointVersion);
var update = Builders<AccountEntity>.Update
.Set(x => x.UpdatedAt, DateTime.UtcNow)
.Inc(x => x.CreatorPoint, amount)
.Inc(x => x.CreatorPointVersion, 1);
var options = new FindOneAndUpdateOptions<AccountEntity>
{
ReturnDocument = ReturnDocument.After,
};
return await Collection.FindOneAndUpdateAsync(filter, update, options);
}
public async Task<AccountEntity?> saveRefreshToken(string userGuid, string refreshToken, DateTime? refreshTokenExpryTime)
{
var filter = Builders<AccountEntity>.Filter
.Eq(x => x.UserGuid, userGuid);
var updateBuilder = Builders<AccountEntity>.Update;
var update = Builders<AccountEntity>.Update
.Set(x => x.UpdatedAt, DateTime.UtcNow)
.Set(x => x.RefreshToken, refreshToken);
if(refreshTokenExpryTime != null)
update = updateBuilder.Combine(update, updateBuilder.Set(x => x.RefreshTokenExpiryTime, refreshTokenExpryTime));
var options = new FindOneAndUpdateOptions<AccountEntity>
{
ReturnDocument = ReturnDocument.After,
};
var updated = await Collection.FindOneAndUpdateAsync(filter, update, options);
return updated;
}
public async Task<AccountEntity?> deleteRefreshToken(string userGuid)
{
var filter = Builders<AccountEntity>.Filter
.Eq(x => x.UserGuid, userGuid);
var updateBuilder = Builders<AccountEntity>.Update;
var update = Builders<AccountEntity>.Update
.Set(x => x.UpdatedAt, DateTime.UtcNow)
.Set(x => x.RefreshToken, "")
.Set(x => x.RefreshTokenExpiryTime, DateTime.Now);
var options = new FindOneAndUpdateOptions<AccountEntity>
{
ReturnDocument = ReturnDocument.After,
};
var updated = await Collection.FindOneAndUpdateAsync(filter, update, options);
return updated;
}
public async Task<AllAccountQueryResult> getAccounts(int pageNumber, int pageSize, string? serachText, AccountSortType sortType)
{
pageNumber = pageNumber < 1 ? 1 : pageNumber;
var filter = Builders<AccountEntity>.Filter.Empty;
var sortBuilder = Builders<AccountItemResult>.Sort;
SortDefinition<AccountItemResult> sort;
switch (sortType)
{
case AccountSortType.CreatedAtDesc:
sort = Builders<AccountItemResult>.Sort.Descending("CreatedAt");
break;
case AccountSortType.CreatedAtAsc:
sort = Builders<AccountItemResult>.Sort.Ascending("CreatedAt");
break;
default:
sort = Builders<AccountItemResult>.Sort.Descending("CreatedAt");
break;
}
var countFacet = AggregateFacet.Create("count",
new EmptyPipelineDefinition<AccountItemResult>()
.Count()
);
var pagingFacet = AggregateFacet.Create("paging",
new EmptyPipelineDefinition<AccountItemResult>()
.Sort(sort)
.Skip((pageNumber - 1) * pageSize)
.Limit(pageSize)
);
var pipeline = AccountQuery.allAccountPipeline<AccountItemResult>(
filter,
AccountQuery.AccountItemResultProjection)
.Facet(countFacet, pagingFacet);
var aggregation = await (await Collection.AggregateAsync(pipeline)).ToListAsync();
var count = aggregation.First()
.Facets.First(x => x.Name == "count")
.Output<AggregateCountResult>()
?.FirstOrDefault()
?.Count;
var paging = aggregation.First()
.Facets.First(x => x.Name == "paging")
.Output<AccountItemResult>();
int totalPages = 0;
if (count != null)
totalPages = (int)Math.Ceiling((double)count / pageSize);
var result = await (await Collection.AggregateAsync(pipeline)).ToListAsync();
return new AllAccountQueryResult
{
PageNumber = pageNumber,
PageSize = pageSize,
TotalPages = totalPages,
Items = paging.ToList(),
};
}
}

View File

@@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using SharpCompress.Common;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using ServerCommon.UGQ;
using System.Drawing;
using UGQDataAccess.Repository.Models;
using UGQDataAccess.Repository.Query;
namespace UGQDataAccess.Repository;
public class AdminAccountRepository : BaseRepository<AdminAccountEntity>
{
private const string CollectionName = "AdminAccount";
public AdminAccountRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task<AdminAccountEntity?> get(string username)
{
var filter = Builders<AdminAccountEntity>.Filter
.Eq(x => x.Username, username);
return await Collection.Find(filter).FirstOrDefaultAsync();
}
public async Task<AdminAccountEntity> signup(string username, string password, UGQAccountRole role)
{
var filter = Builders<AdminAccountEntity>.Filter
.Eq(x => x.Username, username);
var update = Builders<AdminAccountEntity>.Update
.SetOnInsert(x => x.Username, username)
.SetOnInsert(x => x.Password, password)
.SetOnInsert(x => x.Role, role)
.SetOnInsert(x => x.UpdatedAt, DateTime.UtcNow)
.SetOnInsert(x => x.CreatedAt, DateTime.UtcNow);
var option = new FindOneAndUpdateOptions<AdminAccountEntity>
{
IsUpsert = true,
ReturnDocument = ReturnDocument.After
};
return await Collection.FindOneAndUpdateAsync(filter, update, option);
}
public async Task<AdminAccountEntity> changePassword(string username, string newPassword)
{
var filter = Builders<AdminAccountEntity>.Filter
.Eq(x => x.Username, username);
var update = Builders<AdminAccountEntity>.Update
.Set(x => x.Password, newPassword)
.Set(x => x.UpdatedAt, DateTime.UtcNow);
var option = new FindOneAndUpdateOptions<AdminAccountEntity>
{
IsUpsert = true,
ReturnDocument = ReturnDocument.After
};
return await Collection.FindOneAndUpdateAsync(filter, update, option);
}
public async Task<AdminAccountEntity?> saveRefreshToken(string id, string refreshToken, DateTime? refreshTokenExpryTime)
{
var filter = Builders<AdminAccountEntity>.Filter
.Eq(x => x.Id, id);
var updateBuilder = Builders<AdminAccountEntity>.Update;
var update = Builders<AdminAccountEntity>.Update
.Set(x => x.UpdatedAt, DateTime.UtcNow)
.Set(x => x.RefreshToken, refreshToken);
if (refreshTokenExpryTime != null)
update = updateBuilder.Combine(update, updateBuilder.Set(x => x.RefreshTokenExpiryTime, refreshTokenExpryTime));
var options = new FindOneAndUpdateOptions<AdminAccountEntity>
{
ReturnDocument = ReturnDocument.After,
};
var updated = await Collection.FindOneAndUpdateAsync(filter, update, options);
return updated;
}
public async Task<AdminAccountEntity?> deleteRefreshToken(string username)
{
var filter = Builders<AdminAccountEntity>.Filter
.Eq(x => x.Username, username);
var updateBuilder = Builders<AdminAccountEntity>.Update;
var update = Builders<AdminAccountEntity>.Update
.Set(x => x.UpdatedAt, DateTime.UtcNow)
.Set(x => x.RefreshToken, "")
.Set(x => x.RefreshTokenExpiryTime, DateTime.Now);
var options = new FindOneAndUpdateOptions<AdminAccountEntity>
{
ReturnDocument = ReturnDocument.After,
};
var updated = await Collection.FindOneAndUpdateAsync(filter, update, options);
return updated;
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using SharpCompress.Common;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using ServerCommon.UGQ;
namespace UGQDataAccess.Repository
{
public class BookmarkRepository : BaseRepository<BookmarkEntity>
{
private const string CollectionName = "Bookmark";
public BookmarkRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task<BookmarkEntity?> get(long questId, string userGuid)
{
var builder = Builders<BookmarkEntity>.Filter;
var filter = builder.Eq(x => x.QuestId, questId) &
builder.Eq(x => x.UserGuid, userGuid);
BookmarkEntity? entity = await (await Collection.FindAsync(filter)).FirstOrDefaultAsync();
return entity;
}
public async Task<ServerErrorCode> insert(long questId, string userGuid)
{
var builder = Builders<BookmarkEntity>.Filter;
var filter = builder.Eq(x => x.QuestId, questId) &
builder.Eq(x => x.UserGuid, userGuid);
var update = Builders<BookmarkEntity>.Update
.SetOnInsert(x => x.QuestId, questId)
.SetOnInsert(x => x.UserGuid, userGuid)
.SetOnInsert(x => x.CreatedAt, DateTime.UtcNow);
var option = new UpdateOptions
{
IsUpsert = true,
};
var result = await Collection.UpdateOneAsync(filter, update, option);
return ServerErrorCode.Success;
}
public async Task<ServerErrorCode> delete(long questId, string userGuid)
{
var builder = Builders<BookmarkEntity>.Filter;
var filter = builder.Eq(x => x.QuestId, questId) &
builder.Eq(x => x.UserGuid, userGuid);
var result = await Collection.DeleteOneAsync(filter);
if (result.DeletedCount == 0)
return ServerErrorCode.UgqNullEntity;
return ServerErrorCode.Success;
}
}
}

View File

@@ -0,0 +1,95 @@
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using UGQDataAccess.Repository.Models;
using Amazon.SecurityToken.Model;
using Microsoft.AspNetCore.Mvc.RazorPages;
using UGQDataAccess.Repository.Query;
using System.Linq.Expressions;
using MetaAssets;
using ServerCommon.UGQ;
namespace UGQDataAccess.Repository;
public class CreatorPointHistoryRepository : BaseRepository<CreatorPointHistoryEntity>
{
private const string CollectionName = "CreatorPointHistory";
public CreatorPointHistoryRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task<ServerErrorCode> insert(CreatorPointHistoryEntity entity)
{
await Collection.InsertOneAsync(entity);
return ServerErrorCode.Success;
}
public async Task<CreatorPointHistoryQueryResult> getList(string userGuid, int pageNumber, int pageSize, CreatorPointHistoryKind kind, DateTimeOffset startDate, DateTimeOffset endDate)
{
pageNumber = pageNumber < 1 ? 1 : pageNumber;
var filterBuilder = Builders<CreatorPointHistoryEntity>.Filter;
var filter = filterBuilder.Eq(x => x.UserGuid, userGuid);
if (kind != CreatorPointHistoryKind.None)
filter &= filterBuilder.Eq(x => x.Kind, kind);
if (startDate > endDate)
(startDate, endDate) = (endDate, startDate);
if (startDate != DateTimeOffset.MinValue)
filter &= filterBuilder.Gte(x => x.CreatedAt, startDate.UtcDateTime);
if (endDate != DateTimeOffset.MinValue)
filter &= filterBuilder.Lt(x => x.CreatedAt, endDate.UtcDateTime);
var sort = Builders<CreatorPointHistoryEntity>.Sort.Descending(x => x.CreatedAt);
var countFacet = AggregateFacet.Create("count",
new EmptyPipelineDefinition<CreatorPointHistoryEntity>()
.Count()
);
var pagingFacet = AggregateFacet.Create("paging",
new EmptyPipelineDefinition<CreatorPointHistoryEntity>()
.Sort(sort)
.Skip((pageNumber - 1) * pageSize)
.Limit(pageSize)
);
var pipeline = new EmptyPipelineDefinition<CreatorPointHistoryEntity>()
.Match(filter)
.Facet(countFacet, pagingFacet);
var aggregation = await (await Collection.AggregateAsync(pipeline)).ToListAsync();
var count = aggregation.First()
.Facets.First(x => x.Name == "count")
.Output<AggregateCountResult>()
?.FirstOrDefault()
?.Count;
var paging = aggregation.First()
.Facets.First(x => x.Name == "paging")
.Output<CreatorPointHistoryEntity>();
int totalPages = 0;
if (count != null)
totalPages = (int)Math.Ceiling((double)count / pageSize);
return new CreatorPointHistoryQueryResult
{
PageNumber = pageNumber,
PageSize = pageSize,
TotalPages = totalPages,
Items = paging.ToList(),
};
}
}

View File

@@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using ServerCommon.UGQ;
using StackExchange.Redis;
using System.Drawing;
using ServerCommon;
namespace UGQDataAccess.Repository;
public class GameQuestDataRepository : BaseRepository<GameQuestDataEntity>
{
private const string CollectionName = "GameQuestData";
public GameQuestDataRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task<GameQuestDataEntity?> insert(QuestContentEntity content,
QuestContentState state,
List<GameQuestDialogDataEntity> dialogues,
List<QuestMetaInfo> metas,
string ugqGameQuestDataForClientString,
UgqGradeType? gradeType = null)
{
var filterBuilder = Builders<GameQuestDataEntity>.Filter;
var filter = filterBuilder.Eq(x => x.QuestId, content.QuestId) &
filterBuilder.Eq(x => x.Revision, content.Revision) &
filterBuilder.Eq(x => x.State, state);
var updateGradeType = gradeType;
if (updateGradeType == null)
updateGradeType = content.GradeType;
var update = Builders<GameQuestDataEntity>.Update
.Set(x => x.QuestId, content.QuestId)
.Set(x => x.Revision, content.Revision)
.Set(x => x.UserGuid, content.UserGuid)
.Set(x => x.Author, content.Author)
.Set(x => x.BeaconId, content.BeaconId)
.Set(x => x.UgcBeaconGuid, content.UgcBeaconGuid)
.Set(x => x.UgcBeaconNickname, content.UgcBeaconNickname)
.Set(x => x.Title, content.Title)
.Set(x => x.Langs, content.Langs)
.Set(x => x.TitleImagePath, content.TitleImagePath)
.Set(x => x.BannerImagePath, content.BannerImagePath)
.Set(x => x.Description, content.Description)
.Set(x => x.GradeType, updateGradeType)
.Set(x => x.State, state)
.Set(x => x.Cost, content.Cost)
.Set(x => x.Shutdown, false)
.Set(x => x.Tasks, content.Tasks)
.Set(x => x.Dialogs, dialogues)
.Set(x => x.UpdatedAt, DateTime.UtcNow)
.Set(x => x.QuestScriptMetas, metas)
.Set(x => x.UgqGameQuestDataForClientString, ugqGameQuestDataForClientString)
.SetOnInsert(x => x.CreatedAt, DateTime.UtcNow);
var option = new FindOneAndUpdateOptions<GameQuestDataEntity>
{
IsUpsert = true,
ReturnDocument = ReturnDocument.After
};
return await Collection.FindOneAndUpdateAsync(filter, update, option);
}
public async Task delete(long questId, long revision, QuestContentState state)
{
var filterBuilder = Builders<GameQuestDataEntity>.Filter;
var filter = filterBuilder.Eq(x => x.QuestId, questId) &
filterBuilder.Eq(x => x.Revision, revision) &
filterBuilder.Eq(x => x.State, state);
await Collection.DeleteOneAsync(filter);
}
public async Task<GameQuestDataEntity?> get(long questId, long revision, QuestContentState state)
{
var builder = Builders<GameQuestDataEntity>.Filter;
var filter = builder.Eq(x => x.QuestId, questId) &
builder.Eq(x => x.Revision, revision) &
builder.Eq(x => x.State, state);
return await Collection.Find(filter).FirstOrDefaultAsync();
}
public async Task<GameQuestDataEntity?> getLatestRevision(long questId)
{
var builder = Builders<GameQuestDataEntity>.Filter;
var filter = builder.Eq(x => x.QuestId, questId);
GameQuestDataEntity? entity = await Collection.Find(filter)
.SortByDescending(x => x.Revision)
.Limit(1)
.FirstOrDefaultAsync();
return entity;
}
public async Task<GameQuestDataEntity?> setShutdown(long questId, long revision)
{
var builder = Builders<GameQuestDataEntity>.Filter;
var filter = builder.Eq(x => x.QuestId, questId) & builder.Eq(x => x.Revision, revision) &
builder.Eq(x => x.State, QuestContentState.Live);
var update = Builders<GameQuestDataEntity>.Update
.Set(x => x.Shutdown, true);
var options = new FindOneAndUpdateOptions<GameQuestDataEntity>
{
ReturnDocument = ReturnDocument.After,
};
return await Collection.FindOneAndUpdateAsync(filter, update, options);
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using SharpCompress.Common;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using ServerCommon.UGQ;
namespace UGQDataAccess.Repository
{
public class LikeRepository : BaseRepository<LikeEntity>
{
private const string CollectionName = "Like";
public LikeRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task<LikeEntity?> get(long questId, string userGuid)
{
var builder = Builders<LikeEntity>.Filter;
var filter = builder.Eq(x => x.QuestId, questId) &
builder.Eq(x => x.UserGuid, userGuid);
LikeEntity? entity = await (await Collection.FindAsync(filter)).FirstOrDefaultAsync();
return entity;
}
public async Task<ServerErrorCode> insert(long questId, long revision, string userGuid)
{
var builder = Builders<LikeEntity>.Filter;
var filter = builder.Eq(x => x.QuestId, questId) &
builder.Eq(x => x.UserGuid, userGuid);
var update = Builders<LikeEntity>.Update
.SetOnInsert(x => x.QuestId, questId)
.SetOnInsert(x => x.UserGuid, userGuid)
.SetOnInsert(x => x.CreatedAt, DateTime.UtcNow);
var option = new UpdateOptions
{
IsUpsert = true,
};
var result = await Collection.UpdateOneAsync(filter, update, option);
return ServerErrorCode.Success;
}
public async Task<ServerErrorCode> delete(long questId, long revision, string userGuid)
{
var builder = Builders<LikeEntity>.Filter;
var filter = builder.Eq(x => x.QuestId, questId) &
builder.Eq(x => x.UserGuid, userGuid);
var result = await Collection.DeleteOneAsync(filter);
if (result.DeletedCount == 0)
return ServerErrorCode.UgqNullEntity;
return ServerErrorCode.Success;
}
}
}

View File

@@ -0,0 +1,266 @@
using Amazon.DynamoDBv2.Model;
using MongoDB.Bson.Serialization.Attributes;
using System.Text.Json.Serialization;
using UGQDatabase.Models;
namespace UGQDataAccess.Repository.Models;
#pragma warning disable CS8618
public class UGQSaveQuestModel
{
public int BeaconId { get; set; }
public string? UgcBeaconGuid { get; set; }
public string? UgcBeaconNickname { get; set; }
public TextEntity Title { get; set; }
public List<string> Languages { get; set; }
public TextEntity Description { get; set; }
public int Cost { get; set; }
public List<TaskEntity> Tasks { get; set; }
public string Savelanguage { get; set; }
}
public class UGQSaveDialogSequenceAction
{
public DialogTalker Talker { get; set; }
public int Type { get; set; }
public TextEntity Talk { get; set; }
public int Condition { get; set; }
public int ConditionValue { get; set; }
public int NextSequence { get; set; }
public int NpcAction { get; set; }
}
public class UGQSaveDialogSequence
{
public int SequenceId { get; set; }
public List<UGQSaveDialogSequenceAction> Actions { get; set; }
}
public class UGQSaveDialogModel
{
public List<UGQSaveDialogSequence> Sequences { get; set; }
}
public class UGQStats
{
public int Accepted { get; set; } = 0;
public int Completed { get; set; } = 0;
public int Like { get; set; } = 0;
public int Bookmark { get; set; } = 0;
public int Report { get; set; } = 0;
public double TotalProfit { get; set; } = 0;
}
public class SummaryItemResult
{
public string QuestContentId { get; set; }
public long QuestId { get; set; }
public long Revision { get; set; }
public string UserGuid { get; set; }
public string Author { get; set; }
public int BeaconId { get; set; }
public string? UgcBeaconGuid { get; set; }
public string? UgcBeaconNickname { get; set; }
public UgqGradeType GradeType { get; set; }
public TextEntity Title { get; set; }
public List<string> Languages { get; set; }
public TextEntity Description { get; set; }
public int Cost { get; set; }
public string TitleImagePath { get; set; }
public string BannerImagePath { get; set; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public QuestContentState State { get; set; }
public DateTime UpdatedAt { get; set; }
public DateTime CreatedAt { get; set; }
public int AcceptedCount { get; set; }
public int CompletedCount { get; set; }
public int LikeCount { get; set; }
public int BookmarkCount { get; set; }
public int ReportCount { get; set; }
public double TotalProfit { get; set; }
public string Savelanguage { get; set; }
}
public class SummaryQueryResult
{
public int PageNumber { get; set; }
public int PageSize { get; set; }
public int TotalPages { get; set; }
public List<SummaryItemResult> Items { get; set; }
}
public class AllSummaryQueryResult
{
public int PageNumber { get; set; }
public int PageSize { get; set; }
public int TotalPages { get; set; }
public List<SummaryItemResult> Items { get; set; }
}
public class QuestProfitStatsItemResult
{
public string QuestContentId { get; set; }
public long QuestId { get; set; }
public long Revision { get; set; }
public TextEntity Title { get; set; }
public List<string> Languages { get; set; }
public string TitleImagePath { get; set; }
public string BannerImagePath { get; set; }
public int CompletedCount { get; set; }
public double TotalProfit { get; set; }
}
public class QuestProfitStatsQueryResult
{
public int PageNumber { get; set; }
public int PageSize { get; set; }
public int TotalPages { get; set; }
public List<QuestProfitStatsItemResult> Items { get; set; }
}
public class QuestBoardItemResult
{
public long QuestId { get; set; }
public long Revision { get; set; }
public string Author { get; set; }
public TextEntity Title { get; set; }
public List<string> Languages { get; set; }
public TextEntity Description { get; set; }
public int Cost { get; set; }
public UgqGradeType GradeType { get; set; }
public string TitleImagePath { get; set; }
public string BannerImagePath { get; set; }
public DateTime UpdatedAt { get; set; }
public int LikeCount { get; set; }
public int BookmarkCount { get; set; }
}
public class QuestBoardQueryResult
{
public int PageNumber { get; set; }
public int PageSize { get; set; }
public int TotalPages { get; set; }
public List<QuestBoardItemResult> Items { get; set; }
}
public class QuestBoardSportlightQueryResult
{
public class DateRangeResult
{
public QuestBoardItemResult? Today { get; set; }
public QuestBoardItemResult? ThisWeek { get; set; }
public QuestBoardItemResult? ThisMonth { get; set; }
}
public DateRangeResult MostLiked { get; set; }
public DateRangeResult MostBookmarked { get; set; }
}
public class QuestBoardDetailItemResult
{
public long QuestId { get; set; }
public long Revision { get; set; }
public string Author { get; set; }
public TextEntity Title { get; set; }
public List<string> Languages { get; set; }
public TextEntity Description { get; set; }
public int Cost { get; set; }
public UgqGradeType GradeType { get; set; }
public string TitleImagePath { get; set; }
public string BannerImagePath { get; set; }
public int BeaconId { get; set; }
public string? UgcBeaconGuid { get; set; }
public string? UgcBeaconNickname { get; set; }
public DateTime UpdatedAt { get; set; }
public int LikeCount { get; set; }
public int BookmarkCount { get; set; }
public int QuestAcceptedCount { get; set; }
public int QuestCompletedCount { get; set; }
public bool Liked { get; set; }
public bool Bookmarked { get; set; }
}
public class CreatorPointHistoryQueryResult
{
public int PageNumber { get; set; }
public int PageSize { get; set; }
public int TotalPages { get; set; }
public List<CreatorPointHistoryEntity> Items { get; set; }
}
public class AccountItemResult
{
public string UserGuid { get; set; }
public string Nickname { get; set; }
public string AccountId { get; set; }
public int AdditionalSlotCount { get; set; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public UgqGradeType GradeType { get; set; }
public double CreatorPoint { get; set; }
public DateTime CreatedAt { get; set; }
public int QuestCount { get; set; }
}
public class AllAccountQueryResult
{
public int PageNumber { get; set; }
public int PageSize { get; set; }
public int TotalPages { get; set; }
public List<AccountItemResult> Items { get; set; }
}
public class ReserveAccountGradeItemResult
{
public string ReserveId { get; set; }
public string UserGuid { get; set; }
public string AccountId { get; set; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public UgqGradeType CurrentGradeType { get; set; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public UgqGradeType ReserveGradeType { get; set; }
public DateTime ReserveTime { get; set; }
public DateTime UpdatedAt { get; set; }
public bool IsCompleted { get; set; }
}
public class AllReserveAccountGradeResult
{
public int PageNumber { get; set; }
public int PageSize { get; set; }
public int TotalPages { get; set; }
public List<ReserveAccountGradeItemResult> Items { get; set; }
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using ServerCommon.UGQ;
namespace UGQDataAccess.Repository
{
public class NpcNameRepository : BaseRepository<NpcNameEntity>
{
private const string CollectionName = "NpcName";
public NpcNameRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task upsertNpcName(int npcId, TextEntity npcName)
{
var filter = Builders<NpcNameEntity>.Filter.Eq(x => x.NpcId, npcId);
var update = Builders<NpcNameEntity>.Update
.Set(x => x.NpcName, npcName);
var option = new UpdateOptions
{
IsUpsert = true,
};
await Collection.UpdateOneAsync(filter, update, option);
}
}
}

View File

@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using UGQDataAccess.Repository.Models;
using UGQDatabase.Models;
using static UGQDataAccess.Repository.Query.QuestContentQuery;
namespace UGQDataAccess.Repository.Query;
public static class AccountQuery
{
public class AllAccountQueryJoin : AccountEntity
{
public IEnumerable<QuestContentEntity> QuestContents { get; set; } = null!;
public int QuestCount { get; set; } = 0;
}
public static Expression<Func<AllAccountQueryJoin, AccountItemResult>> AccountItemResultProjection =
x => new AccountItemResult
{
UserGuid = x.UserGuid,
Nickname = x.Nickname,
AccountId = x.AccountId ?? "",
AdditionalSlotCount = x.AdditionalSlotCount,
GradeType = x.GradeType,
CreatorPoint = x.CreatorPoint,
CreatedAt = x.CreatedAt,
QuestCount = x.QuestCount,
};
public static PipelineDefinition<AccountEntity, T> allAccountPipeline<T>(
FilterDefinition<AccountEntity> filter,
Expression<Func<AllAccountQueryJoin, T>> projection)
{
var lookupStage1 = new BsonDocument("$lookup",
new BsonDocument
{
{ "from", "QuestContent" },
{ "localField", "UserGuid" },
{ "foreignField", "UserGuid" },
{ "pipeline",
new BsonArray
{
new BsonDocument("$match",
new BsonDocument("IsDeleted", false))
} },
{ "as", "QuestContents" }
});
var addFields1 = new BsonDocument("$addFields",
new BsonDocument("QuestCount",
new BsonDocument("$size", "$QuestContents")));
var pipeline = new EmptyPipelineDefinition<AccountEntity>()
.Match(filter)
.AppendStage<AccountEntity, AccountEntity, AllAccountQueryJoin>(lookupStage1)
.AppendStage<AccountEntity, AllAccountQueryJoin, AllAccountQueryJoin>(addFields1)
.Project(projection);
return pipeline;
}
}

View File

@@ -0,0 +1,563 @@
using System.Linq.Expressions;
using MongoDB.Bson;
using MongoDB.Driver;
using UGQDataAccess.Repository.Models;
using UGQDatabase.Models;
namespace UGQDataAccess.Repository.Query;
public static class QuestContentQuery
{
public class QuestBoardQueryJoin : QuestContentEntity
{
public IEnumerable<LikeEntity> Likes { get; set; } = null!;
public int LikeCount { get; set; } = 0;
public IEnumerable<BookmarkEntity> Bookmarks { get; set; } = null!;
public int BookmarkCount { get; set; } = 0;
public List<QuestAcceptedEntity> QuestAccepteds { get; set; } = null!;
public int QuestAcceptedCount { get; set; } = 0;
public List<QuestAcceptedEntity> QuestCompleteds { get; set; } = null!;
public int QuestCompletedCount { get; set; } = 0;
}
public class QuestSummariesQueryJoin : QuestContentEntity
{
public IEnumerable<LikeEntity> Likes { get; set; } = null!;
public int LikeCount { get; set; } = 0;
public IEnumerable<BookmarkEntity> Bookmarks { get; set; } = null!;
public int BookmarkCount { get; set; } = 0;
public List<QuestAcceptedEntity> QuestAccepteds { get; set; } = null!;
public int QuestAcceptedCount { get; set; } = 0;
public List<QuestAcceptedEntity> QuestCompleteds { get; set; } = null!;
public int QuestCompletedCount { get; set; } = 0;
public List<QuestAcceptedEntity> QuestAborteds { get; set; } = null!;
public int QuestAbortedCount { get; set; } = 0;
public List<ReportEntity> Reports { get; set; } = null!;
public int ReporCount { get; set; } = 0;
public List<CreatorPointHistoryEntity> ProfitHistories { get; set; } = null!;
public double TotalProfit { get; set; } = 0;
}
public class QuestProfitStatsQueryJoin : QuestContentEntity
{
public List<QuestAcceptedEntity> QuestCompleteds { get; set; } = null!;
public int QuestCompletedCount { get; set; } = 0;
public List<CreatorPointHistoryEntity> ProfitHistories { get; set; } = null!;
public double TotalProfit { get; set; } = 0;
}
public class QuestAcceptedLookup : QuestAcceptedEntity
{
}
public static Expression<Func<QuestBoardQueryJoin, QuestBoardItemResult>> QuestBoardItemResultProjection =
x => new QuestBoardItemResult
{
QuestId = x.QuestId,
Revision = x.Revision,
Author = x.Author,
Title = x.Title,
Languages = x.Langs,
Cost = x.Cost,
GradeType = x.GradeType,
TitleImagePath = x.TitleImagePath,
BannerImagePath = x.BannerImagePath,
UpdatedAt = x.UpdatedAt,
LikeCount = x.LikeCount,
BookmarkCount = x.BookmarkCount,
};
public static Expression<Func<QuestSummariesQueryJoin, SummaryItemResult>> SummaryItemResultProjection =
x => new SummaryItemResult
{
QuestContentId = x.Id.ToString(),
QuestId = x.QuestId,
Revision = x.Revision,
BeaconId = x.BeaconId,
UserGuid = x.UserGuid,
Author = x.Author,
UgcBeaconGuid = x.UgcBeaconGuid,
UgcBeaconNickname = x.UgcBeaconNickname,
GradeType = x.GradeType,
Title = x.Title,
Languages = x.Langs,
Description = x.Description,
Cost = x.Cost,
TitleImagePath = x.TitleImagePath,
BannerImagePath = x.BannerImagePath,
State = x.State,
UpdatedAt = x.UpdatedAt,
CreatedAt = x.CreatedAt,
AcceptedCount = x.QuestAcceptedCount,
CompletedCount = x.QuestCompletedCount,
LikeCount = x.LikeCount,
BookmarkCount = x.BookmarkCount,
ReportCount = x.ReporCount,
TotalProfit = x.TotalProfit,
Savelanguage = x.Savelanguage,
};
public static Expression<Func<QuestProfitStatsQueryJoin, QuestProfitStatsItemResult>> QuestProfitStatsResultProjection =
x => new QuestProfitStatsItemResult
{
QuestContentId = x.Id.ToString(),
QuestId = x.QuestId,
Revision = x.Revision,
Title = x.Title,
Languages = x.Langs,
TitleImagePath = x.TitleImagePath,
BannerImagePath = x.BannerImagePath,
CompletedCount = x.QuestCompletedCount,
TotalProfit = x.TotalProfit,
};
static List<UgqGradeType> getGradeTypes(UgqUICategoryGradeType gradeType)
{
switch (gradeType)
{
case UgqUICategoryGradeType.Amateur:
return [UgqGradeType.Amature];
case UgqUICategoryGradeType.RisingStar:
return [UgqGradeType.RisingStar];
case UgqUICategoryGradeType.Master:
return [UgqGradeType.Master1, UgqGradeType.Master2, UgqGradeType.Master3];
}
return [];
}
static async Task<List<long>> getBookmarks(IMongoCollection<BookmarkEntity> bookmarkCollection, string userGuid)
{
var filterBuilder = Builders<BookmarkEntity>.Filter;
var filter = filterBuilder.Eq(x => x.UserGuid, userGuid);
var list = await bookmarkCollection.Find(filter).ToListAsync();
return list.Select(x => x.QuestId).ToList();
}
static async Task<List<int>> searchNpcs(IMongoCollection<NpcNameEntity> npcNameCollection, string searchText)
{
var filterBuilder = Builders<NpcNameEntity>.Filter;
var filter = filterBuilder.Empty;
if (string.IsNullOrEmpty(searchText) == false)
{
filter &= (filterBuilder.Regex(x => x.NpcName.Kr, searchText) |
filterBuilder.Regex(x => x.NpcName.En, searchText) |
filterBuilder.Regex(x => x.NpcName.Jp, searchText));
}
var list = await npcNameCollection.Find(filter).ToListAsync();
return list.Select(x => x.NpcId).ToList();
}
static FilterDefinition<QuestContentEntity> searchTitle(FilterDefinitionBuilder<QuestContentEntity> filterBuilder, string searchText)
{
return filterBuilder.Regex(x => x.Title.Kr, searchText) |
filterBuilder.Regex(x => x.Title.En, searchText) |
filterBuilder.Regex(x => x.Title.Jp, searchText);
}
public static async Task<FilterDefinition<QuestContentEntity>> summariesFilter(string? userGuid,
UgqSearchType searchType, string? searchText, QuestContentState state,
IMongoCollection<AccountEntity> accountCollection,
IMongoCollection<NpcNameEntity> npcNameCollection)
{
var filterBuilder = Builders<QuestContentEntity>.Filter;
var filter = filterBuilder.Eq(x => x.IsDeleted, false);
if (state != QuestContentState.None)
{
if(state == QuestContentState.Uncomplate ||
state == QuestContentState.Editable)
{
var UncomplateOrFilter = filterBuilder.Eq(x => x.State, QuestContentState.Uncomplate);
var EditableOrFilter = filterBuilder.Eq(x => x.State, QuestContentState.Editable);
filter &= filterBuilder.Or(UncomplateOrFilter, EditableOrFilter);
}
else
{
filter &= filterBuilder.Eq(x => x.State, state);
}
}
if (string.IsNullOrEmpty(userGuid) == false)
filter &= filterBuilder.Eq(x => x.UserGuid, userGuid);
if (string.IsNullOrEmpty(searchText) == false)
{
switch (searchType)
{
case UgqSearchType.Title:
filter &= searchTitle(filterBuilder, searchText);
break;
case UgqSearchType.Beacon:
var npcIds = await searchNpcs(npcNameCollection, searchText);
filter &= (filterBuilder.In(x => x.BeaconId, npcIds) |
filterBuilder.Regex(x => x.UgcBeaconNickname, searchText));
break;
}
}
return filter;
}
public static async Task<FilterDefinition<QuestContentEntity>> questBoardFilter(string? userGuid,
UgqUICategoryGradeType gradeType, UgqSearchType searchType, string? searchText,
IMongoCollection<AccountEntity> accountCollection,
IMongoCollection<NpcNameEntity> npcNameCollection)
{
var filterBuilder = Builders<QuestContentEntity>.Filter;
var filter = filterBuilder.Eq(x => x.IsDeleted, false);
filter &= filterBuilder.Eq(x => x.State, QuestContentState.Live);
if (string.IsNullOrEmpty(userGuid) == false)
filter &= filterBuilder.Eq(x => x.UserGuid, userGuid);
if(gradeType != UgqUICategoryGradeType.None)
{
var gradeTypes = getGradeTypes(gradeType);
filter &= filterBuilder.In(x => x.GradeType, gradeTypes);
}
if (string.IsNullOrEmpty(searchText) == false)
{
switch (searchType)
{
case UgqSearchType.Title:
filter &= searchTitle(filterBuilder, searchText);
break;
case UgqSearchType.Beacon:
var npcIds = await searchNpcs(npcNameCollection, searchText);
filter &= (filterBuilder.In(x => x.BeaconId, npcIds) |
filterBuilder.Regex(x => x.UgcBeaconNickname, searchText));
break;
}
}
return filter;
}
public static async Task<FilterDefinition<QuestContentEntity>> questBoardBookmarkFilter(string userGuid,
UgqUICategoryGradeType gradeType, UgqSearchType searchType, string? searchText,
IMongoCollection<NpcNameEntity> npcNameCollection,
IMongoCollection<BookmarkEntity> bookmarkCollection)
{
var filterBuilder = Builders<QuestContentEntity>.Filter;
var filter = filterBuilder.Eq(x => x.IsDeleted, false);
filter &= filterBuilder.Eq(x => x.State, QuestContentState.Live);
if (gradeType != UgqUICategoryGradeType.None)
{
var gradeTypes = getGradeTypes(gradeType);
filter &= filterBuilder.In(x => x.GradeType, gradeTypes);
}
var bookmarkQuestIds = await getBookmarks(bookmarkCollection, userGuid);
filter &= filterBuilder.In(x => x.QuestId, bookmarkQuestIds);
if (string.IsNullOrEmpty(searchText) == false)
{
switch (searchType)
{
case UgqSearchType.Title:
filter &= searchTitle(filterBuilder, searchText);
break;
case UgqSearchType.Beacon:
var npcIds = await searchNpcs(npcNameCollection, searchText);
filter &= (filterBuilder.In(x => x.BeaconId, npcIds) |
filterBuilder.Regex(x => x.UgcBeaconNickname, searchText));
break;
}
}
return filter;
}
public static SortDefinition<T> questBoardSort<T>(UgqSortType sortType)
{
var sortBuilder = Builders<T>.Sort;
SortDefinition<T> sort;
switch (sortType)
{
case UgqSortType.New:
sort = Builders<T>.Sort.Descending("UpdatedAt");
break;
case UgqSortType.Like:
sort = Builders<T>.Sort.Descending("LikeCount");
break;
case UgqSortType.Bookmark:
sort = Builders<T>.Sort.Descending("BookmarkCount");
break;
default:
sort = Builders<T>.Sort.Descending("UpdatedAt");
break;
}
return sort;
}
public static PipelineDefinition<QuestContentEntity, T> summariesPipeline<T>(
IMongoCollection<LikeEntity> likeCollection,
IMongoCollection<BookmarkEntity> bookmarkCollection,
FilterDefinition<QuestContentEntity> filter,
Expression<Func<QuestSummariesQueryJoin, T>> projection)
{
var lookupStage1 = new BsonDocument("$lookup",
new BsonDocument
{
{ "from", "QuestAccepted" },
{ "localField", "QuestId" },
{ "foreignField", "QuestId" },
{ "pipeline",
new BsonArray
{
new BsonDocument("$match",
new BsonDocument("Reason", "Player"))
} },
{ "as", "QuestAccepteds" }
});
var addFields1 = new BsonDocument("$addFields",
new BsonDocument("QuestAcceptedCount",
new BsonDocument("$size", "$QuestAccepteds")));
var lookupStage2 = new BsonDocument("$lookup",
new BsonDocument
{
{ "from", "QuestCompleted" },
{ "localField", "QuestId" },
{ "foreignField", "QuestId" },
{ "as", "QuestCompleteds" }
});
var addFields2 = new BsonDocument("$addFields",
new BsonDocument("QuestCompletedCount",
new BsonDocument("$size", "$QuestCompleteds")));
var lookupStage3 = new BsonDocument("$lookup",
new BsonDocument
{
{ "from", "QuestAborted" },
{ "localField", "QuestId" },
{ "foreignField", "QuestId" },
{ "as", "QuestAborteds" }
});
var addFields3 = new BsonDocument("$addFields",
new BsonDocument("QuestAbortedCount",
new BsonDocument("$size", "$QuestAborteds")));
var lookupStage4 = new BsonDocument("$lookup",
new BsonDocument
{
{ "from", "CreatorPointHistory" },
{ "localField", "QuestId" },
{ "foreignField", "QuestId" },
{ "pipeline",
new BsonArray
{
new BsonDocument("$match",
new BsonDocument("Kind", "QuestProfit"))
} },
{ "as", "ProfitHistories" }
});
var addFields4 = new BsonDocument("$addFields",
new BsonDocument("TotalProfit",
new BsonDocument("$sum", "$ProfitHistories.Amount")));
var lookupStage5 = new BsonDocument("$lookup",
new BsonDocument
{
{ "from", "Report" },
{ "localField", "QuestId" },
{ "foreignField", "QuestId" },
{ "as", "Reports" }
});
var addFields5 = new BsonDocument("$addFields",
new BsonDocument("ReporCount",
new BsonDocument("$size", "$Reports")));
var pipeline = new EmptyPipelineDefinition<QuestContentEntity>()
.Match(filter)
.Lookup<QuestContentEntity, QuestContentEntity, LikeEntity, QuestSummariesQueryJoin>(
likeCollection,
x => x.QuestId,
x => x.QuestId,
x => x.Likes)
.Lookup<QuestContentEntity, QuestSummariesQueryJoin, BookmarkEntity, QuestSummariesQueryJoin>(
bookmarkCollection,
x => x.QuestId,
x => x.QuestId,
x => x.Bookmarks)
.AppendStage<QuestContentEntity, QuestSummariesQueryJoin, QuestSummariesQueryJoin>("{$addFields: {LikeCount: {$size:'$Likes'}}}")
.AppendStage<QuestContentEntity, QuestSummariesQueryJoin, QuestSummariesQueryJoin>("{$addFields: {BookmarkCount: {$size:'$Bookmarks'}}}")
.AppendStage<QuestContentEntity, QuestSummariesQueryJoin, QuestSummariesQueryJoin>(lookupStage1)
.AppendStage<QuestContentEntity, QuestSummariesQueryJoin, QuestSummariesQueryJoin>(addFields1)
.AppendStage<QuestContentEntity, QuestSummariesQueryJoin, QuestSummariesQueryJoin>(lookupStage2)
.AppendStage<QuestContentEntity, QuestSummariesQueryJoin, QuestSummariesQueryJoin>(addFields2)
.AppendStage<QuestContentEntity, QuestSummariesQueryJoin, QuestSummariesQueryJoin>(lookupStage3)
.AppendStage<QuestContentEntity, QuestSummariesQueryJoin, QuestSummariesQueryJoin>(addFields3)
.AppendStage<QuestContentEntity, QuestSummariesQueryJoin, QuestSummariesQueryJoin>(lookupStage4)
.AppendStage<QuestContentEntity, QuestSummariesQueryJoin, QuestSummariesQueryJoin>(addFields4)
.AppendStage<QuestContentEntity, QuestSummariesQueryJoin, QuestSummariesQueryJoin>(lookupStage5)
.AppendStage<QuestContentEntity, QuestSummariesQueryJoin, QuestSummariesQueryJoin>(addFields5)
.Project(projection);
return pipeline;
}
public static PipelineDefinition<QuestContentEntity, T> questProfitStatsPipeline<T>(
FilterDefinition<QuestContentEntity> filter,
Expression<Func<QuestProfitStatsQueryJoin, T>> projection)
{
var lookupStage1 = new BsonDocument("$lookup",
new BsonDocument
{
{ "from", "QuestCompleted" },
{ "localField", "QuestId" },
{ "foreignField", "QuestId" },
{ "as", "QuestCompleteds" }
});
var addFields1 = new BsonDocument("$addFields",
new BsonDocument("QuestCompletedCount",
new BsonDocument("$size", "$QuestCompleteds")));
var lookupStage2 = new BsonDocument("$lookup",
new BsonDocument
{
{ "from", "CreatorPointHistory" },
{ "localField", "QuestId" },
{ "foreignField", "QuestId" },
{ "pipeline",
new BsonArray
{
new BsonDocument("$match",
new BsonDocument("Kind", "QuestProfit"))
} },
{ "as", "ProfitHistories" }
});
var addFields2 = new BsonDocument("$addFields",
new BsonDocument("TotalProfit",
new BsonDocument("$sum", "$ProfitHistories.Amount")));
var pipeline = new EmptyPipelineDefinition<QuestContentEntity>()
.Match(filter)
.AppendStage<QuestContentEntity, QuestContentEntity, QuestProfitStatsQueryJoin>(lookupStage1)
.AppendStage<QuestContentEntity, QuestProfitStatsQueryJoin, QuestProfitStatsQueryJoin>(addFields1)
.AppendStage<QuestContentEntity, QuestProfitStatsQueryJoin, QuestProfitStatsQueryJoin>(lookupStage2)
.AppendStage<QuestContentEntity, QuestProfitStatsQueryJoin, QuestProfitStatsQueryJoin>(addFields2)
.Project(projection);
return pipeline;
}
public static PipelineDefinition<QuestContentEntity, T> questBoardPipeline<T>(
IMongoCollection<LikeEntity> likeCollection,
IMongoCollection<BookmarkEntity> bookmarkCollection,
FilterDefinition<QuestContentEntity> filter,
Expression<Func<QuestBoardQueryJoin, T>> projection)
{
var pipeline = new EmptyPipelineDefinition<QuestContentEntity>()
.Match(filter)
.Lookup<QuestContentEntity, QuestContentEntity, LikeEntity, QuestBoardQueryJoin>(
likeCollection,
x => x.QuestId,
x => x.QuestId,
x => x.Likes)
.Lookup<QuestContentEntity, QuestBoardQueryJoin, BookmarkEntity, QuestBoardQueryJoin>(
bookmarkCollection,
x => x.QuestId,
x => x.QuestId,
x => x.Bookmarks)
.AppendStage<QuestContentEntity, QuestBoardQueryJoin, QuestBoardQueryJoin>("{$addFields: {LikeCount: {$size:'$Likes'}}}")
.AppendStage<QuestContentEntity, QuestBoardQueryJoin, QuestBoardQueryJoin>("{$addFields: {BookmarkCount: {$size:'$Bookmarks'}}}")
.Project(projection);
return pipeline;
}
public static PipelineDefinition<QuestContentEntity, T> questBoardDetailPipeline<T>(
IMongoCollection<LikeEntity> likeCollection,
IMongoCollection<BookmarkEntity> bookmarkCollection,
FilterDefinition<QuestContentEntity> filter,
Expression<Func<QuestBoardQueryJoin, T>> projection)
{
var lookupStage1 = new BsonDocument("$lookup",
new BsonDocument
{
{ "from", "QuestAccepted" },
{ "localField", "QuestId" },
{ "foreignField", "QuestId" },
{ "pipeline",
new BsonArray
{
new BsonDocument("$match",
new BsonDocument("Reason", "Player"))
} },
{ "as", "QuestAccepteds" }
});
var lookupStage2 = new BsonDocument("$lookup",
new BsonDocument
{
{ "from", "QuestCompleted" },
{ "localField", "QuestId" },
{ "foreignField", "QuestId" },
{ "as", "QuestCompleteds" }
});
var pipeline = new EmptyPipelineDefinition<QuestContentEntity>()
.Match(filter)
.Lookup<QuestContentEntity, QuestContentEntity, LikeEntity, QuestBoardQueryJoin>(
likeCollection,
x => x.QuestId,
x => x.QuestId,
x => x.Likes)
.Lookup<QuestContentEntity, QuestBoardQueryJoin, BookmarkEntity, QuestBoardQueryJoin>(
bookmarkCollection,
x => x.QuestId,
x => x.QuestId,
x => x.Bookmarks)
.AppendStage<QuestContentEntity, QuestBoardQueryJoin, QuestBoardQueryJoin>(lookupStage1)
.AppendStage<QuestContentEntity, QuestBoardQueryJoin, QuestBoardQueryJoin>(lookupStage2)
.AppendStage<QuestContentEntity, QuestBoardQueryJoin, QuestBoardQueryJoin>("{$addFields: {LikeCount: {$size:'$Likes'}}}")
.AppendStage<QuestContentEntity, QuestBoardQueryJoin, QuestBoardQueryJoin>("{$addFields: {BookmarkCount: {$size:'$Bookmarks'}}}")
.AppendStage<QuestContentEntity, QuestBoardQueryJoin, QuestBoardQueryJoin>("{$addFields: {QuestAcceptedCount: {$size:'$QuestAccepteds'}}}")
.AppendStage<QuestContentEntity, QuestBoardQueryJoin, QuestBoardQueryJoin>("{$addFields: {QuestCompletedCount: {$size:'$QuestCompleteds'}}}")
.Project(projection);
return pipeline;
}
}

View File

@@ -0,0 +1,51 @@
using MongoDB.Bson;
using MongoDB.Driver;
using System.Linq.Expressions;
using UGQDataAccess.Repository.Models;
using UGQDatabase.Models;
public static class ReserveAccountGradeQuery
{
public class AllReserveAccountGradeQueryJoin : ReserveAccountGradeEntity
{
public IEnumerable<AccountEntity> Accounts { get; set; } = null!;
}
public static Expression<Func<AllReserveAccountGradeQueryJoin, ReserveAccountGradeItemResult>> ReserveAccountGradeItemResultProjection =
x => new ReserveAccountGradeItemResult
{
ReserveId = x.Id.ToString(),
UserGuid = x.UserGuid,
CurrentGradeType = x.BeforeGradeType,
AccountId = x.Accounts.First().AccountId ?? string.Empty,
ReserveGradeType = x.ReserveGradeType,
ReserveTime = x.ReserveTime,
UpdatedAt = x.UpdatedAt,
IsCompleted = x.IsCompleted,
};
public static PipelineDefinition<ReserveAccountGradeEntity, T> allReserveAccountGradePipeline<T>(
FilterDefinition<ReserveAccountGradeEntity> filter,
Expression<Func<AllReserveAccountGradeQueryJoin, T>> projection)
{
var lookupStage1 = new BsonDocument("$lookup",
new BsonDocument
{
{ "from", "Account" },
{ "localField", "UserGuid" },
{ "foreignField", "UserGuid" },
{ "as", "Accounts" }
});
var pipeline = new EmptyPipelineDefinition<ReserveAccountGradeEntity>()
.Match(filter)
.AppendStage<ReserveAccountGradeEntity, ReserveAccountGradeEntity, AllReserveAccountGradeQueryJoin>(lookupStage1)
.Project(projection);
return pipeline;
}
}

View File

@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using SharpCompress.Common;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using ServerCommon.UGQ;
namespace UGQDataAccess.Repository;
public class QuestAbortedRepository : BaseRepository<QuestAbortedEntity>
{
private const string CollectionName = "QuestAborted";
public QuestAbortedRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task<List<QuestAbortedEntity>> getAll()
{
return await Collection.Find(Builders<QuestAbortedEntity>.Filter.Empty).ToListAsync();
}
public async Task<ServerErrorCode> insert(long questId, long revision, string author, UGQAbortReason reason, string userGuid)
{
var entity = new QuestAbortedEntity
{
QuestId = questId,
Revision = revision,
Author = author,
UserGuid = userGuid,
Reason = reason,
CreatedAt = DateTime.UtcNow,
};
await Collection.InsertOneAsync(entity);
return ServerErrorCode.Success;
}
public async Task<QuestAbortedEntity?> setAuthor(string id, string author)
{
var filterBuilder = Builders<QuestAbortedEntity>.Filter;
var filter = filterBuilder.Eq(x => x.Id, id);
var update = Builders<QuestAbortedEntity>.Update
.Set(x => x.Author, author);
var options = new FindOneAndUpdateOptions<QuestAbortedEntity>
{
ReturnDocument = ReturnDocument.After,
};
return await Collection.FindOneAndUpdateAsync(filter, update, options);
}
}

View File

@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using SharpCompress.Common;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using ServerCommon.UGQ;
namespace UGQDataAccess.Repository;
public class QuestAcceptedRepository : BaseRepository<QuestAcceptedEntity>
{
private const string CollectionName = "QuestAccepted";
public QuestAcceptedRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task<List<QuestAcceptedEntity>> getAll()
{
return await Collection.Find(Builders<QuestAcceptedEntity>.Filter.Empty).ToListAsync();
}
public async Task<ServerErrorCode> insert(long questId, long revision, string author, UGQAcceptReason reason, string userGuid)
{
var entity = new QuestAcceptedEntity
{
QuestId = questId,
Revision = revision,
Author = author,
UserGuid = userGuid,
Reason = reason,
CreatedAt = DateTime.UtcNow,
};
await Collection.InsertOneAsync(entity);
return ServerErrorCode.Success;
}
public async Task<QuestAcceptedEntity?> setAuthor(string id, string author)
{
var filterBuilder = Builders<QuestAcceptedEntity>.Filter;
var filter = filterBuilder.Eq(x => x.Id, id);
var update = Builders<QuestAcceptedEntity>.Update
.Set(x => x.Author, author);
var options = new FindOneAndUpdateOptions<QuestAcceptedEntity>
{
ReturnDocument = ReturnDocument.After,
};
return await Collection.FindOneAndUpdateAsync(filter, update, options);
}
}

View File

@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using SharpCompress.Common;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using ServerCommon.UGQ;
using ServerCommon;
namespace UGQDataAccess.Repository;
public class QuestCompletedRepository : BaseRepository<QuestCompletedEntity>
{
private const string CollectionName = "QuestCompleted";
public QuestCompletedRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task<List<QuestCompletedEntity>> getAll()
{
return await Collection.Find(Builders<QuestCompletedEntity>.Filter.Empty).ToListAsync();
}
public async Task<ServerErrorCode> insert(long questId, long revision, string author, string userGuid)
{
var entity = new QuestCompletedEntity
{
QuestId = questId,
Revision = revision,
Author = author,
UserGuid = userGuid,
CreatedAt = DateTime.UtcNow,
};
await Collection.InsertOneAsync(entity);
return ServerErrorCode.Success;
}
public async Task<QuestCompletedEntity?> setAuthor(string id, string author)
{
var filterBuilder = Builders<QuestCompletedEntity>.Filter;
var filter = filterBuilder.Eq(x => x.Id, id);
var update = Builders<QuestCompletedEntity>.Update
.Set(x => x.Author, author);
var options = new FindOneAndUpdateOptions<QuestCompletedEntity>
{
ReturnDocument = ReturnDocument.After,
};
return await Collection.FindOneAndUpdateAsync(filter, update, options);
}
public async Task<long> getCount(string author)
{
var builder = Builders<QuestCompletedEntity>.Filter;
var filter = builder.Eq(x => x.Author, author);
var result = await Collection.Find(filter).CountDocumentsAsync();
return result;
}
}

View File

@@ -0,0 +1,686 @@
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using UGQDataAccess.Repository.Models;
using Amazon.SecurityToken.Model;
using Microsoft.AspNetCore.Mvc.RazorPages;
using UGQDataAccess.Repository.Query;
using System.Linq.Expressions;
using ServerCommon.UGQ;
using ServerCommon.UGQ.Models;
using UGQDataAccess;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using static System.Net.Mime.MediaTypeNames;
namespace UGQDataAccess.Repository;
public class QuestContentRepository : BaseRepository<QuestContentEntity>
{
internal enum SpotlightSort
{
MostLiked,
MostBookmarked,
}
internal class SportlightQuery
{
internal SpotlightSort Sort { get; set; }
internal DateRange DateRange { get; set; }
internal List<QuestBoardItemResult> Items { get; set; } = new();
internal SportlightQuery(SpotlightSort sort, DateRange dateRange)
{
Sort = sort;
DateRange = dateRange;
}
}
private const string CollectionName = "QuestContent";
public QuestContentRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task<QuestContentEntity> insert(QuestContentEntity entity)
{
await Collection.InsertOneAsync(entity);
return entity;
}
public async Task<List<QuestContentEntity>> getAll(string userGuid)
{
var builder = Builders<QuestContentEntity>.Filter;
var filter = builder.Eq(x => x.IsDeleted, false);
filter &= builder.Eq(x => x.UserGuid, userGuid);
var result = await Collection.Find(filter).ToListAsync();
return result;
}
public async Task<long> getAllCount()
{
var builder = Builders<QuestContentEntity>.Filter;
var filter = builder.Eq(x => x.IsDeleted, false);
var result = await Collection.Find(filter).CountDocumentsAsync();
return result;
}
public async Task<List<QuestContentEntity>> getUserQuests(string userGuid, IEnumerable<QuestContentState> states)
{
var builder = Builders<QuestContentEntity>.Filter;
var filter = builder.Eq(x => x.IsDeleted, false);
filter = builder.Eq(x => x.UserGuid, userGuid) &
builder.In(x => x.State, states);
return await Collection.Find(filter).ToListAsync();
}
public async Task<SummaryQueryResult> getSummaries(int pageNumber, int pageSize, string userGuid, QuestContentState state, string? searchText)
{
var accountCollection = _mongoDatabase.GetCollection<AccountEntity>("Account");
var likeCollection = _mongoDatabase.GetCollection<LikeEntity>("Like");
var bookmarkCollection = _mongoDatabase.GetCollection<BookmarkEntity>("Bookmark");
var npcNameCollection = _mongoDatabase.GetCollection<NpcNameEntity>("NpcName");
pageNumber = pageNumber < 1 ? 1 : pageNumber;
var filter = await QuestContentQuery.summariesFilter(userGuid,
UgqSearchType.Title, searchText, state,
accountCollection, npcNameCollection);
var countFacet = AggregateFacet.Create("count",
new EmptyPipelineDefinition<SummaryItemResult>()
.Count()
);
var pagingFacet = AggregateFacet.Create("paging",
new EmptyPipelineDefinition<SummaryItemResult>()
.Skip((pageNumber - 1) * pageSize)
.Limit(pageSize)
);
var pipeline = QuestContentQuery.summariesPipeline<SummaryItemResult>(
likeCollection, bookmarkCollection,
filter,
QuestContentQuery.SummaryItemResultProjection)
.Facet(countFacet, pagingFacet);
var aggregation = await (await Collection.AggregateAsync(pipeline)).ToListAsync();
var count = aggregation.First()
.Facets.First(x => x.Name == "count")
.Output<AggregateCountResult>()
?.FirstOrDefault()
?.Count;
var paging = aggregation.First()
.Facets.First(x => x.Name == "paging")
.Output<SummaryItemResult>();
int totalPages = 0;
if (count != null)
totalPages = (int)Math.Ceiling((double)count / pageSize);
var result = await (await Collection.AggregateAsync(pipeline)).ToListAsync();
return new SummaryQueryResult
{
PageNumber = pageNumber,
PageSize = pageSize,
TotalPages = totalPages,
Items = paging.ToList(),
};
}
public async Task<AllSummaryQueryResult> getAllSummaries(int pageNumber, int pageSize, QuestContentState state, string? searchText)
{
var accountCollection = _mongoDatabase.GetCollection<AccountEntity>("Account");
var likeCollection = _mongoDatabase.GetCollection<LikeEntity>("Like");
var bookmarkCollection = _mongoDatabase.GetCollection<BookmarkEntity>("Bookmark");
var npcNameCollection = _mongoDatabase.GetCollection<NpcNameEntity>("NpcName");
pageNumber = pageNumber < 1 ? 1 : pageNumber;
var filter = await QuestContentQuery.summariesFilter(null,
UgqSearchType.Title, searchText, state,
accountCollection, npcNameCollection);
var countFacet = AggregateFacet.Create("count",
new EmptyPipelineDefinition<SummaryItemResult>()
.Count()
);
var pagingFacet = AggregateFacet.Create("paging",
new EmptyPipelineDefinition<SummaryItemResult>()
.Skip((pageNumber - 1) * pageSize)
.Limit(pageSize)
);
var pipeline = QuestContentQuery.summariesPipeline<SummaryItemResult>(
likeCollection, bookmarkCollection,
filter,
QuestContentQuery.SummaryItemResultProjection)
.Facet(countFacet, pagingFacet);
var aggregation = await (await Collection.AggregateAsync(pipeline)).ToListAsync();
var count = aggregation.First()
.Facets.First(x => x.Name == "count")
.Output<AggregateCountResult>()
?.FirstOrDefault()
?.Count;
var paging = aggregation.First()
.Facets.First(x => x.Name == "paging")
.Output<SummaryItemResult>();
int totalPages = 0;
if (count != null)
totalPages = (int)Math.Ceiling((double)count / pageSize);
return new AllSummaryQueryResult
{
PageNumber = pageNumber,
PageSize = pageSize,
TotalPages = totalPages,
Items = paging.ToList(),
};
}
public async Task<QuestContentEntity?> get(string id)
{
var builder = Builders<QuestContentEntity>.Filter;
var filter = builder.Eq(x => x.IsDeleted, false);
filter &= builder.Eq(x => x.Id, id);
return await Collection.Find(filter).FirstOrDefaultAsync();
}
public async Task<QuestContentEntity?> getByQuestId(long questId)
{
var builder = Builders<QuestContentEntity>.Filter;
var filter = builder.Eq(x => x.IsDeleted, false);
filter &= builder.Eq(x => x.QuestId, questId);
return await Collection.Find(filter).FirstOrDefaultAsync();
}
public async Task<QuestContentEntity?> getByQuestIdRevision(long questId, long revision)
{
var builder = Builders<QuestContentEntity>.Filter;
var filter = builder.Eq(x => x.IsDeleted, false);
filter &= builder.Eq(x => x.QuestId, questId) & builder.Eq(x => x.Revision, revision);
return await Collection.Find(filter).FirstOrDefaultAsync();
}
public async Task<QuestContentEntity?> updateContent(string id, UGQSaveQuestModel model, int? contentVersion)
{
var builder = Builders<QuestContentEntity>.Filter;
var filter = builder.Eq(x => x.IsDeleted, false);
filter &= builder.Eq(x => x.Id, id) &
builder.Eq(x => x.ContentVersion, contentVersion);
var State = QuestContentState.Editable;
foreach (var task in model.Tasks)
{
if (task.ActionId == 0)
{
State = QuestContentState.Uncomplate;
break;
}
}
var update = Builders<QuestContentEntity>.Update
.Set(x => x.BeaconId, model.BeaconId)
.Set(x => x.UgcBeaconGuid, model.UgcBeaconGuid)
.Set(x => x.UgcBeaconNickname, model.UgcBeaconNickname)
.Set(x => x.Title, model.Title)
.Set(x => x.Langs, model.Languages)
.Set(x => x.Savelanguage, model.Savelanguage)
.Set(x => x.Description, model.Description)
.Set(x => x.Cost, model.Cost)
.Set(x => x.Tasks, model.Tasks)
.Set(x => x.State, State)
.Inc(x => x.ContentVersion, 1)
.Set(x => x.UpdatedAt, DateTime.UtcNow);
var options = new FindOneAndUpdateOptions<QuestContentEntity>
{
ReturnDocument = ReturnDocument.After,
};
return await Collection.FindOneAndUpdateAsync(filter, update, options);
}
public async Task<QuestContentEntity?> updateTasks(string id, List<TaskEntity> tasks, int? contentVersion)
{
var builder = Builders<QuestContentEntity>.Filter;
var filter = builder.Eq(x => x.IsDeleted, false);
filter &= builder.Eq(x => x.Id, id) &
builder.Eq(x => x.ContentVersion, contentVersion);
var update = Builders<QuestContentEntity>.Update
.Set(x => x.Tasks, tasks)
.Inc(x => x.ContentVersion, 1)
.Set(x => x.UpdatedAt, DateTime.UtcNow);
var options = new FindOneAndUpdateOptions<QuestContentEntity>
{
ReturnDocument = ReturnDocument.After,
};
return await Collection.FindOneAndUpdateAsync(filter, update, options);
}
public async Task<QuestContentEntity?> updateImages(string id, string? titleImage, string? bannerImage)
{
var builder = Builders<QuestContentEntity>.Filter;
var filter = builder.Eq(x => x.IsDeleted, false);
filter &= builder.Eq(x => x.Id, id);
var updateBuilder = Builders<QuestContentEntity>.Update;
var update = updateBuilder.Set(x => x.UpdatedAt, DateTime.UtcNow);
if (titleImage != null)
update = updateBuilder.Combine(update, updateBuilder.Set(x => x.TitleImagePath, titleImage));
if (bannerImage != null)
update = updateBuilder.Combine(update, updateBuilder.Set(x => x.BannerImagePath, bannerImage));
var options = new FindOneAndUpdateOptions<QuestContentEntity>
{
ReturnDocument = ReturnDocument.After,
};
return await Collection.FindOneAndUpdateAsync(filter, update, options);
}
public async Task<QuestContentEntity?> updateState(string id, long questId, long revision,
IEnumerable<QuestContentState> before, QuestContentState after, UgqGradeType? gradeType = null)
{
var builder = Builders<QuestContentEntity>.Filter;
var filter = builder.Eq(x => x.IsDeleted, false);
filter &= builder.Eq(x => x.Id, id) &
builder.In(x => x.State, before);
// Test->Standby <20><> <20><> toNextRevision<6F><6E> true<75><65> <20>ؼ<EFBFBD> Live <20><> <20><> Revision + 1 ó<><C3B3> <20>Ѵ<EFBFBD>.
bool toNextRevision = before.Any(x => x == QuestContentState.Test) && (after == QuestContentState.Standby);
var updateBuilder = Builders<QuestContentEntity>.Update;
var update = updateBuilder
.Set(x => x.UpdatedAt, DateTime.UtcNow)
.Set(x => x.QuestId, questId)
.Set(x => x.Revision, revision)
.Set(x => x.State, after)
.Set(x => x.ToNextRevision, toNextRevision);
if (gradeType != null)
update = updateBuilder.Combine(update, updateBuilder.Set(x => x.GradeType, gradeType));
var options = new FindOneAndUpdateOptions<QuestContentEntity>
{
ReturnDocument = ReturnDocument.After,
};
return await Collection.FindOneAndUpdateAsync(filter, update, options);
}
public async Task<(ServerErrorCode, int)> incUploadCounter(string questContentId)
{
var builder = Builders<QuestContentEntity>.Filter;
var filter = builder.Eq(x => x.IsDeleted, false);
filter &= builder.Eq(x => x.Id, questContentId);
var update = Builders<QuestContentEntity>.Update
.Inc(x => x.UploadCounter, 1)
.Set(x => x.UpdatedAt, DateTime.UtcNow);
var options = new FindOneAndUpdateOptions<QuestContentEntity>()
{
ReturnDocument = ReturnDocument.After
};
var updated = await Collection.FindOneAndUpdateAsync(filter, update, options);
return (ServerErrorCode.Success, updated.UploadCounter);
}
public async Task<ServerErrorCode> deleteQuest(string userGuid, string questContentId)
{
var builder = Builders<QuestContentEntity>.Filter;
var filter = builder.Eq(x => x.IsDeleted, false);
filter &= builder.Eq(x => x.UserGuid, userGuid) & builder.Eq(x => x.Id, questContentId);
var update = Builders<QuestContentEntity>.Update
.Set(x => x.UpdatedAt, DateTime.UtcNow)
.Set(x => x.DeletedAt, DateTime.UtcNow)
.Set(x => x.IsDeleted, true);
var result = await Collection.UpdateOneAsync(filter, update);
if(result.ModifiedCount == 0)
return ServerErrorCode.UgqNullEntity;
return ServerErrorCode.Success;
}
public async Task<QuestBoardQueryResult> getQuestBoard(string? userGuid,
UgqQuestBoardRequest request, int pageSize)
{
var accountCollection = _mongoDatabase.GetCollection<AccountEntity>("Account");
var likeCollection = _mongoDatabase.GetCollection<LikeEntity>("Like");
var bookmarkCollection = _mongoDatabase.GetCollection<BookmarkEntity>("Bookmark");
var npcNameCollection = _mongoDatabase.GetCollection<NpcNameEntity>("NpcName");
request.PageNumber = request.PageNumber < 1 ? 1 : request.PageNumber;
var filter = await QuestContentQuery.questBoardFilter(userGuid, request.GradeType,
request.SearchType, request.SearchText, accountCollection, npcNameCollection);
var sort = QuestContentQuery.questBoardSort<QuestBoardItemResult>(request.SortType);
var countFacet = AggregateFacet.Create("count",
new EmptyPipelineDefinition<QuestBoardItemResult>()
.Count()
);
var pagingFacet = AggregateFacet.Create("paging",
new EmptyPipelineDefinition<QuestBoardItemResult>()
.Sort(sort)
.Skip((request.PageNumber - 1) * pageSize)
.Limit(pageSize)
);
var pipeline = QuestContentQuery.questBoardPipeline<QuestBoardItemResult>(
likeCollection, bookmarkCollection, filter,
QuestContentQuery.QuestBoardItemResultProjection)
.Facet(countFacet, pagingFacet);
var aggregation = await (await Collection.AggregateAsync(pipeline)).ToListAsync();
var count = aggregation.First()
.Facets.First(x => x.Name == "count")
.Output<AggregateCountResult>()
?.FirstOrDefault()
?.Count;
var paging = aggregation.First()
.Facets.First(x => x.Name == "paging")
.Output<QuestBoardItemResult>();
int totalPages = 0;
if(count != null)
totalPages = (int)Math.Ceiling((double)count / pageSize);
return new QuestBoardQueryResult
{
PageNumber = request.PageNumber,
PageSize = pageSize,
TotalPages = totalPages,
Items = paging.ToList(),
};
}
public async Task<QuestBoardDetailItemResult?> getQuestBoardDetail(string userGuid, long questId, long revision)
{
var likeCollection = _mongoDatabase.GetCollection<LikeEntity>("Like");
var bookmarkCollection = _mongoDatabase.GetCollection<BookmarkEntity>("Bookmark");
var filterBuilder = Builders<QuestContentEntity>.Filter;
var filter = filterBuilder.Eq(x => x.IsDeleted, false);
filter &= filterBuilder.Eq(x => x.QuestId, questId);
filter &= filterBuilder.Eq(x => x.Revision, revision);
filter &= filterBuilder.Eq(x => x.State, QuestContentState.Live);
Expression<Func<QuestContentQuery.QuestBoardQueryJoin, QuestBoardDetailItemResult>> questBoardDetailItemProjection =
x => new QuestBoardDetailItemResult
{
QuestId = x.QuestId,
Revision = x.Revision,
Author = x.Author,
Title = x.Title,
Languages = x.Langs,
Description = x.Description,
Cost = x.Cost,
GradeType = x.GradeType,
TitleImagePath = x.TitleImagePath,
BannerImagePath = x.BannerImagePath,
UpdatedAt = x.UpdatedAt,
LikeCount = x.LikeCount,
BookmarkCount = x.BookmarkCount,
QuestAcceptedCount = x.QuestAcceptedCount,
QuestCompletedCount = x.QuestCompletedCount,
BeaconId = x.BeaconId,
UgcBeaconGuid = x.UgcBeaconGuid,
UgcBeaconNickname = x.UgcBeaconNickname,
Liked = x.Likes.Any(x => x.UserGuid == userGuid),
Bookmarked = x.Bookmarks.Any(x => x.UserGuid == userGuid),
};
var pipeline = QuestContentQuery.questBoardDetailPipeline<QuestBoardDetailItemResult>(
likeCollection, bookmarkCollection,
filter,
questBoardDetailItemProjection);
return await (await Collection.AggregateAsync(pipeline)).FirstOrDefaultAsync();
}
public async Task<QuestBoardQueryResult> getBookmarkQuests(string userGuid, UgqQuestBoardRequest request, int pageSize)
{
var likeCollection = _mongoDatabase.GetCollection<LikeEntity>("Like");
var bookmarkCollection = _mongoDatabase.GetCollection<BookmarkEntity>("Bookmark");
var npcNameCollection = _mongoDatabase.GetCollection<NpcNameEntity>("NpcName");
request.PageNumber = request.PageNumber < 1 ? 1 : request.PageNumber;
var filter = await QuestContentQuery.questBoardBookmarkFilter(userGuid,
request.GradeType, request.SearchType, request.SearchText,
npcNameCollection, bookmarkCollection);
var sort = QuestContentQuery.questBoardSort<QuestBoardItemResult>(request.SortType);
var countFacet = AggregateFacet.Create("count",
new EmptyPipelineDefinition<QuestBoardItemResult>()
.Count()
);
var pagingFacet = AggregateFacet.Create("paging",
new EmptyPipelineDefinition<QuestBoardItemResult>()
.Sort(sort)
.Skip((request.PageNumber - 1) * pageSize)
.Limit(pageSize)
);
var pipeline = QuestContentQuery.questBoardPipeline<QuestBoardItemResult>(
likeCollection, bookmarkCollection, filter,
QuestContentQuery.QuestBoardItemResultProjection)
.Facet(countFacet, pagingFacet);
var aggregation = await (await Collection.AggregateAsync(pipeline)).ToListAsync();
var count = aggregation.First()
.Facets.First(x => x.Name == "count")
.Output<AggregateCountResult>()
?.FirstOrDefault()
?.Count;
var paging = aggregation.First()
.Facets.First(x => x.Name == "paging")
.Output<QuestBoardItemResult>();
int totalPages = 0;
if (count != null)
totalPages = (int)Math.Ceiling((double)count / pageSize);
return new QuestBoardQueryResult
{
PageNumber = request.PageNumber,
PageSize = pageSize,
TotalPages = totalPages,
Items = paging.ToList(),
};
}
public async Task<QuestBoardSportlightQueryResult> getQuestBoardSpotlight()
{
var accountCollection = _mongoDatabase.GetCollection<AccountEntity>("Account");
var likeCollection = _mongoDatabase.GetCollection<LikeEntity>("Like");
var bookmarkCollection = _mongoDatabase.GetCollection<BookmarkEntity>("Bookmark");
SportlightQuery[] queries = [
new SportlightQuery(SpotlightSort.MostLiked, DataRangeHelper.Yesterday(DateTime.Now)),
new SportlightQuery(SpotlightSort.MostBookmarked, DataRangeHelper.Yesterday(DateTime.Now)),
new SportlightQuery(SpotlightSort.MostLiked, DataRangeHelper.LastWeek(DateTime.Now)),
new SportlightQuery(SpotlightSort.MostBookmarked, DataRangeHelper.LastWeek(DateTime.Now)),
new SportlightQuery(SpotlightSort.MostLiked, DataRangeHelper.LastMonth(DateTime.Now)),
new SportlightQuery(SpotlightSort.MostBookmarked, DataRangeHelper.LastMonth(DateTime.Now)),
];
var filterBuilder = Builders<QuestContentEntity>.Filter;
var filter = filterBuilder.Eq(x => x.IsDeleted, false);
foreach (var (value, i) in queries.Select((value, i) => (value, i)))
{
int limit = 1;
switch(value.Sort)
{
case SpotlightSort.MostLiked:
{
var sort = Builders<QuestBoardItemResult>.Sort.Descending("LikeCount").Descending("CreatedAt");
var pipeline = QuestContentQuery.questBoardPipeline<QuestBoardItemResult>(
likeCollection, bookmarkCollection, filter,
QuestContentQuery.QuestBoardItemResultProjection)
.Sort(sort)
.Limit(limit);
value.Items = await (await Collection.AggregateAsync(pipeline)).ToListAsync();
}
break;
case SpotlightSort.MostBookmarked:
{
var sort = Builders<QuestBoardItemResult>.Sort.Descending("BookmarkCount").Descending("CreatedAt");
var pipeline = QuestContentQuery.questBoardPipeline<QuestBoardItemResult>(
likeCollection, bookmarkCollection, filter,
QuestContentQuery.QuestBoardItemResultProjection)
.Sort(sort)
.Limit(limit);
value.Items = await (await Collection.AggregateAsync(pipeline)).ToListAsync();
}
break;
}
}
/*
// <20>ߺ<EFBFBD> <20><><EFBFBD><EFBFBD>
foreach (var (value, i) in queries.Select((value, i) => (value, i)))
{
if (value.Items.Count == 0)
continue;
long questId = value.Items[0].QuestId;
long revision = value.Items[0].Revision;
for (int s = i + 1; s < queries.Length; s++)
{
queries[s].Items.RemoveAll(x => x.QuestId == questId && x.Revision == revision);
}
}
*/
return new QuestBoardSportlightQueryResult
{
MostLiked = new()
{
Today = queries[0].Items.FirstOrDefault(),
ThisWeek = queries[2].Items.FirstOrDefault(),
ThisMonth = queries[4].Items.FirstOrDefault(),
},
MostBookmarked = new()
{
Today = queries[1].Items.FirstOrDefault(),
ThisWeek = queries[3].Items.FirstOrDefault(),
ThisMonth = queries[5].Items.FirstOrDefault(),
},
};
}
public async Task<QuestProfitStatsQueryResult> getQuestProfitStats(string userGuid, int pageNumber, int pageSize)
{
var accountCollection = _mongoDatabase.GetCollection<AccountEntity>("Account");
var likeCollection = _mongoDatabase.GetCollection<LikeEntity>("Like");
var bookmarkCollection = _mongoDatabase.GetCollection<BookmarkEntity>("Bookmark");
var npcNameCollection = _mongoDatabase.GetCollection<NpcNameEntity>("NpcName");
var questAcceptedCollection = _mongoDatabase.GetCollection<QuestAcceptedEntity>("QuestAccepted");
var questCompletedCollection = _mongoDatabase.GetCollection<QuestCompletedEntity>("QuestCompleted");
var questAbortedCollection = _mongoDatabase.GetCollection<QuestAbortedEntity>("QuestAborted");
var creatorPointHistoryCollection = _mongoDatabase.GetCollection<CreatorPointHistoryEntity>("CreatorPointHistory");
pageNumber = pageNumber < 1 ? 1 : pageNumber;
var filterBuilder = Builders<QuestContentEntity>.Filter;
var filter = filterBuilder.Eq(x => x.IsDeleted, false);
filter &= filterBuilder.Eq(x => x.UserGuid, userGuid);
var countFacet = AggregateFacet.Create("count",
new EmptyPipelineDefinition<QuestProfitStatsItemResult>()
.Count()
);
var pagingFacet = AggregateFacet.Create("paging",
new EmptyPipelineDefinition<QuestProfitStatsItemResult>()
.Skip((pageNumber - 1) * pageSize)
.Limit(pageSize)
);
var pipeline = QuestContentQuery.questProfitStatsPipeline<QuestProfitStatsItemResult>(
filter,
QuestContentQuery.QuestProfitStatsResultProjection)
.Facet(countFacet, pagingFacet);
var aggregation = await (await Collection.AggregateAsync(pipeline)).ToListAsync();
var count = aggregation.First()
.Facets.First(x => x.Name == "count")
.Output<AggregateCountResult>()
?.FirstOrDefault()
?.Count;
var paging = aggregation.First()
.Facets.First(x => x.Name == "paging")
.Output<QuestProfitStatsItemResult>();
int totalPages = 0;
if (count != null)
totalPages = (int)Math.Ceiling((double)count / pageSize);
return new QuestProfitStatsQueryResult
{
PageNumber = pageNumber,
PageSize = pageSize,
TotalPages = totalPages,
Items = paging.ToList(),
};
}
}

View File

@@ -0,0 +1,62 @@
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;
using SharpCompress.Common;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using ServerCommon.UGQ;
namespace UGQDataAccess.Repository;
public class QuestDialogRepository : BaseRepository<QuestDialogEntity>
{
private const string CollectionName = "QuestDialog";
public QuestDialogRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task<(ServerErrorCode, QuestDialogEntity)> add(QuestDialogEntity entity)
{
await Collection.InsertOneAsync(entity);
return (ServerErrorCode.Success, entity);
}
public async Task<QuestDialogEntity?> get(string id)
{
var filter = Builders<QuestDialogEntity>.Filter
.Eq(x => x.Id, id);
var entity = await Collection.Find(filter).FirstOrDefaultAsync();
return entity;
}
public async Task<List<QuestDialogEntity>> get(IEnumerable<string> ids)
{
var filter = Builders<QuestDialogEntity>.Filter
.In(x => x.Id, ids);
return await Collection.Find(filter).ToListAsync();
}
public async Task<(ServerErrorCode, QuestDialogEntity?)> updateSequences(string dialogId, List<DialogSequenceEntity> sequences)
{
var filter = Builders<QuestDialogEntity>.Filter
.Eq(x => x.Id, dialogId);
var update = Builders<QuestDialogEntity>.Update
.Set(x => x.Sequences, sequences)
.Set(x => x.UpdatedAt, DateTime.UtcNow);
var options = new FindOneAndUpdateOptions<QuestDialogEntity>
{
ReturnDocument = ReturnDocument.After,
};
var updated = await Collection.FindOneAndUpdateAsync(filter, update, options);
return (ServerErrorCode.Success, updated);
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using ServerCommon.UGQ;
namespace UGQDataAccess.Repository
{
public class QuestIdSequenceRepository : BaseRepository<QuestIdSequenceEntity>
{
private const string CollectionName = "QuestIdSequence";
public QuestIdSequenceRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task init()
{
var found = await Collection.FindAsync(x => x.Id == "QuestId");
if(found.FirstOrDefault() == null)
{
QuestIdSequenceEntity entity = new ()
{
Id = "QuestId",
Sequence = 0,
UpdatedAt = DateTime.UtcNow,
CreatedAt = DateTime.UtcNow,
};
await Collection.InsertOneAsync(entity);
}
}
public async Task<long> getNextSequence()
{
var filter = Builders<QuestIdSequenceEntity>.Filter.Eq(x => x.Id, "QuestId");
var update = Builders<QuestIdSequenceEntity>.Update
.Inc(x => x.Sequence, 1)
.Set(x => x.UpdatedAt, DateTime.UtcNow);
var options = new FindOneAndUpdateOptions<QuestIdSequenceEntity>()
{
ReturnDocument = ReturnDocument.After
};
var result = await Collection.FindOneAndUpdateAsync(filter, update, options);
return result.Sequence;
}
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using SharpCompress.Common;
using UGQDatabase.Models;
using UGQDataAccess.Settings;
using ServerCommon.UGQ;
using System.Runtime.CompilerServices;
namespace UGQDataAccess.Repository
{
public class ReportRepository : BaseRepository<ReportEntity>
{
private const string CollectionName = "Report";
public ReportRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task<ReportEntity?> get(long questId, long revision, string userGuid)
{
var builder = Builders<ReportEntity>.Filter;
var filter = builder.Eq(x => x.QuestId, questId) &
builder.Eq(x => x.Revision, revision) &
builder.Eq(x => x.UserGuid, userGuid);
ReportEntity? entity = await (await Collection.FindAsync(filter)).FirstOrDefaultAsync();
return entity;
}
public async Task<ServerErrorCode> insert(long questId, long revision, string userGuid, string contents)
{
var entity = new ReportEntity
{
QuestId = questId,
Revision = revision,
UserGuid = userGuid,
Contents = contents,
CreatedAt = DateTime.UtcNow,
};
await Collection.InsertOneAsync(entity);
return ServerErrorCode.Success;
}
}
}

View File

@@ -0,0 +1,230 @@
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using UGQDataAccess.Repository.Models;
using UGQDataAccess.Settings;
using UGQDatabase.Models;
public enum AccountGradeSortType
{
UpdatedAtAsc,
UpdatedAtDesc,
GradeAsc,
GradeDesc,
ReservedAtAsc,
ReservedDesc,
}
public enum AccountGradeProcessType
{
All,
Processing,
Completed,
}
namespace UGQDataAccess.Repository
{
public class ReserveAccountGradeRepository : BaseRepository<ReserveAccountGradeEntity>
{
private const string CollectionName = "ReserveAccountGrade";
public ReserveAccountGradeRepository(IMongoClient mongoClient, IOptions<UGQDatabaseSettings> settings) :
base(mongoClient, settings.Value.DatabaseName, CollectionName)
{
}
public async Task<ReserveAccountGradeEntity?> get(string userGuid)
{
var builder = Builders<ReserveAccountGradeEntity>.Filter;
var filter = builder.Eq(x => x.IsCompleted, false);
filter &= builder.Eq(x => x.UserGuid, userGuid);
return await Collection.Find(filter).FirstOrDefaultAsync();
}
public async Task<List<ReserveAccountGradeEntity>> get(string userGuid, AccountGradeProcessType processType)
{
var builder = Builders<ReserveAccountGradeEntity>.Filter;
var filter = builder.Eq(x => x.UserGuid, userGuid);
switch (processType)
{
case AccountGradeProcessType.Processing:
filter &= builder.Eq(x => x.IsCompleted, false);
break;
case AccountGradeProcessType.Completed:
filter &= builder.Eq(x => x.IsCompleted, true);
break;
case AccountGradeProcessType.All:
default:
break;
}
return await Collection.Find(filter).ToListAsync();
}
public async Task<long> getAllCount()
{
var builder = Builders<ReserveAccountGradeEntity>.Filter;
var filter = builder.Empty;
var result = await Collection.Find(filter).CountDocumentsAsync();
return result;
}
public async Task<ReserveAccountGradeEntity> reserveAccountGrade(string userGuid, UgqGradeType beforeGrade, UgqGradeType reserveGrade, DateTime reserveTime)
{
var entity = new ReserveAccountGradeEntity
{
UserGuid = userGuid,
BeforeGradeType = beforeGrade,
ReserveGradeType = reserveGrade,
ReserveTime = reserveTime,
UpdatedAt = DateTime.UtcNow,
IsCompleted = false,
};
await Collection.InsertOneAsync(entity);
return entity;
}
public async Task<ReserveAccountGradeEntity> modifyReserveAccountGrade(string reserveId, UgqGradeType reserveGrade, DateTime reserveTime)
{
var builder = Builders<ReserveAccountGradeEntity>.Filter;
var filter = builder.Eq(x => x.IsCompleted, false);
filter &= builder.Eq(x => x.Id, reserveId);
var update = Builders<ReserveAccountGradeEntity>.Update
.Set(x => x.ReserveGradeType, reserveGrade)
.Set(x => x.ReserveTime, reserveTime)
.Set(x => x.UpdatedAt, DateTime.UtcNow);
var options = new FindOneAndUpdateOptions<ReserveAccountGradeEntity>
{
ReturnDocument = ReturnDocument.After,
};
return await Collection.FindOneAndUpdateAsync(filter, update, options);
}
public async Task<List<ReserveAccountGradeEntity>> completeReserveAccountGrade()
{
var builder = Builders<ReserveAccountGradeEntity>.Filter;
var filter = builder.Eq(x => x.IsCompleted, false);
filter &= builder.Lte(x => x.ReserveTime, DateTime.UtcNow);
var update = Builders<ReserveAccountGradeEntity>.Update
.Set(x => x.IsCompleted, true)
.Set(x => x.UpdatedAt, DateTime.UtcNow);
var result = await Collection.Find(filter).ToListAsync();
await Collection.UpdateManyAsync(filter, update);
return result;
}
public async Task<ServerErrorCode> deleteReserveAccountGrade(string reserveId)
{
var builder = Builders<ReserveAccountGradeEntity>.Filter;
var filter = builder.Eq(x => x.IsCompleted, false);
filter &= builder.Eq(x => x.Id, reserveId);
var result = await Collection.DeleteOneAsync(filter);
if (result.DeletedCount == 0)
return ServerErrorCode.UgqNullEntity;
return ServerErrorCode.Success;
}
public async Task<AllReserveAccountGradeResult> getAccounts(int pageNumber, int pageSize, AccountGradeSortType sortType, AccountGradeProcessType processType, string userGuid)
{
pageNumber = pageNumber < 1 ? 1 : pageNumber;
var builder = Builders<ReserveAccountGradeEntity>.Filter;
var filter = Builders<ReserveAccountGradeEntity>.Filter.Empty;
switch (processType)
{
case AccountGradeProcessType.Processing:
filter = builder.Eq(x => x.IsCompleted, false);
break;
case AccountGradeProcessType.Completed:
filter = builder.Eq(x => x.IsCompleted, true);
break;
case AccountGradeProcessType.All:
default:
break;
}
if(userGuid != string.Empty)
filter &= builder.Eq(x => x.UserGuid, userGuid);
var sortBuilder = Builders<ReserveAccountGradeItemResult>.Sort;
SortDefinition<ReserveAccountGradeItemResult> sort;
switch (sortType)
{
case AccountGradeSortType.UpdatedAtAsc:
sort = Builders<ReserveAccountGradeItemResult>.Sort.Ascending("UpdatedAt");
break;
case AccountGradeSortType.UpdatedAtDesc:
sort = Builders<ReserveAccountGradeItemResult>.Sort.Descending("UpdatedAt");
break;
case AccountGradeSortType.GradeAsc:
sort = Builders<ReserveAccountGradeItemResult>.Sort.Ascending("CurrentGradeType");
break;
case AccountGradeSortType.GradeDesc:
sort = Builders<ReserveAccountGradeItemResult>.Sort.Descending("CurrentGradeType");
break;
case AccountGradeSortType.ReservedAtAsc:
sort = Builders<ReserveAccountGradeItemResult>.Sort.Ascending("ReserveTime");
break;
case AccountGradeSortType.ReservedDesc:
sort = Builders<ReserveAccountGradeItemResult>.Sort.Descending("ReserveTime");
break;
default:
sort = Builders<ReserveAccountGradeItemResult>.Sort.Descending("UpdatedAt");
break;
}
var countFacet = AggregateFacet.Create("count",
new EmptyPipelineDefinition<ReserveAccountGradeItemResult>()
.Count()
);
var pagingFacet = AggregateFacet.Create("paging",
new EmptyPipelineDefinition<ReserveAccountGradeItemResult>()
.Sort(sort)
.Skip((pageNumber - 1) * pageSize)
.Limit(pageSize)
);
var pipeline = ReserveAccountGradeQuery.allReserveAccountGradePipeline<ReserveAccountGradeItemResult>(
filter,
ReserveAccountGradeQuery.ReserveAccountGradeItemResultProjection)
.Facet(countFacet, pagingFacet);
var aggregation = await (await Collection.AggregateAsync(pipeline)).ToListAsync();
var count = aggregation.First()
.Facets.First(x => x.Name == "count")
.Output<AggregateCountResult>()
?.FirstOrDefault()
?.Count;
var paging = aggregation.First()
.Facets.First(x => x.Name == "paging")
.Output<ReserveAccountGradeItemResult>();
int totalPages = 0;
if (count != null)
totalPages = (int)Math.Ceiling((double)count / pageSize);
var result = await (await Collection.AggregateAsync(pipeline)).ToListAsync();
return new AllReserveAccountGradeResult
{
PageNumber = pageNumber,
PageSize = pageSize,
TotalPages = totalPages,
Items = paging.ToList(),
};
}
}
}