2016-06-28 23 views
6

Używam Elasticsearch 2.3 i próbuję wykonać dwustopniowe obliczenia przy użyciu agregacji potoków. Interesuje mnie tylko wynik końcowy mojej agregacji potoków, ale Elasticsearch zwraca wszystkie informacje o zasobnikach.Jak wykonać agregację potoków bez zwracania wszystkich segmentów w Elasticsearch

Ponieważ mam ogromną liczbę wiader (dziesiątek lub setek milionów), jest to wygórowane. Niestety, nie mogę znaleźć sposobu, aby powiedzieć Es, aby nie zwrócił wszystkich tych informacji.

Oto przykład zabawek. Mam indeks test-index z typem dokumentu obj. obj ma dwa pola, key i 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" 
}' 

chcę uzyskać wartość średnią (ponad wszystko key ów) minimalnych value z obj s mających te same key s. Średnia minima.

Elasticsearch pozwala mi to zrobić:

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" 
     } 
    } 
    } 
}' 

Ale ta kwerenda zwraca minimum dla każdego wiadra, chociaż nie muszę go:

{ 
    "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 
    } 
    } 
} 

Czy istnieje sposób, aby pozbyć wszystkich informacji wewnątrz "buckets": [...]? Interesuje mnie tylko avg_min_value.

To może nie wydawać się problemem w tym zabawkowym przykładzie, ale gdy liczba różnych key s nie jest duża (dziesiątki lub setki milionów), odpowiedź zapytania jest zbyt duża i chciałbym ją przyciąć.

Czy można to zrobić w Elasticsearch? Czy mogę źle modelować dane?

Uwaga: niedopuszczalne jest wstępne agregowanie danych według klucza, ponieważ część mojego zapytania może zostać zastąpiona złożonymi i nieznanymi filtrami.

NB2: zmiana size na nieujemną liczbę w mojej agregacji terms jest nie do przyjęcia, ponieważ zmieniłaby wynik.

Odpowiedz

5

Miałem ten sam problem i po zrobieniu sporo badań znalazłem rozwiązanie i pomyślałem, że będę się tutaj dzielić.

Możesz użyć funkcji Response Filtering, aby przefiltrować część odpowiedzi, którą chcesz odebrać.

Powinieneś być w stanie osiągnąć to, co chcesz, dodając parametr zapytania filter_path=aggregations.avg_min_value do adresu URL wyszukiwania. W przykładowym przypadku powinien wyglądać podobnie do tego:

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: Jeśli znalazłeś inne rozwiązanie, czy mógłbyś podzielić się nim tutaj? Dzięki!

+1

To wydaje się idealnym rozwiązaniem. Gdybyśmy tylko znaleźli to! Nie znaleźliśmy bezpośredniego rozwiązania tego problemu, więc przyjęliśmy sposób agregacji skryptów: tworzenie mapy, której kluczem jest pole "klucz" i wartości minima dla wszystkich dokumentów o danej wartości dla pola "klucz"; następnie agregowanie wartości tej mapy.Nie wiem, jak te dwa porównania pod względem wydajności, ale najprawdopodobniej Twoje rozwiązanie powinno być szybsze! – jrjd