2016-06-14 8 views
1

Ich verwende NEST 2.3.2. Und ich versuche, eine Abfrage mit verschachtelten Aggregationen zu erstellen. Grundsätzlich habe ich einen Index mit Protokollen, die einen Zeitstempel und einen Ergebniscode haben. Ich möchte diese Protokolle zuerst in Minuteneinheiten speichern und sie dann entsprechend dem Ergebniscode klassifizieren.Elasticsearch NEST-Client mit verschachtelten Aggregationen

Ich habe den folgenden F # Code zum Generieren der Abfrage.

/// Generate an aggregation to put buckets by result code 
let generateAggregationByResultCode() = 
    let resultAggregationName = "result_aggregation" 
    let aggregationByResults = new TermsAggregation(resultAggregationName) 
    aggregationByResults.Field <- new Field(Name = "Result") 
    aggregationByResults.ExecutionHint <- new Nullable<TermsAggregationExecutionHint>(TermsAggregationExecutionHint.GlobalOrdinals); 
    aggregationByResults.MinimumDocumentCount <- new Nullable<int>(0); 
    aggregationByResults.Size <- new Nullable<int>(bucketSize); 
    aggregationByResults.Missing <- "-128" 
    aggregationByResults 

/// Generate an aggregation to classify into buckets by minutes and then by result code 
let generateNewDateHistogramByMinute() = 
    let dateHistogramByMinute = new DateHistogramAggregation("by_minute") 
    dateHistogramByMinute.Field <- new Field(Name = "OperationTime") 
    dateHistogramByMinute.Interval <- new Union<DateInterval, Time>(DateInterval.Minute) // can also use TimeSpan.FromMinutes(1.0) 
    dateHistogramByMinute.MinimumDocumentCount <- new Nullable<int>(0) 
    dateHistogramByMinute.Format <- "strict_date_hour_minute" 
    let innerAggregations = new AggregationDictionary() 
    innerAggregations.[resultInnerAggregationName] <- new AggregationContainer(Terms = generateAggregationByResultCode()) 
    dateHistogramByMinute.Aggregations <- innerAggregations 
    dateHistogramByMinute 

ich diese Aggregation verwenden, um die Anfrage von

let dateHistogram = generateNewDateHistogramByMinute() 
let aggregations = new AggregationDictionary() 
aggregations.[histogramName] <- new AggregationContainer(DateHistogram = dateHistogram) 
(* ... code omitted ... *) 
dslRequest.Aggregations <- aggregations 

einstellen Wenn ich den Antrag ausdrucken, ist die Aggregation Teil wie dies

"aggs": { 
    "BucketsByMinutes": { 
     "date_histogram": { 
     "field": "OperationTime", 
     "interval": "minute", 
     "format": "strict_date_hour_minute", 
     "min_doc_count": 0 
     } 
    } 
    } 

Die innere Aggregation vollständig verloren geht. Weiß jemand wie ich eine Anfrage richtig aufbauen soll? Und wie kann ich diese inneren Buckets abrufen, wenn die Antwort zurückgegeben wird? Ich habe dafür keine geeigneten Eigenschaften oder Methoden gefunden, und die Dokumentation ist im Grunde genommen nicht existent.

+0

Haben Sie die 2.x-Dokumentation unter https://www.elastic.co/guide/en/elasticsearch/client/net-api/2.x/index.html gesehen? –

+0

@RussCam Ich bin während meiner Suche nach Lösungen darauf gestoßen, aber es hat nicht viel geholfen. Danke für den Link. – LLS

Antwort

1

Ich bin nicht sicher, warum Sie die innere Aggregation auf der Anfrage nicht sehen; Ich bin mit dem folgenden zu sehen, leicht modifizierte Version von dem, was Sie

open Nest 
open Elasticsearch.Net 

type Document() = 
    member val Name = "" with get, set 

let pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")) 
let settings = new ConnectionSettings(pool, new InMemoryConnection()) 

settings.DisableDirectStreaming() 
     .PrettyJson() 
     .OnRequestCompleted(fun response -> 
      if (response.RequestBodyInBytes <> null) 
      then 
       Console.WriteLine("{0} {1} \n{2}\n", response.HttpMethod, response.Uri, Encoding.UTF8.GetString(response.RequestBodyInBytes)); 
      else Console.WriteLine("{0} {1} \n", response.HttpMethod, response.Uri); 

      if (response.ResponseBodyInBytes <> null) 
      then 
       Console.WriteLine("Status: {0}\n{1}\n{2}\n", response.HttpStatusCode, Encoding.UTF8.GetString(response.ResponseBodyInBytes), new String('-', 30)); 
      else Console.WriteLine("Status: {0}\n{1}\n", response.HttpStatusCode, new String('-', 30)); 
     ) |> ignore 

