2013-01-06 12 views
14

Potrzebuję agregować (grupować) za pomocą 3 pól w ES.Wiele grup w Elasticsearch

Czy mogę zrobić to w 1 kwerendzie lub że muszę użyć facet + iteracji dla każdej kolumny?

Dziękuję

+0

https://github.com/ elasticsearch/elasticsearch/issues/256 – ehsanul

Odpowiedz

7

Można to zrobić na 2 sposoby:

1) przy użyciu wielu pól w jednym wyniku fasetowanie:

przykład dla pojedynczych pól FACET:

curl -X GET "http://localhost:9200/sales/order/_search?pretty=true" -d '{ 
    "query": { 
    "query_string": { 
     "query": "shohi*", 
     "fields": [ 
     "billing_name" 
     ] 
    } 
    }, 
    "facets": { 
    "facet_result": { 
     "terms": { 
     "fields": [ 
      "status" 
     ], 
     "order": "term", 
     "size": 15 
     } 
    } 
    } 
}' 

przykład dla wielu pól w wyniku pojedynczego aspektu:

curl -X GET "http://localhost:9200/sales/order/_search?pretty=true" -d '{ 
    "query": { 
    "query_string": { 
     "query": "shohi*", 
     "fields": [ 
     "billing_name" 
     ] 
    } 
    }, 
    "facets": { 
    "facet_result": { 
     "terms": { 
     "fields": [ 
      "status", 
      "customer_gender", 
      "state" 
     ], 
     "order": "term", 
     "size": 15 
     } 
    } 
    } 
}' 

2) Za pomocą wielu aspekt zestaw wyników:

curl -X GET "http://localhost:9200/sales/order/_search?pretty=true" -d '{ 
    "query": { 
    "query_string": { 
     "query": "*", 
     "fields": [ 
     "increment_id" 
     ] 
    } 
    }, 
    "facets": { 
    "status_facets": { 
     "terms": { 
     "fields": [ 
      "status" 
     ], 
     "size": 50, 
     "order": "term" 
     } 
    }, 
    "gender_facets": { 
     "terms": { 
     "fields": [ 
      "customer_gender" 
     ] 
     } 
    }, 
    "state_facets": { 
     "terms": { 
     "fields": [ 
      "state" 
     ], 
     , 
     "order": "term" 
     } 
    } 
    } 
}' 

referencyjny Link: http://www.elasticsearch.org/guide/reference/api/search/facets/terms-facet.html

+6

To proste pytanie, co z grupami? Myślę, że OP jest proszony o grupowanie wyników wyszukiwania. (Nawet jeśli potrzebuję grupowania w ES) –

28

Począwszy od wersji 1.0 ElasticSearch nowa aggregations API umożliwia grupowanie według wielu pól przy użyciu podrzędne agregacje. Załóżmy, że chcesz do grupy pól field1, field2 i field3:

{ 
    "aggs": { 
    "agg1": { 
     "terms": { 
     "field": "field1" 
     }, 
     "aggs": { 
     "agg2": { 
      "terms": { 
      "field": "field2" 
      }, 
      "aggs": { 
      "agg3": { 
       "terms": { 
       "field": "field3" 
       } 
      } 
      }   
     } 
     } 
    } 
    } 
} 

Oczywiście może to trwać tak wielu dziedzinach, jak chcesz.

Aktualizacja:
Dla kompletności, tutaj jest jak wyjście z powyższym zapytaniu wygląda. Poniżej znajduje się również kod Pythona do generowania kwerendy agregacji i spłaszczenia wyniku do listy słowników.

{ 
    "aggregations": { 
    "agg1": { 
     "buckets": [{ 
     "doc_count": <count>, 
     "key": <value of field1>, 
     "agg2": { 
      "buckets": [{ 
      "doc_count": <count>, 
      "key": <value of field2>, 
      "agg3": { 
       "buckets": [{ 
       "doc_count": <count>, 
       "key": <value of field3> 
       }, 
       { 
       "doc_count": <count>, 
       "key": <value of field3> 
       }, ... 
       ] 
      }, 
      { 
      "doc_count": <count>, 
      "key": <value of field2>, 
      "agg3": { 
       "buckets": [{ 
       "doc_count": <count>, 
       "key": <value of field3> 
       }, 
       { 
       "doc_count": <count>, 
       "key": <value of field3> 
       }, ... 
       ] 
      }, ... 
      ] 
     }, 
     { 
     "doc_count": <count>, 
     "key": <value of field1>, 
     "agg2": { 
      "buckets": [{ 
      "doc_count": <count>, 
      "key": <value of field2>, 
      "agg3": { 
       "buckets": [{ 
       "doc_count": <count>, 
       "key": <value of field3> 
       }, 
       { 
       "doc_count": <count>, 
       "key": <value of field3> 
       }, ... 
       ] 
      }, 
      { 
      "doc_count": <count>, 
      "key": <value of field2>, 
      "agg3": { 
       "buckets": [{ 
       "doc_count": <count>, 
       "key": <value of field3> 
       }, 
       { 
       "doc_count": <count>, 
       "key": <value of field3> 
       }, ... 
       ] 
      }, ... 
      ] 
     }, ... 
     ] 
    } 
    } 
} 

Poniższy kod Python wykonuje grupa po danej listy pól. I podać include_missing=True, zawiera również kombinacje wartości, gdzie niektóre z pól brakuje (nie trzeba go, jeśli masz wersję 2.0 z Elasticsearch dzięki this)

def group_by(es, fields, include_missing): 
    current_level_terms = {'terms': {'field': fields[0]}} 
    agg_spec = {fields[0]: current_level_terms} 

    if include_missing: 
     current_level_missing = {'missing': {'field': fields[0]}} 
     agg_spec[fields[0] + '_missing'] = current_level_missing 

    for field in fields[1:]: 
     next_level_terms = {'terms': {'field': field}} 
     current_level_terms['aggs'] = { 
      field: next_level_terms, 
     } 

     if include_missing: 
      next_level_missing = {'missing': {'field': field}} 
      current_level_terms['aggs'][field + '_missing'] = next_level_missing 
      current_level_missing['aggs'] = { 
       field: next_level_terms, 
       field + '_missing': next_level_missing, 
      } 
      current_level_missing = next_level_missing 

     current_level_terms = next_level_terms 

    agg_result = es.search(body={'aggs': agg_spec})['aggregations'] 
    return get_docs_from_agg_result(agg_result, fields, include_missing) 


def get_docs_from_agg_result(agg_result, fields, include_missing): 
    current_field = fields[0] 
    buckets = agg_result[current_field]['buckets'] 
    if include_missing: 
     buckets.append(agg_result[(current_field + '_missing')]) 

    if len(fields) == 1: 
     return [ 
      { 
       current_field: bucket.get('key'), 
       'doc_count': bucket['doc_count'], 
      } 
      for bucket in buckets if bucket['doc_count'] > 0 
     ] 

    result = [] 
    for bucket in buckets: 
     records = get_docs_from_agg_result(bucket, fields[1:], include_missing) 
     value = bucket.get('key') 
     for record in records: 
      record[current_field] = value 
     result.extend(records) 

    return result 
Powiązane problemy