Как получить результат Elasticsearch, такой же, как у кибаны или почтальона, как и у остальных клиентов в агрегированном запросе NEST term c# - PullRequest
0 голосов
/ 31 марта 2020

kibana dev-tool

GET gltrans/_search?size=0
{
  "aggs": {
    "code": {
      "terms": {
        "field": "code.keyword"
      },
      "aggs": {
       "total":  {
          "sum": {
             "field": "tot"
          }
       }
      }
    }
  }
}

return

 "buckets" : [
        {
          "key" : "0220",
          "doc_count" : 30182,
          "total" : {
            "value" : 169779.83551708516
          }
        },
        {
          "key" : "3000",
          "doc_count" : 20360,
          "total" : {
            "value" : -477618.27972452715
          }
        },................

nest query

var result = _connectionToEs.EsClient().Search<gltrans>(s => s.Size(0)
    .Aggregations(a => a
        .Terms("code", st => st
            .Field(o => o.code.Suffix("keyword"))
            .Size(10)
            .Aggregations(aa => aa
                .Sum("total", m => m
                    .Field(o => o.tot))))));

return без «ключа» как получить ключ?

 "Items": [
        {
          "tot": {
            "Value": 169779.83551708516,
            "ValueAsString": null,
            "Meta": null
          }
        },
        {
          "tot": {
            "Value": -477618.27972452715,
            "ValueAsString": null,
            "Meta": null
          }
        },

1 Ответ

1 голос
/ 02 апреля 2020

Ключ можно получить из ответа

var result = _connectionToEs.EsClient().Search<gltrans>(s => s.Size(0)
    .Aggregations(a => a
        .Terms("code", st => st
            .Field(o => o.code.Suffix("keyword"))
            .Size(10)
            .Aggregations(aa => aa
                .Sum("total", m => m
                    .Field(o => o.tot))))));

var termsAgg = result.Aggregations.Terms("code");

foreach(var bucket in termsAgg.Buckets)
{
    // get the key
    var key = bucket.Key;

    // get the sum aggregation for this bucket
    var sumAgg = bucket.Sum("total");       
}

Взгляните на документы по обработке ответов агрегации .

JSON, которые вы ' Выложенное сообщение выглядит как результат сериализации SearchResponse<T> с другим JSON сериализатором, таким как JSON. NET. Это не будет работать так, как ожидалось, поскольку

  1. SearchResponse<T> не был предназначен для повторной сериализации, только для того, чтобы быть материализованным путем десериализации ответа Elasticsearch JSON
  2. Если SearchResponse<T> предназначен для повторной сериализации, он, вероятно, не будет работать с любым другим сериализатором, кроме сериализатора клиента, потому что для типов может потребоваться спецификация c подпрограмм сериализации.

Если вы хотите отправить дословный ответ от Elasticsearch до вызывающего абонента, есть несколько вариантов:

1. Захватите байты ответа с помощью DisableDirectStreaming() и отправьте их вызывающей стороне

Либо на основе запроса

var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(pool).DefaultIndex("gltrans");
var client = new ElasticClient(settings);

var searchResponse = client.Search<gltrans>(s => s
    .RequestConfiguration(r => r
        .DisableDirectStreaming()
    )
);

Или для всех вызовов

var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(pool)
    .DefaultIndex("gltrans")
    .DisableDirectStreaming();
var client = new ElasticClient(settings);

Затем Ответные байты доступны в ответе

var bytes = searchResponse.ApiCall.ResponseBodyInBytes;
var json = Encoding.UTF8.GetString(bytes);

Не то, чтобы это буферизировало байты запроса и ответа в памяти, так что происходит за счет более высокого использования памяти и выделения.

или

2. Используйте низкоуровневый клиент для совершения вызова, возвращая ответ низкого уровня

var client = new ElasticClient();

var searchRequest = new SearchDescriptor<gltrans>()
    .Query(q => q.MatchAll());

var index = "gltrans";

var searchResponse = client.LowLevel.Search<BytesResponse>(
    index, 
    PostData.Serializable(searchRequest));

var bytes = searchResponse.Body;

Вы можете использовать client.RequestResponseSerializer, чтобы превратить ответ низкого уровня в ответ высокого уровня, если вам нужно с ним работать

var bytes = searchResponse.Body;
SearchResponse<gltrans> response = null; 

using (var stream = client.ConnectionSettings.MemoryStreamFactory.Create(bytes))
{
    response = client.RequestResponseSerializer.Deserialize<SearchResponse<gltrans>>(stream);
}
...