Elasticsearch 기본(1) - 인덱스, 도큐먼트, 매핑

Index

  • 클러스터에 생성
  • 도큐먼트를 저장하는 논리적 구분자
  • 하나의 인덱스에 다수의 도큐먼트 포함
  • 같은 인덱스에 포함된 도큐먼트는 동일한 스키마를 가짐
  • 인덱스 이름
    • 영어 소문자
    • \, /, *, ?, ", <, >, |, #, 공백, 쉼포 제외한 특수문자 사용 가능
    • 최대 255바이트
  • 스키마에 따라 인덱스 구분
  • 기본적으로 용량이나 숫제 제한없이 무한대의 도큐먼트 포함 가능
  • 인덱스가 커지면 성능 문제
  • 특정 도큐먼트 개수에 도달하거나 용량을 넘어서면 인덱스 분리
  • API
    • 생성: PUT {index_name} (POST도 가능)
    • 조회: GET {index_name}
    • 삭제: DELETE {index_name}

Document

  • 인덱스 내부에 JSON 형태로 다수의 도큐먼트 존재
  • 실제 데이터를 저장하는 단위
  • 여러 필드와 값을 가짐
  • 매핑으로 필드의 데이터 타입 지정
  • 인덱싱(indexing)
    • 도큐먼트를 인덱스에 포함시키는 것
    • 인덱스를 생성하면서 동시에 도큐먼트를 해당 인덱스에 인덱싱 가능
    • _doc은 엔드포인트 구분을 위한 예약어, 1은 도큐먼트의 고유 아이디가 됨

      // PUT index1/_doc/1
      {
        "name": "Tom",
        "age": 42,
        "gender": "male"
      }
      
    • 인덱스를 확인을 통해 설정값과 mappings 확인
    • 다이내믹 매핑(dynamic mapping): 도큐먼트의 필드와 값을 보고 자동으로 지정

      // GET index1
      {
        "index1": {
          "alias": {
          
          },
          "mappings": {
            "properties": {
              "age": {
                "type": "long",
                ...
              },
              "gender": {
                "type": "text",
                ...
              },
              "name": {
                "type": "text",
                ...
              },
              ...
            }
          }
        }
      }
      
    • 데이터 형변환 진행
      • 숫자 필드에 문자열이 입력되면 숫자로 변환
      • 정수 필드에 소수가 입력되면 소수점 아래 자리 무시
  • 도큐먼트 읽기
    • 특정 도큐먼트 읽기: GET {index_name}/_doc/{document_id}
    • 모든 도큐먼트 읽기: GET {index_name}/_search
  • 도큐먼트 수정
    • PUT {index_name}/_doc/{document_id}
    // PUT index1/_doc1/1
    {
      "name": "Tom",
      "age": 45,
      "gender": "male"
    }
    
    • POST {index_name}/_update/{document_id}
    // POST index1/_update/1
    {
      "doc" : {
        "name" : "Mark"
      }
    }
    
    • 도큐먼트 수정은 비용이 많이 드는 작업
  • 도큐먼트 삭제
    • DELETE {index_name}/_doc/{document_id}
    • 도큐먼트 삭제도 비용이 많이 드는 작업

응답 메세지

코드 상태 해결 방법
20, 201 정상 수행  
4xx 클라이언트 오류 클라이언트에서 문제 수정
404 요청 리소스가 없음 인덱스나 도큐먼트가 존재하는지 확인
405 요청 메소드 지원 안 함 API 확인
429 요청 과부화(busy) 재전송, 노드 추가
5xx 서버 오류 엘라스틱서치 로그 확인

