Elasticsearch 데이터 처리
🙊

Elasticsearch 데이터 처리

Created
May 9, 2024 01:05 AM
Last edited time
Last updated May 9, 2024
Tags
ElasticSearch
Language
URL

Intro::

Elasticsearch의 데이터 처리에 대해 알아봅시다.
 

REST API

💡
Elasticsearch는 http 프로토콜로 접근이 가능한 REST API를 지원합니다. 자원별로 고유 URL로 접근이 가능하며 http 메서드 PUT, POST, GET, DELETE 를 이용해서 자원을 처리합니다. 이런 특성을 가진 시스템을 보통 RESTFul 한 시스템이라고 말합니다.
 

유닉스 curl

MacOS, 리눅스와 같은 유닉스 기반 운영체제에서는 curl 명령어로 REST API 사용이 가능합니다. Elasticsearch를 실행한 후 curl 명령을 이용해서 elasticsearch 클러스터의 최상위 경로를 호출하면 다음과 같은 json 형식의 리턴을 확인할 수 있습니다.
$ curl -XGET "http://localhost:9200" { "name" : "Jongminui-MacBook-Pro.local", "cluster_name" : "elasticsearch", "cluster_uuid" : "hpmT8TPiR1Kk69YNao9V3w", "version" : { "number" : "7.3.0", "build_flavor" : "default", "build_type" : "tar", "build_hash" : "de777fa", "build_date" : "2019-07-24T18:30:11.767338Z", "build_snapshot" : false, "lucene_version" : "8.1.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }
 

Kibana Dev Tools

엘라스틱 홈페이지에서 운영체제별로 맞는 Kibana 버전을 다운받고 파일을 실행 시키면 디폴트로 같은 호스트의 localhost:9200 에서 실행중인 elasticsearch와 통신하며 실행이 됩니다.
kibana.yml 파일을 수정하여 통신포트 혹은 자체 포트를 변경할 수 도 있습니다.
Kibana를 실행한 뒤 웹 브라우저를 열고 http://localhost:5601 로 접속하면 Kibana를 바로 사용할 수 있습니다. Kibana Dev Tools는 쿼리의 자동 완성도 되고 호스트 경로도 별도로 입력할 필요가 없습니다. 그리고 Dev Tools 에서 입력한 명령을 curl 명령으로 변환하여 클립보드에 복사하는 것도 가능합니다.

CRUD - 입력, 조회, 수정, 삭제

입력(PUT)

// 최초 입력 PUT my_index/_doc/1 { "name":"Jongmin Kim", "message":"안녕하세요 Elasticsearch" }
// 최초 입력 결과 { "_index" : "my_index", "_type" : "_doc", "_id" : "1", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 0, "_primary_term" : 1 }
💡
만약에 이미 존재하는 도큐먼트라면 입력 결과의 “result”=”updated” 로 표시된다. 즉, 생성이 아닌 덮어쓰기가 된다.
 
다음과 같이 작성하면 새로운 도큐먼트 입력만 허용하는 것도 가능합니다.
// 입력 PUT my_index/_create/1 { "name":"Jongmin Kim", "message":"안녕하세요 Elasticsearch" }
 

조회(GET)

// 도큐먼트 조회 GET my_index/_doc/1
// 도큐먼트 조회 결과 { "_index" : "my_index", "_type" : "_doc", "_id" : "1", "_version" : 2, "_seq_no" : 1, "_primary_term" : 1, "found" : true, "_source" : { "name" : "Jongmin Kim", "message" : "안녕하세요 Elasticsearch" } }
 

삭제(DELETE)

💡
도큐먼트 또는 인덱스 단위의 삭제가 가능합니다.
// 도큐먼트 삭제 DELETE my_index/_doc/1
// 도큐먼트 삭제 결과 { "_index" : "my_index", "_type" : "_doc", "_id" : "1", "_version" : 3, "result" : "deleted", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 }, "_seq_no" : 2, "_primary_term" : 1 }
 
// 인덱스 삭제 DELETE my_index
// 인덱스 삭제 결과 { "acknowledged" : true }
// 삭제된 인덱스 또는 처음부터 없는 인덱스의 도큐먼트를 조회 결과 { "error" : { "root_cause" : [ { "type" : "index_not_found_exception", "reason" : "no such index [my_index]", "resource.type" : "index_expression", "resource.id" : "my_index", "index_uuid" : "_na_", "index" : "my_index" } ], "type" : "index_not_found_exception", "reason" : "no such index [my_index]", "resource.type" : "index_expression", "resource.id" : "my_index", "index_uuid" : "_na_", "index" : "my_index" }, "status" : 404 }
 

수정(POST)

💡
POST와 PUT은 유사하게 데이터 입력에 사용을 합니다. POST의 경우 도큐먼트의 id가 자동으로 생성되지만 PUT은 id가 생성되지 않습니다.
// 도큐먼트 입력 POST my_index/_doc { "name":"Jongmin Kim", "message":"안녕하세요 Elasticsearch" }
// 도큐먼트 입력 결과 { "_index" : "my_index", "_type" : "_doc", "_id" : "ZuFv12wBspWtEG13dOut",// 자동생성된 결과 "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 0, "_primary_term" : 1 }
 

_update

💡
입력된 도큐먼트를 수정하기 위해서는 기존 도큐먼트의 URL에 변경될 내용의 도큐먼트 내용을 다시 PUT 하는 것으로 대치가 가능합니다. 하지만 필드가 여럿 있는 도큐먼트에서 필드 하나만 바꾸기 위해 전체 도큐먼트 내용을 매번 다시 입력하는 것은 번거로운 작업일 것입니다. 이 때는 POST <인덱스>/_update/<도큐먼트 id> 명령을 이용해 원하는 필드의 내용만 업데이트가 가능합니다. 업데이트 할 내용에 "doc" 이라는 지정자를 사용합니다.
 
// 도큐먼트의 message 필드 업데이트 POST my_index/_update/1 { "doc": { "message":"안녕하세요 Kibana" } }
// 실행 결과 { "_index" : "my_index", "_type" : "_doc", "_id" : "1", "_version" : 2, "result" : "updated", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 }, "_seq_no" : 1, "_primary_term" : 1 }

벌크 API - _bulk API

💡
여러 명령을 배치로 수행하기 위해서 _bulk API의 사용이 가능합니다. _bulk API로 index, create, update, delete의 동작이 가능하며 delete를 제외하고는 명령문과 데이터문을 한 줄씩 순서대로 입해야 합니다. delete는 내용 입력이 필요 없기 때문에 명령문만 있습니다.
 
// _bulk 명령 실행 POST _bulk {"index":{"_index":"test", "_id":"1"}} {"field":"value one"} {"index":{"_index":"test", "_id":"2"}} {"field":"value two"} {"delete":{"_index":"test", "_id":"2"}} {"create":{"_index":"test", "_id":"3"}} {"field":"value three"} {"update":{"_index":"test", "_id":"1"}} {"doc":{"field":"value two"}}
 
💡
모든 명령이 동일한 인덱스에서 수행되는 경우는 <인덱스명>/_bulk 형식으로도 사용이 가능합니다.
POST test/_bulk {"index":{"_id":"1"}} {"field":"value one"} {"index":{"_id":"2"}} {"field":"value two"} {"delete":{"_id":"2"}} {"create":{"_id":"3"}} {"field":"value three"} {"update":{"_id":"1"}} {"doc":{"field":"value two"}}
 
💡
벌크 동작은 따로따로 수행하는 것 보다 속도가 훨씬 빠릅니다. 특히 대량의 데이터를 입력 할 때는 반드시 _bulk API를 사용해야 불필요한 오버헤드가 없습니다. Logstash Beats 그리고 Elastic 웹페이지에서 제공하는 대부분의 언어별 클라이언트에서는 데이터를 입력할 때 _bulk를 사용하도록 개발되어 있습니다.
 

파일에 저장 내용 실행

// bulk.json 파일 {"index":{"_index":"test","_id":"1"}} {"field":"value one"} {"index":{"_index":"test","_id":"2"}} {"field":"value two"} {"delete":{"_index":"test","_id":"2"}} {"create":{"_index":"test","_id":"3"}} {"field":"value three"} {"update":{"_index":"test","_id":"1"}} {"doc":{"field":"value two"}}
$ curl -XPOST "http://localhost:9200/_bulk" -H 'Content-Type: application/json' --data-binary @bulk.json
 

검색 API - _search API

URI 검색

// value 검색 q 파라미터 사용 GET test/_search?q=value
{ "took" : 3, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 0.105360515, "hits" : [ { "_index" : "test", "_type" : "_doc", "_id" : "3", "_score" : 0.105360515, "_source" : { "field" : "value three" } }, { "_index" : "test", "_type" : "_doc", "_id" : "1", "_score" : 0.105360515, "_source" : { "field" : "value two" } } ] } }
 
💡
두 개의 검색어 "value" 그리고 "three"AND 조건으로 검색 하려면 다음과 같이 입력합니다. URI 쿼리에서는 AND, OR, NOT 의 사용이 가능하며 반드시 모두 대문자로 입력해야합니다.
💡
검색어 value 을 field 필드에서 찾고 싶으면 다음과 같이 <필드명>:<검색어> 형태로 입력합니다. 검색은 항상 필드를 지정해서 하는 것이 좋습니다.
// field 필드에서 검색어 value 검색 GET test/_search?q=field:value
 

데이터 본문 검색

💡
데이터 본문(data body) 검색은 검색 쿼리를 데이터 본문으로 입력하는 방식입니다. Elasticsearch의 QueryDSL을 사용하며 쿼리 또한 Json 형식으로 되어 있습니다. 처음 익힐때는 다소 복잡 해 보일 수 있으나 주로 사용하는 쿼리 몇가지들 부터 차근 차근 익혀나가면 크게 어렵지 않게 사용이 가능합니다.
가장 쉽고 많이 사용되는 것은 match 쿼리입니다. 여기서는 문법만 살펴보고 다음 검색 장에서 더 많은 쿼리들에 대해 자세히 다뤄보도록 하겠습니다. 데이터 본문 검색으로 field 필드값이 value 인 도큐먼트를 검색하기 위해서는 다음 명령을 실행합니다.
GET test/_search { "query": { "match": { "field": "value" } } }
 

멀티테넌시 (Multitenancy)

💡
여러 개의 인덱스를 한번에 묶어서 검색할 수 있는 멀티테넌시를 지원합니다.
 
// 쉼표로 나열해서 여러 인덱스 검색 GET logs-2018-01,2018-02,2018-03/_search // 와일드카드 *을 이용해서 여러 인덱스 검색 GET logs-2018-*/_search
 
💡
인덱스명 대신 _all 지정자를 사용해서 모든 인덱스를 대상으로 검색가능하지만 권장하지 않는다.

References::

Loading Comments...