Page tree
Skip to end of metadata
Go to start of metadata

Elasticsearch에서의 데이터

  • 논리적 구조(Logical layout)
    • Document는 mapping type으로 그룹핑 되어 있고, type 이라고 부른다.
    • index>type
  • 물리적 구조(Physical layout)
    • 엘라스틱서치는 인덱스르 샤드로 분배하는데 이것은 클러스터로 만들어서 통합할 수도 있다.
    • Node > primary(index 포함) , replica 또는 secondary(index 포함)

document

  • 문서는 색인화할 수 있는 기본 정보 단위이다.
  • JSON(JavaScript Object Notation) 형식
  • 하나의 색인에 원하는 개수의 문서를 저장할 수 있다.

index

  • 색인은 비슷한 특성을 가진 문서의 모음.
  • 색인은 이름(모두 소문자)으로 식별되며, 이 이름은 색인에 포함된 문서에 대한 색인화, 검색, 업데이트, 삭제 작업에서 해당 색인을 가리키는 데 쓰인다.
  • 단일 클러스터에서 원하는 개수의 색인을 정의할 수 있다.

type (Deprecated 7.x & Removed 8.x)

  • 하나의 색인에 하나 이상의 유형을 정의할 수 있다. (Before 6.x)

[Removal of Types](https://www.elastic.co/guide/en/elasticsearch/reference/master/removal-of-types.html)

document 색인

색인은 하나 이상의 문서를 색인에 저장하는 것을 의미한다. 관계형 데이터베이스에서 레코드를 추가하는 개념과 유사하다.

curl -X PUT "localhost:9200/twitter/_doc/1" -H 'Content-Type: application/json' -d'
{
 "user" : "kimchy",
 "post_date" : "2009-11-15T14:12:12",
 "message" : "trying out Elasticsearch"
}


{
  "_index": "twitter",
  "_type": "_doc",
  "_id": "1",       // 명시적으로 주었으므로 1
  "_version": 1,      // Optimistic Concurrency Control(낙관적 동시성 제어)에 대한 색인된 문서 버전
  "result": "created",  // 레코드 생성 여부
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}

색인 절차

  1. ID 나 라우팅/부모 메타데이터에 따라 호출을 올바른 샤드로 라우팅, 클라이언트 ID 를 제공하지 않으면 새로운 ID 를 생성한다.
  2. 전송한 JSON 유효성 검증
  3. 매핑에 따라 JSON 처리, 문서에 새 필드가 있고 매핑을 변경할 수 있다면 새 필드를 매핑에 추가한다.
  4. 샤드에서 문서 색인, ID 가 이미 있다면 변경한다.
  5. 중첩 문서를 포함한다면 추출한 다음 별도로 처리한다.
  6. 저장된 문서 관련 정보를 반환한다. (ID 와 버전) 데이터를 색일할 올바른 ID 를 선택하는 것이 중요하다. ID 를 제공하지 않으면 색인 단계에서 elasticsearch 는 문서에 새 ID 를 부여한다.
-- {id} 를 제거하고 response 데이터를 확인해본다. (PUT 대신에 POST 호출임을 주의하자!)
curl -X POST "localhost:9200/twitter/_doc" -H 'Content-Type: application/json' -d'  
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch2"
}
'

매핑에 따라 색인 단계에서 다른 작업(레플리카 전파, 중첩 처리 등)이 수행된다.

Automatic Index Creation

색인이 존재하지 않는 경우, 자동으로 색인을 생성하고 구성된 색인 템플릿을 적용한다. Automatic index creation은 action.auto_create_index.setting 값에 의해 관리된다. 이 값은 true 가 기본, 즉 index 는 항상 자동으로 생성된다. 이 설정값은 특정 패턴과 일치하는 index에 대해서만 자동 생성을 적용할 수 있으며, false로 변경하여 완전히 비활성화할 수 있다.

-- 패턴으로 적용하는 경우
curl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'
{
    "persistent": {
        "action.auto_create_index": "twitter,index10,-index1*,+ind*" 
    }
}
'

-- 비활성화 / 활성화
curl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'
{
    "persistent": {
        "action.auto_create_index": "false" 
    }
}
'

추가 파라미터

