티스토리 뷰

728x90

 

안녕하세요. 개발개입니다.

 

위키북스에서 나온 <엘라스틱서치 실무 가이드>를 공부하면서
정리한 부분을 다음과 같은 목차에 따라 공유합니다.

(설치와 관련된 포스트는 많기 때문에 따로 작성하지 않았습니다.)

 

  1. 엘라스틱서치의 이해 (1)

  2. 엘라스틱서치의 이해 (2)

  3. 데이터 모델링

  4. 엘라스틱서치 분석기

  5. 커스텀 분석기

 

이번 글에서는 데이터 모델링과 관련하여 다음에 내용에 대해 다룹니다.

목차
- 매핑 파라미터
- 메타 필드
- 데이터 타입

 

오타, 오류 혹은 기타 의견은 언제든지 환영합니다.



 

 


 

1. 매핑 파라미터

- anlayzer

  • 해당 필드의 데이터를 형태소 분석의 대상으로 함

  • 색인 및 검색 시 지정한 분석기로 형태소 분석을 수행 (디폴트 standard analyzer)

 

- normalizer

  • term query에 분석기를 사용하기 위함

  • asciifolding 필터를 사용하면 cafe, Cafe, Café를 같은 데이터로 인식

 

- boost

  • 필드에 가중치 부여 → 유사도(_score) 산출이 달라짐 → 검색 결과 노출 순서에 영향 

  • 색인 시점에서 사용하면 가중치를 변경할 수 없으므로 검색 시점에서 사용하는 것을 권장

    (루씬7.0부터 색인 시 BOOST 설정 기능이 제거되어 최신 엘라스틱 서치도 불가능해짐)

 

- coerce

  • 색인 시 자동 변환을 허용할지 여부

 

- copy_to

  • 해당 필드의 값을 지정한 필드로 복사

    (keyword to text인 경우, 형태소 분석도 가능)

 

- fielddata

  • 엘라스틱서치가 힙 공간에 생성하는 메모리 캐시

  • 형태소 분석을 하는 text 타입의 경우 집계/정렬을 수행하기 위해 사용

  • 메모리 부족 현상 등으로 최소한 사용 권장

  • 디폴트는 false, 활성화 코드는 아래 참고

PUT [인덱스명]/_mapping/_doc
{
  "properties" : {
    "[컬럼명]" : {
      "type" : "text",
      "fielddata" : true
    }
  }
}

 

- doc_values

  • 엘라스틱서치 기본 캐시 (루씬 기반)

  • text 타입을 제외한 모든 타입에서 기본적으로 사용

  • 한 번 비활성화된 필드는 재색인해야 변경 가능

 

- dynamic

  • 매핑에 필드를 추가할 때 동적으로 할지 말지 여부

    • true

    • false(무시되므로 검색불가, _source엔 있음)

    • strict (새로운 필드 감지 시 예외 발생)

 

- enabled

  • 검색 결과(_source)에는 포함하지만 색인은 하고 싶지 않은 경우 (e.g. 메타 데이터)

 

- format

  • 날짜/시간을 문자열로 변경 시 포매팅

포맷 날짜 형식 비고
basic_date yyyyMMdd 년도/월/일
basic_date_time yyyyMMdd'T'HHmmss.SSSZ 년도/월/일/T/시/분/초/밀리초/Z
basic_time HHmmss.SSS 시/분/초/밀리초/Z
date/strict_date yyyy-MM-dd 년도/시/분
date_hour_minute_second/
strict_date_hore_minute_second
yyyy-MM-dd'T'HH:mm:ss. 년도/시/분/T/시/분/초
date_hour_misnute_second_millis/
strict_date_hour_minute_second_millis
yyyy-MM-dd'T'HH:mm:ss.SSS 년도/시/분/T/시/분/초/밀리초
date_time/strict_date_time yyyy-MM-dd'T'HH:mm:ss.SSSZZ 년도/시/분/T/시/분/초/밀리초/ZZ

 

- ignore_above

  • 지정한 크기를 넘어선 필드 문자열을 빈 값으로 색인

 

- ignore_malformed

  • 예외가 발생하는 필드를 무시하고 문서를 색인

 

- index

  • 필드값을 색인할지 여부 (디폴트는 true)

 

- fields

  • 멀티 필드를 설정할 수 있는 옵션

 

- norms

  • _score 값 계산에 필요한 정규화 인수를 사용할 지 여부 (디폴트는 true)

  • _score 값 계산이 불필요하고 단순 필터링 용도의 필드는 비활성화 함으로써 디스크 공간 절약

 

- null_value

  • 필드 값이 null이더라도 필드를 생성
    (기본적으로는 색인 시 문서에 필드가 없거나 값이 null이면 필드를 생성하지 않음)
