refactor:使用缓存优化轨迹订单查询

This commit is contained in:
hardstylewyl 2025-01-03 16:38:56 +08:00
parent db200c2212
commit 5a43e54139

View File

@ -1,3 +1,4 @@
using Microsoft.Extensions.Caching.Memory;
using SJZY.Expand.ABP.Core.Logger; using SJZY.Expand.ABP.Core.Logger;
using SJZY.Track.Domain; using SJZY.Track.Domain;
using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.OrderAggregate;
@ -10,16 +11,178 @@ namespace SJZY.Track.Repository.Repositories;
public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, ITransientDependency public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, ITransientDependency
{ {
//MemoryCache本身线程安全简单使用,短暂数据不一致可以容忍,每过固定时间强制清除缓存
private static readonly MemoryCache _memoryCache = new(new MemoryCacheOptions());
private static readonly Dictionary<int, string> _empty = new();
private static readonly Dictionary<string, Dictionary<int, string>> _empty2 = new();
private const int ThirdPartyOrderNumberCacheTimeSpan = 3 * 60;
private const int MainDataEnumCacheTimeSpan = 5 * 60;
private async Task<Dictionary<int, string>> GetThirdPartyOrderNumberForCacheAsync(int[] orderIds)
{
const string key = "ThirdPartyOrderNumber";
if (orderIds.Length == 0) return _empty;
var dict = _memoryCache.Get<Dictionary<int, string>>(key);
orderIds = orderIds.Distinct().ToArray();
if (dict != null && dict.Count != 0 && !orderIds.Except(dict.Keys).Any()) return dict;
var orders = await Context.Queryable<OrderEntity>()
.Includes(a => a.OrderPlatformNumbers)
.LeftJoin<OrderPlatformNumberEntity>((a, b) => a.Id == b.OrderId && b.IsDeleted == false)
.Where((a, b) => orderIds.Contains(a.Id))
.Select(a => new OrderEntity()
{
Id = a.Id,
OrderPlatformNumbers = a.OrderPlatformNumbers
})
.ToListAsync();
if (orders.Count == 0)
return _empty;
orders = orders.DistinctBy(x => x.Id).ToList();
dict = orders.ToDictionary(x => x.Id, x => BuildThirdPartyOrderNumber(x.OrderPlatformNumbers));
_memoryCache.Set(key, dict, new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(ThirdPartyOrderNumberCacheTimeSpan),
Size = dict.Count
});
return dict;
}
private async Task<Dictionary<string, Dictionary<int, string>>> GetMainDataEnumForCacheAsync(List<int> orderTypes, List<int> questTypes)
{
const string key = "EnumForMainData";
if (orderTypes.Count == 0 && questTypes.Count == 0) return _empty2;
var dict = _memoryCache.Get<Dictionary<string, Dictionary<int, string>>>(key);
if (dict != null && dict.Count != 0
&& !orderTypes.Except(dict[GlobalConst.MainDataKey_OrderType].Keys).Any()
&& !questTypes.Except(dict[GlobalConst.MainDataKey_TrackQuestionType].Keys).Any())
{
return dict;
}
//从主数据中心查询类型描述
dict = (await Context.Queryable<VEnumValueInfoEntity>()
.Where(x =>
(x.Property == GlobalConst.MainDataKey_OrderType && orderTypes.Contains(x.Enumkey))
|| (x.Property == GlobalConst.MainDataKey_TrackQuestionType && questTypes.Contains(x.Enumkey))
)
.Select(x => new
{
x.Property,
x.Enumkey,
x.Disp
})
.ToListAsync()
)
.GroupBy(x => x.Property)
.ToDictionary(
g => g.Key,
y => y.ToDictionary(x => x.Enumkey, x => x.Disp)
);
if (dict.Count == 0)
return _empty2;
_memoryCache.Set(key, dict, new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(MainDataEnumCacheTimeSpan),
Size = dict.Count
});
return dict;
}
public async Task<UnifyPageResultDto<TrackOrderVO>> GetTrackOrderPagedList(GetPageTrackOrderInputVO input) public async Task<UnifyPageResultDto<TrackOrderVO>> GetTrackOrderPagedList(GetPageTrackOrderInputVO input)
{ {
//查询完去重 //查询完去重
var pageList = await Context.Queryable<OrderEntity>() UnifyPageResultDto<TrackOrderVO> pageList;
.Includes(a => a.OrderPlatformNumbers) //没传递单号时
if (input.OrderNos.IsNullOrEmpty())
{
pageList = await Context.Queryable<OrderEntity>()
.LeftJoin<VExternalSubjectEntity>((a, b) => a.CustomId == b.Id && b.IsDeleted == false)
.LeftJoin<VSystemEntity>((a, b, c) => a.SubSystemId == c.Id && c.IsDeleted == false)
.WhereIF(input.SubSystemId > 0, (a, b, c) => a.SubSystemId == input.SubSystemId)
.WhereIF(input.CreateTimeStart.HasValue && input.CreateTimeEnd.HasValue,
(a, b, c) => a.CreateTime >= input.CreateTimeStart && a.CreateTime <= input.CreateTimeEnd)
.WhereIF(input.CreateTimeStart.HasValue && (!input.CreateTimeEnd.HasValue),
(a, b, c) => a.CreateTime >= input.CreateTimeStart)
.WhereIF((!input.CreateTimeStart.HasValue) && input.CreateTimeEnd.HasValue,
(a, b, c) => a.CreateTime <= input.CreateTimeEnd)
.WhereIF(input.CustomerId > 0, (a, b, c) => a.CustomId == input.CustomerId)
.WhereIF(input.TrackOrderType > 0, (a, b, c) => a.OrderType == input.TrackOrderType)
.WhereIF(input.TabType > 0, (a, b, c) => a.QuestionType == input.TabType)
.WhereIF(input.TabType == (int) TrackProblemType.Warn, (a, b, c) => !a.IsCompleted)
.OrderByDescending((a, b, c) => a.CreateTime)
.Select((a, b, c) => new TrackOrderVO
{
Id = a.Id,
OrderNumber = a.OrderNo,
OrderType = a.OrderType,
QuestionType = a.QuestionType,
CustomerShortName = b.Abbreviation,
CustomerCode = b.Code,
CustomerId = a.CustomId,
NewestTrackContent = a.LatestTrackContent,
NewestTrackEnContent = a.LatestTrackEnContent,
NewestTrackPlace = a.LatestTrackPlace,
NewestTrackTime = a.LatestTrackTime,
IsFinish = a.IsCompleted,
CreateTime = a.CreateTime,
SubSystem = c.CnName,
SubSystemId = c.Id,
DestinationTimeZone = a.DestinationTimeZone,
EstimatedDeliveryDate = a.EstimatedDeliveryDate
})
.ToPagedListAsync(input.PageIndex, input.PageSize);
}
//传递单号时
else
{
var orderNos = input.OrderNos!.Distinct().ToList();
//匹配主单
var orderIds = await Context.Queryable<OrderEntity>()
.Where(x => orderNos.Contains(x.OrderNo))
.Select(x => x.Id)
.ToListAsync();
//匹配外部单
var orderIdsForThirdParty = await Context.Queryable<OrderPlatformNumberEntity>()
.Where(x => !string.IsNullOrWhiteSpace(x.OrderNumber) && orderNos.Contains(x.OrderNumber))
.Select(x => x.OrderId)
.ToListAsync();
var orderHashset = orderIds.ToHashSet();
orderHashset.UnionWith(orderIdsForThirdParty);
orderIds = orderHashset.ToList();
//没有任何单
if (orderIds.Count == 0)
{
return new UnifyPageResultDto<TrackOrderVO>
{
List = new List<TrackOrderVO>(),
Pagination = new PageInfoOutput()
{
PageIndex = input.PageIndex,
PageSize = input.PageSize,
Total = 0
}
};
}
pageList = await Context.Queryable<OrderEntity>()
.Where(x => orderIds.Contains(x.Id))
.LeftJoin<VExternalSubjectEntity>((a, b) => a.CustomId == b.Id && b.IsDeleted == false) .LeftJoin<VExternalSubjectEntity>((a, b) => a.CustomId == b.Id && b.IsDeleted == false)
.LeftJoin<VSystemEntity>((a, b, c) => a.SubSystemId == c.Id && c.IsDeleted == false) .LeftJoin<VSystemEntity>((a, b, c) => a.SubSystemId == c.Id && c.IsDeleted == false)
.LeftJoin<OrderPlatformNumberEntity>((a, b, c, d) => a.Id == d.OrderId && d.IsDeleted == false)
.WhereIF(input.SubSystemId > 0, (a, b, c) => a.SubSystemId == input.SubSystemId) .WhereIF(input.SubSystemId > 0, (a, b, c) => a.SubSystemId == input.SubSystemId)
.WhereIF(!input.OrderNos.IsNullOrEmpty(), (a, b, c, d) => input.OrderNos!.Contains(a.OrderNo) || input.OrderNos!.Contains(d.OrderNumber))
.WhereIF(input.CreateTimeStart.HasValue && input.CreateTimeEnd.HasValue, .WhereIF(input.CreateTimeStart.HasValue && input.CreateTimeEnd.HasValue,
(a, b, c) => a.CreateTime >= input.CreateTimeStart && a.CreateTime <= input.CreateTimeEnd) (a, b, c) => a.CreateTime >= input.CreateTimeStart && a.CreateTime <= input.CreateTimeEnd)
.WhereIF(input.CreateTimeStart.HasValue && (!input.CreateTimeEnd.HasValue), .WhereIF(input.CreateTimeStart.HasValue && (!input.CreateTimeEnd.HasValue),
@ -31,7 +194,6 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
.WhereIF(input.TabType > 0, (a, b, c) => a.QuestionType == input.TabType) .WhereIF(input.TabType > 0, (a, b, c) => a.QuestionType == input.TabType)
.WhereIF(input.TabType == (int) TrackProblemType.Warn, (a, b, c) => !a.IsCompleted) .WhereIF(input.TabType == (int) TrackProblemType.Warn, (a, b, c) => !a.IsCompleted)
.OrderByDescending((a, b, c) => a.CreateTime) .OrderByDescending((a, b, c) => a.CreateTime)
.Distinct()
.Select((a, b, c) => new TrackOrderVO .Select((a, b, c) => new TrackOrderVO
{ {
Id = a.Id, Id = a.Id,
@ -51,47 +213,35 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
SubSystemId = c.Id, SubSystemId = c.Id,
DestinationTimeZone = a.DestinationTimeZone, DestinationTimeZone = a.DestinationTimeZone,
EstimatedDeliveryDate = a.EstimatedDeliveryDate, EstimatedDeliveryDate = a.EstimatedDeliveryDate,
ThirdPartyOrderNumber = BuildThirdPartyOrderNumber(a.OrderPlatformNumbers)
}) })
.ToPagedListAsync(input.PageIndex, input.PageSize); .ToPagedListAsync(input.PageIndex, input.PageSize);
}
//查询订单类型描述
//补三方单号,从缓存中加速查
var orderIdArr = pageList.List.Select(x => x.Id).ToArray();
var thirdPartyOrderNumbers = await GetThirdPartyOrderNumberForCacheAsync(orderIdArr);
pageList.List.ForEach(x => x.ThirdPartyOrderNumber = thirdPartyOrderNumbers[x.Id]);
//查询订单类型描述,从缓存中加速查
var orderTypes = pageList.List.Select(x => x.OrderType).Distinct().ToList(); var orderTypes = pageList.List.Select(x => x.OrderType).Distinct().ToList();
var questTypes = pageList.List.Select(x => x.QuestionType).Distinct().ToList(); var questTypes = pageList.List.Select(x => x.QuestionType).Distinct().ToList();
//从主数据中心查询类型描述 var typeDisplayDict = await GetMainDataEnumForCacheAsync(orderTypes, questTypes);
var typeDispDict = (await Context.Queryable<VEnumValueInfoEntity>()
.Where(x =>
(x.Property == GlobalConst.MainDataKey_OrderType && orderTypes.Contains(x.Enumkey))
|| (x.Property == GlobalConst.MainDataKey_TrackQuestionType && questTypes.Contains(x.Enumkey))
)
.Select(x => new
{
x.Property,
x.Enumkey,
x.Disp
})
.ToListAsync()
)
.GroupBy(x => x.Property)
.ToDictionary(
g => g.Key,
y => y.ToDictionary(x => x.Enumkey, x => x.Disp)
);
//填充数描述信息 //填充数描述信息
pageList.List.ForEach(x => pageList.List.ForEach(x =>
{ {
x.OrderTypeName = typeDispDict.TryGetValue(GlobalConst.MainDataKey_OrderType, out var orderTypeDisplayDict) x.OrderTypeName = typeDisplayDict.TryGetValue(GlobalConst.MainDataKey_OrderType, out var orderTypeDisplayDict)
? orderTypeDisplayDict.TryGetValue(x.OrderType, out var orderTypeDisplay) ? orderTypeDisplayDict.TryGetValue(x.OrderType, out var orderTypeDisplay)
? orderTypeDisplay ? orderTypeDisplay
: $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_OrderType}] Enumkey:[{x.OrderType}]" : $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_OrderType}] "
: $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_OrderType}]"; : $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_OrderType}] EnumKey:[{x.OrderType}]";
x.QuestionTypeName = typeDispDict.TryGetValue(GlobalConst.MainDataKey_TrackQuestionType, out var questDisplayDict) x.QuestionTypeName = typeDisplayDict.TryGetValue(GlobalConst.MainDataKey_TrackQuestionType, out var questDisplayDict)
? questDisplayDict.TryGetValue(x.QuestionType, out var questDisplay) ? questDisplayDict.TryGetValue(x.QuestionType, out var questDisplay)
? questDisplay ? questDisplay
: $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_OrderType}] Enumkey:[{x.OrderType}]" : $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_OrderType}]"
: $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_TrackQuestionType}]"; : $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_TrackQuestionType}] EnumKey:[{x.OrderType}]";
}); });
return pageList; return pageList;
@ -275,10 +425,12 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
/// <returns></returns> /// <returns></returns>
private static string BuildThirdPartyOrderNumber(List<OrderPlatformNumberEntity> orderPlatformNumberEntities) private static string BuildThirdPartyOrderNumber(List<OrderPlatformNumberEntity> orderPlatformNumberEntities)
{ {
if (orderPlatformNumberEntities.Count == 0) return GlobalConst.EmptyString;
const string separator = "、"; const string separator = "、";
var thirdPartyOrderNumbers = orderPlatformNumberEntities var thirdPartyOrderNumbers = orderPlatformNumberEntities
.Where(x => !string.IsNullOrWhiteSpace(x.OrderNumber)) .Where(x => !string.IsNullOrWhiteSpace(x.OrderNumber))
.Select(x => $"{x.OrderNumber}({x.Platform})").ToList(); .Select(x => $"{x.OrderNumber}({x.Platform})")
.ToList();
return string.Join(separator, thirdPartyOrderNumbers); return string.Join(separator, thirdPartyOrderNumbers);
} }