2014-09-23 125 views
11

我有一些文件:Elasticsearch过滤文件组通过现场

{"name": "John", "district": 1}, 
{"name": "Mary", "district": 2}, 
{"name": "Nick", "district": 1}, 
{"name": "Bob", "district": 3}, 
{"name": "Kenny", "district": 1} 

如何过滤/按地区选择不同的文件?

{"name": "John", "district": 1}, 
{"name": "Mary", "district": 2}, 
{"name": "Bob", "district": 3} 

在SQL中,我可以使用GROUP BY。我尝试了术语聚合,但它只返回了不同的数字。

"aggs": { 
    "distinct": { 
    "terms": { 
     "field": "district", 
     "size": 0 
    } 
    } 
} 

感谢您的帮助! :-)

+0

难道我的答案解决您的问题 – 2014-09-23 04:51:31

回答

29

如果您ElasticSearch版本是1.3或更高版本做到这一点,你可以使用top_hits型subaggregation这会给你(默认情况下)排序在你的查询分数上的前三个匹配文档(在你使用match_all查询时,这里是1)。

您可以将size参数设置为超过3

下面的数据集和查询:

POST /test/districts/ 
{"name": "John", "district": 1} 

POST /test/districts/ 
{"name": "Mary", "district": 2} 

POST /test/districts/ 
{"name": "Nick", "district": 1} 

POST /test/districts/ 
{"name": "Bob", "district": 3} 

POST test/districts/_search 
{ 
    "size": 0, 
    "aggs":{ 
    "by_district":{ 
     "terms": { 
     "field": "district", 
     "size": 0 
     }, 
     "aggs": { 
     "tops": { 
      "top_hits": { 
      "size": 10 
      } 
     } 
     } 
    } 
    } 
} 

将输出文件你想要的方式:

{ 
    "took": 5, 
    "timed_out": false, 
    "_shards": { 
     "total": 5, 
     "successful": 5, 
     "failed": 0 
    }, 
    "hits": { 
     "total": 4, 
     "max_score": 0, 
     "hits": [] 
    }, 
    "aggregations": { 
     "by_district": { 
     "buckets": [ 
      { 
       "key": 1, 
       "key_as_string": "1", 
       "doc_count": 2, 
       "tops": { 
        "hits": { 
        "total": 2, 
        "max_score": 1, 
        "hits": [ 
         { 
          "_index": "test", 
          "_type": "districts", 
          "_id": "XYHu4I-JQcOfLm3iWjTiOg", 
          "_score": 1, 
          "_source": { 
           "name": "John", 
           "district": 1 
          } 
         }, 
         { 
          "_index": "test", 
          "_type": "districts", 
          "_id": "5dul2XMTRC2IpV_tKRRltA", 
          "_score": 1, 
          "_source": { 
           "name": "Nick", 
           "district": 1 
          } 
         } 
        ] 
        } 
       } 
      }, 
      { 
       "key": 2, 
       "key_as_string": "2", 
       "doc_count": 1, 
       "tops": { 
        "hits": { 
        "total": 1, 
        "max_score": 1, 
        "hits": [ 
         { 
          "_index": "test", 
          "_type": "districts", 
          "_id": "I-9Gd4OYSRuexhP1dCdQ-g", 
          "_score": 1, 
          "_source": { 
           "name": "Mary", 
           "district": 2 
          } 
         } 
        ] 
        } 
       } 
      }, 
      { 
       "key": 3, 
       "key_as_string": "3", 
       "doc_count": 1, 
       "tops": { 
        "hits": { 
        "total": 1, 
        "max_score": 1, 
        "hits": [ 
         { 
          "_index": "test", 
          "_type": "districts", 
          "_id": "bti2y-OUT3q2mBNhhI3xeA", 
          "_score": 1, 
          "_source": { 
           "name": "Bob", 
           "district": 3 
          } 
         } 
        ] 
        } 
       } 
      } 
     ] 
     } 
    } 
} 
+0

优秀的,你救了我的命! – Geany 2014-09-23 08:42:54

+0

嘿@ThomasC,任何想法如何也过滤这样的聚合记录?我已经尝试了半个小时了。谢谢 ! – lisak 2015-11-30 12:05:18

+0

Hi @lisak!您不能在top_hits下嵌套聚合,但是,相反是可能的。尝试使用过滤器聚合并嵌套top_hits。或者,你可以在查询部分过滤结果 – ThomasC 2015-12-17 08:48:45

2

弹性搜索不会通过唯一值为值或组提供不同的文档。 但有工作围绕这个你可以,如果你使用的是Java客户端或可以将其转换成适合自己的语言

SearchResponse response = client.prepareSearch().execute().actionGet(); 
SearchHits hits = response.getHits(); 

Iterator<SearchHit> iterator = hits.iterator(); 
Map<String, SearchHit> distinctObjects = new HashMap<String,SearchHit>(); 
while (iterator.hasNext()) { 
    SearchHit searchHit = (SearchHit) iterator.next(); 
    Map<String, Object> source = searchHit.getSource(); 
    if(source.get("district") != null){ 
     distinctObjects.put(source.get("district").toString(),source); 
    } 

} 
+0

如果您使用分页方式,该怎么办?获得8个结果的页面,其他10个和其他7个页面,如果每页获得10个结果? – 2017-12-12 15:35:37