PUT [인덱스명]/_mapping/_doc
{
  "properties" : {
    "[컬럼명]" : {
      "type" : "integer",
      "null_value" : "0"
    }
  }
}

 

- position_increment_gap

  • 필드 데이터 중 단어와 단어 사이의 간격(slop)을 허용할지 여부

  • 배열 형태의 베이터를 색인할 때 검색의 정확도를 높임

    (e.g. 데이터가 ["apple mango", "juice mixer"]일 때, "mango juice"로도 검색이 가능)

 

- properties

  • Object 타입이나 Nested(중첩) 타입의 스키마를 정의할 때 사용

 

- search_analyzer

  • 색인과 검색에 다른 분석기를 사용하고 싶은 경우, 검색 시 사용할 분석기 별도 설정

 

- similarity

  • 유사도 측정 알고리즘 지정 (기본 알고리즘은 BM25)

 

- store

  • 필드의 값을 저장해 검색 결과에 값을 포함하기 위한 매핑 파라미터

  • _source를 로드해서 해당 필드를 찾는 것보다 사용할 각 필드만 로드하는 것이 효율적이지만 디스크를 많이 사용함

 

- term_vector

  • 루씬에서 분석된 용어 정보를 포함할지 여부

  • no / yes / with_positions / sith_offsets / with_positions_offsets

 


 

2. 메타 필드

 

_index

  • 해당 문서가 속한 인덱스의 이름

  • 해당 인덱스에 몇 개의 문서가 있는지 확인

POST [인덱스명]/_search
{
  "size" : 0,
  "aggs" : {
    "indices" : {
      "terms" : {
        "field" : "_index",
        "size" : 10
      }
    }
  }
}
  • 결과

{
  "took" : 10,
  "timed_out" : false,
  "_shards" : {
    "total" : 3,
    "successful" : 3,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 10,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "indices" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "[인덱스명]",
          "doc_count" : 10
        }
      ]
    }
  }
}

 

_type

  • 해당 문서가 속한 매핑의 타입 정보

  • 해당 인덱스 내에서 타입별로 몇 개의 문서가 있는지 확인

POST [인덱스명]/_search
{
  "size" : 0,
  "aggs" : {
    "indices" : {
      "terms" : {
        "field" : "_type",
        "size" : 10
      }
    }
  }
}
  • 결과

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 3,
    "successful" : 3,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 10,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "indices" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "_doc",
          "doc_count" : 10
        }
      ]
    }
  }
}

 

_id

  • 문서를 식별하는 유일한 키 값

  • 해당 인덱스 내에서 키 값 별 문서 수 확인

POST [인덱스명]/_search
{
  "size" : 0,
  "aggs" : {
    "indices" : {
      "terms" : {
        "field" : "_id",
        "size" : 10
      }
    }
  }
}
  • 결과

{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 3,
    "successful" : 3,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 10,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "indices" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "a4Y60nABDzsvV4duypRx",
          "doc_count" : 1
        },
        {
          "key" : "aoY10nABDzsvV4duY5T8",
          "doc_count" : 1
        },
        {
          "key" : "b4ZT0nABDzsvV4dusJRr",
          "doc_count" : 1
        },
        {
          "key" : "bIY70nABDzsvV4du45SB",
          "doc_count" : 1
        },
        {
          "key" : "bYY90nABDzsvV4duIZQs",
          "doc_count" : 1
        },
        {
          "key" : "c4ZX0nABDzsvV4dunJRx",
          "doc_count" : 1
        },
        {
          "key" : "cIZU0nABDzsvV4duX5SD",
          "doc_count" : 1
        },
        {
          "key" : "cYZV0nABDzsvV4duFZSl",
          "doc_count" : 1
        },
        {
          "key" : "dIZY0nABDzsvV4duaZSP",
          "doc_count" : 1
        },
        {
          "key" : "dYZa0nABDzsvV4duGpTT",
          "doc_count" : 1
        }
      ]
    }
  }
}

 

_uid

  • [_type]#[_id] 형태의 식별키 (내부적으로만 사용되므로 검색 시 조회되진 않음)

  • 해당 인덱스 내에서 uid값 별 문서수 확인

POST [인덱스명]/_search
{
  "size" : 0,
  "aggs" : {
    "indices" : {
      "terms" : {
        "field" : "_id",
        "size" : 10
      }
    }
  }
}

결과

