본문 바로가기

시스템/DB

ElasticSearch (Mapping & Analysis)

분석 API 소개

  • 때로는 텍스트 분석이라고도 함
    • 텍스트 필드/값에 적용 가능
    • 문서 인덱스 시 텍스트 값이 분석됨
    • 결과는 검색 등에 효율적인 데이터 구조에 저장
    • _source 객체는 문서 검색 시 사용되지 않음
      • 문서 색인 시 지정된 정확한 값을 포함함

문자 필터

  • 문자를, 추가, 제거 또는 변경함
    • 분석기는 0개 이상의 문자 필터를 포함함
    • 문자 필터는 지정된 순서대로 적용됨
    • 예시 (html_strip 필터)
      • 입력: "I'm in a <em>good</em> mood - and I <strong>love</strong> açaí!"
      • 출력: "I'm in a good mood - and I love açaí!"

토큰나이저

  • 분석기는 하나의 토큰화기를 포함함
    • 문자열을 토큰화함, 즉 토큰으로 분할함
    • 토큰화 과정에서 문자가 제거될 수 있음
    • 예시
      • 입력: "I REALLY like beer!"
      • 출력: ["I", "REALLY", "like", "beer"]

토큰 필터

  • 토큰화기의 출력(즉, 토큰)을 입력으로 받음
    • 토큰 필터는 토큰을 추가, 제거 또는 수정할 수 있음
    • 분석기는 0개 이상의 토큰 필터를 포함함
    • 토큰 필터는 지정된 순서대로 적용됨
    • 예시 (소문자 필터)
      • 입력: ["I", "REALLY", "like", "beer"]
      • 출력: ["i", "really", "like", "beer"]

내장 및 사용자 정의 구성 요소

  • 내장된 분석기, 문자 필터, 토큰화기 및 토큰 필터를 사용할 수 있음
    • 사용자 정의 구성 요소도 구축 가능함
      • 이 섹션의 뒷부분에서 방법을 볼 수 있음

 

POST /_analyze
{
  "text": "2 guys walk into   a bar, but the third... DUCKS! :-)",
  "analyzer": "standard"
}

는 아래와 동일하다

POST /_analyze
{
  "text": "2 guys walk into   a bar, but the third... DUCKS! :-)",
  "char_filter": [],
  "tokenizer": "standard",
  "filter": ["lowercase"]
}


>>>

더보기

{
  "tokens" : [
    {
      "token" : "2",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "",
      "position" : 0
    },
    {
      "token" : "guys",
      "start_offset" : 2,
      "end_offset" : 6,
      "type" : "",
      "position" : 1
    },
    {
      "token" : "walk",
      "start_offset" : 7,
      "end_offset" : 11,
      "type" : "",
      "position" : 2
    },
    {
      "token" : "into",
      "start_offset" : 12,
      "end_offset" : 16,
      "type" : "",
      "position" : 3
    },
    {
      "token" : "a",
      "start_offset" : 19,
      "end_offset" : 20,
      "type" : "",
      "position" : 4
    },
    {
      "token" : "bar",
      "start_offset" : 21,
      "end_offset" : 24,
      "type" : "",
      "position" : 5
    },
    {
      "token" : "but",
      "start_offset" : 26,
      "end_offset" : 29,
      "type" : "",
      "position" : 6
    },
    {
      "token" : "the",
      "start_offset" : 30,
      "end_offset" : 33,
      "type" : "",
      "position" : 7
    },
    {
      "token" : "third",
      "start_offset" : 34,
      "end_offset" : 39,
      "type" : "",
      "position" : 8
    },
    {
      "token" : "ducks",
      "start_offset" : 43,
      "end_offset" : 48,
      "type" : "",
      "position" : 9
    }
  ]
}

 

 

역 색인(Inverted Indices) 이해

소개

  • 필드의 값은 여러 데이터 구조 중 하나에 저장됨
    • 데이터 구조는 필드의 데이터 타입에 따라 다름
    • 효율적인 데이터 접근(예: 검색)을 보장함
    • Elasticsearch가 아닌 Apache Lucene에 의해 처리됨
    • 이 강의는 역색인에 초점을 맞춤

