분석 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 필드에 이것을 적용했음
- 모든 필드는 0개 이상의 값을 포함할 수 있음
제약 조건
- 배열 값은 동일한 데이터 타입이어야 함
- 강제 변환은 이미 매핑된 필드에만 작동함
- 동적 매핑으로 필드 매핑을 생성하는 경우, 배열은 동일한 데이터 타입을 포함해야 함
- 강제 변환 사용을 권장하지 않음(적어도 의도적으로는)
- 강제 변환은 이미 매핑된 필드에만 작동함
중첩 배열
- 배열은 중첩 배열을 포함할 수 있음
- 배열은 색인 중에 평면화됨
- [ 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 |