fix:索引404

This commit is contained in:
xiaolipro 2026-10-08 15:38:29 +08:00
parent d21149a973
commit 9379c3bb1e
4 changed files with 122 additions and 42 deletions

View File

@ -9,38 +9,61 @@ namespace TrackCenter.Repository.ES;
/// </summary>
public static class EsExtensions
{
/// <summary>
/// 月度索引读请求:走 {index}-* 通配符,无匹配索引时返回空结果(首次部署 / 尚未创建别名)。
/// </summary>
public static SearchDescriptor<T> UseMonthlyIndex<T>(this SearchDescriptor<T> descriptor, string indexPrefix)
where T : class
{
return descriptor
.Index($"{indexPrefix}-*")
.IgnoreUnavailable()
.AllowNoIndices();
}
/// <summary>
/// 月度索引按查询更新:目标索引不存在时视为无匹配文档。
/// </summary>
public static UpdateByQueryDescriptor<T> UseMonthlyIndex<T>(this UpdateByQueryDescriptor<T> descriptor,
string indexPrefix)
where T : class
{
return descriptor
.Index($"{indexPrefix}-*")
.IgnoreUnavailable()
.AllowNoIndices();
}
/// <summary>
/// 月度索引按查询删除:目标索引不存在时视为无匹配文档。
/// </summary>
public static DeleteByQueryDescriptor<T> UseMonthlyIndex<T>(this DeleteByQueryDescriptor<T> descriptor,
string indexPrefix)
where T : class
{
return descriptor
.Index($"{indexPrefix}-*")
.IgnoreUnavailable()
.AllowNoIndices();
}
/// <summary>
/// 轨迹明细实际写入月度索引 track_details-yyyy.MM;读请求走通配符,
/// 无匹配索引时返回空结果(首次部署 / 尚未 Migrate 别名)。
/// </summary>
public static SearchDescriptor<T> UseTrackDetailsIndex<T>(this SearchDescriptor<T> descriptor) where T : class
{
return descriptor
.Index($"{GlobalConst.TrackDetailsIndex}-*")
.IgnoreUnavailable()
.AllowNoIndices();
}
=> descriptor.UseMonthlyIndex(GlobalConst.TrackDetailsIndex);
/// <summary>
/// 轨迹明细按查询更新:目标索引不存在时视为无匹配文档。
/// </summary>
public static UpdateByQueryDescriptor<T> UseTrackDetailsIndex<T>(this UpdateByQueryDescriptor<T> descriptor)
where T : class
{
return descriptor
.Index($"{GlobalConst.TrackDetailsIndex}-*")
.IgnoreUnavailable()
.AllowNoIndices();
}
=> descriptor.UseMonthlyIndex(GlobalConst.TrackDetailsIndex);
public static DeleteByQueryDescriptor<T> UseTrackDetailsIndex<T>(this DeleteByQueryDescriptor<T> descriptor)
where T : class
{
return descriptor
.Index($"{GlobalConst.TrackDetailsIndex}-*")
.IgnoreUnavailable()
.AllowNoIndices();
}
=> descriptor.UseMonthlyIndex(GlobalConst.TrackDetailsIndex);
/// <summary>
/// 索引/别名不存在(含 NEST 对 404 的包装错误)。

View File

@ -67,13 +67,21 @@ public class OrderOperationRecordEsRepository : ElasticSearchContextAbstract<Ord
public async Task<List<OrderOperationRecordIndex>> GetOrderOperationsByIdAsync(int orderId)
{
var data = await Context.SearchAsync<OrderOperationRecordIndex>(x => x
.Index(GlobalConst.OrderOperationRecordIndex)
.UseMonthlyIndex(GlobalConst.OrderOperationRecordIndex)
.Query(q =>
q.Term(t => t.OrderId, orderId)
)
.Size(GlobalConst.NormalLimit)
.Sort(s => s.Field(f => f.CreateTime, SortOrder.Descending)));
if (!data.IsValid)
{
if (data.IsIndexUnavailable())
return [];
throw new InvalidOperationException($"订单操作记录查询失败,原因:{data.DebugInformation}。");
}
return data.ToIdList();
}
}

View File

