2015-09-21 3 views
1

Например, у меня есть следующие записи с колоннами, как: (страна, город, дата, доход)как сортировать и предельные скопления в ElasticSearch

USA SF 2015-08 50 
USA SF 2015-05 30 
USA SF 2015-01 20 
USA NY 2015-05 70 
USA NY 2015-02 10 
U.K LD 2015-05 90 

My SQL, как: select country,city,max(date) as maxDate,sum(income) as sumIncome from testTable group by country,city order by maxDate desc,sumIncome desc limit 3. Таким образом, результат должен быть:

USA SF 2015-08 100 
U.K LD 2015-05 90 
USA NY 2015-05 80 

Я написал агрегаты ES следующим образом, но это не так:

"aggs":{"sub1": {"terms":{"field":"contry"}, 
    "aggs":{"sub2":{"terms":{"field":"city", 
     "order":[{"submax":"DESC"},{"subsum":"DESC"}]}, 
    "aggs":{"submax":{"max":{"field":"date"}},"subsum":{"sum":{"field":"income"}}}}}}} 

По моему выше сценарию, он получил неправильный результат, как следующее:

USA SF 2015-08 100 
USA NY 2015-05 80 
U.K LD 2015-05 90 
+0

ES является не реляционная база данных. SQL-запрос не всегда дает вам тот же результат, в той же форме в ES. –

+0

Спасибо, Андрей, но я считаю, что ES может сделать вышеупомянутый sql, просто я все еще новичок ES :) – Jack

+0

Любые идеи, пожалуйста? Я действительно застрял здесь, головная боль ... – Jack

ответ

1

У вас, на самом деле, есть два варианта, теперь, когда я понял это требование.

Вариант 1

Используйте script к "сцепить" country поля и city поля. Использование регулярных скоплений для каждого поля для выполнения того, что вы хотите, невозможно в Elasticsearch.

Вместо этого вам нужно сделать что-то вроде этого:

GET /test/test/_search?search_type=count 
{ 
    "aggs": { 
    "sub1": { 
     "terms": { 
     "script": "doc['country'].value + ' ' + doc['city'].value", 
     "size": 3, 
     "order": [ 
      { 
      "submax": "DESC" 
      }, 
      { 
      "subsum": "DESC" 
      } 
     ] 
     }, 
     "aggs": { 
     "submax": { 
      "max": { 
      "field": "date" 
      } 
     }, 
     "subsum": { 
      "sum": { 
      "field": "income" 
      } 
     } 
     } 
    } 
    } 
} 

С curl:

curl -XPOST "http://localhost:9200/livebox/type1/_search?search_type=count" -d' 
{ 
    "aggs": { 
    "sub1": { 
     "terms": { 
     "script": "doc[\"boxname\"].value + \" \" + doc[\"app\"].value", 
     "size": 3, 
     "order": [ 
      { 
      "submax": "DESC" 
      }, 
      { 
      "subsum": "DESC" 
      } 
     ] 
     }, 
     "aggs": { 
     "submax": { 
      "max": { 
      "field": "date" 
      } 
     }, 
     "subsum": { 
      "sum": { 
      "field": "count" 
      } 
     } 
     } 
    } 
    } 
}' 

И результат агрегирования будет генерировать термины, которые имеют следующий вид: country + + city.

 "buckets": [ 
     { 
      "key": "usa sf", 
      "doc_count": 3, 
      "subsum": { 
       "value": 100 
      }, 
      "submax": { 
       "value": 1438387200000, 
       "value_as_string": "2015-08" 
      } 
     }, 
     { 
      "key": "uk ld", 
      "doc_count": 1, 
      "subsum": { 
       "value": 90 
      }, 
      "submax": { 
       "value": 1430438400000, 
       "value_as_string": "2015-05" 
      } 
     }, 
     { 
      "key": "usa ny", 
      "doc_count": 2, 
      "subsum": { 
       "value": 80 
      }, 
      "submax": { 
       "value": 1430438400000, 
       "value_as_string": "2015-05" 
      } 
     } 
    ] 

Вариант 2

Использование _source transformation, что будет строить новое поле в индексации времени, который будет «двигаться» влияние на производительность выполнения сценария во время агрегации.

отображение индекса, так как она нуждается в некоторых изменениях, все, что вы сейчас находитесь:

PUT /test 
{ 
    "mappings": { 
    "test": { 
     "transform": { 
     "script": "ctx._source['country_and_city'] = ctx._source['country'] + ' ' + ctx._source['city']" 
     }, 
     "properties": { 
     "country": { 
      "type": "string" 
     }, 
     "city": { 
      "type": "string" 
     }, 
     "income": { 
      "type": "integer" 
     }, 
     "date": { 
      "type": "date", 
      "format": "yyyy-MM" 
     }, 
     "country_and_city": { 
      "type": "string", 
      "index": "not_analyzed" 
     } 
     } 
    } 
    } 
} 

Запрос:

GET /test/test/_search?search_type=count 
{ 
    "aggs": { 
    "sub1": { 
     "terms": { 
     "field": "country_and_city", 
     "order": [ 
      { 
      "submax": "DESC" 
      }, 
      { 
      "subsum": "DESC" 
      } 
     ] 
     }, 
     "aggs": { 
     "submax": { 
      "max": { 
      "field": "date" 
      } 
     }, 
     "subsum": { 
      "sum": { 
      "field": "income" 
      } 
     } 
     } 
    } 
    } 
} 

И результат:

 "buckets": [ 
     { 
      "key": "usa sf", 
      "doc_count": 3, 
      "subsum": { 
       "value": 100 
      }, 
      "submax": { 
       "value": 1438387200000, 
       "value_as_string": "2015-08" 
      } 
     }, 
     { 
      "key": "uk ld", 
      "doc_count": 1, 
      "subsum": { 
       "value": 90 
      }, 
      "submax": { 
       "value": 1430438400000, 
       "value_as_string": "2015-05" 
      } 
     }, 
     { 
      "key": "usa ny", 
      "doc_count": 2, 
      "subsum": { 
       "value": 80 
      }, 
      "submax": { 
       "value": 1430438400000, 
       "value_as_string": "2015-05" 
      } 
     } 
    ] 
+0

спасибо, Андрей, к сожалению, он не работает. Вышеприведенный скрипт будет сортироваться только в каждой стране по своему усмотрению по стране и городу. – Jack

+0

Итак, вы имеете в виду, что вы хотите иметь 'US NY 2015-09 100 ||| USA SF 2015-05 160 ||| CAN OT 2015-05 150 ||| USA WA 2015-02 100'? Это означает, что страны переплетаются? –

+0

Я изменил вопрос с правильными и неправильными результатами. И я установил предел 3 вместо 2. – Jack

Смежные вопросы