Elasticsearch 는 문서 색인 방법을 제어하기 위해 URL에 다수의 쿼리 파라미터를 전달할 수 있다.

  • routing: 어떤 샤드가 색인에 사용될지 지정
  • timestamp: 문서 색인에 사용할 타임스탬프, 매핑에 활성화 되어 있어야 한다.
  • replication(sync/async): async 로 설정되면 프라이메어리 샤드 에서 색인 작업을 동기로 실행하고 세컨더리 샤드 에서는 비동기로 실행한다.
  • version: 현재 색인 버전이 전달된 버전과 매치될 경우에만 색인한다.
  • os_type: 문서를 생성하게 강제하는 데 사용할 수 있다. 같은 ID 를 가진 문서가 있다면 색인은 실패한다.
  • refresh: 문서를 색인한 후에 강제로 새로 고침을 해서 색인 직후 문서를 검색할 수 있게 한다.
  • timeout: 프라이메어리 샤드가 사용 가능해질 때까지 대기하는 시간을 정의한다.

document 조회

문서를 색인한 후에 어플리케이션 수명이 끝날 때까지 검색된다.

curl -X GET "localhost:9200/twitter/_doc/1"
-- 성공 (데이터 있음)
{
  "_index": "twitter",	// 문서를 저장한 색인
  "_type": "_doc",		// 문서 타입
  "_id": "1",				// 문서 ID
  "_version": 1,			// 문서 버전
  "_seq_no": 0,
  "_primary_term": 1,
  "found": true,			// 문서 조회 여부
  "_source": {
    "user": "kimchy",
    "post_date": "2009-11-15T14:12:12",
    "message": "trying out Elasticsearch"
  }
}
-- 실패 (데이터 없음)
{
  "_index": "twitter",
  "_type": "_doc",
  "_id": "0",
  "found": false
}

다른 오버헤드 없이 문서가 담신 샤드에만 검색을 리다이렉션하고 문서 ID 는 빠른 검색을 위해 메모리에 캐시되는 경우가 많으므로 Get API 는 매우 빠르다. 원본 문서는 _source 필드가 저장돼 있을 경우에만 사용할 수 있다.

추가 파라미터

  • _source: _source 검색을 해제할 수 있다. 그리고 전체 _source 에서 특정 필드만 필요한 경우, _source_includes 또는 _source_exclude 변수를 사용하여 필요한 필드만 포함 또는 필터링할 수 있다. 이는 부분 검색으로 네트워크 오버헤드를 절약할 수 있는 큰 문서에 특히 유용하다.
  • stored_fields: 필드 특정 하위 집합(매핑시 stored 필드를 true로 설정한 필드)만 검색할 수 있다. 네트워크 오버헤드를 절약하거나 계산된 필드를 검색하는데 매우 유용하다.
  • routing: GET 작업에 사용될 샤드를 기술한다. 문서를 조회하려면 색인할 때 사용된 라우팅이 검색할 때 사용한 것과 같아야 한다.
  • refresh: GET 작업을 실행하기 전에 현재 샤드를 새로 고친다.( 색인을 느리게하고 오버헤드가 발생하므로 신중하게 사용해야 한다.)
  • preference: GET 메소드를 실행하기 위해 어떤 샤드 레플리카를 선택할지 제어할 수 있다. (_primary, _local, 또는 custom value)

document 삭제

레코드를 삭제하면 문서가 있는 샤드만 접근하므로 오버헤드가 없다. 문서가 자식일 경우 부모는 올바른 샤드를 찾을 수 있도록 설정해야 한다. 문서 삭제는 DELETE 또는 delete_by_query 2가지 방법이 있다.

DELTE

