2016-06-28 14 views
6

Ich verwende Elasticsearch 2.3 und versuche, eine zweistufige Berechnung mithilfe einer Pipeline-Aggregation durchzuführen. Ich bin nur am Endergebnis meiner Pipeline-Aggregation interessiert, aber Elasticsearch gibt alle Bucket-Informationen zurück.So führen Sie eine Pipeline-Aggregation ohne Rückgabe aller Buckets in Elasticsearch aus

Da ich eine riesige Anzahl von Eimern (Dutzende oder Hunderte von Millionen) habe, ist dies unerschwinglich. Leider kann ich keine Möglichkeit finden, Es mitzuteilen, dass ich nicht alle diese Informationen zurückgeben soll.

Hier ist ein Spielzeugbeispiel. Ich habe einen Index test-index mit einem Dokumenttyp obj. obj hat zwei Felder, key und values.

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{ 
    "value": 100, 
    "key": "foo" 
}' 

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{ 
    "value": 20, 
    "key": "foo" 
}' 

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{ 
    "value": 50, 
    "key": "bar" 
}' 

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{ 
    "value": 60, 
    "key": "bar" 
}' 

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{ 
    "value": 70, 
    "key": "bar" 
}' 

Ich möchte den Mittelwert erhalten (über alle key s) der Mindest value von obj s die gleichen key s. Ein Durchschnitt von Minima.

Elasticsearch ermöglicht es mir, dies zu tun:

curl -XPOST 'http://10.10.0.7:9200/test-index/obj/_search' -d '{ 
    "size": 0, 
    "query": { 
    "match_all": {} 
    }, 
    "aggregations": { 
    "key_aggregates": { 
     "terms": { 
     "field": "key", 
     "size": 0 
     }, 
     "aggs": { 
     "min_value": { 
      "min": { 
      "field": "value" 
      } 
     } 
     } 
    }, 
    "avg_min_value": { 
     "avg_bucket": { 
     "buckets_path": "key_aggregates>min_value" 
     } 
    } 
    } 
}' 

Aber diese Abfrage gibt das Minimum für jeden Eimer, obwohl ich es nicht brauchen:

{ 
    "took": 21, 
    "timed_out": false, 
    "_shards": { 
    "total": 5, 
    "successful": 5, 
    "failed": 0 
    }, 
    "hits": { 
    "total": 4, 
    "max_score": 0, 
    "hits": [ 

    ] 
    }, 
    "aggregations": { 
    "key_aggregates": { 
     "doc_count_error_upper_bound": 0, 
     "sum_other_doc_count": 0, 
     "buckets": [ 
     { 
      "key": "bar", 
      "doc_count": 2, 
      "min_value": { 
      "value": 50 
      } 
     }, 
     { 
      "key": "foo", 
      "doc_count": 2, 
      "min_value": { 
      "value": 20 
      } 
     } 
     ] 
    }, 
    "avg_min_value": { 
     "value": 35 
    } 
    } 
} 

Gibt es eine Möglichkeit, um loszuwerden, von allen Informationen innerhalb "buckets": [...]? Ich bin nur an avg_min_value interessiert.

Dies scheint nicht ein Problem in diesem Spielzeug Beispiel, aber wenn die Anzahl der verschiedenen key s ist nicht groß (Dutzende oder Hunderte von Millionen), ist die Abfrage Antwort zu groß, und ich möchte es beschneiden.

Gibt es eine Möglichkeit, dies mit Elasticsearch zu tun? Oder modelliere ich meine Daten falsch?

NB: Es ist nicht akzeptabel, meine Daten pro Schlüssel vorzufördern, da der Teil der Abfrage match_all durch komplexe und unbekannte Filter ersetzt werden kann.

NB2: Ändern size zu einer nicht negativen Zahl in meiner terms Aggregation ist nicht akzeptabel, weil es das Ergebnis ändern würde.

Antwort

5

Ich hatte das gleiche Problem und nach einigem Nachforschungen fand ich eine Lösung und dachte, ich würde hier teilen.

Sie können die Funktion Response Filtering verwenden, um den Teil der Antwort zu filtern, den Sie erhalten möchten.

Sie können erreichen, was Sie wollen, indem Sie den Abfrageparameter filter_path=aggregations.avg_min_value zur Such-URL hinzufügen. Im Beispielfall sollte es ähnlich aussehen:

curl -XPOST 'http://10.10.0.7:9200/test-index/obj/_search?filter_path=aggregations.avg_min_value' -d '{ 
    "size": 0, 
    "query": { 
    "match_all": {} 
    }, 
    "aggregations": { 
    "key_aggregates": { 
     "terms": { 
     "field": "key", 
     "size": 0 
     }, 
     "aggs": { 
     "min_value": { 
      "min": { 
      "field": "value" 
      } 
     } 
     } 
    }, 
    "avg_min_value": { 
     "avg_bucket": { 
     "buckets_path": "key_aggregates>min_value" 
     } 
    } 
    } 
}' 

PS: wenn Sie eine andere Lösung gefunden würde etwas dagegen, es hier zu teilen? Vielen Dank!

+1

Dies scheint wie eine perfekte Lösung. Wenn wir das nur gefunden hätten! Wir haben keine direkte Lösung für dieses Problem gefunden, daher haben wir den Script-Aggregations-Weg übernommen: Erstellen einer Map, deren Schlüssel das Feld "key" sind und die Minima über alle Dokumente mit einem gegebenen Wert für das Feld "key" festlegt; dann Aggregieren der Werte dieser Karte.Ich weiß nicht, wie die beiden in Bezug auf die Leistung vergleichen, aber Ihre Lösung sollte aller Wahrscheinlichkeit nach schneller sein! – jrjd