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. Опитах агрегиране на термини, но то върна само count distinct.

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

Благодаря за помощта! :-)


person Kevin    schedule 23.09.2014    source източник
comment
Отговорът ми решава ли проблема ви   -  person Akash Yadav    schedule 23.09.2014


Отговори (2)


Ако вашата версия на ElasticSearch е 1.3 или по-нова, можете да използвате подгрупа от тип top_hits, което ще ви даде (по подразбиране) първите три съвпадащи документа, сортирани според резултата на вашата заявка (тук 1, тъй като използвате заявка match_all).

Можете да зададете параметъра 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
                           }
                        }
                     ]
                  }
               }
            }
         ]
      }
   }
}
person ThomasC    schedule 23.09.2014
comment
Страхотно, спасявате живота ми!! - person Kevin; 23.09.2014
comment
Хей, @ThomasC, някаква идея как да филтрирате записи, които трябва да бъдат обобщени по този начин? Опитвам се от половин час вече. Благодаря ! - person lisak; 30.11.2015
comment
Здравей @lisak! Не можете да вложите агрегиране под top_hits, но обратното е възможно. Опитайте да използвате филтърно агрегиране и вмъкнете top_hits под. Или можете да филтрирате резултатите в секцията за заявка - person ThomasC; 17.12.2015
comment
@ThomasC можеш ли да отговориш на това stackoverflow.com/questions/46764307/ - person Sunil Garg; 16.10.2017
comment
Това работи, но ако има повече от 500 уникални района, има ли начин да направя пагинация, къде да поставя от ключова дума, агрегирането на термини не го поддържа - person Abhijit; 01.01.2020

Еластичното търсене не предоставя различни документи по стойност или групи по уникална стойност. Но има работа за това, можете да направите това, ако използвате 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);
    }

} 
person Akash Yadav    schedule 23.09.2014
comment
Ами ако използвате пагинация? Получавате ли страници с 8 резултата, други с 10 и други със 7, ако получавате 10 резултата на страница? - person Vladimir Nul; 12.12.2017
comment
не е заобиколно решение. това е собствено колело презаписване. Ще прочетеш ли всички обекти в паметта си? ами ако има милиони от тях? - person walv; 10.09.2018