인덱스 문서 API

인덱스 문서 API (Index Document API)

인덱스에 JSON 문서를 넣고 검색 가능하게 만들고 싶으시죠? 인덱스 문서 API가 지정된 인덱스에 JSON 문서를 추가하고 검색 가능하게 해줘요. 같은 ID의 문서가 이미 있으면 API가 문서를 업데이트하고 버전 번호를 증가시켜요.

출처: 문서

본문

1.0에서 도입

인덱스 문서 API는 지정된 인덱스에 JSON 문서를 추가하고 검색 가능하게 해줘요. 같은 ID의 문서가 이미 존재하면 API가 문서를 업데이트하고 버전 번호를 증가시켜요.

엔드포인트

PUT {index}/_doc/{id}
POST {index}/_doc

PUT {index}/_create/{id}
POST {index}/_create/{id}

다음 엔드포인트 조합을 사용해 문서를 인덱싱하는 방법을 제어해요.

  • PUT {index}/_doc/{id}: 지정된 ID로 새 문서를 추가하거나 같은 ID의 기존 문서를 업데이트해요.
  • POST {index}/_doc: 새 문서를 추가하고 고유 ID를 자동 생성해요.
  • PUT {index}/_create/{id} 또는 POST {index}/_create/{id}: 지정된 ID의 문서가 아직 없을 때만 새 문서를 추가해요. 문서가 존재하면 연산이 실패해요.

경로 파라미터

다음 표는 사용 가능한 경로 파라미터예요.

Parameter Data type Description
index String 인덱스의 이름이에요. 인덱스가 존재하지 않으면 자동 인덱스 생성이 비활성화되지 않는 한 OpenSearch가 자동으로 만들어요. 필수예요.
id String 고유 문서 ID예요. PUT을 사용할 때 필수예요. POST를 사용할 때는 이 파라미터를 생략해 OpenSearch가 고유 ID를 자동 생성하게 해요.

쿼리 파라미터

다음 표는 사용 가능한 쿼리 파라미터예요. 모든 쿼리 파라미터는 선택적이에요.

Parameter Data type Description
if_seq_no Integer 문서의 현재 시퀀스 번호가 지정된 값과 일치할 때만 연산을 수행해요. 낙관적 동시성 제어에 사용돼요. Optimistic concurrency control을 참고하세요.
if_primary_term Integer 문서의 현재 primary term이 지정된 값과 일치할 때만 연산을 수행해요. 낙관적 동시성 제어에 사용돼요. Optimistic concurrency control을 참고하세요.
op_type Enum 연산 유형이에요. 유효한 값은 create(문서가 아직 없을 때만 인덱싱)와 index(새 문서 생성 또는 기존 문서 업데이트)예요. 문서 ID가 지정되면 기본값은 index이고, 그렇지 않으면 기본값은 create예요.
pipeline String 인덱싱 전에 문서를 전처리하는 데 사용할 ingest 파이프라인의 ID예요.
routing String 연산을 특정 샤드로 라우팅하는 데 사용되는 사용자 정의 라우팅 값이에요. Routing을 참고하세요.
refresh Enum 연산 후 영향받은 샤드를 refresh할지 여부예요. 유효한 값은 true(즉시 refresh), false(refresh 안 함), wait_for(응답 전에 refresh 발생을 기다림)예요. 기본값은 false예요. Refresh를 참고하세요.
timeout Time primary 샤드를 사용할 수 없을 때 사용 가능해질 때까지 기다리는 시간이에요. 기본값은 1m예요. Timeout을 참고하세요.
version Integer 동시성 제어를 위한 명시적 버전 번호예요. 문서의 현재 버전이 이 값과 일치할 때만 문서가 인덱싱돼요. Versioning을 참고하세요.
version_type Enum 외부 버전 관리를 위한 버전 유형이에요. 유효한 값은 external(지정 버전이 저장된 버전보다 클 때만 인덱싱)과 external_gte(지정 버전이 저장된 버전보다 크거나 같을 때만 인덱싱)예요. 기본값은 internal이에요. Versioning을 참고하세요.
wait_for_active_shards String 연산을 진행하기 전에 필요한 활성 샤드 복사본 수예요. 유효한 값은 all 또는 총 샤드 수까지의 양의 정수예요. 기본값은 1(primary 샤드만)이에요. Wait for active shards를 참고하세요.
require_alias Boolean 대상 인덱스 이름이 인덱스 alias여야 하는지 여부예요. true이고 대상이 alias가 아니면 요청이 실패해요. 기본값은 false예요.