역색인

  • 용어와 해당 용어를 포함하는 문서 간의 매핑
    • 분석기 컨텍스트 외부에서는 "용어(terms)"라는 용어를 사용함
    • 용어는 알파벳 순으로 정렬됨
    • 역색인은 용어와 문서 ID 외에도 더 많은 정보를 포함함
      • 예: 관련성 점수 매기기 위한 정보
    • 텍스트 필드당 하나의 역색인
    • 다른 데이터 타입은 예를 들어 BKD 트리를 사용함

요약 (1/2)

  • 텍스트 필드의 값은 분석되고 결과는 역색인 내에 저장됨
    • 각 필드는 전용 역색인을 가짐
    • 역색인은 용어와 해당 용어를 포함하는 문서 간의 매핑임
    • 성능상의 이유로 용어는 알파벳 순으로 정렬됨
    • Elasticsearch가 아닌 Apache Lucene에 의해 생성되고 유지됨

요약 (2/2)

  • 역색인은 빠른 검색을 가능하게 함
    • 역색인은 다른 데이터도 포함함
      • 예: 관련성 점수 매기기에 사용되는 것들(나중에 다룸)
    • Elasticsearch(기술적으로는 Apache Lucene)는 다른 데이터 구조도 사용함
      • 예: 숫자 값, 날짜 및 지리 공간 데이터를 위한 BKD 트리

역 색인 이미지화

 

Mapping

매핑이란 무엇인가?

  • 문서의 구조(예: 필드 및 데이터 타입)를 정의함
    • 값이 어떻게 색인되는지 구성하는 데도 사용됨
  • 관계형 데이터베이스의 테이블 스키마와 유사함
  • 명시적 매핑
    • 필드 매핑을 직접 정의함
  • 동적 매핑
    • Elasticsearch는 동적 매핑을 지원하기 때문에, 인덱스에 도큐먼트를 추가하면 자동 매핑 생성된다.