{
  "took" : 7,
  "timed_out" : false,
  "_shards" : {
    "total" : 3,
    "successful" : 3,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 10,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "indices" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "_doc#a4Y60nABDzsvV4duypRx",
          "doc_count" : 1
        },
        {
          "key" : "_doc#aoY10nABDzsvV4duY5T8",
          "doc_count" : 1
        },
        {
          "key" : "_doc#b4ZT0nABDzsvV4dusJRr",
          "doc_count" : 1
        },
        {
          "key" : "_doc#bIY70nABDzsvV4du45SB",
          "doc_count" : 1
        },
        {
          "key" : "_doc#bYY90nABDzsvV4duIZQs",
          "doc_count" : 1
        },
        {
          "key" : "_doc#c4ZX0nABDzsvV4dunJRx",
          "doc_count" : 1
        },
        {
          "key" : "_doc#cIZU0nABDzsvV4duX5SD",
          "doc_count" : 1
        },
        {
          "key" : "_doc#cYZV0nABDzsvV4duFZSl",
          "doc_count" : 1
        },
        {
          "key" : "_doc#dIZY0nABDzsvV4duaZSP",
          "doc_count" : 1
        },
        {
          "key" : "_doc#dYZa0nABDzsvV4duGpTT",
          "doc_count" : 1
        }
      ]
    }
  }
}

 

_source

  • 문서의 원본 데이터 제공

  • 원본 JSON 문서를 검색 결과로 표시할 때 사용

 

_all

  • 색인에 사용된 모든 필드의 데이터를 하나의 텍스트로 합쳐서 제공
    (e.g. [field1] || [field2 || … )

  • 데이터 크기가 너무 커서 엘라스틱서치 6.0부터 없어졌고, copy_to를 이용해 동일하게 구현할 수 있음

 

_routing

  • 특정 문서를 특정 샤드에 저장하기 위해 사용자가 지정하는 메타 필드

  • 별도 설정이 없는 경우, 샤드에 골고루 분산 저장됨

 


 

3. 데이터 타입

keyword

  • 문자열 타입
  • 분석기를 거치지 않고 원문 그대로 색인

  • 정형화 된 컨텐츠에 사용

  • 검색 시 필터링되는 항목

  • 정렬 기능(Sorting)이 필요한 항목

  • 집계 기능(Aggregation)을 사용해야 하는 항목

 

text

  • 문자열 타입
  • 지정한 분석기(미지정시 Standard Analyzer)를 거쳐 색인

  • 전문 검색 가능 (포함된 특정 단어 검색 가능)

  • 정렬/집계 기능을 사용해야 할 경우 Text 타입과 Keyword 타입을 동시에 설정 가능(멀티 필드)

 

Array

하나의 필드에 여러 데이터가 들어가는 경우 사용 (OR 연산)

# Example

PUT goods_sample/_doc
{
  "goodsNm" : "갤럭시 Z플립",
  "vendor" : "Samsung",
  "colour" : ["gold", "black", "purple"]  
}

 

Numeric

데이터 크기별 숫자 데이터 타입 제공

- long

- integer

- short

- byte

- double

- float

- half_float

 

Date

JSON 포맷에서 문자열 처리되며 포매팅 설정 가능

# Example

PUT goods_sample/_mapping/_doc
{
  "properties" : {
    "orderDate" : {
      "type" : "date",
      "format" : "yyyy-MM-dd HH:mm:ss"
    }
  }
}

 

Range

범위가 있는 데이터가 인입되는 경우 사용

- integer_range

- float_range

- long_range

- double_range

- date_range

- ip_range

# Example

## deliveryPeriod 필드 타입을 date_range로 설정
PUT goods_sample/_mapping/_doc
{
  "properties" : {
    "deliveryPeriod" : {
      "type" : "date_range",
      "format" : "yyyy-MM-dd"
    }
  }
}

## 2020-03-02 ~ 2020-03-06
PUT goods_sample/_doc/1
{
  "deliveryPeriod" : {
    "gte" : "2020-03-02",
    "lte" : "2020-03-06"
  }
}

 

Boolean

참/거짓 논리값

- true, "true"

- false, "false"

# Example

## delivered 필드 타입을 boolean으로 설정
PUT goods_sample/_mapping/_doc
{
  "properties" : {
    "delivered" : {
      "type" : "boolean"
    }
  }
}

PUT goods_sample/_doc/1
{
  "delivered" : true
}

 

Geo-Point

  • 위도, 경도 등 위치 정보를 담은 데이터를 저장할 경우 사용

  • 위치 기반 쿼리를 이용해 반경 내 쿼리, 위치 기반 집계, 위치별 정렬 등을 사용할 수 있음

  • 해당 필드 타입을 geo_point로 매핑 후, 해당 값에 lat(위도; latitud)와 lon(경도; longitude)값을 지정

 

IP

IPv4, IPv6 모두 가능

 

 

 

다음 이야기 : [Elasticsearch] - 4. 엘라스틱서치 분석기

 

 

 


 

 

 

본 글은 다음을 참고하여 작성되었습니다.

 

권택환 외, 엘라스틱서치 실무가이드, 위키북스

 

 

 

728x90
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
04-29 04:52