ElasticSearch-고유 값 반환


122

languages레코드에서 모든 값을 가져와 고유하게 만드는 방법은 무엇입니까 ?

기록

PUT items/1
{ "language" : 10 }

PUT items/2
{ "language" : 11 }

PUT items/3
{ "language" : 10 }

질문

GET items/_search
{ ... }

# => Expected Response
[10, 11]

어떤 도움이라도 좋을 것입니다.


1
fields: [languages]주어진 필드의 값만 제공하지만 코드에서 고유하게 만드는 것이 아마도 더 쉬울 것입니다. 당신을 위해 그것을 할 수있는 편리한 집계가있을 수 있습니다.
Ashalynd 2014-08-23

1
이 주제를 연구하는 사람들을 위해 여기에도 유용한 토론이 있습니다. elasticsearch에서 고유 한 개수가 아닌 고유 한 값 찾기
blong

답변:


165

집계라는 용어 를 사용할 수 있습니다 .

{
"size": 0,
"aggs" : {
    "langs" : {
        "terms" : { "field" : "language",  "size" : 500 }
    }
}}

검색하면 다음과 같은 결과가 반환됩니다.

{
"took" : 16,
"timed_out" : false,
"_shards" : {
  "total" : 2,
  "successful" : 2,
  "failed" : 0
},
"hits" : {
"total" : 1000000,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
  "langs" : {
    "buckets" : [ {
      "key" : "10",
      "doc_count" : 244812
    }, {
      "key" : "11",
      "doc_count" : 136794

    }, {
      "key" : "12",
      "doc_count" : 32312
       } ]
    }
  }
}

size집계 지정 내의 파라미터 용어의 최대 수는 집계 결과에 포함한다. 모든 결과가 필요한 경우 데이터의 고유 용어 수보다 큰 값으로 설정하십시오.


2
"fields" : ["language"]동일한 결과를 가져옵니다. 집계 프레임 워크가 언어 값만 반환 할 수 있는지 확인하기 위해 답변을 확장 할 수 있습니까? #=> [10, 11, 10]
ChuckJHardy 2014 년

1
@CharlesJHardy, 동일한 결과가 없습니다. 찾고있는 데이터는 "집계"키 아래에 있습니다. 예제 결과로 내 대답을 편집했습니다. 문서를 포함하지 않으려면 원하는 집계 결과 만 포함하려면 "크기"를 0으로 설정할 수도 있습니다.
Anton

1
가능한 값이 많은 경우 및 language을 추가 size=0하여 모든shard_size=0을 얻을 있습니다. elasticsearch.org/guide/en/elasticsearch/reference/current/…
Dror

3
이 답변은 OP를 다루지 않는다고 생각합니다. 원래 질문은 중요하지 않은 고유 한 값을 원합니다 . 내가 뭔가를 놓치고 있습니까?
bhurlow

4
@BHBH, 대답은 고유 한 값을 제공합니다. "키"값, 즉 "10", "11"및 "12"입니다. (aggregations> langs> buckets> key ...)
Anton

9

Elasticsearch 1.1+에는 고유 한 개수를 제공 하는 카디널리티 집계 가 있습니다.

실제로는 근사치이며 높은 카디널리티 데이터 세트로 정확도가 떨어질 수 있지만 일반적으로 테스트에서는 꽤 정확합니다.

precision_threshold매개 변수를 사용하여 정확도를 조정할 수도 있습니다 . 절충 또는 과정은 메모리 사용량입니다.

문서의이 그래프는 더 높은 값 precision_threshold이 훨씬 더 정확한 결과로 이어지는 방법을 보여줍니다 .


상대 오류 대 임계 값


2
카디널리티 집계 는 용어가 존재하는 경우 결과에 표시되도록 보장 합니까 (개수> = 1)? 아니면 대규모 데이터 세트에서 한 번만 나타나는 일부 용어를 놓칠 수 있습니까?
마크

2
@mark는 설정 한 정밀도 임계 값에 따라 다릅니다. 임계 값이 높을수록 놓칠 가능성이 적습니다. 정밀도 임계 값 설정에는 40,000 제한이 있습니다. 즉, 그보다 높은 데이터 세트는 추정치가 있으므로 단일 값을 놓칠 수 있습니다
Sundar

12
이 대답이 틀렸다고 생각합니다. 카디널리티 집계는 훌륭한 도구입니다. 그러나 작업은 용어가 몇 개 있는지 추정하는 것이 아니라 용어 자체를 검색하는 것이 었습니다.
안톤

4

language필드 고유 값에 대한 첫 번째 문서를 얻으려면 다음을 수행하십시오.

{
 "query": {
    "match_all": {
    }
  },
  "collapse": {
    "field": "language.keyword",
    "inner_hits": {
    "name": "latest",
      "size": 1
    }
  }
}

3

저도 제 자신을 위해 이런 종류의 해결책을 찾고 있습니다. 집계 용어 에서 참조를 찾았습니다 .

따라서 다음은 적절한 해결책입니다.

{
"aggs" : {
    "langs" : {
        "terms" : { "field" : "language",  
                    "size" : 500 }
    }
}}

그러나 다음과 같은 오류가 발생한 경우 :

"error": {
        "root_cause": [
            {
                "type": "illegal_argument_exception",
                "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [fastest_method] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."
            }
        ]}

이 경우 다음과 같이 요청에 " KEYWORD " 를 추가해야합니다 .

   {
    "aggs" : {
        "langs" : {
            "terms" : { "field" : "language.keyword",  
                        "size" : 500 }
        }
    }}

1

근사치 또는 매직 넘버 ( size: 500) 설정없이 모든 고유 값 을 얻으려면 COMPOSITE AGGREGATION (ES 6.5+)을 사용하십시오 .

에서 공식 문서 :

"중첩 된 용어 집계에서 모든 용어 또는 모든 용어 조합을 검색 하려면 용어 집계에서 필드의 카디널리티보다 큰 크기를 설정하는 대신 가능한 모든 용어에 대해 페이지를 매길 수 있는 COMPOSITE AGGREGATION사용해야합니다 . 용어 집계는 상위 용어를 반환하기위한 것이며 페이지 매김을 허용하지 않습니다. "

JavaScript의 구현 예 :

const ITEMS_PER_PAGE = 1000;

const body =  {
    "size": 0, // Returning only aggregation results: https://www.elastic.co/guide/en/elasticsearch/reference/current/returning-only-agg-results.html
    "aggs" : {
        "langs": {
            "composite" : {
                "size": ITEMS_PER_PAGE,
                "sources" : [
                    { "language": { "terms" : { "field": "language" } } }
                ]
            }
        }
     }
};

const uniqueLanguages = [];

while (true) {
  const result = await es.search(body);

  const currentUniqueLangs = result.aggregations.langs.buckets.map(bucket => bucket.key);

  uniqueLanguages.push(...currentUniqueLangs);

  const after = result.aggregations.langs.after_key;

  if (after) {
      // continue paginating unique items
      body.aggs.langs.composite.after = after;
  } else {
      break;
  }
}

console.log(uniqueLanguages);

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.