curl -X DELETE "localhost:9200/twitter/_doc/1"
--- 성공
{
  "_index": "twitter",
  "_type": "_doc",
  "_id": "1",
  "_version": 2,
  "result": "deleted",
  "_shards": {
    "total": 2,
    "successful": 2,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1
}
--- 실패 
{
  "_index": "twitter",
  "_type": "_doc",
  "_id": "1",
  "_version": 3,
  "result": "not_found",
  "_shards": {
    "total": 2,
    "successful": 2,
    "failed": 0
  },
  "_seq_no": 2,
  "_primary_term": 1
}

추가 파라미터

  • routing: 삭제 작업에 샤용되는 샤드를 기술할 수 있다.
  • version: 문서 업데이트를 방지하기 위해 삭제될 문서 버전을 지정할 수 있다.
  • parent: 문서가 자식 문서라면 라우팅과 유사한 parent 가 필요하다.

delete_by_query

쿼리와 일치하는 모든 문서를 삭제한다.

curl -X POST "localhost:9200/twitter/_delete_by_query?scroll_size=5000" -H 'Content-Type: application/json' -d'
{
  "query": {
    "term": {
      "user": "kimchy"
    }
  }
}
'
--- 성공
{
  "took": 139,		 
  "timed_out": false,	
  "total": 1,						// 쿼리로 매치된 문서 개수
  "deleted": 1,					// 삭제된 문서 개수
  "batches": 1,					// 문서 삭제를 위해 실행한 벌크 작업 횟수
  "version_conflicts": 0,			// 벌크 작업시에 버전 충돌때문에 삭제하지 못한 문서
  "noops": 0,						// noop 이벤트로 식제 삭제되지 않은 삭제 개수
  "retries": {
    "bulk": 0,					// 재시도한 벌크 작업 횟수
    "search": 0					// 재시도한 검색 횟수
  },
  "throttled_millis": 0,
  "requests_per_second": -1.0,
  "throttled_until_millis": 0,
  "failures": [
  ]
}
  • delete_by_query 호출은 자동으로 백프레셔를 관리한다.(서버 부하가 높은 경우 삭제 명령 비율을 줄인다.)

추가 파라미터

  • conflicts: proceed 로 설정하면 버전 출동이 발생할 때 호출을 종료하지 않고 에러를 건너 뛰며, 실행을 종료한다.
  • routing: 특정 샤드만 실행 대상으로 사용한다.
  • scroll_size: 스크롤 및 벌크 크기(기본: 1,000)를 제어한다.

document 업데이트

제공된 스크립트를 기반으로 문서를 업데이트할 수 있도록 한다. 이 작업은 색인에서 문서를 가져오고, 스크립트를 실행하며, 결과를 색인한다. 이 특성이 작동하려면 _source 필드를 활성화해야 한다. 문서 변경은 UPDATE 또는 update_by_query 2가지 방법이 있다.

UPDATE

--- 1. 간단하게 문서 색인
curl -X PUT "localhost:9200/test/_doc/1" -H 'Content-Type: application/json' -d'
{
    "counter" : 1,
    "tags" : ["red"]
}
'
--- 2. 스크립트 업데이트
curl -X POST "localhost:9200/test/_doc/1/_update" -H 'Content-Type: application/json' -d'
{
    "script" : {
        "source": "ctx._source.counter += params.count",
        "lang": "painless",
        "params" : {
            "count" : 4
        }
    }
}
'
또는 
curl -X POST "localhost:9200/test/_doc/1/_update" -H 'Content-Type: application/json' -d'
{
    "script" : {
        "source": "ctx._source.tags.add(params.tag)",
        "lang": "painless",
        "params" : {
            "tag" : "blue"
        }
    }
}
'
  • painless: 엘라스틱서치의 스크립팅 표준 언어

update_by_query

쿼리로 매치되는 레코드 집합을 다시 색인한다. delete_by_query 와 비슷하다(?)

curl -X POST "localhost:9200/test/_update_by_query?conflicts=proceed" -H 'Content-Type: application/json' -d'
{
  "query": {
    "term": {
      "counter": "5"
    }
  }
}
'
--- 
{
  "took": 76,
  "timed_out": false,
  "total": 1,						
  "updated": 1,					
  "deleted": 0,					
  "batches": 1,					
  "version_conflicts": 0,
  "noops": 0,
  "retries": {
    "bulk": 0,
    "search": 0
  },
  "throttled_millis": 0,
  "requests_per_second": -1.0,
  "throttled_until_millis": 0,
  "failures": [
  ]
}

document 다중 조회

여러 개의 ID 로 많은 문서를 가져오기 위해 엘라스틱서치는 Multi Get API 를 지원한다. 엘라스틱서치는 내부적으로 여러 GET 작업을 여러 샤드에 병렬로 분산시키고 결과를 수집해서 사용자에게 반환한다.

curl -X GET "localhost:9200/_mget" -H 'Content-Type: application/json' -d'
{
    "docs" : [
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "1"
        },
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "2"
        }
    ]
}
'

다음과 같은 필드를 포함할 수 있다.

  • _index: 문서가 포함된 색인. URL 로 전달했다면 생략 가능하다.
  • _type: 문서 타입. URL 로 전달했다면 생략 가능하다.
  • _id: 문서 ID
  • stored_fields: (Optional) 검색할 필드 목록
  • _source: (Optional) 원폰 필터 객체
  • routing: (Optional) 샤드 라우팅 필드. 쿼리 파라미터도 가능

bulk 작업