예시 요청

다음 예시 요청은 sample_index라는 인덱스에 대한 샘플 인덱스 문서를 만들어요.

예시 PUT 요청

PUT /sample_index/_doc/1
{
  "name": "Example",
  "price": 29.99,
  "description": "To be or not to be, that is the question"
}

예시 POST 요청

POST /sample_index/_doc
{
  "name": "Another Example",
  "price": 19.99,
  "description": "We are such stuff as dreams are made on"
}

예시 응답

{
  "_index": "sample-index",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}

응답 본문 필드

다음 표는 모든 응답 본문 필드를 나열해요.

Field Data type Description
_index String 문서가 추가된 인덱스의 이름이에요.
_id String 문서의 고유 식별자예요.
_version Integer 문서의 버전 번호예요. 문서가 업데이트될 때마다 증가해요.
result String 인덱싱 연산의 결과예요. 가능한 값은 created(새 문서 생성)와 updated(기존 문서 업데이트)예요.
_shards Object 복제 과정에 대한 정보예요.
_shards.total Integer 연산이 실행돼야 하는 샤드 복사본 수(primary와 replica)예요.
_shards.successful Integer 연산이 성공한 샤드 복사본 수예요. 연산이 성공하면 이 값은 최소 1(primary 샤드)예요.
_shards.failed Integer 연산이 실패한 샤드 복사본 수예요. 연산이 성공하면 이 값은 0이에요.
_seq_no Integer 이 인덱싱 연산에 대해 문서에 할당된 시퀀스 번호예요. 시퀀스 번호는 이전 버전의 문서가 더 새로운 버전을 덮어쓰지 않도록 보장하는 데 사용돼요. Optimistic concurrency control을 참고하세요.
_primary_term Integer 이 인덱싱 연산에 대해 문서에 할당된 primary term이에요. Optimistic concurrency control을 참고하세요.

자동 인덱스 생성 (Automatic index creation)

기본적으로 지정된 인덱스가 존재하지 않으면 인덱스 문서 API가 자동으로 만들고 구성된 인덱스 템플릿을 적용해요. 명시적 매핑이 없으면 API는 새 필드에 대한 동적 매핑도 만들어요.

자동 인덱스 생성은 action.auto_create_index 설정으로 제어돼요. 기본적으로 이 설정은 true라서 어떤 인덱스든 자동 생성이 허용돼요. 이 설정을 수정해 특정 패턴에 따라 인덱스 생성을 허용하거나 차단하거나 자동 인덱스 생성을 완전히 비활성화할 수 있어요. 자세한 내용은 Create index를 참고하세요.

낙관적 동시성 제어 (Optimistic concurrency control)

if_seq_no와 if_primary_term 파라미터를 사용해 문서의 현재 시퀀스 번호와 primary term에 기반한 조건부 인덱싱을 수행할 수 있어요. 이는 문서를 마지막으로 가져온 이후 수정되지 않은 경우에만 연산이 성공하도록 보장해요.

예를 들어 문서가 시퀀스 번호 3과 primary term 1을 가질 때만 업데이트하려면 요청에 이 파라미터를 포함해요.

PUT sample-index/_doc/1?if_seq_no=3&if_primary_term=1
{
  "name": "Updated Example",
  "price": 39.99
}

시퀀스 번호나 primary term이 현재 값과 일치하지 않으면 OpenSearch는 버전 충돌 오류(HTTP 409)를 반환하며, 최신 버전을 가져와 연산을 재시도할 수 있어요.

자동 ID 생성 (Automatic ID generation)

문서 ID를 지정하지 않고 POST 메서드를 사용하면 OpenSearch가 문서에 고유 ID를 자동 생성해요. op_type이 자동으로 create로 설정되어 항상 새 문서가 만들어지도록 보장해요.

다음 예시는 ID를 지정하지 않고 문서를 인덱싱해 OpenSearch가 자동으로 생성하게 해요.

POST sample-index/_doc
{
  "user": "john_doe",
  "post_date": "2024-01-15T10:30:00",
  "message": "Hello, OpenSearch!"
}

응답에는 자동 생성된 ID가 포함돼요.