PUT books/_doc/1
{
  "title": "Romeo and Juliet",
  "author": "William Shakespeare",
  "category": "Tragedies",
  "publish_date": "1562-12-01T00:00:00",
  "pages": 125
}
GET books/_mapping
>>>
{
  "books" : {
    "mappings" : {
      "properties" : {
        "author" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "category" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "pages" : {
          "type" : "long"
        },
        "publish_date" : {
          "type" : "date"
        },
        "title" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}


참고: https://esbook.kimjmin.net/07-settings-and-mappings/7.2-mappings

 

데이터 타입

object 데이터 타입

  • 모든 JSON 객체에 사용됨
    • 객체는 중첩될 수 있음
    • properties 매개변수를 사용하여 매핑됨
    • 객체는 Apache Lucene에서 객체로 저장되지 않음
      • 객체는 유효한 JSON을 색인할 수 있도록 변환됨
      • 특히, 객체는 평면화됨(flattened)

nested 데이터 타입

  • object 데이터 타입과 유사하지만, 객체 관계를 유지함
    • 객체 배열을 색인할 때 유용함
  • 객체를 독립적으로 쿼리할 수 있게 함
    • nested 쿼리를 사용해야 함
  • nested 객체는 숨겨진 문서로 저장됨

keyword 데이터 타입

  • 값의 정확한 일치에 사용됨
    • 일반적으로 필터링, 집계 및 정렬에 사용됨
    • 예: PUBLISHED 상태의 기사 검색
  • 전체 텍스트 검색의 경우 대신 text 데이터 타입을 사용함
    • 예: 기사의 본문 텍스트 검색

 

keyword 필드가 분석되는 방법

keyword 필드는 keyword 분석기로 분석됨

  • keyword 분석기는 아무 작업도 하지 않는(no-op) 분석기임
    • 수정되지 않은 문자열을 단일 토큰으로 출력함
    • 이 토큰은 역색인에 배치됨
  • keyword 필드는 정확한 일치, 집계 및 정렬에 사용됨

 

타입 강제(Coercion)

타입 강제 변환 소개

  • 문서 색인 시 데이터 타입이 검사됨
    • 유효성이 검증되며, 일부 유효하지 않은 값은 거부됨
    • 예: text 필드에 객체를 색인하려고 시도함
  • 때로는 잘못된 데이터 타입을 제공해도 괜찮음

_source 객체 이해하기

  • 색인 시 제공된 값("7.4")을 포함함
    • 색인된 값(7.4)이 아님
  • 검색 쿼리는 _source가 아닌 색인된 값을 사용함
    • BKD 트리, 역색인 등
  • _source는 값이 어떻게 색인되는지 반영하지 않음
    • _source의 값을 사용할 경우 강제 변환을 염두에 둘 것
    • 이 예시에서는 문자열 또는 부동 소수점일 수 있음

몇 가지 더 알아둘 점...

  • 정수 필드에 부동 소수점을 제공하면 정수로 잘림
  • 동적 매핑에는 강제 변환이 사용되지 않음
    • 새 필드에 "7.4"를 제공하면 text 매핑이 생성됨
  • 항상 올바른 데이터 타입을 사용하도록 노력할 것
    • 특히 필드를 처음 색인할 때
  • 강제 변환 비활성화는 선호도 문제임
    • 기본적으로 활성화되어 있음

 

배열 이해

배열 소개

  • 배열 데이터 타입이라는 것은 존재하지 않음
    • 모든 필드는 0개 이상의 값을 포함할 수 있음
      • 구성이나 매핑이 필요하지 않음
      • 문서 색인 시 배열을 제공하기만 하면 됨
    • products 색인의 tags 필드에 이것을 적용했음

제약 조건

  • 배열 값은 동일한 데이터 타입이어야 함
    • 강제 변환은 이미 매핑된 필드에만 작동함
      • 동적 매핑으로 필드 매핑을 생성하는 경우, 배열은 동일한 데이터 타입을 포함해야 함
    • 강제 변환 사용을 권장하지 않음(적어도 의도적으로는)

중첩 배열

  • 배열은 중첩 배열을 포함할 수 있음
    • 배열은 색인 중에 평면화됨
    • [ 1, [ 2, 3 ] ]는 [ 1, 2, 3 ]이 됨

작은 알림 객체 배열을 독립적으로 쿼리해야 하는 경우 nested 데이터 타입을 사용하는 것을 잊지 마세요.

 

POST /_analyze
{
  "text": ["Strings are simply", "merged together."],
  "analyzer": "standard"
}

 

매핑 정의

PUT /reviews
{
  "mappings": {
    "properties": {
      "rating" : {"type": "float"},
      "content": {"type": "text"},
      "product_id": {"type": "integer"},
      "author": {
        "properties": {
          "first_name":{"type": "text"},
          "last_name": {"type": "text"},
          "email": {"type": "keyword"}
        }
      }
    }
  }
}

 

PUT /reviews/_doc/1
{
  "rating": 5.0,
  "content": "Outstanding course! Bo really taught me a lot about Elasticsearch!",
  "product_id": 123,
    "author": {
    "first_name": "John",
    "last_name": "Doe",
    "email": "johndoe123@example.com"
  }
}

 

GET /reviews/_mapping


{
  "reviews" : {
    "mappings" : {
      "properties" : {
        "author" : {
          "properties" : {
            "email" : {
              "type" : "keyword"
            },
            "first_name" : {
              "type" : "text"
            },
            "last_name" : {
              "type" : "text"
            }
          }
        },
        "content" : {
          "type" : "text"
        },
        "product_id" : {
          "type" : "integer"
        },
        "rating" : {
          "type" : "float"
        }
      }
    }
  }
}
GET /reviews/_mapping/field/content

field를 붙여야 한다(?)
{
  "reviews" : {
    "mappings" : {
      "content" : {
        "full_name" : "content",
        "mapping" : {
          "content" : {
            "type" : "text"
          }
        }
      }
    }
  }
}
GET /reviews/_mapping/field/author.email {
  "reviews" : {
    "mappings" : {
      "author.email" : {
        "full_name" : "author.email",
        "mapping" : {
          "email" : {
            "type" : "keyword"
          }
        }
      }
    }
  }
}

 

혹은 

(⭐️) Dot notation 사용

계층 필드를 표현할 때는 아래와 같이 하는 것이 편하다.

 

PUT /reviews_dot_notation
{
  "mappings": {
    "properties": {
      "rating" : {"type": "float"},
      "content": {"type": "text"},
      "product_id": {"type": "integer"},
      "author.first_name":{"type": "text"},
      "author.last_name": {"type": "text"},
      "author.email": {"type": "keyword"}
    }
  }
}

GET /reviews_dot_notation/_mapping

GET /reviews/_mapping

와 결과 동일하다.

 

 

반응형

'시스템 > DB' 카테고리의 다른 글

ElasticSearch (Mapping Documents)  (0) 2025.03.07
SELECT 기본 용법  (0) 2022.08.02