let client = new ElasticClient(settings) 

/// Generate an aggregation to put buckets by result code 
let generateAggregationByResultCode() = 
    let bucketSize = 10 
    let resultAggregationName = "result_aggregation" 
    let aggregationByResults = new TermsAggregation(resultAggregationName) 
    aggregationByResults.Field <- Field.op_Implicit("Result") 
    aggregationByResults.ExecutionHint <- new Nullable<TermsAggregationExecutionHint>(TermsAggregationExecutionHint.GlobalOrdinals); 
    aggregationByResults.MinimumDocumentCount <- new Nullable<int>(0); 
    aggregationByResults.Size <- new Nullable<int>(bucketSize); 
    aggregationByResults.Missing <- "-128" 
    aggregationByResults 

/// Generate an aggregation to classify into buckets by minutes and then by result code 
let generateNewDateHistogramByMinute() = 
    let dateHistogramByMinute = new DateHistogramAggregation("by_minute") 
    dateHistogramByMinute.Field <- Field.op_Implicit("OperationTime") 
    dateHistogramByMinute.Interval <- new Union<DateInterval, Time>(DateInterval.Minute) // can also use TimeSpan.FromMinutes(1.0) 
    dateHistogramByMinute.MinimumDocumentCount <- new Nullable<int>(0) 
    dateHistogramByMinute.Format <- "strict_date_hour_minute" 
    dateHistogramByMinute.Aggregations <- AggregationDictionary.op_Implicit(generateAggregationByResultCode()) 
    dateHistogramByMinute 

let request = new SearchRequest<Document>() 
request.Aggregations <- (AggregationDictionary.op_Implicit(generateNewDateHistogramByMinute())) 

let response = client.Search<Document>(request) 

haben diese ergibt die folgende in der Konsole

POST http://localhost:9200/_search?pretty=true 
{ 
    "aggs": { 
    "by_minute": { 
     "date_histogram": { 
     "field": "OperationTime", 
     "interval": "minute", 
     "format": "strict_date_hour_minute", 
     "min_doc_count": 0 
     }, 
     "aggs": { 
     "result_aggregation": { 
      "terms": { 
      "field": "Result", 
      "size": 10, 
      "min_doc_count": 0, 
      "execution_hint": "global_ordinals", 
      "missing": "-128" 
      } 
     } 
     } 
    } 
    } 
} 

Status: 200 
------------------------------ 

Die oben kann nützlich sein, während Sie entwickeln; Wenn Sie zur Ausführung gegen Elasticsearch bereit sind, entfernen Sie die InMemoryConnection aus dem ConnectionSettings Konstruktor und entfernen Sie auch die Aufrufe .DisableDirectStreaming(), .PrettyJson() und .OnRequestCompleted(fun) auf ConnectionSettings.

+0

Vielen Dank. Ich habe gerade 'Aggregationen. [HistogramName] <- new AggregationContainer()' mit 'request.Aggregations <- (AggregationDictionary.op_Implicit (some_aggregation))' ersetzt und es funktioniert. Anscheinend ist es falsch, zu versuchen, die Aggregation selbst dem 'AggregationDictionary' hinzuzufügen. Ich habe einfach angenommen, dass es wie ein normales Wörterbuch mit Schlüssel-Item-Werten funktioniert und sich der impliziten Cast nicht bewusst ist. – LLS

+0

Indizierung in das 'AggregationDictionary' sollte auch so funktionieren, wie Sie es hatten (gerade ausprobiert), aber diese Route zu gehen ist ein bisschen umständlicher, da Sie die Aggregation gegen den Namen indexieren müssen, den Sie ihm geben; die implizite Konvertierung macht das für Sie –

+0

Ich weiß nicht warum, aber das Ersetzen der zwei Zeilen funktioniert. Und jetzt habe ich Probleme, die inneren Eimer von der Antwort zu bekommen. Ich kann sie sehen, wenn ich die Antwort im Klartext drucke, aber ich weiß nicht, wie ich programmgesteuert darauf zugreifen soll. Ich habe "Aggregationen": {"BucketsByMinutes": {"items": [{... "aggregations": {"result_aggregation": {"items": [{"key": "2003", "docCount": 4}, ...]}}}]}} Danke. – LLS