{
  "_index": "sample-index",
  "_id": "W0tpsmIBdwcYyG50zbta",
  "_version": 1,
  "_seq_no": 0,
  "_primary_term": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  }
}

생성된 ID는 클러스터 전체에서 고유성을 보장하는 Base64 인코딩된 UUID예요.

라우팅 (Routing)

기본적으로 OpenSearch는 문서 ID의 해시를 계산해 문서를 저장할 샤드를 결정해요. 사용자 정의 routing 파라미터 값을 제공해 이 동작을 재정의할 수 있어요.

다음 예시는 라우팅 값 user123에 따라 문서를 샤드로 라우팅해요.

POST sample-index/_doc?routing=user123
{
  "user": "john_doe",
  "message": "Hello, world!"
}

인덱싱 시 사용자 정의 라우팅을 사용하면 문서를 검색, 업데이트, 삭제할 때도 같은 라우팅 값을 제공해야 해요. 그렇지 않으면 OpenSearch가 문서를 찾을 수 없어요.

분산 모델 (Distributed model)

인덱스 연산은 문서의 라우팅 값(문서 ID 또는 사용자 정의 라우팅 값)에 따라 primary 샤드로 보내져요. primary 샤드가 연산을 완료하면 OpenSearch는 업데이트를 복제 그룹의 모든 적용 가능한 replica 샤드로 분배해요.

이 분산 접근 방식은 모든 샤드 복사본이 동기화 상태를 유지하도록 보장해요. primary 샤드가 복제 과정을 조정하고, 필요한 수의 활성 샤드로부터 확인을 기다린 후 클라이언트에 성공을 승인해요.

활성 샤드 대기 (Wait for active shards)

쓰기 연산의 복원력을 향상시키기 위해 인덱스 문서 API를 진행하기 전에 특정 수의 활성 샤드 복사본을 기다리도록 구성할 수 있어요. 기본적으로 연산은 primary 샤드만 활성이면 됩니다(wait_for_active_shards=1).

wait_for_active_shards를 all 또는 총 샤드 복사본 수(number_of_replicas + 1)까지의 양의 정수로 설정할 수 있어요. 필요한 수의 활성 샤드를 사용할 수 없으면 연산은 샤드가 사용 가능해질 때까지 또는 타임아웃이 발생할 때까지 기다렸다가 재시도해요.

예를 들어 세 개의 노드(A, B, C)가 있고 number_of_replicas가 3으로 설정된 인덱스(4개 샤드 복사본: primary 하나와 replica 세 개)가 있는 클러스터를 생각해 보세요. 기본적으로 노드 B와 C가 다운돼 있고 노드 A가 primary 샤드 복사본을 호스팅해도 인덱싱 연산은 primary 샤드를 사용할 수 있다면 진행돼요.

요청에 wait_for_active_shards=3을 설정하면 인덱싱 연산은 진행 전에 3개의 활성 샤드 복사본을 요구해요. 이 요구는 모든 3개 노드가 실행 중이고 각 노드가 샤드 복사본을 하나씩 포함할 때 충족될 수 있어요. 그러나 wait_for_active_shards=all(또는 4)로 설정하면 4개 복사본을 모두 활성화해야 하는데 노드는 3개뿐이므로 인덱싱 연산이 진행되지 않아요. 새 노드가 합류해 네 번째 샤드 복사본을 호스팅하지 않으면 연산이 타임아웃돼요.

다음 예시는 진행 전에 최소 2개의 활성 샤드 복사본(primary와 replica 하나)을 요구해요.

PUT sample-index/_doc/1?wait_for_active_shards=2
{
  "name": "Example",
  "price": 29.99
}

이 설정은 충분하지 않은 수의 샤드 복사본에 쓰는 위험을 줄여주지만 완전히 없애지는 않아요. 검사는 쓰기 연산이 시작되기 전에 발생해요. 연산이 시작된 후에는 primary에서 성공하면서 일부 replica에서는 복제가 여전히 실패할 수 있어요. 응답의 _shards 섹션은 몇 개의 샤드 복사본이 성공했는지 실패했는지를 나타내요.

Refresh

refresh 파라미터는 인덱싱된 문서가 검색 연산에 언제 표시되는지 제어해요. 대부분의 사용 사례에는 최적의 성능을 위해 기본값(false)을 사용해요.