@ -69,13 +69,21 @@ public class TrackPushRecordEsRepository : ElasticSearchContextAbstract<TrackPus
public async Task<List<TrackPushRecordIndex>> GetTrackPushRecordsAsync(int orderId)
{
var data = await Context.SearchAsync<TrackPushRecordIndex>(x => x
.Index(GlobalConst.TrackPushRecordIndex)
.UseMonthlyIndex(GlobalConst.TrackPushRecordIndex)
.Query(q =>
q.Term(t => t.OrderId, orderId)
)
.Size(1000)
.Sort(s => s.Field(f => f.CreateTime, SortOrder.Descending)));
if (!data.IsValid)
{
if (data.IsIndexUnavailable())
return [];
throw new InvalidOperationException($"轨迹推送记录查询失败,原因:{data.DebugInformation}。");
}
return data.ToIdList();
}
@ -114,7 +122,7 @@ public class TrackPushRecordEsRepository : ElasticSearchContextAbstract<TrackPus
if (isShouldQuery)
{
r = await Context.SearchAsync<TrackPushRecordIndex>(x => x
.Index(GlobalConst.TrackPushRecordIndex)
.UseMonthlyIndex(GlobalConst.TrackPushRecordIndex)
.Query(q => q.Bool(b => b
.Must(mu => mu.Terms(t => t.Field(f => f.IsSuccess).Terms(input.IsSuccess)))
.Should(musts)
@ -126,7 +134,7 @@ public class TrackPushRecordEsRepository : ElasticSearchContextAbstract<TrackPus
{
musts.Add(mu => mu.Terms(t => t.Field(f => f.IsSuccess).Terms(input.IsSuccess)));
r = await Context.SearchAsync<TrackPushRecordIndex>(x => x
.Index(GlobalConst.TrackPushRecordIndex)
.UseMonthlyIndex(GlobalConst.TrackPushRecordIndex)
.Query(q => q.Bool(b => b
.Must(musts))
)
@ -136,6 +144,9 @@ public class TrackPushRecordEsRepository : ElasticSearchContextAbstract<TrackPus
if (!r.IsValid)
{
if (r.IsIndexUnavailable())
return [];
throw new InvalidOperationException($"轨迹推送记录查询失败,原因:{r.DebugInformation}。");
}
@ -153,7 +164,7 @@ public class TrackPushRecordEsRepository : ElasticSearchContextAbstract<TrackPus
musts.Add(mu => mu.Term(t => t.IsSuccess, true));
var data = await Context.SearchAsync<TrackPushRecordIndex>(x => x
.Index(GlobalConst.TrackPushRecordIndex)
.UseMonthlyIndex(GlobalConst.TrackPushRecordIndex)
.Query(q =>
q.Bool(b =>
b.Must(musts))
@ -161,13 +172,21 @@ public class TrackPushRecordEsRepository : ElasticSearchContextAbstract<TrackPus
.Size(1000)
.Sort(s => s.Field(f => f.CreateTime, SortOrder.Descending)));
if (!data.IsValid)
{
if (data.IsIndexUnavailable())
return null;
throw new InvalidOperationException($"轨迹推送记录查询失败,原因:{data.DebugInformation}。");
}
return data.Documents.FirstOrDefault();
}
public async Task<List<TrackPushRecordIndex>> GetHistorySuccessTrackPushRecordAsync(int orderId)
{
var data = await Context.SearchAsync<TrackPushRecordIndex>(x => x
.Index(GlobalConst.TrackPushRecordIndex)
.UseMonthlyIndex(GlobalConst.TrackPushRecordIndex)
.Source(s =>
s.Excludes(fs =>
fs.Field(f => f.PushContent)))
@ -179,6 +198,15 @@ public class TrackPushRecordEsRepository : ElasticSearchContextAbstract<TrackPus
)
.Size(1000)
.Sort(s => s.Field(f => f.CreateTime, SortOrder.Descending)));
if (!data.IsValid)
{
if (data.IsIndexUnavailable())
return [];
throw new InvalidOperationException($"轨迹推送记录查询失败,原因:{data.DebugInformation}。");
}
return data.ToIdList();
}
}

View File

@ -50,7 +50,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
c => c.Match(f => f.Field(d => d.NotifyUsers).Query(input.NotifyUserId)));
var r = await _client.SearchAsync<TransportWarningDetailsIndex>(x => x
.Index(GlobalConst.TransportWarningDetailsIndex)
.UseMonthlyIndex(GlobalConst.TransportWarningDetailsIndex)
.Query(q => q.Bool(b => b.Must(musts)))
.Sort(s => s.Ascending(f => f.Status).Descending(f => f.CreateTime))
.From((input.PageIndex - 1) * input.PageSize)
@ -60,6 +60,9 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
if (!r.IsValid)
{
if (r.IsIndexUnavailable())
return new PagedResult<TransportWarningDetailsIndex>(0, []);
throw new InvalidOperationException($"运输预警明细查询失败,原因:{r.DebugInformation}。");
}
@ -116,7 +119,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
if (isShouldQuery)
{
r = await _client.SearchAsync<TransportWarningDetailsIndex>(x => x
.Index(GlobalConst.TransportWarningDetailsIndex)
.UseMonthlyIndex(GlobalConst.TransportWarningDetailsIndex)
.Query(q => q.Bool(b => b
.Must(mu => mu.Terms(t => t.Field(f => f.Status).Terms(input.Status)))
.Should(musts)
@ -128,7 +131,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
{
musts.Add(mu => mu.Terms(t => t.Field(f => f.Status).Terms(input.Status)));
r = await _client.SearchAsync<TransportWarningDetailsIndex>(x => x
.Index(GlobalConst.TransportWarningDetailsIndex)
.UseMonthlyIndex(GlobalConst.TransportWarningDetailsIndex)
.Query(q => q.Bool(b => b.Must(musts)))
.Size(SafelyLimit)
);
@ -136,6 +139,9 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
if (!r.IsValid)
{
if (r.IsIndexUnavailable())
return [];
throw new InvalidOperationException($"运输预警明细查询失败,原因:{r.DebugInformation}。");
}
@ -294,7 +300,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
musts.AddIf(x => x.HasOrderIds, c => c.Terms(t => t.Field(f => f.OrderId).Terms(input.OrderIds)));
var r = await _client.UpdateByQueryAsync<TransportWarningDetailsIndex>(u =>
u.Index(GlobalConst.TransportWarningDetailsIndex)
u.UseMonthlyIndex(GlobalConst.TransportWarningDetailsIndex)
.Query(q => q.Bool(b => b.Must(musts)))
.Script(s => s
.Source(@"ctx._source.status = params.status;
@ -310,7 +316,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
)
);
if (!r.IsValid)
if (!r.IsValid && !r.IsIndexUnavailable())
{
throw new InvalidOperationException(
$"运输时效预警明细更新失败,input:{input.ToJson()},原因:{r.DebugInformation}。");
@ -387,7 +393,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
c => c.Match(f => f.Field(d => d.Customer).Query(input.Customer)));
var r = await _client.SearchAsync<ReturnWarningDetailsIndex>(x => x
.Index(GlobalConst.ReturnWarningDetailsIndex)
.UseMonthlyIndex(GlobalConst.ReturnWarningDetailsIndex)
.Query(q => q.Bool(b => b.Must(musts)))
.Sort(s => s.Ascending(f => f.Status).Descending(f => f.CreateTime))
.From((input.PageIndex - 1) * input.PageSize)
@ -397,6 +403,9 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
if (!r.IsValid)
{
if (r.IsIndexUnavailable())
return new PagedResult<ReturnWarningDetailsIndex>(0, []);
throw new InvalidOperationException($"回传预警明细查询失败,原因:{r.DebugInformation}。");
}
@ -442,7 +451,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
if (isShouldQuery)
{
r = await _client.SearchAsync<ReturnWarningDetailsIndex>(x => x
.Index(GlobalConst.ReturnWarningDetailsIndex)
.UseMonthlyIndex(GlobalConst.ReturnWarningDetailsIndex)
.Query(q => q.Bool(b => b
.Must(mu => mu.Terms(t => t.Field(f => f.Status).Terms(input.Status)))
.Should(musts)
@ -454,7 +463,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
{
musts.Add(c => c.Terms(t => t.Field(f => f.Status).Terms(input.Status)));
r = await _client.SearchAsync<ReturnWarningDetailsIndex>(x => x
.Index(GlobalConst.ReturnWarningDetailsIndex)
.UseMonthlyIndex(GlobalConst.ReturnWarningDetailsIndex)
.Query(q => q.Bool(b => b
.Must(musts)
))
@ -464,6 +473,9 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
if (!r.IsValid)
{
if (r.IsIndexUnavailable())
return [];
throw new InvalidOperationException($"回传预警明细查询失败,原因:{r.DebugInformation}。");
}
@ -473,13 +485,16 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
public async Task<List<ReturnMessageRecordIndex>> GetReturnMessageRecordListByIdAsync(string esId)
{
var r = await _client.SearchAsync<ReturnMessageRecordIndex>(x => x
.Index(GlobalConst.ReturnMessageRecordIndex)
.UseMonthlyIndex(GlobalConst.ReturnMessageRecordIndex)
.Query(q => q.Match(f => f.Field(d => d.WarningDetailsIds).Query(esId)))
.Size(SafelyLimit)
);
if (!r.IsValid)
{
if (r.IsIndexUnavailable())
return [];
throw new InvalidOperationException($"回传预警明细查询失败,原因:{r.DebugInformation}。");
}
@ -489,13 +504,13 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
public async Task ReturnWarningDetailsRetryIncrementAsync(HashSet<string> esIds)
{
var r = await _client.UpdateByQueryAsync<ReturnWarningDetailsIndex>(u =>
u.Index(GlobalConst.ReturnWarningDetailsIndex)
u.UseMonthlyIndex(GlobalConst.ReturnWarningDetailsIndex)
.Query(q => q.Ids(i => i.Values(esIds)))
.Script(s => s
.Source("ctx._source.retryCount = ctx._source.retryCount+1;")
)
);
if (!r.IsValid)
if (!r.IsValid && !r.IsIndexUnavailable())
{
throw new InvalidOperationException($"回传预警明细更新失败,原因:{r.DebugInformation}。");
}
@ -661,7 +676,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
musts.AddIf(x => x.HasOrderIds, c => c.Terms(t => t.Field(f => f.OrderId).Terms(input.OrderIds)));
var r = await _client.UpdateByQueryAsync<ReturnWarningDetailsIndex>(u =>
u.Index(GlobalConst.ReturnWarningDetailsIndex)
u.UseMonthlyIndex(GlobalConst.ReturnWarningDetailsIndex)
.Query(q => q.Bool(b => b.Must(musts)))
.Script(s => s
.Source("ctx._source.status = params.status")
@ -669,7 +684,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
)
);
if (!r.IsValid)
if (!r.IsValid && !r.IsIndexUnavailable())
{
throw new InvalidOperationException(
$"回传预警明细更新失败,input:{input.ToJson()},原因:{r.DebugInformation}。");
@ -766,7 +781,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
.Params(p => p.Add("value", input.MissingTrackStatusId.ToString())))));
var r = await _client.SearchAsync<CompleteWarningDetailsIndex>(x => x
.Index(GlobalConst.CompleteWarningDetailsIndex)
.UseMonthlyIndex(GlobalConst.CompleteWarningDetailsIndex)
.Query(q => q.Bool(b => b.Must(musts)))
.Sort(s => s.Ascending(f => f.Status).Descending(f => f.CreateTime))
.From((input.PageIndex - 1) * input.PageSize)
@ -776,6 +791,9 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
if (!r.IsValid)
{
if (r.IsIndexUnavailable())
return new PagedResult<CompleteWarningDetailsIndex>(0, []);
throw new InvalidOperationException($"回传预警明细查询失败,原因:{r.DebugInformation}。");
}
@ -830,7 +848,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
if (isShouldQuery)
{
r = await _client.SearchAsync<CompleteWarningDetailsIndex>(x => x
.Index(GlobalConst.CompleteWarningDetailsIndex)
.UseMonthlyIndex(GlobalConst.CompleteWarningDetailsIndex)
.Query(q => q.Bool(b => b
.Must(mu => mu.Terms(t => t.Field(f => f.Status).Terms(input.Status)))
.Should(musts)
@ -842,7 +860,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
{
musts.Add(c => c.Terms(t => t.Field(f => f.Status).Terms(input.Status)));
r = await _client.SearchAsync<CompleteWarningDetailsIndex>(x => x
.Index(GlobalConst.CompleteWarningDetailsIndex)
.UseMonthlyIndex(GlobalConst.CompleteWarningDetailsIndex)
.Query(q => q.Bool(b => b
.Must(musts)
))
@ -852,6 +870,9 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
if (!r.IsValid)
{
if (r.IsIndexUnavailable())
return [];
throw new InvalidOperationException($"完整预警明细查询失败,原因:{r.DebugInformation}。");
}
@ -872,7 +893,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
musts.AddIf(x => x.HasOrderIds, c => c.Terms(t => t.Field(f => f.OrderId).Terms(input.OrderIds)));
var r = await _client.UpdateByQueryAsync<CompleteWarningDetailsIndex>(u =>
u.Index(GlobalConst.CompleteWarningDetailsIndex)
u.UseMonthlyIndex(GlobalConst.CompleteWarningDetailsIndex)
.Query(q => q.Bool(b => b.Must(musts)))
.Script(s => s
.Source(@"
@ -886,7 +907,7 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
)
);
if (!r.IsValid)
if (!r.IsValid && !r.IsIndexUnavailable())
{
throw new InvalidOperationException(
$"完整预警明细更新失败,input:{input.ToJson()},原因:{r.DebugInformation}。");