Я заметил странную вещь в поведении свойства ISearchResponse.HitsMetadata.Total в библиотеке NEST.Всякий раз, когда я удаляю документ асинхронно и хочу немедленно извлечь оставшиеся документы из Elasticsearch, поле HitsMetadata.Total, доступное для объекта ISearchResponse, почти никогда не обновляется корректно.Обычно он указывает общее количество документов на момент, предшествующий операции удаления.Поведение возвращается к нормальному состоянию, когда я приостанавливаю выполнение запроса, по крайней мере, на 700 миллисекунд, как если бы NEST (или, возможно, сам Elasticsearch) требовалось больше времени для обновления состояния свойства.Я новичок в использовании NEST и Elasticsearch, поэтому возможно, что я делаю что-то здесь не так, или я не совсем понимаю работу библиотеки, но я потратил довольно много времени на эту проблему и не могу понятьвокруг него.В результате метаданные пагинации, которые я отправляю клиенту, вычисляются неправильно.Я использую NEST 6.6.0 и Elasticsearch 6.6.2.
Действие DELETE:
[HttpDelete("errors/{index}/{logeventId}")]
public async Task<IActionResult> DeleteErrorLog([FromRoute] string index, [FromRoute] string logeventId)
{
if (string.IsNullOrEmpty(index))
{
return BadRequest();
}
if (string.IsNullOrEmpty(logeventId))
{
return BadRequest();
}
var getResponse = await _client.GetAsync<Logevent>(new GetRequest(index, typeof(Logevent), logeventId));
if(!getResponse.Found)
{
return NotFound();
}
var deleteResponse = await _client.DeleteAsync(new DeleteRequest(index, typeof(Logevent), logeventId));
if (!deleteResponse.IsValid)
{
throw new Exception($"Deleting document id {logeventId} failed");
}
return NoContent();
}
Действие GET:
[HttpGet("errors/{index}", Name = "GetErrors")]
public async Task<IActionResult> GetErrorLogs([FromRoute] string index,
[FromQuery]int pageNumber = 1, [FromQuery] int pageSize = 5)
{
if (string.IsNullOrEmpty(index))
{
return BadRequest();
}
if(pageSize > MAX_PAGE_SIZE || pageSize < 1)
{
pageSize = 5;
}
if(pageNumber < 1)
{
pageNumber = 1;
}
var from = (pageNumber - 1) * pageSize;
ISearchResponse<Logevent> searchResponse = await GetSearchResponse(index, from, pageSize);
if (searchResponse.Hits.Count == 0)
{
return NotFound();
}
int totalPages = GetTotalPages(searchResponse, pageSize);
var previousPageLink = pageNumber > 1 ?
CreateGetLogsForIndexResourceUri(ResourceUriType.PreviousPage, pageNumber, pageSize, "GetErrors") : null;
var nextPageLink = pageNumber < totalPages ?
CreateGetLogsForIndexResourceUri(ResourceUriType.NextPage, pageNumber, pageSize, "GetErrors") : null;
/* HERE, WHEN EXECUTED IMMMEDIATELY (UP TO 700 MILISSECONDS, THE
totalCount FIELD GETS MISCALCULATED AS IT RETURNS THE VALUE PRECEDING
THE DELETION OF A DOCUMENT
*/
var totalCount = searchResponse.HitsMetadata.Total;
var count = searchResponse.Hits.Count;
var paginationMetadata = new
{
totalCount = searchResponse.HitsMetadata.Total,
totalPages,
pageSize,
currentPage = pageNumber,
previousPageLink,
nextPageLink
};
Response.Headers.Add("X-Pagination", Newtonsoft.Json.JsonConvert.SerializeObject(paginationMetadata));
var logeventsDtos = Mapper.Map<IEnumerable<LogeventDto>>(searchResponse.Hits);
return Ok(logeventsDtos);
}
GetSearchResponseMethod:
private async Task<ISearchResponse<Logevent>> GetSearchResponse(string index, int from, int pageSize)
{
return await _client.SearchAsync<Logevent>(s =>
s.Index(index).From(from).Size(pageSize).Query(q => q.MatchAll()));
}
Код на стороне клиента, инициирующий действия на стороне сервера:
async deleteLogevent(item){
this.deleteDialog = false;
let logeventId = item.logeventId;
let level = this.defaultSelected.name;
let index = 'logstash'.concat('-', this.defaultSelected.value, '-', this.date);
LogsService.deleteLogevent(level, index, logeventId).then(response => {
if(response.status == 204){
let logeventIndex = this.logs.findIndex(element => {return element.logeventId === item.logeventId});
this.logs.splice(logeventIndex, 1);
LogsService.getLogs(level, index, this.pageNumber).then(reloadResponse => {
this.logs.splice(0);
reloadResponse.data.forEach(element => {
this.logs.push(element)
});
this.setPaginationMetadata(reloadResponse.headers["x-pagination"]);
})
}
}).catch(error => {
})