Opensearch에 대한 이론학습을 기반으로 실습을 진행해본다.
환경 변수 설정
OpenSearch의 모든 기능이 REST API형태이기 때문에 REST 클라이언트 툴이 필요하다.
나는 curl을 사용하여 opensearch 노드에 요청을 보낼 것이다!
일단, OpenSearch REST API url을 환경변수로 export 한다.
# OpenSearch REST API Url을 환경 변수로 export 한다.
$ export OPENSEARCH_REST_API=http://localhost:9200
1. Opensearch CRUD
OpenSearch REST API를 사용해서 인덱스, 매핑, 도큐먼트를 직접 생성, 삭제해본다.
Opensearch의 도큐먼트는 모두 json 형식이기 때문에 JSON 응답을 읽기 쉽도록 ?pretty=true쿼리를 사용한다.
(그 외에도 OpenSearch에서는 모든 REST API 작업에서 사용할 수 있는 공통 쿼리를 지원하고 있음)
<인덱스 생성 : PUT /:index>
다음 명령어로 movie index 를 생성할 수 있다.
# rest api 경로 / 인덱스 이름
$ curl -XPUT $OPENSEARCH_REST_API/movie
#응답
{"acknowledged":true,"shards_acknowledged":true,"index":"movie"}%
acknowledged 는 거의 모든 응답에서 필드로 있는 것, true로 되어있으면 내가 원하는 동작이 제대로 적용된 것이다.
<인덱스 확인 : HEAD/: index>
다음 명령어로 movie 인덱스 존재 여부를 확인할 수 있다.
$ curl --head $OPENSEARCH_REST_API/movie
#응답
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 265
200 OK 면 인덱스가 만들어졌다는 것 , 404가 오면 실패했다는 의미이다.
<인덱스 조회 : GET /:index>
다음 명령어로 movie 인덱스 설정이나 매핑에 관한 정보를 조회할 수 있다.
$ curl -XGET "$OPENSEARCH_REST_API/movie?pretty=true"
#응답
{
"movie" : {
"aliases" : { },
"mappings" : { },
"settings" : {
"index" : {
"replication" : {
"type" : "DOCUMENT"
},
"number_of_shards" : "1",
"provided_name" : "movie",
"creation_date" : "1696680892699",
"number_of_replicas" : "1",
"uuid" : "IJLH3bIKQQWUIsNfeQ5j5A",
"version" : {
"created" : "136307827"
}
}
}
}
}
아직 매핑 설정을 안 했기 때문에 mapping 필드값이 빈 객체임을 확인할 수 있다.
shard와 replica는 하나씩 존재한다.
❓shard란 ?
분산 데이터베이스(분산 검색엔진)에서 shard란 데이터를 저장할 때 나누어진 하나의 조각에 대한 단위
각각의 shard는 데이터에 대한 복사본이 아니라, 데이터 그 자체이다!
그림과 같이 shard가 하나의 노드에 저장되어있는 상태에서 노드가 추가된다면, 기존에 존재하던 shard는 각각의 노드에 재분산된다.
이때 가장 먼저 존재하는 데이터 shard를 primary shard라고 한다.
분산 데이터베이스에서는 이렇게 데이터를 나누어 저장하는 방식으로 대용량 데이터에 대한 분산처리를 가능하게 한다.
primary shard는 각 인덱스 별로 최소 1개 이상 존재해야한다.
shard가 많아지면 그만큼 데이터 양에 증가에 대한 노드의 확장으로 대응이 가능하다는 장점이 있지만 shard 그 자체도 비용이기 때문에 적절한 수의 shard를 결정하는 것이 중요하다.
❓ replica란?
replica란 또 다른 형태의 shard로 opensearch(elasticsearch)에서의 기본값은 1이다.
replica가 1이라는 것이 primary shard가 1개라는 것을 의미하지 않고, 이와 같은 복제본이 1개 있다는 것이다.
즉, replica의 개수는 primary shard를 제외한 복제본의 개수이다.
replica가 필요한 이유는
replica shard는 동일한 데이터를 갖고 있는 primary shard와 같은 opensearch(elasticsearch)의 노드 상에 존재할 수 없다.
그 이유는 하나의 노드에 문제가 발생해도 나머지 노드에 모든 데이터 shard들이 존재하기 때문에 정상적인 서비스가 가능하며, 문제가 없는 노드에 있던 replica shard가 자동적으로 primary shard가 된다.
(출처 : https://brownbears.tistory.com/4)
<명시적 매핑 : PUT /:index/_mapping>
다음 명령어로 movie 인덱스에 매핑을 생성할 수 있다.
movie 인덱스에 저장할 도큐먼트의 title 필드 타입을 text로 설정해본다.
$ curl -XPUT $OPENSEARCH_REST_API/movie/_mapping \
# HTTP 헤더를 설정하는 옵션
#"Content-Type" 헤더를 "application/json"으로 설정하여 요청 본문이 JSON 형식임을 나타냄
-H "Content-Type: application/json" \
# json형식의 매핑을 요청
-d '
{
"properties": {
"title": {
"type": "text"
}
}
}
'
#응답
{"acknowledged":true}
다시 인덱스 조회를 해보면 mapping 필드에 필드값이 입력된 것을 확인할 수 있다.
<도큐먼트 생성과 다이나믹 매핑 : POST /:index/_doc>
다음 명령어로 도큐먼트를 movie 인덱스에 저장해보자
POST를 사용하여 인덱싱할 경우 OpenSearch가 도큐먼트 ID를 자동으로 생성해주며,
응답 본문의 _id 필드를 통해 생성된 ID값을 확인할 수 있다.
$ curl -XPOST "$OPENSEARCH_REST_API/movie/_doc?pretty=true" \
-H "Content-Type: application/json" \
-d '
{
"title": "Love Actually",
"genre": "Drama"
}
'
#응답
{
"_index" : "movie",
#id 확인 가능!
"_id" : "2tRKCosBZqsF76AIMQXd",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
또한 shard가 2개가 된 것을 확인할 수 있다.
또한 opensearch는 모든 필드가 nullabel이어도 상관없기 때문에 title에대한 필드값만 전달해줘도 인덱싱 할 수 있다.
즉, 매핑한 모든 필드를 사용할 필요가 없음!
다이나믹 매핑의 가장 큰 특징 ! 명시적으로 매핑한 필드(title, genere 외의) 다른 필드를 사용해서 도큐먼트를 생성할 수 있다.
$ curl -XPOST "$OPENSEARCH_REST_API/movie/_doc?pretty=true" \
-H "Content-Type: application/json" \
-d '
{
"title": "Top Gun: Maverick",
"rate": 8.4,
"director": "Joseph Kosinski"
}
'
#응답
{
"_index" : "movie",
"_id" : "3NRRCosBZqsF76AI7AW3",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1
}
GET /:index를 호출해보면 mappings에 rate와 director 필드가 추가된 것을 확인할 수 있다.
다이나믹 매핑을 사용하면 opensearch가 도큐먼트의 필드값을 보고 데이터 타입을 자동으로 추론해주는데,
string 필드의 경우 text와 keyword 타입이 모두 지원되는 멀티 필드로 구성된다.
멀티 필드는 동일한 필드를 여러 방식으로 인덱싱하고 싶을 때 사용하며 fields 파라미터로 생성할 수 있다.
opensearch는 director 필드의 동일한 값을 text 타입으로 한 번, keyword 타입으로 한 번, 총 두 번 인덱싱하게 된다.
<도큐먼트 조회 : GET /:index/_doc/:id, GET /:index/_search>
인덱싱한 도큐먼트를 ID로 조회해보자
# ID로 조회하는 방법
$ curl -XGET "$OPENSEARCH_REST_API/movie/_doc/2tRKCosBZqsF76AIMQXd?pretty=true"
#응답
{
"_index" : "movie",
"_id" : "2tRKCosBZqsF76AIMQXd",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "Love Actually",
"genre" : "Drama"
}
}
쿼리 DSL 을 사용해서 movie 인덱스 내 모든 도큐먼트를 조회할 수도 있다.
$ curl -XGET "$OPENSEARCH_REST_API/movie/_search?pretty=true"
#응답
{
"took" : 59,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "movie",
"_id" : "2tRKCosBZqsF76AIMQXd",
"_score" : 1.0,
"_source" : {
"title" : "Love Actually",
"genre" : "Drama"
}
},
{
"_index" : "movie",
"_id" : "29RNCosBZqsF76AIOQXH",
"_score" : 1.0,
"_source" : {
"title" : "Interstellar"
}
},
{
"_index" : "movie",
"_id" : "3NRRCosBZqsF76AI7AW3",
"_score" : 1.0,
"_source" : {
"title" : "Top Gun: Maverick",
"rate" : 8.4,
"director" : "Joseph Kosinski"
}
}
]
}
}
<도큐먼트 수정: PUT /:index/_doc/:id, POST /:index/_update/:id>
$ curl -XPUT "$OPENSEARCH_REST_API/movie/_doc/2tRKCosBZqsF76AIMQXd?pretty=true" \
-H "Content-Type: application/json" \
-d '
{
"director": "Richard Curtis"
}
'
#응답
{
"_index" : "movie",
"_id" : "2tRKCosBZqsF76AIMQXd",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 3,
"_primary_term" : 1
}
업데이트 후 도큐먼트를 조회해보니 기존에 인덱싱했던 title 과 genre 필드가 없어졌다.
PUT을 사용하면 동일한 도큐먼트 ID가 존재할 경우 덮어쓰기 작업을 수행하기 때문이다.
ID가 존재하지 않는다면 요청된 ID를 사용하여 새로운 도큐먼트를 만들게 된다.
<도큐먼트 삭제 :DELETE /:index/_doc/:id>
삭제한 도큐먼트는 복구할 수 없으므로 주의해야한다!
$ curl -XDELETE "$OPENSEARCH_REST_API/movie/_doc/2tRKCosBZqsF76AIMQXd?pretty=true"
#응답
{
"_index" : "movie",
"_id" : "2tRKCosBZqsF76AIMQXd",
"_version" : 3,
"result" : "deleted",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 4,
"_primary_term" : 1
}
이 외에도 document apis 에 대한 명령은 공식문서를 통해 확인할 수 있다.
https://opensearch.org/docs/latest/api-reference/document-apis/index/
해당 포스터는 패스트캠퍼스 <한 번에 끝내는 데이터 엔지니어링 초격자 패키지 Online 강의>를 기반으로 작성되었습니다.
'데이터 > 데이터 엔지니어링' 카테고리의 다른 글
[Apache Airflow] ETL 프로젝트 #1 (ETL 파이프라인 구축) (1) | 2023.11.25 |
---|---|
[Apache Airflow] Airflow로 Branch, ML 예제 수행해보기 (1) | 2023.11.19 |
[Chapter 06] 분산시스템의 이해, Zookeeper (1) | 2023.10.01 |
[Chapter 05 | Observability] Grafana로 대시보드 구축하기 (0) | 2023.09.23 |
[Chatper 05 | Observability] Prometheus 이해하기 (0) | 2023.09.23 |