任务描述
需求描述
需求背景:数据归档,解决存储问题,提高性能
需求实现:
替换掉之前根据在售报告判断逻辑,减少业务表数据量以提高性能,及磁盘空间合理分配使用。
Listing打标表:Amazon_MarkListing.MarkListing_N
Listing属性表:Amazon_AutoPublish.AmazonListingInfo_N
1、遍历“Listing打标表”的下架记录,在“Listing删除记录表”(Amazon_MarkListing.DeletedListing_N)判断Listing是否存在,如果删除记录存在且删除时间超过一个月,则将该Listing归档到现有“Listing归档表”(Amazon_Archive.MarkListing_N)
2、遍历“Listing属性表”,如果Listing不是母体则从“Listing打标表”查询Listing是否下架,如果已下架且记录存在于“Listing删除记录表”(Amazon_MarkListing.DeletedListing_N)中的删除时间超过一个月,则归档到现有“Listing属性归档表”(Amazon_Archive.AmazonListingInfo);如果是母体,判断母体是否在“删除Listing队列表”(ES索引库:aq_amazonqueuedelete_n)中,如果母体已删除则归档到现有“Listing属性归档表”(Amazon_Archive.AmazonListingInfo)
验收标准
暂无
1 Listing打标表归档
添加同步配置
string strDicMaxId = _hotColdDictionaryService.GetDictionaryValue<string>(typeName);
涉及的表:
原始表:Amazon_MarkListing.MarkListing_N
备份表:Amazon_Archive.MarkListing_N
验证逻辑表:Amazon_MarkListing.DeletedListing_N
自测结果:
逻辑代码:
/// <summary>
/// 通过DeletedListing_N表是否存在记录归档
/// </summary>
/// <param name="cancellation"></param>
/// <returns></returns>
public async Task ArchiveByMarkListingAsync(string siteCode, CancellationToken cancellation)
{
int limit = 500;
//备份表
string archiveTbName = _markListing_N_Archive_MgoRepository.GetCollName(siteCode);
//备份源表
string sourceTbName = _mgo.GetCollName(siteCode);
//业务类型
string typeName = $"MarkListing_N_{nameof(ArchiveByMarkListingAsync)}:{siteCode}";
//当前事件
var eventId = new EventId(0, nameof(ArchiveByMarkListingAsync));
while (!cancellation.IsCancellationRequested)
{
try
{
//获取截止上一次同步结果
var maxMongoId = ObjectId.Empty;
string strDicMaxId = _hotColdDictionaryService.GetDictionaryValue<string>(typeName);
if (!string.IsNullOrEmpty(strDicMaxId))
{
maxMongoId = ObjectId.Parse(strDicMaxId);
}
//获取MarkListing_N表的数据
List<MarkListing_N> list = await _mgo.GetMarkListingListAsync(siteCode, limit, maxMongoId);
//无数据跳出循环
if (list.Count() <= 0)
{
break;
}
//获取当前批次的最大id
maxMongoId = list.Max(a => a.ID);
//判断DeletedListing_N表中是否存在一个月前的数据
var dataList = list.Select(o => new MarkListingOrListingInfoViewModel { OrderSourceId = o.OrderSourceId, OrderSourceSku = o.OrderSourceSKU }).ToList();
List<DeletedListing_N> deletedListingList = await _deletedListingNMgoRepository.GetDeletedListingListAsync(siteCode, dataList);
//获取已经存在的数据==>需要归档的数据
List<MarkListing_N> archiveData = list.Where(o => deletedListingList.Any(t => t.OrderSourceId == o.OrderSourceId && t.OrderSourceSku == o.OrderSourceSKU)).ToList();
//没有需要归档的数据
if (archiveData?.Count() <= 0)
{
//保存状态
_hotColdDictionaryService.Save(new HotColdDictionary()
{
TypeName = typeName,
Value = BsonString.Create(maxMongoId.ToString()),
UpdateTime = DateTime.Now
});
continue;
}
//归档==>将数据插入到MarkListing_N 并删除 MarkListing_N的数据
var clearIds = archiveData.Select(o => o.ID).ToList();
var isSucc = await _markListing_N_Archive_MgoRepository.SaveAsync(archiveData, archiveTbName);
if (isSucc)
{
//从打标表移除
await _mgo.GetCollection(sourceTbName).DeleteManyAsync(f => clearIds.Contains(f.ID));
}
//保存状态
_hotColdDictionaryService.Save(new HotColdDictionary()
{
TypeName = typeName,
Value = BsonString.Create(maxMongoId.ToString()),
UpdateTime = DateTime.Now
});
}
catch (Exception ex)
{
_logger.LogInformation(eventId, $"{ex.StackTrace}");
throw;
}
}
}
/// <summary>
/// 根据站点,状态获取打标签表的数据
/// </summary>
/// <param name="siteCode"></param>
/// <param name="skus"></param>
/// <returns></returns>
public async Task<List<MarkListing_N>> GetMarkListingListAsync(string siteCode, int limit, ObjectId maxId)
{
try
{
if (string.IsNullOrEmpty(siteCode))
{
return new List<MarkListing_N>();
}
var collName = GetCollName(siteCode);
var filter = this.GetFilter();
var where = this.GetWhere();
where.Add(filter.Eq(a => a.ListingStatus, AmazonListingStatus.下架));
var sort = Builders<MarkListing_N>.Sort.Ascending(o => o.ID);
if (!maxId.Equals(ObjectId.Empty))
{
where.Add(filter.Gt(f => f.ID, maxId));
}
return await FindListAsync(filter.And(where), limit, sort, null, null, GetCollName(siteCode));
}
catch (Exception ex)
{
return new List<MarkListing_N>();
}
}
2 Listing属性表归档
添加同步配置
string strDicMaxId = _hotColdDictionaryService.GetDictionaryValue<string>(typeName);
涉及的表:
原始表:Amazon_AutoPublish.AmazonListingInfo_N
备份表:Amazon_Archive.AmazonListingInfo
验证逻辑表:Amazon_MarkListing.MarkListing_N,Amazon_MarkListing.DeletedListing_N,aq_amazonqueuedelete_n
自测结果:
逻辑代码:
/// <summary>
/// 通过DeletedListing_N表是否存在记录归档
/// </summary>
/// <param name="cancellation"></param>
/// <returns></returns>
public async Task ArchiveByListingInfoAsync(string siteCode, CancellationToken cancellation)
{
int limit = 500;
//备份表
string archiveTbName = _amazonListingInfoNArchiveMgoRepository.GetCollName(siteCode);
//备份源表
string sourceTbName = _amazonListingInfoMgo_N_Repository.GetCollName(siteCode);
//业务类型
string typeName = $"ListingInfo_N_{nameof(ArchiveByListingInfoAsync)}:{siteCode}";
//当前事件
var eventId = new EventId(0, nameof(ArchiveByListingInfoAsync));
while (true)
{
try
{
//获取截止上一次同步结果
var maxMongoId = ObjectId.Empty;
var strDicMaxId = _hotColdDictionaryService.GetDictionaryValue<string>(typeName);
if (!string.IsNullOrEmpty(strDicMaxId))
{
maxMongoId = ObjectId.Parse(strDicMaxId);
}
//获取AmazonListingInfo_N表的数据
List<AmazonListingInfo_N> list = await _amazonListingInfoMgo_N_Repository.GetListingInfoListAsync(siteCode, limit, maxMongoId);
//无数据跳出循环
if (list.Count() <= 0)
{
break;
}
//获取当前批次的最大id
maxMongoId = list.Max(a => a.ID);
//将数据分为母体和非母体
List<AmazonListingInfo_N> NotParentProductList = list.Where(o => o.IsParentProduct == false).ToList();
List<AmazonListingInfo_N> ParentProductList = list.Where(o => o.IsParentProduct != false).ToList();
List<int> ints = new List<int>() { 0, 1 };
foreach (var item in ints)
{
//需要归档的数据
List<AmazonListingInfo_N> archiveData = new List<AmazonListingInfo_N>();
switch (item)
{
case 0:
#region 非母体处理逻辑
if (NotParentProductList?.Count() <= 0)
{
break;
}
//查询Listing打标表是否下架
List<MarkListing_N> MarkListingList = await _markListing_N_MgoRepository.GetMarkListingListByStatusAsync(siteCode, NotParentProductList);
if (MarkListingList?.Count() <= 0)
{
break;
}
List<MarkListingOrListingInfoViewModel> MarkListingDataList = MarkListingList.Select(o => new MarkListingOrListingInfoViewModel { OrderSourceId = o.OrderSourceId, OrderSourceSku = o.OrderSourceSKU }).ToList();
//判断Listing删除记录表是否存在大于30天的数据
List<DeletedListing_N> HavData = await _deletedListingNMgoRepository.GetDeletedListingListAsync(siteCode, MarkListingDataList);
if (HavData?.Count() <= 0)
{
break;
}
//需要归档的数据
archiveData = NotParentProductList.Where(o => HavData.Any(t => t.OrderSourceId == o.OrderSourceID && t.OrderSourceSku == o.OrderSourceSKU)).ToList();
#endregion
break;
case 1:
#region 母体处理逻辑
if (ParentProductList?.Count() <= 0)
{
break;
}
List<MarkListingOrListingInfoViewModel> dataList = ParentProductList.Select(o => new MarkListingOrListingInfoViewModel { OrderSourceId = o.OrderSourceID, OrderSourceSku = o.OrderSourceSKU }).ToList();
List<MarkListingOrListingInfoViewModel> dataListES = GetDeleteQueue(dataList);
if (dataListES?.Count() <= 0)
{
break;
}
//需要归档的数据
archiveData = ParentProductList.Where(o => dataListES.Any(t => t.OrderSourceId == o.OrderSourceID && t.OrderSourceSku == o.OrderSourceSKU)).ToList();
#endregion
break;
default:
break;
}
#region 归档
if (archiveData?.Count() <= 0)
{
continue;
}
//归档==>将数据插入到AmazonListingInfo 并删除 Amazon_AutoPublish.AmazonListingInfo_N的数据
var clearIds = archiveData.Select(o => o.ID).ToList();
var isSucc = await _amazonListingInfoNArchiveMgoRepository.SaveAsync(archiveData, archiveTbName);
if (isSucc)
{
//从打标表移除
await _amazonListingInfoMgo_N_Repository.GetCollection(sourceTbName).DeleteManyAsync(f => clearIds.Contains(f.ID));
}
#endregion
}
//保存状态
_hotColdDictionaryService.Save(new HotColdDictionary()
{
TypeName = typeName,
Value = BsonString.Create(maxMongoId.ToString()),
UpdateTime = DateTime.Now
});
}
catch (Exception ex)
{
_logger.LogInformation(eventId, $"{ex.StackTrace}");
throw;
}
}
}
/// <summary>
/// 查询指定状态的数据
/// </summary>
/// <param name="siteCode"></param>
/// <param name="limit"></param>
/// <param name="maxId"></param>
/// <returns></returns>
public async Task<List<MarkListing_N>> GetMarkListingListByStatusAsync(string siteCode, List<AmazonListingInfo_N> list)
{
try
{
if (string.IsNullOrEmpty(siteCode))
{
return new List<MarkListing_N>();
}
var projection = Builders<MarkListing_N>.Projection;
var returnFields = projection.Include(t => t.OrderSourceId).Include(o => o.OrderSourceSKUID);
var filter = Builders<MarkListing_N>.Filter;
var fd = filter.Eq(o => o.ListingStatus, AmazonListingStatus.下架);
var listFilter = filter.And(list.Select(item =>
filter.And(
filter.Eq(t => t.OrderSourceId, item.OrderSourceID),
filter.Eq(t => t.OrderSourceSKU, item.OrderSourceSKU)
)).ToArray());
return await FindListAsync(filter.And(fd, listFilter), GetCollName(siteCode));
}
catch (Exception ex)
{
return new List<MarkListing_N>();
}
}
/// <summary>
/// 根据MarkListing_N表中的OrderSourceId,OrderSourceSku,DeletedUpdateTime 判断DeletedListing_N表中是否存在
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public async Task<List<DeletedListing_N>> GetDeletedListingListAsync(string siteCode, List<MarkListingOrListingInfoViewModel> list)
{
try
{
if (string.IsNullOrEmpty(siteCode))
{
return new List<DeletedListing_N>();
}
var projection = Builders<DeletedListing_N>.Projection;
var returnFields = projection.Include(t => t.OrderSourceId).Include(o => o.OrderSourceSku);
var filter = Builders<DeletedListing_N>.Filter;
var deletedUpdateTime = DateTime.Now.AddDays(-30);
var fd = filter.Lt(o => o.DeletedUpdateTime, deletedUpdateTime);
var listFilter = filter.And(list.Select(item =>
filter.And(
filter.Eq(t => t.OrderSourceId, item.OrderSourceId),
filter.Eq(t => t.OrderSourceSku, item.OrderSourceSku)
)).ToArray());
return await FindListAsync(filter.And(fd, listFilter), GetCollName(siteCode));
}
catch (Exception ex)
{
return new List<DeletedListing_N>();
}
}
/// <summary>
/// 根据OrderSourceId,OrderSourceSku 查询数据是否存在
/// </summary>
/// <param name="amazonQueueDeleteSearchViewModels"></param>
/// <returns></returns>
public async Task<List<Aq_AmazonQueueDelete>> GetDeleteQueue(List<AmazonQueueDeleteSearchViewModel> amazonQueueDeleteSearchViewModels)
{
var indexName = GetIndexName();
var response = await EsClient.SearchAsync<Aq_AmazonQueueDelete>(s =>
{
s.Index(indexName);
s.From(0).Size(1000);
s.Sort(x => x.Ascending(m => m.AddTime));
s.Query(a => a.Bool(b =>
{
var musts = new List<Func<QueryContainerDescriptor<Aq_AmazonQueueDelete>, QueryContainer>>();
musts.Add(a => a.Terms(b => b.Field(c => c.OrderSourceId).Terms(amazonQueueDeleteSearchViewModels.Select(o => o.OrderSourceId).ToList())));
musts.Add(a => a.Terms(b => b.Field(c => c.OrderSourceSku).Terms(amazonQueueDeleteSearchViewModels.Select(o => o.OrderSourceSku).ToList())));
b.Must(musts);
return b;
}));
return s;
});
return response.Documents.ToList();
}