다량의 문서를 입력/삭제/변경할 때 HTTP 오베허드는 두드러진다. 속도 향상을 위해 엘라스틱서치는 Bulk CRUD 호출을 실행할 수 있다. (\n 개행문자가 꼭!필요하다)

curl -X POST "localhost:9200/_bulk" -H 'Content-Type: application/json' -d'
{ "index" : { "_index" : "test", "_type" : "_doc", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_type" : "_doc", "_id" : "2" } }
{ "create" : { "_index" : "test", "_type" : "_doc", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_type" : "_doc", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }
'

index 생성

데이터를 색인하기 전에 첫 작업은 데이터의 주 컨테이너라고 할 수 있는 index 를 만드는 것 index 는 SQL의 데이터베이스 개념, type(table?) 과 document(record?)을 위한 컨테이너다

curl -X PUT "localhost:9200/twitter" -H 'Content-Type: application/json' -d'
{
    "settings" : {
        "index" : {
            "number_of_shards" : 3, 
            "number_of_replicas" : 2 
        }
    }
}
'
-- 성공
{"acknowledged":true,"shards_acknowledged":true,"index":"twitter"}
-- 실패 (동일 index 가 있는 경우)
{
  "error" : {
    "root_cause" : [
      {
        "type" : "resource_already_exists_exception",
        "reason" : "index [twitter/9ImsuIKGQUiqYgMh-Jm2Bw] already exists",
        "index_uuid" : "9ImsuIKGQUiqYgMh-Jm2Bw",
        "index" : "twitter"
      }
    ],
    "type" : "resource_already_exists_exception",
    "reason" : "index [twitter/9ImsuIKGQUiqYgMh-Jm2Bw] already exists",
    "index_uuid" : "9ImsuIKGQUiqYgMh-Jm2Bw",
    "index" : "twitter"
  },
  "status" : 400
}
  • number_of_shards: index를 작성하는 샤드 개수(각 샤드는 232개의 document 까지 저장 가능)
  • number_of_replicas: 복제 개수 (이 값은 1 이상으로 설정하는 것이 좋다)

동작 방식

  • primary node 에 처음 index를 생성하며, 클러스터의 모든 node에 그 상태를 전파한다.
  • 기본 매핑(빈 매핑)을 작성한다.
  • index에 필요한 모든 shard 를 초기화하고 데이터를 수신할 준비를 한다.

index name 제약

아스키 문자 [a-z], 숫자[0-9], 특수기호[., -, &, _]

index 삭제

index 삭제는 index shard, mapping, document 를 삭제한다. 삭제할 때는 관련된 모든 index가 디스크로부터 삭제되서 잃게되며 백업이 따로 없다면 복구할 수 없다. index 명 대신 _all 로 전체 index 를 삭제할 수 있다. 운영 환경에서는 action.destructive_requireds_name:true 로 변경하여 전체 index 삭제를 비활성화하는 것이 좋다.

curl -X DELETE "localhost:9200/twitter"
-- 성공
{"acknowledged":true}
-- 실패 (index 가 없는 경우)
{
  "error" : {
    "root_cause" : [
      {
        "type" : "index_not_found_exception",
        "reason" : "no such index",
        "resource.type" : "index_or_alias",
        "resource.id" : "twitter",
        "index_uuid" : "_na_",
        "index" : "twitter"
      }
    ],
    "type" : "index_not_found_exception",
    "reason" : "no such index",
    "resource.type" : "index_or_alias",
    "resource.id" : "twitter",
    "index_uuid" : "_na_",
    "index" : "twitter"
  },
  "status" : 404
}

index 온/오프라인 변경

데이터를 유지하면서 자원(메모리/CPU)를 절약하려면 index 삭제 대신 닫아두는 것이 좋다. 엘라스틱서치는 index 를 열거나 닫아 온라인이나 오프라인모드로 설정할 수 있다.

curl -X POST "localhost:9200/my_index/_close"
curl -X POST "localhost:9200/my_index/_open"

index 를 닫는 경우, 메타데이터 상태 변경을 제외하고 클러스터의 오버헤드가 없다. 또한 index shard 는 꺼지고 파일 디스크립터, 메모리, 스레드는 사용하지 않는다.

index 맵핑 정의

index 에 type mapping을 하는 방법으로 SQL로 치면 테이블 생성정도로 보면된다. index 의 유무를 확인하고 정의된 대로 한개 이상의 매핑을 만든다. 매핑을 위한 삭제 API 는 없다. 매핑을 삭제하거나 변경하려면 새로운 index 를 만들어서 전체레코드를 다시 색인해야한다. 엘라스틱서치에서는 속도향상을 위해 reindex 명령을 제공하고 있다.

curl -X PUT "localhost:9200/twitter" -H 'Content-Type: application/json' -d'
{}
'
curl -X PUT "localhost:9200/twitter/_mapping/_doc" -H 'Content-Type: application/json' -d'
{
  "properties": {
    "email": {
      "type": "keyword"
    }
  }
}
'

index 생성에 _mapping 필드를 정의하면 생성과 함께 타입 매핑을 정의할 수 있다.

curl -X PUT "localhost:9200/test" -H 'Content-Type: application/json' -d'
{
    "settings" : {
        "number_of_shards" : 1
    },
    "mappings" : {
        "_doc" : {
            "properties" : {
                "field1" : { "type" : "text" }
            }
        }
    }
}
'

타입매핑 참고

mapping 조회

index d에 정의된 매핑을 조회한다. 매핑을 클러스터 수준으로 저장한다. 조회 호출은 색인과 타입이 있는지 모두 확인하고 저장된 매핑을 반환한다.

curl -X GET "localhost:9200/_mapping"
curl -X GET "localhost:9200/twitter/_mapping"
curl -X GET "localhost:9200/twitter/_doc/_mapping"

reindex

5.x 부터 추가된 기능이며, 하나의 index 에서 다른 index로 document를 복사한다. 아래 예제는 twitter 를 new_twitter 로 복사하는 예제이다.

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter"
  }
}
'
  • 원본 색인의 모든 문서에 대해 _source 를 활성화 해야 한다.
  • reindex 는 목적지 색인에 설정을 변경하지 않는다. Reindex 를 실행하기 전에 색인의 설정(매핑, 샤드 개수, 리플리카 등등)을 진행해야 한다.

?refresh

엘라스틱서치는 색인 강제 새로고침을 사용해 검색자의 상태를 제어할 수 있다. 강제하지 않으면 최근 색인된 문서는 일정 시간(일반적으로 1초)이후에야 검색이 가능해 질 것이다.

curl -X PUT "localhost:9200/test/_doc/1?refresh" -H 'Content-Type: application/json' -d'
{"test": "test"}
' 

엘라스틱서치는 파일 디스크립터를 닫았다가 다시 여는 데 필요한 과도한 I/O 로 인한 성능 저하 방지를 위해 문서를 입력할 때마다 매번 색인 상태를 새로 고치지는 않는다. 일반적으로 새로 고침을 호출하는 가장 적절한 때는 많은 데이터를 색인한 바로 다음이다.

타입 매핑

  • 디스크의 색인 크기를 줄인다.(사용자 정의 필드를 위한 기능을 비활성화 한다.)
  • 관심 필드만 색인한다.(일반적인 속도 향상)
  • 빠른 검색이나 실시간 분석을 위한 패싯같은 선행처리한 데이터
  • 필드가 다중 토큰으로 분석돼야 하는지, 또는 단일 토큰으로 처리해야 하는지를 올바르게 정의

Core datatypes

mapping parameter

  • store: 필드를 별도 색인 조작에 저장해서 조회를 빠르게 한다. 필드 저장은 디스크 공간을 소모하지만, 문서로부터 추출해야 하는 연산(즉, 스크립팅과 집계)을 줄인다. (기본값: false)
  • index: 필드를 색인해야 할 때 사용한다. 색이이 되지 않은 필드는 검색이 되지 않는다.
  • null_value: 필드가 null일 때 기본값을 지정한다.
  • boost: 필드의 중요도를 변경하는데 사용한다. (기본값: 1.0)
    • boost 는 term 수준에서만 동작하므로 term, terms, match 쿼리에 주로 사용한다.
  • analyzer: 사용할 기본 분석기를 설정한다(기본값: null)
  • search_analyzer: 검색 시 사용할 분석기를 지정한다. 지정하지 않으면 부모 객체의 분석기를 사용한다. (기본값: null)

Complex datatypes

Geo datatypes

Specialised datatypes

Multi-fields

It is often useful to index the same field in different ways for different purposes. For instance, a string field could be mapped as a text field for full-text search, and as a keyword field for sorting or aggregations. Alternatively, you could index a text field with the standard analyzer , the english analyzer, and the french analyzer . This is the purpose of multi-fields. Most datatypes support multi-fields via the fields parameter.


참고


  • No labels