유효한 옵션은 다음과 같아요.

  • false(기본값): 문서가 인덱스 refresh 간격(기본적으로 1초)에 따라 표시돼요.
  • true: 인덱싱 후 즉시 refresh를 강제해 문서를 즉시 검색 가능하게 해요. 자주 refresh하면 성능에 큰 영향을 줄 수 있으므로 아껴서 사용해요.
  • wait_for: 응답하기 전에 다음 예약된 refresh를 기다려요. 일괄 연산에서 true보다 효율적이에요.

타임아웃 (Timeout)

인덱스 요청을 제출할 때 primary 샤드를 사용할 수 없으면(예: 복구나 재배치 중) 연산은 기본적으로 실패하기 전에 최대 1분을 기다려요. timeout 파라미터로 이 동작을 조정할 수 있어요.

PUT sample-index/_doc/1?timeout=5m
{
  "name": "Example",
  "price": 29.99
}

버전 관리 (Versioning)

인덱싱된 모든 문서에는 버전 번호가 있어요. 기본적으로 OpenSearch는 내부 버전 관리를 사용해 1에서 시작해 업데이트나 삭제 연산마다 증가해요.

외부 버전 관리(예: 별도 데이터베이스에서 버전 번호를 유지)의 경우 version_type 파라미터를 설정해 OpenSearch가 버전 충돌을 처리하는 방식을 제어해요. 다음 표는 사용 가능한 버전 유형을 나열해요.

Version type Description
internal 지정된 버전이 저장된 문서의 버전과 동일할 때만 문서를 인덱싱해요. 기본 버전 유형이에요.
external or external_gt 지정된 버전이 저장된 문서의 버전보다 엄격히 크거나 기존 문서가 없을 때만 문서를 인덱싱해요. 지정된 버전이 새 버전으로 사용되어 문서와 함께 저장돼요. 제공된 버전은 음수가 아닌 long 정수여야 해요.
external_gte 지정된 버전이 저장된 문서의 버전보다 크거나 같을 때만 문서를 인덱싱해요. 기존 문서가 없으면 연산이 성공해요. 지정된 버전이 새 버전으로 사용되어 문서와 함께 저장돼요. 제공된 버전은 음수가 아닌 long 정수여야 해요.

external_gte 버전 유형은 특수한 사용 사례를 위한 것이며 주의해서 사용해야 해요. 잘못 사용하면 데이터 손실이 발생할 수 있어요.

예를 들어 외부 버전 관리를 사용해 문서를 인덱싱하려면:

PUT sample-index/_doc/1?version=5&version_type=external
{
  "name": "Example",
  "price": 29.99,
  "description": "Updated from external system"
}

제공된 버전이 지정된 버전 유형의 요구 사항을 충족하지 않으면 OpenSearch는 버전 충돌 오류를 반환해요. 버전 관리는 완전히 실시간이며 검색 연산의 근실시간 측면에 영향을 받지 않아요.

무작동 업데이트 (No-op updates)

인덱스 문서 API로 문서를 업데이트하면 문서 내용이 변경되지 않았어도 OpenSearch는 항상 새 버전의 문서를 만들어요. 같은 내용으로 문서를 자주 재인덱싱하면 이 동작이 비효율적일 수 있어요.

불필요한 문서 버전 생성을 피해야 한다면 detect_noop 파라미터를 true로 설정한 Update Document API를 사용해요. Update API는 기존 문서를 가져와 새 내용과 비교하고, 내용이 변경된 경우에만 새 버전을 만들어요.

인덱스 문서 API는 비교를 위해 이전 소스를 가져오지 않으므로 무작동 감지를 지원하지 않아요. 무작동 업데이트가 문제가 되는지는 데이터 소스가 문서를 변경하지 않는 업데이트를 얼마나 자주 보내는지, 그리고 업데이트를 받는 샤드의 쿼리 부하 등 여러 요소에 따라 달라져요.

보안

Security 플러그인을 사용한다면 적절한 권한이 있는지 확인해야 해요: indices:data/write/index.

더 알아보기 (Learn more)

  • _create 엔드포인트를 쓰면 같은 ID의 문서가 존재할 때 덮어쓰기를 피할 수 있어요.
  • 외부 버전 관리를 쓸 때는 버전 유형별 규칙을 지켜야 데이터 손실을 막을 수 있어요.