Mapping

  • RDB의 스키마와 비슷한 역할을 하며 JSON 형태의 데이터를 루씬이 이해할 수 있도록 바꾸는 작업

  • 다이나믹 매핑
    • 데이터 타입에 맞춰 엘라스틱서치가 자동으로 매핑하는 것
    데이터 타입 다이나믹 매핑으로 변환된 데이터 타입
    null 필드 추가 X
    boolean boolean
    float float
    integer long
    object object
    string 데이터 형태에 따라 date, text/keyword
  • 명시적 매핑
    • 사용자가 직접 정의
    • 인덱스 생성할 때 정의하거나 mapping API 사용
    // PUT {index_name}
    {
      "mappings" : {
        "properties" : {
          "age" : {"type" : "long"},
          "name" : {"type" : "text"},
          ...
        }
      }
    }
    
  • 매핑 타입
형태 타입 설명
문자열 text 전문 검색이 필요한 데이터
텍스트 분석기가 텍스트를 작은 단위로 분리
문자열 keyword 정렬이나 집계에 사용되는 데이터
분석하지 않고 원문 통째로 인덱싱
날짜 date 날짜/시간 데이터
정수 byte, short, integer, long byte: 부호 있는 8비트 데이터(-128~127)
short: 부호 있는 16비트 데이터(-32768~32767)
integer: 부호 있는 32비트 데이터(-2^31~2^31-1)
long: 부호 있는 64비트 데이터(-2^63~2^63-1)
실수 scaled_float, half_float, double, float scaled_float: float 데이터에 특정 값을 곱해 정수형으로 바꾼 데이터
half_float: 16비트 부동소수점 실수 데이터
double: 32비트 부동소수점 실수 데이터
float: 64비트 부동소수점 실수 데이터
boolean boolean true, false만 값으로 가짐
IP 주소 ip ipv4, ipv6 타입 IP 주소
위치 정보 geto-point, geo-shape geo-point: 위도, 경도 값
geo-shape: 하나의 위치 포인트가 아닌 임의의 지형
범위 값 integer_range, long_range,
float_range, double_range,
ip_range, date_range
범위를 설정할 수 있는 데이터
integer_range, long_range: 정수형 범위
float_range, double_range: 실수형 범위
ip_range: IP 주소 범위
date_range: 날짜/시간 데이터 범위
객체 형 object 계층 구조를 갖는 형태
필드 안에 다른 필트가 들어갈 수 있음
배열 형 nested 배열형 객체 저장
객체를 따로 인덱싱하여 객체가 하나로 합쳐지는(flatten) 것을 막음
배열 내부의 객체에 쿼리로 접근 가능
배열 형 join 부모/자식 관계 표현
  • text
    • 문장이나 여러 단어가 나열된 문자열은 텍스트 타입으로 지정
    • 역인덱스(inverted index): 분석기에 의해 토큰으로 분리된 후 인덱싱됨
    • 용어(term): 역인덱스에 저장된 토큰
    • 용어는 역인덱스에 저장되어 전문 검색 가능
    • 집계나 정렬 지원 X
  • keyword
    • 범주형 데이터에 주로 사용
    • 분석기를 거치지 않고 문자열 전체가 하나의 용어로 인덱싱
    • 부분 일치 검색 X
    • 완전 일치 검색 사용 가능
    • 집계, 정렬 사용 가능
  • multi field
    • 단일 필드 입력에 대해 여러 하위 필드 정의
    • fields 매핑 파라미터 사용
    • 하나의 필드를 여러 용도로 사용 가능
    • 아래 예제에서 contensts 필드는 멀티 타입으로 text, keyword 타입을 가짐
    // PUT index2
    {
      "mappings": {
        "properties": {
          "message": {
            "type": "text"
          },
          "contents": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword"
              }
            }
          }
        }
      }
    }
    
    • 사용자가 지정한 명칭인 keyword를 이용해서 검색 가능
    // GET index2/_search
    {
      "query" : {
        "term" : {
          "contents.keyword" : "hello"
        }
      }
    }
    
    • 키워드 타입은 aggs 이용하여 집계 쿼리 가능
    // GET index2/_search
    {
      "size": 0,
      "aggs": {
        "contents": {
          "terms": {
            "field": "contents.keyword"
          } 
        }
      }
    }