2015-08-05 2 views
1

Я хочу сделать довольно сложный запрос/агрегацию. Я не вижу, как, потому что я только начал работать с ES. Документы у меня выглядеть примерно так:Агрегация метрик Elasticsearch: количество элементов в массиве

{ 
    "keyword": "some keyword", 
    "items": [ 
    { 
     "name":"my first item", 
     "item_property_1":"A", 
     (other properties here) 
    }, 
    { 
     "name":"my second item", 
     "item_property_1":"B", 
     (other properties here) 
    }, 
    { 
     "name":"my third item", 
     "item_property_1":"A", 
     (other properties here) 
    } 
    ] 
    (other properties...) 
}, 
{ 
    "keyword": "different keyword", 
    "items": [ 
    { 
     "name":"cool item", 
     "item_property_1":"A", 
     (other properties here) 
    }, 
    { 
     "name":"awesome item", 
     "item_property_1":"C", 
     (other properties here) 
    }, 
    ] 
    (other properties...) 
}, 
(other documents...) 

Теперь, что я хотел бы сделать это, для каждого ключевого слова, подсчитать, сколько элементов есть, для которых из нескольких возможных значений, которые могут иметь property_1. То есть, я хочу агрегацию ведра, который будет иметь следующий ответ:

{ 
    "keyword": "some keyword", 
    "item_property_1_aggretation": [ 
    { 
     "key":"A", 
     "count": 2, 
    }, 
    { 
     "key":"B", 
     "count": 1, 
    } 
    ] 
}, 
{ 
    "keyword": "different keyword", 
    "item_property_1_aggretation": [ 
    { 
     "key":"A", 
     "count": 1, 
    }, 
    { 
     "key":"C", 
     "count": 1, 
    } 
    ] 
}, 
(other keywords...) 

Если отображения необходимы, могли бы вы также specificy который? У меня нет никаких сопоставлений по умолчанию, я просто бросил все там.

EDIT: избавляя Вас, разместив здесь насыпной PUT для предыдущего примера

PUT /test/test/_bulk 
{ "index": {}} 
{ "keyword": "some keyword", "items": [ {  "name":"my first item",  "item_property_1":"A" }, {  "name":"my second item",  "item_property_1":"B" }, {  "name":"my third item",  "item_property_1":"A"  } ]} 
{ "index": {}} 
{ "keyword": "different keyword", "items": [ {  "name":"cool item",  "item_property_1":"A" }, {  "name":"awesome item",  "item_property_1":"C" } ]} 

EDIT2:

Я просто попытался это:

и получил это:

"aggregations": { 
    "property_1_count": { 
     "doc_count_error_upper_bound": 0, 
     "sum_other_doc_count": 0, 
     "buckets": [ 
     { 
      "key": "a", 
      "doc_count": 2 
     }, 
     { 
      "key": "b", 
      "doc_count": 1 
     }, 
     { 
      "key": "c", 
      "doc_count": 1 
     } 
     ] 
    } 
} 

близко, но нет сигары. Вы можете видеть, что происходит, это bucketing над каждым item_property_1 независимо от того, keyword принадлежит. Я уверен, что решение предполагает правильное добавление правильного отображения, но я не могу на него наложить. Предложения?

EDIT3: Исходя из этого: https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-nested-type.html Я хочу попробовать добавить nested тип собственности items. Чтобы сделать это, я попробовал:

PUT /test/_mapping/test 
{ 
    "test":{ 
     "properties": { 
      "items": { 
       "type": "nested", 
       "properties": { 
        "item_property_1":{"type":"string"} 
       } 
      } 
     } 
    } 
} 

Однако это возвращает ошибку:

{ 
    "error": "MergeMappingException[Merge failed with failures {[object mapping [items] can't be changed from non-nested to nested]}]", 
    "status": 400 
} 

Это, возможно, придется делать с предупреждением о том URL: «Изменение типа объекта для вложенного типа требует индексирование этого «.

Итак, как мне это сделать?

ответ

4

Ницца пытается, вы были почти там! Вот что я придумал. На основании вашего отображения предложения, отображение я использую следующее:

curl -XPUT localhost:9200/test/_mapping/test -d '{ 
    "test": { 
    "properties": { 
     "keyword": { 
     "type": "string", 
     "index": "not_analyzed" 
     }, 
     "items": { 
     "type": "nested", 
     "properties": { 
      "name": { 
      "type": "string" 
      }, 
      "item_property_1": { 
      "type": "string", 
      "index": "not_analyzed" 
      } 
     } 
     } 
    } 
    } 
}' 

Примечание: вам необходимо очистить и индексировать ваши данные, так как вы не можете изменить тип поля от того, не nested к nested.

Затем я создал некоторые данные с насыпным запросом вы поделились:

curl -XPOST localhost:9200/test/test/_bulk -d ' 
{ "index": {}} 
{ "keyword": "some keyword", "items": [ {  "name":"my first item",  "item_property_1":"A" }, {  "name":"my second item",  "item_property_1":"B" }, {  "name":"my third item",  "item_property_1":"A"  } ]} 
{ "index": {}} 
{ "keyword": "different keyword", "items": [ {  "name":"cool item",  "item_property_1":"A" }, {  "name":"awesome item",  "item_property_1":"C" } ]} 
' 

Наконец, здесь является агрегирование запросов вы можете использовать, чтобы получить результаты, которые вы ожидаете. Мы сначала ведем keyword, используя terms aggregation, а затем для каждого ключевого слова мы ведем вложенное поле item_property_1.Так как items теперь является типом nested, ключ должен использовать nested aggregation для items, а затем для подкатегории terms для поля item_property_1.

{ 
    "size": 0, 
    "aggregations": { 
    "by_keyword": { 
     "terms": { 
     "field": "keyword" 
     }, 
     "aggs": { 
     "prop_1_count": { 
      "nested": { 
      "path": "items" 
      }, 
      "aggs": { 
      "prop_1": { 
       "terms": { 
       "field": "items.item_property_1" 
       } 
      } 
      } 
     } 
     } 
    } 
    } 
} 

Выполнение этого запроса на наборе данных даст это:

{ 
    ... 
    "aggregations" : { 
    "by_keyword" : { 
     "doc_count_error_upper_bound" : 0, 
     "sum_other_doc_count" : 0, 
     "buckets" : [ { 
     "key" : "different keyword",  <---- keyword 1 
     "doc_count" : 1, 
     "prop_1_count" : { 
      "doc_count" : 2, 
      "prop_1" : { 
      "doc_count_error_upper_bound" : 0, 
      "sum_other_doc_count" : 0, 
      "buckets" : [ {    <---- buckets for item_property_1 
       "key" : "A", 
       "doc_count" : 1 
      }, { 
       "key" : "C", 
       "doc_count" : 1 
      } ] 
      } 
     } 
     }, { 
     "key" : "some keyword",   <---- keyword 2 
     "doc_count" : 1, 
     "prop_1_count" : { 
      "doc_count" : 3, 
      "prop_1" : { 
      "doc_count_error_upper_bound" : 0, 
      "sum_other_doc_count" : 0, 
      "buckets" : [ {    <---- buckets for item_property_1 
       "key" : "A", 
       "doc_count" : 2 
      }, { 
       "key" : "B", 
       "doc_count" : 1 
      } ] 
      } 
     } 
     } ] 
    } 
    } 
} 
+0

Это именно то, что я искал, спасибо. Кроме того, хорошая идея иметь индекс 'item_property_1' как« не проанализированный »:-) Просто последнее. Фактический индекс в моем db уже имеет 7k больших документов, которые я бы больше не собирал. Я могу создать новый индекс с новым сопоставлением, но как я могу затем скопировать старый индекс в новый? – oneloop

+0

См. [Этот вопрос] (http://stackoverflow.com/questions/31853262/how-to-move-data-from-one-elasticsearch-index-to-another-using-the-bulk-api/31853454#31853454), Я просто ответил на это ;-) – Val

+0

Ах, если мне нужно установить logstash для написания скриптов, я бы предпочел не изучать новый инструмент, который я не буду использовать в ближайшее время, и вместо этого напишу скрипты в Python:) Спасибо в любом случае mate – oneloop

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