본문으로 바로가기

[7.10] elasticSearch REST API spec

category ElasticSearch/ElasticSearch 2021. 9. 24. 02:06

api specification 좀 깔끔히 정리해주면 덧나나. 정말로 찾기가 힘들다고 회사에서 툴툴댔는데 7 버전으로 올라오면서 좀 나아지긴 했다.

 

https://logz.io/blog/elasticsearch-api/

여기 있는 API에 익숙해지면 버전이 변경되어도 어디를 찾아야할지 대충 감이 오기 때문에 일단 한 버전에 익숙해지도록 노력해보자...

 

그리고 이전 버전 ELK를 사용한다고 해서 문제가 될 건 없지만 기술 지원은 받을 수 없다는 것을 알아두자.

상당히 빠르게 버전업되고, 이에 따라 기술 지원을 포기하게 되는 버전이 생각보다 높다.

https://www.elastic.co/kr/support/eol

 

Elastic product end of life dates | Elastic

다음 표에는 위의 정책이 간단하게 설명되어 있습니다. 예를 들어, 새 메이저 버전이 릴리즈된 후에 새 마이너 버전을 릴리즈하는 경우가 있을 수도 있습니다. 그런 경우, 아래 표는 업데이트되

www.elastic.co

 

 

Cluster APIs

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/cluster.html

 

 

cluster health api

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/cluster-health.html

GET /_cluster/health/<target>

 

node stats api

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/cluster-nodes-stats.html

GET /_nodes/stats
GET /_nodes/<node_id>/stats    // <node_id> Comma-separated list of node IDs or names

 

node info API

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/cluster-nodes-info.html#cluster-nodes-info

GET /_nodes

 

 

index APIs(과거명 : indicies APIs)

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices.html

* 참고로 논리적인 document의 구분은 indicies, document를 저장하는 행위는 indexing이라고 합니다.

우리는 index를 생성한 다음 해당 index에 document를 넣는 indexing(색인) 작업을 할 것입니다.

작업순서로 보면 index(indicies)생성 -> document를 특정 index에 저장(indexing)

 

create index

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-create-index.html

PUT /<index>

 

delete index

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-delete-index.html

* 만약, 지우지 않고, 같은 이름의 index이되 새로운 데이터셋을 넣고 싶다면, index pattern 자체를 지워야 한다. kibana - stack manager - index patterns - delete 로!

DELETE /<index>

 

get mapping

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-get-mapping.html

GET /<target>/_mapping

 

 

Document APIs

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/docs.html#docs

* Document APIs 내부에  다양한 api들이 존재하는데, Index api, delete api와 같이 단순히 document를 CRUD하는 api부터 bulk api 등 multi-document를 다루는 api도 존재함.

 

index api 

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/docs-index_.html

* 당연하겠지만 여기서의 index는 indexing, 즉, document 저장을 의미한다.

* 만약, indexing하고자 하는 데이터가 고유한 id를 이미 가지고 있는 경우 식별자 필드를 그대로 id로 넣어주는 것이 편리하다! 즉, DB Record의 식별자 키를 elasticSearch의 실제 키로 사용하는 것이 좋다는 말이다.

* id를 직접 부여할 경우 PUT 메서드, 자동 id 부여는 POST 메서드를 사용한다.

* 같은 id를 가진 document를 PUT하게 되면 오류가 발생하는 것이 아니라 기존 document는 overwritten되는 방식으로 update 되며, 결과값 필드 중 _version이 올라가는 것을 확인할 수 있다.

* 생성, 수정, 삭제시 해당 id의 _version이 올라간다. 자세한 내용은 versioning

* document가 바뀌지 않더라도 언제나 새로운 버전의 document가 생성된다. 자세한 내용은 noop update

PUT /<target>/_doc/<_id> // natural_identifier가 존재한다면 이 녀석을 id로 설정하자
POST /<target>/_doc/     // Automatic ID generation. natural_identifier가 없는 경우 편함

 

만약 indexing하는 과정 중 기존에 존재하는 id가 같아 document를 overwrite하고 싶지 않다면, operation type을 create로 명시해주면 된다. 이것도 elasticSearch 버전마다 표기법이 달라져서 쬐끔 번거로운 면이 있다.

_create guarantees that the document is only indexed if it does not already exist. - https://www.elastic.co/guide/en/elasticsearch/reference/7.10/docs-index_.html#docs-index-api-desc

만약, 해당 id에 이미 도큐먼트가 존재한다면 version_conflict_engine_exception 에러를 발생시킨다. 

PUT /<target>/_create/<_id>
POST /<target>/_create/<_id>

 

 

get api

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/docs-get.html

* CRUD로 치면 Read에 해당하는 부분이다.

GET <index>/_doc/<_id>

 

 

update api

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/docs-update.html

// update_part_of_a_document. 즉, 추가적인 부분만 업데이트 되지, overwrite하는 것이 아님.
POST /<index>/_update/<_id> 
{
  "doc": { ... }
}

 

delete api

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/docs-delete.html

DELETE /<index>/_doc/<_id>

 

 

reindex api

https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html

