using System.Threading;
using Dpz.Core.Public.ViewModel.Request;
using Dpz.Core.Public.ViewModel.RequestEvent;
using Dpz.Core.Public.ViewModel.Response;
namespace Dpz.Core.Service.RepositoryServiceImpl;
public class PictureRecordService(
IRepository<PictureRecord> repository,
IMapper mapper,
IFusionCache fusionCache,
IMediator mediator
) : AbstractCacheService(fusionCache), IPictureRecordService
{
protected override TimeSpan CacheDefaultExpiration => TimeSpan.FromDays(1);
private readonly IFusionCache _fusionCache = fusionCache;
public async Task<List<string>> GetTagsAsync()
{
return await GetOrSetCacheAsync<List<string>>(
nameof(GetTagsAsync),
async (_, cancellationToken) =>
{
var tags = await repository
.MongodbQueryable
//.Select(x => x.Tags)
.SelectMany(x => x.Tags)
.GroupBy(x => x)
.Select(x => x.Key)
.ToListAsync(cancellationToken);
return tags;
}
);
}
public async Task<ICollection<PictureRecordResponse>> GetBannerAsync()
{
return await GetOrSetCacheAsync<List<PictureRecordResponse>>(
nameof(GetBannerAsync),
async (_, _) =>
{
var pagedList = await repository
.SearchFor(x => x.Tags.Any(y => y == "banner"))
.OrderByDescending(x => x.UploadTime)
.ToListAsync<PictureRecord, PictureRecordResponse>();
pagedList.ForEach(x => x.AccessUrl += "!banner");
return pagedList;
}
);
}
public async Task<IPagedList<PictureRecordResponse>> GetPagesAsync(
List<string>? tags,
string? description,
int pageIndex = 1,
int pageSize = 20,
string? account = null
)
{
return await GetOrSetPagedListAsync<PictureRecordResponse>(
nameof(GetPagesAsync),
async _ =>
{
var filterEmpty = Builders<PictureRecord>.Filter.Empty;
var filters = new List<FilterDefinition<PictureRecord>>();
var clearTags =
tags?.Where(x => !string.IsNullOrEmpty(x)).Select(x => x).ToList() ?? [];
if (clearTags.Count > 0)
{
var filter = Builders<PictureRecord>.Filter.AnyIn(x => x.Tags, clearTags);
filters.Add(filter);
}
if (!string.IsNullOrEmpty(description))
{
var filter = Builders<PictureRecord>.Filter.Regex(
x => x.Description,
new BsonRegularExpression(description, "i")
);
filters.Add(filter);
}
if (!string.IsNullOrEmpty(account))
{
var filter = Builders<PictureRecord>.Filter.Eq(x => x.Creator.Id, account);
filters.Add(filter);
}
var filterResult =
filters.Count > 0 ? Builders<PictureRecord>.Filter.And(filters) : filterEmpty;
return await repository
.SearchFor(filterResult)
.SortByDescending(x => x.Id)
.ToPagedListAsync<PictureRecord, PictureRecordResponse>(pageIndex, pageSize);
},
new
{
tags,
description,
pageIndex,
pageSize,
account,
}
);
}
public async Task<PictureRecordResponse?> GetPictureRecordAsync(string id)
{
return await GetOrSetCacheAsync<PictureRecordResponse?>(
nameof(GetPictureRecordAsync),
async (_, _) =>
{
var entity = await repository.TryGetAsync(id);
return entity == null ? null : mapper.Map<PictureRecordResponse>(entity);
},
new { id }
);
}
public async Task<PictureRecordResponse> CreateRecordAsync(
CreatePictureRecordRequest request,
CancellationToken cancellationToken = default
)
{
var entity = mapper.Map<PictureRecord>(request);
await repository.InsertAsync(entity, cancellationToken);
if (entity.Tags.Any(x => x == "banner"))
{
await _fusionCache.RemoveAsync(CacheKey.HomeContainerKey, token: cancellationToken);
}
await ClearCacheAsync();
return mapper.Map<PictureRecordResponse>(entity);
}
public async Task<PictureRecordResponse?> ChangeInformationAsync(
EditPictureRecordRequest request,
CancellationToken cancellationToken = default
)
{
if (!ObjectId.TryParse(request.Id, out var oid))
{
return null;
}
var update = Builders<PictureRecord>
.Update.Set(x => x.Category, request.Category)
.Set(x => x.Description, request.Description)
.Set(x => x.Tags, request.Tags);
await repository.UpdateAsync(x => x.Id == oid, update, cancellationToken);
if (request.Tags.Any(x => x == "banner"))
{
await _fusionCache.RemoveAsync(CacheKey.HomeContainerKey, token: cancellationToken);
}
await ClearCacheAsync();
var entity = await repository.FindAsync(oid, cancellationToken);
return entity == null ? null : mapper.Map<PictureRecordResponse>(entity);
}
public async Task DeleteAsync(string id)
{
var entity = await repository.TryGetAsync(id);
if (entity == null)
{
return;
}
await repository.DeleteAsync(entity.Id);
await mediator.Send(new RemoveImagesRequest { Images = [entity.AccessUrl] });
await ClearCacheAsync();
}
public async Task ClearCacheAsync()
{
var removeTags = new[]
{
CachePrefixKey + nameof(GetTagsAsync),
CachePrefixKey + nameof(GetPagesAsync),
CachePrefixKey + nameof(GetBannerAsync),
CachePrefixKey + nameof(GetPictureRecordAsync),
};
await _fusionCache.RemoveByTagAsync(removeTags);
}
}
⚠⚠ 以下内容为AI分析的结果,请根据实际情况进行判断。
PictureRecordService 代码分析
这个 PictureRecordService 是一个图片记录服务类,主要处理图片记录的相关操作,包括标签管理、横幅图片获取、分页查询、创建、修改和删除图片记录等功能。下面是详细的功能解释:
主要功能
1. 缓存功能
- 继承自
AbstractCacheService,提供了缓存功能 - 默认缓存过期时间为1天 (
TimeSpan.FromDays(1)) - 使用
IFusionCache进行缓存管理 - 提供了
ClearCacheAsync()方法来清除相关缓存
2. 标签管理
GetTagsAsync(): 获取所有图片标签的列表(去重)
3. 横幅图片获取
GetBannerAsync(): 获取标记为"banner"的图片列表,并按上传时间降序排列- 返回的图片URL会自动追加"!banner"后缀
4. 分页查询
GetPagesAsync(): 根据标签、描述和账户进行分页查询图片记录- 支持多标签筛选
- 支持描述模糊搜索(不区分大小写)
- 支持按账户筛选
- 结果按ID降序排列
5. 单个图片记录操作
GetPictureRecordAsync(): 根据ID获取单个图片记录CreateRecordAsync(): 创建新的图片记录ChangeInformationAsync(): 修改图片记录的信息(分类、描述和标签)DeleteAsync(): 删除图片记录,并发送删除图片文件的请求
技术特点
缓存策略:
- 使用缓存提高性能
- 当相关数据变更时自动清除缓存
- 特别是当操作涉及"banner"标签时,会清除首页容器缓存
数据库操作:
- 使用MongoDB进行数据存储
- 使用构建器模式创建查询条件
- 支持分页查询
其他技术:
- 使用AutoMapper进行对象映射
- 使用MediatR进行事件处理(如图片删除时发送删除图片文件的请求)
异常处理:
- 在修改操作时检查ObjectId的有效性
- 在删除操作时检查记录是否存在
使用场景
这个服务类适用于需要管理图片记录的系统,特别是:
- 需要展示横幅图片的网站
- 需要按标签分类管理图片的系统
- 需要支持多条件筛选和分页查询的图片库
服务通过缓存机制优化了频繁查询的性能,并通过事件机制处理了图片文件与记录的一致性。
评论加载中...