OpenSearch에는 인덱스 API와 _bluk API 두 가지가 있다.
새로운 데이터가 점진적으로 ( 소규모 비즈니스의 고객 주문 등 ) 쌓이는 구조의 경우 인덱스 API를 사용하여 개별적으로 문서를 추가할 수 있다.
데이터의 흐름이 더욱 천천히 쌓이는 경우 ( 마케팅 웹사이트에 대한 주간 업데이트 등 ) 파일을 생성하여 _bluk API로 보내는 것이 좋습니다.
많은 수의 문서에 대해 함께 묶어서 _bluk API를 사용하면 우수한 성능을 제공 받을 수 있습니다. 하지만 문서가 그보다 방대하다면 개별적으로 인덱스를 생성하는 것이 좋습니다.
데이터를 검색하려면 먼저 인덱스를 생성해야 합니다. OpenSearch는 고유 ID를 사용하여 각 문서를 식별합니다.
// Index API 요청
PUT <index>/_doc/<id>
{ "A JSON": "document" }
_bulk API에 대한 요청은 데이터 내부에서 인덱스와 ID를 지정하기 때문에 약간 다르게 보일 수 있습니다.
// _bulk API 요청
POST _bulk
{ "index": { "_index": "<index>", "_id": "<id>" } }
{ "A JSON": "document" }
bulk(대량의) 데이터는 마지막 줄을 포함하여 모든 줄 끝에 개행문자 '\n'를 붙여야 합니다.
Action and metadata\n
Optional document\n
Action and metadata\n
Optional document\n
curl 명령어로 bulk(대량의) 데이터를 인덱싱하려면, 데이터가 저장되어있는 폴더로 이동하여 아래 명령어를 수행해야 합니다.
// curl 명령어를 통한 대량 데이터 인덱싱 커멘드
curl -H "Content-Type: application/x-ndjson" -POST https://localhost:9200/data/_bulk -u 'admin:admin' --insecure --data-binary "@data.json"
만약 여러 _bulk API들 중 하나가 fail이 나도 OpenSearch는 다른 작업들을 계속 수행합니다.
OpenSearch는 존재하지 않는 index에 문서를 추가할 때 자동으로 index를 생성합니다. 또한 요청에 ID를 지정하지 않으면 자동으로 ID를 생성합니다. 아래는 간단한 예제입니다.
// 자동 ID 생성의 예
POST movies/_doc // 자동 ID생성의 단점 : ID를 지정하지 않았기 때문에 나중에 문서를 업데이트하기 어려움. 이같은 요청을 10번 실행한다면 이 문서를 고유한 ID를 가진 10개의 다른 문서로 인덱싱함.
{ "title": "Spirited Away" }
// ID 지정하여 생성 (ID지정하여 생성 시 PUT으로 요청)
PUT movies/_doc/1 // ID를 지정하여 생성했기 때문에 이 명령을 10번 실행하면, _version필드가 10으로 증가된 index에 하나의 문서만 남게된다.
{ "title": "Spirited Away" }
인덱스는 기본적으로 하나의 기본 샤드와 하나의 복제본으로 설정됩니다. 기본값이 아닌 다른 설정을 원하면 문서를 추가하기 전에 색인을 생성해야 합니다.
// 인덱스 커스텀 설정
PUT more-movies
{ "settings": { "number_of_shards": 6, "number_of_replicas": 2 } }
:: 데이터 읽기
문서를 인덱싱 한 후 동일한 엔드포인트에 GET 요청을 보내 문서를 검색할 수 있습니다.
// 인덱스 GET 요청 및 응답
GET movies/_doc/1
{
"_index" : "movies",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "Spirited Away"
}
}
// _source 개체에서 문서를 볼 수 있습니다. 문서를 찾을 수 없는 경우 found 값은 false로 나타납니다.
// 다중 문서 검색
GET _mget
{
"docs": [
{
"_index": "<index>",
"_id": "<id>"
},
{
"_index": "<index>",
"_id": "<id>"
}
]
}
// 단일 명령으로 여러 문서를 검색하려면 _mget 요청을 보내면 됩니다.
요청 데이터는 본문에 _index와 _id를 보내야하는 _bulk 요청과 유사합니다.
// 특정 필드 반환 검색
GET _mget
{
"docs": [
{
"_index": "<index>",
"_id": "<id>",
"_source": "field1"
},
{
"_index": "<index>",
"_id": "<id>",
"_source": "field2"
}
]
}
// 문서가 있는지 확인하려면
HEAD movies/_doc/<doc-id>
// 문서가 있으면 200 OK 응답을 반환하고, 없으면 404 - Not Found 오류를 반환합니다.
:: 데이터 업데이트
문서에 기존 필드를 업데이트하거나 새 필드를 추가하려면 개체의 변경사항과 함께 POST _update 요청을 보냅니다.
// 데이터 추가 및 업데이트
POST movies/_update/1
{
"doc": {
"title": "Castle in the Sky", // 기존에 있는 필드
"genre": ["Animation", "Fantasy"] // 기존에 없던 필드
}
}
// 업데이트 후 GET 요청
GET movies/_doc/1
{
"_index" : "movies",
"_type" : "_doc",
"_id" : "1",
"_version" : 2,
"_seq_no" : 1,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "Castle in the Sky", // update 처리됨
"genre" : [ // 새로 add 됨.
"Animation",
"Fantasy"
]
}
}
// 문서에는 업데이트된 횟수를 추적할 수 있는 _version필드가 있습니다.
// POST 요청은 문서를 부분적으로 업데이트할 때 쓰입니다.
// 문서를 완전히 바꾸려면 PUT요청을 사용해야 합니다.
PUT movies/_doc/1
{
"title": "Spirited Away"
}
// 위 PUT 요청에 해당 문서는 title 필드 하나만 있는 문서로 업데이트 됩니다.
upsert요청으로 문서가 이미 존재하는지 여부에 따라 조건부로 문서를 업데이트할 수 있습니다.
// 문서가 있는 경우 title 필드는 'Castle in the Sky'로 변경됩니다.
// 문서가 없는 경우 upsert 객체로 인덱싱 합니다.
POST movies/_update/2
{
"doc": {
"title": "Castle in the Sky"
},
"upsert": {
"title": "Only Yesterday",
"genre": ["Animation", "Fantasy"],
"date": 1993
}
}
// 응답 예시
{
"_index" : "movies",
"_type" : "_doc",
"_id" : "2",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 3,
"_primary_term" : 1
}
// 각 업데이트 작업에는 _seq_no와 _primary_term 두 개의 값으로 유니크가 걸려지게 됩니다.
// OpenSearch는 먼저 기본 샤드에 업데이트를 기록한 다음 변경 사항을 모든 복제본 샤드에 보냅니다.
// OpenSearch에서 여러 사용자가 동일한 index에 있는 동일한 문서를 업데이트하면 문제가 발생할 수 있습니다.
// 이 상황에서 다른 사용자는 기본 샤드에서 업데이트를 수신하기 전에 복제본에서 문서를 읽고 업데이트할 수 있습니다.
// 이러한 상황을 방지하려면 요청헤더에 _seq_no와 _primary_term값을 사용해야 합니다.
POST movies/_update/2?if_seq_no=3&if_primary_term=1
{
"doc": {
"title": "Castle in the Sky",
"genre": ["Animation", "Fantasy"]
}
}
// 문서를 검색한 후 업데이트하면 _seq_no 및 _primary_term값이 다르며 업데이트 작업이 409 - Conflict 오류와 함께 실패하게 됩니다.
// _bulk API에서는 데이터 내에서 _seq_no와 _primary_term값을 지정합니다.
:: 데이터 삭제
// 데이터 삭제
DELETE movies/_doc/1
// DELETE 작업은 _version 필드를 증가시킵니다. 문서를 동일한 ID에 다시 추가하면 _version필드가 다시 증가합니다.
// OpenSearch에서는 문서의 _source를 삭제하지만 해당 메타데이터는 유지하기 때문입니다.
'OpenSearch (ElasticSearch)' 카테고리의 다른 글
[6] 데이터 스트림 (0) | 2022.02.25 |
---|---|
[5] 인덱스 별칭 (aliases) (0) | 2022.02.22 |
[3] 인덱스 생성과 설정 예제 (0) | 2022.02.17 |
[2] Opensearch와 클러스터 설정 (0) | 2022.02.14 |
[1] OpenSearch란? Opensearch와 일반 RDB 비교 (0) | 2022.02.12 |