* mapping을 수정하기 위해 사용된다. mapping을 수정하는 것은 불가능하기 때문에 새로운 mapping을 가진 index를 새로 만들어서 재색인 작업을 해야하는데, 이 작업에 reindex api 빡! 

* https://yookeun.github.io/elasticsearch/2018/12/28/elastic-reindex/ 개인 블로그인데 정리 잘 되어 있다. ㅎ

POST _reindex
{
  "source": {
    "index": "my-index-000001"
  },
  "dest": {
    "index": "my-new-index-000001"
  }
}

 

 

bulk api

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/docs-bulk.html

POST _bulk
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_id" : "2" } }
{ "create" : { "_index" : "test", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }

 

 

Search APIs

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/search.html

 

 

search api

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/search-search.html

* 순수하게 search api만 사용되는 것이 아니라 query DSL이라던가, aggregation과 함께 사용됩니다!

 

기본적으로 size가 10이니까 쿼리 결과물로 10개만 반환되었다고 당황 ㄴㄴ

GET /<target>/_search
GET /_search
POST /<target>/_search
POST /_search

 

또한, 반환값중 total 값도 최대 10000개까지만 반환됨. => "total" : { "value" : 10000, "relation" : "gte" },

만약 정확한 최대 갯수를 알고 싶다면 track_total_hits를 true로 설정해두자.

GET <target>/_search
{
  "track_total_hits": true
}

 

query DSL을 활용하여 결과값을 받을 수도 있다. 여기서는 range를 사용해보았다.

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/query-dsl.html

* range외에도 매우 다양한 query field들이 존재합니다.

* compound query도 존재합니다. query DSL은 내용이 꽤나 방대하기 때문에 별도의 글에서 다룰 것입니다.

 

GET news_headlines/_search
{
  "query": {
    "range": {
      "date": {
        "gte": "2015-06-20",
        "lte": "2015-09-22"
      }
    }
  }
}

 

* match의 경우 operator 기본값이 OR이기에 띄어쓰기마다 단어가 존재하면 일치로 본다. 예를 들어 capital of korea면 capital, of, korea 세 단어 중 하나만 존재해도 일치로 본다. OR 연산을 할 경우 Recall(재현율)이 높아지는 결과를 가져오겠죠. 다만 Precision-Recall Trade-off 법칙에 의해 Precision(정밀도)가 떨어질 수 있다는 단점이 있습니다.

* 반대로 match의 operator를 AND로 설정한다면, Precision이 높아지지만 Recall이 낮아집니다.

* OR이나 AND가 각각 너무 극단적이라면 minimum_should_match를 설정해볼 수 있습니다.

GET news_headlines/_search
{
  "query": {
    "match": {
      "headline": {
        "query": "Khloe Kardashian Kendall Jenner",
        "operator": "and" // AND 연산을하여 precision은 높아지고, recall이 낮아짐
      }
    }
  }
}
GET news_headlines/_search
{
  "query": {
    "match": {
      "headline": {
        "query": "Khloe Kardashian Kendall Jenner",
        "minimum_should_match": 3 // OR 연산을 하되 3개 이상 매칭되어야 함
      }
    }
  }
}

 

 

Aggregation과 함께 쓰일 수도 있다! 

 

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/search-aggregations.html

You can run aggregations as part of a search by specifying the search API's aggs parameter!

 

여기서는 term aggregation을 사용했습니다.

GET news_headlines/_search
{
  "aggs": {
    // my-agg-name라는 필드명으로, category 별로 종합하길 원함
    "my-agg-name": {
      "terms": {
        "field": "category",
        "size": 100
      }
    }
  }
}

 

결과값은 아래와 같습니다.

... hits 생략
  "aggregations" : {
    "my-agg-name" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "POLITICS",
          "doc_count" : 32739
        },
        {
          "key" : "WELLNESS",
          "doc_count" : 17827
        },
        {
          "key" : "ENTERTAINMENT",
          "doc_count" : 16058
        },
     ...

 

 

query DSL과 Aggregation을 함께 사용할 수도 있다. (여기서는 significant_text aggregation을 사용하였다.)

아래 쿼리가 요구하는 바는, "category 필드가 ENTERTAINMENT인 도큐먼트를 가져오되, 그 안에서 significant_text aggregation을 적용하여 popular_in_etnertainment라는 이름으로 반환하라"입니다. 다른 건 몰라도, "쿼리 결과 내에서 aggregation을 한다"라고 알아두면 되겠습니다.

GET news_headlines/_search
{
  "query": {
    "match": {
      "category": "ENTERTAINMENT"
    }
  },
  "aggregations": {
    "popular_in_entertainment": {
      "significant_text": {
        "field": "headline"
      }
    }
  }
}

 

대략적으로 쿼리 결과물은 아래와 같이 나오겠죠.

{
  "took" : 29,
  "timed_out" : false,
  "_shards" : {...},
  "hits" : {
    "total" : {
      "value" : 10000,
      "relation" : "gte"
    },
    "max_score" : 1.0,
    "hits" : [...]
  },
  "aggregations" : {
    "my-agg-name" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [...]
    }
  }
}

 

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체