2015-07-27 2 views
3

Я пытаюсь запустить то, что стало выглядеть простым запросом на Elasticsearch, но я просто не могу получить результат, который я ищу.Запросить последний документ каждого типа на Elasticsearch

Вот краткий пример того, что я пытаюсь сделать:

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

Я хочу получить заголовок, основанный на отметке времени (timestamp based) для каждого доступного источника для данного пользователя.

#!/bin/bash 

export ELASTICSEARCH_ENDPOINT="http://localhost:9200" 

# Create indexes 

curl -XPUT "$ELASTICSEARCH_ENDPOINT/news" -d '{ 
    "mappings": { 
     "news": { 
      "properties": { 
       "source": { "type": "string", "index": "not_analyzed" }, 
       "headline": { "type": "object" }, 
       "timestamp": { "type": "date", "format": "date_hour_minute_second_millis" }, 
       "user": { "type": "string", "index": "not_analyzed" } 
      } 
     } 
    } 
}' 

# Index documents 
curl -XPOST "$ELASTICSEARCH_ENDPOINT/_bulk?refresh=true" -d ' 
{"index":{"_index":"news","_type":"news"}} 
{"user": "John", "source": "CNN", "headline": "Great news", "timestamp": "2015-07-28T00:07:29.000"} 
{"index":{"_index":"news","_type":"news"}} 
{"user": "John", "source": "CNN", "headline": "More great news", "timestamp": "2015-07-28T00:08:23.000"} 
{"index":{"_index":"news","_type":"news"}} 
{"user": "John", "source": "ESPN", "headline": "Sports news", "timestamp": "2015-07-28T00:09:32.000"} 
{"index":{"_index":"news","_type":"news"}} 
{"user": "John", "source": "ESPN", "headline": "More sports news", "timestamp": "2015-07-28T00:10:35.000"} 
{"index":{"_index":"news","_type":"news"}} 
{"user": "Mary", "source": "Yahoo", "headline": "More news", "timestamp": "2015-07-28T00:11:54.000"} 
{"index":{"_index":"news","_type":"news"}} 
{"user": "Mary", "source": "Yahoo", "headline": "Crazy news", "timestamp": "2015-07-28T00:12:31.000"} 
' 

Так как я могу получить последние CNN и последние заголовки ESPN от Джона, например?

Я изучал API многопользовательского поиска, но это означало бы, что мне нужно будет знать все источники заранее (в данном случае CNN и ESPN).

ответ

8

Во-первых, обратите внимание, что я должен был изменить отображение на headline поле string, как в ваших образцов документов заголовки string s и не object s.

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

curl -XPOST "$ELASTICSEARCH_ENDPOINT/news/_search" -d '{ 
    "size": 0, 
    "query": { 
    "filtered": { 
     "filter": { 
     "term": { 
      "user": "John"   <--- filter for user=John 
     } 
     } 
    } 
    }, 
    "aggs": { 
    "sources": { 
     "terms": { 
     "field": "source"   <--- aggregate by source 
     }, 
     "aggs": { 
     "latest": { 
      "top_hits": { 
      "size": 1,    <--- only take the first... 
      "_source": [   <--- only the date and headline 
       "headline", 
       "timestamp" 
      ], 
      "sort": { 
       "timestamp": "desc" <--- ...and only the latest hit 
      } 
      } 
     } 
     } 
    } 
    } 
}' 

Это даст что-то вроде этого:

{ 
    ... 
    "aggregations" : { 
    "sources" : { 
     "doc_count_error_upper_bound" : 0, 
     "sum_other_doc_count" : 0, 
     "buckets" : [ { 
     "key" : "CNN", 
     "doc_count" : 2, 
     "latest" : { 
      "hits" : { 
      "total" : 2, 
      "max_score" : null, 
      "hits" : [ { 
       "_index" : "news", 
       "_type" : "news", 
       "_id" : "AU7Sh3VDGDddn2ZNuDVl", 
       "_score" : null, 
       "_source":{ 
        "headline": "More great news", 
        "timestamp": "2015-07-28T00:08:23.000" 
       }, 
       "sort" : [ 1438042103000 ] 
      } ] 
      } 
     } 
     }, { 
     "key" : "ESPN", 
     "doc_count" : 2, 
     "latest" : { 
      "hits" : { 
      "total" : 2, 
      "max_score" : null, 
      "hits" : [ { 
       "_index" : "news", 
       "_type" : "news", 
       "_id" : "AU7Sh3VDGDddn2ZNuDVn", 
       "_score" : null, 
       "_source":{ 
        "headline": "More sports news", 
        "timestamp": "2015-07-28T00:10:35.000" 
       }, 
       "sort" : [ 1438042235000 ] 
      } ] 
      } 
     } 
     } ] 
    } 
    } 
} 
+1

Thx так много! Это именно то, что я искал! Я понятия не имел, что вы можете использовать скопления для извлечения фактического источника, хотя это было просто для статистики. –

+0

@Val У меня проблема, подобная предыдущей, но я хочу еще один уровень агрегации поверх того, что достигается здесь. Ждем вашего ответа. http://stackoverflow.com/questions/38195420/elasticsearch-aggregation-over-top-hits – SuperCoder

+0

Можно ли агрегировать по нескольким полям таким же образом? –

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