Elasticsearch 클러스터는 마스터 노드, 데이터 노드, 코디네이터 노드로 구성되며, 각 노드가 다운될 경우 시스템의 안정성과 가용성에 영향을 미칠 수 있다. 따라서 각 노드 유형별로 장애 발생 시 대응 방안을 마련해야 한다.


1. 마스터 노드 장애 복구 전략

(1) 마스터 노드의 역할

  • 클러스터의 헬스 체크, 노드 관리, 샤드 할당, 설정 변경 등의 중요한 역할을 수행
  • 마스터 노드가 장애를 일으키면 클러스터 상태를 업데이트하거나 새로운 노드를 추가할 수 없음

(2) 마스터 노드 장애 발생 시 증상

  • GET _cluster/health 요청 시 red 또는 yellow 상태
  • 클러스터 상태 변경이 불가능
  • 노드 추가 및 샤드 할당 불가

(3) 복구 방법

  1. 다른 마스터 노드가 있는지 확인
    • 정상적으로 선출된 새로운 마스터 노드가 있으면 자동 복구 진행됨
  2. GET _cat/master?v
  3. 마스터 노드가 1개뿐인 경우 클러스터가 중단됨
    • 최소 3개의 마스터 노드를 유지해야 함
    • 마스터 노드가 모두 다운된 경우 수동 복구 필요
  4. 새로운 마스터 노드 추가
    • 기존 마스터 노드가 복구 불가능할 경우 새로운 노드를 추가하고 elasticsearch.yml에서 마스터 노드로 설정
    node.master: true
    
  5. 클러스터 재시작 후 상태 확인
  6. GET _cluster/health
  7. 마스터 노드 선출이 안 될 경우 강제 복구
    • 강제로 클러스터를 재구성하여 노드를 재배치
  8. curl -XPOST "http://localhost:9200/_cluster/reroute?retry_failed=true"

예방 조치

  • 마스터 노드는 반드시 3개 이상 유지하여 선출이 가능하도록 구성
  • 마스터 전용 노드를 설정하여 데이터 노드와 분리
  • 고가용성을 위해 마스터 노드를 다른 물리 서버에 배포

2. 데이터 노드 장애 복구 전략

(1) 데이터 노드의 역할

  • 인덱스 데이터 저장 및 검색 요청 처리
  • 장애 발생 시 저장된 데이터가 유실될 가능성이 있음

(2) 데이터 노드 장애 발생 시 증상

  • 일부 데이터 조회 불가
  • 클러스터 헬스 체크 시 yellow 또는 red 상태
  • 샤드 불균형 발생

(3) 복구 방법

  1. 장애 노드 상태 확인
    • 노드가 다운되었는지 확인하고 문제 원인 파악 (디스크 공간 부족, 메모리 문제 등)
  2. GET _cat/nodes?v
  3. 샤드 재할당 확인
    • UNASSIGNED 상태의 샤드가 있으면 자동 복구되지 않았음을 의미
  4. GET _cat/shards?v
  5. 노드 재시작 후 샤드 복구 확인
    • 데이터 노드를 다시 시작한 후, 클러스터가 자동으로 샤드를 복구하는지 확인
    systemctl restart elasticsearch
    
  6. 수동 샤드 복구 실행 (필요 시)
  7. POST _cluster/reroute?retry_failed=true
  8. 샤드 강제 할당 (긴급 복구 필요 시)
    • 할당이 실패한 이유를 확인한 후 적절한 노드로 수동 할당
  9. POST _cluster/allocation/explain

예방 조치

  • 복제 샤드 설정(number_of_replicas: 1 이상)으로 장애 발생 시 자동 복구 가능하도록 설정
  • 디스크 사용량 모니터링 (GET _cat/allocation?v 명령어 활용)
  • 데이터 노드 장애 발생 시 ILM(인덱스 수명 주기 관리) 적용하여 오래된 데이터를 자동으로 Cold 노드로 이동

3. 코디네이터 노드 장애 복구 전략

(1) 코디네이터 노드의 역할

  • 검색 쿼리 및 집계 요청을 분산하여 성능 최적화
  • 장애 발생 시 데이터 노드의 부하가 증가할 수 있음

(2) 코디네이터 노드 장애 발생 시 증상

  • 검색 및 집계 쿼리 속도 저하
  • CPU 사용량 증가
  • 클러스터 전체의 응답 속도 저하

(3) 복구 방법

  1. 장애 노드 상태 확인
    • 코디네이터 노드가 다운되었는지 확인
  2. GET _cat/nodes?v
  3. 노드 재시작
    • 노드가 단순한 장애(메모리 부족, 네트워크 문제)라면 재시작으로 해결 가능
  4. systemctl restart elasticsearch
  5. 노드 추가 및 부하 분산
    • 코디네이터 노드가 과부하로 다운되었다면 새로운 코디네이터 노드 추가
    node.master: false
    node.data: false
    node.ingest: false
    
  6. 쿼리 로드 밸런싱 설정
    • 애플리케이션에서 Elasticsearch에 요청할 때 라운드 로빈 방식을 사용하여 요청을 여러 노드로 분산

예방 조치

  • 검색 요청이 많은 경우 코디네이터 노드를 2개 이상 운영
  • 로드 밸런서를 활용하여 요청 부하를 분산
  • 쿼리 최적화 적용 (필요한 필드만 검색, 애그리게이션 최소화)

4. 결론

  • 마스터 노드 장애 시: 3개 이상의 마스터 노드를 유지하여 자동 선출 가능하도록 구성
  • 데이터 노드 장애 시: 복제 샤드를 설정하고 ILM을 적용하여 자동 복구 가능하도록 운영
  • 코디네이터 노드 장애 시: 로드 밸런서를 활용하여 부하를 분산하고, 검색 요청이 많은 경우 추가적인 코디네이터 노드를 운영

엘라스틱 서치(Elasticsearch)를 선택해야 하는 이유

데이터 저장소는 다양한 종류가 있으며, 각각의 특성에 따라 적절한 활용 분야가 다릅니다. 그중에서도 엘라스틱 서치(Elasticsearch)는 강력한 검색 기능과 빠른 데이터 처리 성능을 바탕으로 많은 기업과 개발자들이 선택하는 솔루션입니다. 이번 글에서는 엘라스틱 서치가 다른 데이터 저장소와 비교했을 때 어떤 장점이 있는지 살펴보겠습니다.

 

1. 엘라스틱 서치의 핵심 특징

엘라스틱 서치는 분산형 검색 및 분석 엔진으로, 특히 대량의 데이터를 빠르게 검색하고 분석하는 데 최적화된 솔루션입니다. 주요 특징은 다음과 같습니다.

  • 풀텍스트 검색(Full-text Search) 최적화: 자연어 처리(NLP) 및 다양한 검색 알고리즘을 활용하여 고급 검색 기능을 제공
  • 역색인(Inverted Index) 방식: 문서를 저장할 때 단어 단위로 색인을 생성하여 검색 속도를 극대화
  • 실시간 검색 및 데이터 분석: 새로운 데이터가 추가될 때 즉각적으로 색인화되어 실시간으로 검색 가능
  • 확장성(Scalability): 클러스터 기반으로 노드를 추가하여 수평 확장이 가능
  • RESTful API 지원: 다양한 프로그래밍 언어 및 애플리케이션과 손쉽게 통합 가능
  • 로그 및 모니터링 시스템과 연계 가능: ELK 스택(Elasticsearch, Logstash, Kibana)으로 시스템 로그 분석 및 시각화 가능

이제 다른 데이터 저장소와 비교하여 엘라스틱 서치가 언제 유용한지 알아보겠습니다.

 

2. 엘라스틱 서치 vs. 관계형 데이터베이스(RDBMS)

항목 엘라스틱 서치 관계형 데이터베이스(RDBMS)
데이터 모델 문서 기반(JSON) 테이블(행/열 구조)
검색 성능 대량의 데이터에서 빠른 검색 가능 인덱싱이 없으면 검색 성능 저하
색인 방식 역색인 방식 사용 B-트리 또는 해시 기반 인덱스
실시간 데이터 처리 가능 실시간 분석 어려움
확장성 수평 확장 가능 일반적으로 수직 확장
트랜잭션 지원 X (ACID 미지원) O (ACID 지원)

언제 엘라스틱 서치를 선택해야 할까?

  • 빠른 검색이 필요한 경우 (예: e-커머스 검색, 로그 분석, 추천 시스템)
  • 구조화되지 않은 데이터를 저장하고 검색해야 할 때 (예: JSON, 로그 데이터)
  • 수많은 검색 쿼리를 처리해야 하는 경우

 

3. 엘라스틱 서치 vs. NoSQL 데이터베이스(MongoDB, Cassandra 등)

항목 엘라스틱 서치 NoSQL (MongoDB, Cassandra 등)
데이터 모델 문서 기반(JSON) 문서/키-값/컬럼 기반
주요 목적 고속 검색 및 분석 데이터 저장 및 처리
검색 성능 고급 검색 및 필터링 최적화 기본적인 인덱싱 지원
색인 방식 역색인 방식 사용 기본적인 B-트리 또는 해시 기반 인덱스
확장성 자동 샤딩으로 수평 확장 가능 대부분 수평 확장 가능
트랜잭션 지원 제한적 일부 지원

언제 엘라스틱 서치를 선택해야 할까?

  • 대량의 데이터를 실시간으로 검색하고 필터링해야 할 경우
  • MongoDB나 Cassandra의 기본 검색 기능이 부족할 때 보완 용도로 사용
  • 검색뿐만 아니라 데이터 분석이 필요한 경우

 

4. 엘라스틱 서치 vs. 데이터 웨어하우스 (Snowflake, BigQuery, Redshift 등)

항목 엘라스틱 서치 데이터 웨어하우스
데이터 모델 JSON 문서 기반 구조화된 데이터 테이블
분석 목적 실시간 검색 및 분석 대규모 데이터 처리 및 배치 분석
검색 속도 실시간 검색 최적화 대량 데이터를 기반으로 배치 분석
색인 방식 역색인 방식 사용 컬럼 기반 저장 및 분석 최적화
사용 사례 로그 분석, 텍스트 검색 BI(비즈니스 인텔리전스), 데이터 마이닝

언제 엘라스틱 서치를 선택해야 할까?

  • 실시간 검색과 즉각적인 데이터 분석이 중요한 경우
  • 정형화된 데이터보다 비정형 데이터(텍스트, 로그 등)를 다루는 경우
  • BI 툴보다는 빠른 응답 속도를 제공하는 검색 중심 환경을 원할 때

 

5. 엘라스틱 서치의 최적 활용 사례

1. 로그 및 시스템 모니터링

  • Kibana와 연계하여 시스템 로그를 시각화하고 분석 가능
  • 장애 감지 및 실시간 대응 시스템 구축 가능

2. 검색 엔진 구축

  • 전자상거래 사이트의 상품 검색
  • 뉴스 및 문서 검색 시스템
  • 사용자 맞춤형 검색 추천 시스템

3. 데이터 분석 및 BI

  • 실시간 데이터 스트림 분석
  • 사용자의 행동 패턴 분석

 

6. 결론: 언제 엘라스틱 서치를 선택해야 할까?

엘라스틱 서치는 데이터 저장이 목적이 아니라, 데이터 검색과 분석을 빠르게 수행하는 것이 핵심입니다. 따라서, 다음과 같은 경우 엘라스틱 서치가 강력한 도구가 될 수 있습니다.

빠르고 효율적인 검색이 필요한 경우 (예: 전자상거래, 로그 분석, 텍스트 검색) 대량의 데이터를 실시간으로 처리해야 하는 경우 데이터 웨어하우스보다는 검색 중심의 환경이 필요한 경우 MongoDB, RDBMS 등의 기본 검색 기능이 부족할 때 보완 용도로 활용

반면, 트랜잭션이 중요한 금융 시스템이나 구조화된 데이터를 안정적으로 저장해야 하는 경우에는 RDBMS나 데이터 웨어하우스가 더 적합할 수 있습니다.

결국, 엘라스틱 서치는 데이터베이스가 아니라 검색 엔진이라는 점을 명확히 이해하고, 필요에 따라 적절한 데이터 저장소를 선택하는 것이 중요합니다.

🔍 문제 분석

  1. Must specify either --ca or --ca-cert/--ca-key or --self-signed 오류
    • elasticsearch-certutil cert 실행 시 CA 인증서를 명시적으로 지정하지 않아서 발생한 오류입니다.
    • CA 인증서를 사용하려면 --ca-cert 및 --ca-key 옵션을 지정해야 합니다.
  2. Expand-Archive: 파일이 이미 있어서 압축 해제 실패
    • 기존 certs 폴더에 instance.crt, instance.key 파일이 있어서 덮어쓰지 못함.
    • -Force 옵션을 추가하면 기존 파일을 덮어쓸 수 있음.

✅ 해결 방법

아래 순서대로 진행하세요.


1️⃣ 기존 certs 폴더 삭제 후 새로 생성

Remove-Item -Recurse -Force certs
mkdir certs
  • 기존 인증서 삭제 후 새로운 인증서를 만들기 위한 폴더 생성.

2️⃣ CA 인증서 생성

docker run --rm -v ${PWD}/certs:/usr/share/elasticsearch/config/certs `
  -it docker.elastic.co/elasticsearch/elasticsearch:8.17.2 `
  bin/elasticsearch-certutil ca --pem -out /usr/share/elasticsearch/config/certs/ca.zip

certs/ca.zip 파일이 생성됨.


3️⃣ CA 인증서 압축 해제

Expand-Archive -Path certs\ca.zip -DestinationPath certs -Force

certs/ca/ca.crt, certs/ca/ca.key 파일이 생성됨.


4️⃣ Elasticsearch 인증서 생성

docker run --rm -v ${PWD}/certs:/usr/share/elasticsearch/config/certs `
  -it docker.elastic.co/elasticsearch/elasticsearch:8.17.2 `
  bin/elasticsearch-certutil cert --pem --ca-cert /usr/share/elasticsearch/config/certs/ca/ca.crt `
  --ca-key /usr/share/elasticsearch/config/certs/ca/ca.key `
  -out /usr/share/elasticsearch/config/certs/elasticsearch.zip

certs/elasticsearch.zip 파일이 생성됨.


5️⃣ Elasticsearch 인증서 압축 해제

Expand-Archive -Path certs\elasticsearch.zip -DestinationPath certs -Force

certs/elasticsearch/elasticsearch.crt, certs/elasticsearch/elasticsearch.key 파일이 생성됨.


6️⃣ .p12 인증서 변환

openssl pkcs12 -export -out certs/elasticsearch.p12 -inkey certs/elasticsearch/elasticsearch.key `
  -in certs/elasticsearch/elasticsearch.crt -passout pass:your-keystore-password

certs/elasticsearch.p12 파일이 생성됨.


7️⃣ docker-compose.yml 수정

version: '3.8'

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.17.2
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=true  # ✅ 보안 활성화
      - ELASTIC_PASSWORD=your-secure-password
      - xpack.security.http.ssl.enabled=true  # ✅ SSL 활성화
      - xpack.security.http.ssl.keystore.path=/usr/share/elasticsearch/config/certs/elasticsearch.p12
      - xpack.security.http.ssl.truststore.path=/usr/share/elasticsearch/config/certs/elasticsearch.p12
      - xpack.security.http.ssl.keystore.password=your-keystore-password
      - xpack.security.http.ssl.truststore.password=your-keystore-password
    ports:
      - "9200:9200"
      - "9300:9300"
    networks:
      - elastic-net
    volumes:
      - ${PWD}/certs:/usr/share/elasticsearch/config/certs  # ✅ 인증서 파일 연결

volumes:
  elasticsearch-data:
    driver: local

networks:
  elastic-net:
    driver: bridge

8️⃣ application.yml 수정

spring:
  elasticsearch:
    uris: https://localhost:9200
    username: elastic
    password: your-secure-password
    restclient:
      ssl:
        enabled: true
        trust-store: classpath:certs/elasticsearch.p12
        trust-store-password: your-keystore-password

9️⃣ Docker 컨테이너 다시 실행

docker-compose down
docker-compose up -d

🔟 Elasticsearch SSL 연결 확인

curl -X GET "https://localhost:9200" --user "elastic:your-secure-password" --insecure

JSON 응답이 나오면 SSL이 정상적으로 적용된 것! 🚀


🎯 최종 정리

  1. 기존 인증서 삭제 후 새로 생성
  2. CA 인증서 생성
  3. Elasticsearch 인증서 생성 (elasticsearch.zip)
  4. .p12 변환
  5. Docker에서 SSL 설정
  6. Spring Boot에서 https://localhost:9200로 연결
  7. Docker 컨테이너 다시 실행
  8. curl로 연결 확인

이제 Elasticsearch의 SSL이 Docker에서 설정되었습니다! 🚀
문제가 발생하면 docker logs elasticsearch 로그를 확인하고 알려주세요!

Elasticsearch: Pipeline Aggregations (파이프라인 집계) 완벽 정리 🚀

1. Pipeline Aggregations 개요

Metrics Aggregation의 결과를 다시 연산하는 기능
다른 Aggregation 결과를 입력값으로 사용 가능
데이터의 이동 평균, 미분, 누적 합계, 통계 분석 수행 가능


2. Pipeline Aggregations 주요 기능

설명 사용 예시
min_bucket 버킷 중 최솟값 찾기 월별 최소 승객 수
max_bucket 버킷 중 최댓값 찾기 월별 최대 승객 수
avg_bucket 버킷들의 평균값 주간 평균 방문자 수
sum_bucket 버킷들의 합계 분기별 총 매출
stats_bucket min, max, sum, avg 등 한 번에 계산 다양한 통계 분석
cumulative_sum 누적 합계 계산 매월 누적 방문자 수
moving_avg 이동 평균 계산 3개월 이동 평균 승객 수
derivative 값의 미분 계산 방문자 수 증가율

 

Elasticsearch에서 "버킷(Bucket)"이란?
👉 버킷은 데이터를 특정 기준에 따라 그룹화하는 컨테이너입니다.
👉 **"버킷을 만든다"**는 것은 데이터를 특정 조건에 따라 분류하는 것입니다.
👉 각 버킷에는 해당하는 **도큐먼트 개수(doc_count)**가 자동으로 계산됩니다.


3. 데이터 예제 (지하철 승객 수 데이터)

먼저 테스트 데이터를 준비합니다.

📌 예제 1: my_stations 인덱스 생성 및 데이터 입력

PUT my_stations/_bulk
{"index": {"_id": "1"}}
{"date": "2019-06-01", "line": "1호선", "station": "종각", "passangers": 2314}
{"index": {"_id": "2"}}
{"date": "2019-06-01", "line": "2호선", "station": "강남", "passangers": 5412}
{"index": {"_id": "3"}}
{"date": "2019-07-10", "line": "2호선", "station": "강남", "passangers": 6221}
{"index": {"_id": "4"}}
{"date": "2019-07-15", "line": "2호선", "station": "강남", "passangers": 6478}
{"index": {"_id": "5"}}
{"date": "2019-08-07", "line": "2호선", "station": "강남", "passangers": 5821}
{"index": {"_id": "6"}}
{"date": "2019-08-18", "line": "2호선", "station": "강남", "passangers": 5724}
{"index": {"_id": "7"}}
{"date": "2019-09-02", "line": "2호선", "station": "신촌", "passangers": 3912}
{"index": {"_id": "8"}}
{"date": "2019-09-11", "line": "3호선", "station": "양재", "passangers": 4121}
{"index": {"_id": "9"}}
{"date": "2019-09-20", "line": "3호선", "station": "홍제", "passangers": 1021}
{"index": {"_id": "10"}}
{"date": "2019-10-01", "line": "3호선", "station": "불광", "passangers": 971}

승객 수 데이터가 포함된 샘플 데이터 생성


4. 누적 합계 (Cumulative Sum Aggregation)

월별 승객 수 합계를 누적 계산
buckets_path 옵션을 이용해 다른 집계 결과를 참조

📌 예제 2: cumulative_sum으로 누적 승객 수 계산

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "months": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      },
      "aggs": {
        "sum_psg": {
          "sum": {
            "field": "passangers"
          }
        },
        "accum_sum_psg": {
          "cumulative_sum": {
            "buckets_path": "sum_psg"
          }
        }
      }
    }
  }
}

각 월별 합계를 누적하여 계산하는 예제
buckets_path: "sum_psg" → sum_psg 값을 입력으로 사용


5. 이동 평균 (Moving Average Aggregation)

이전 버킷 값을 참조하여 이동 평균 계산
데이터의 변동성을 부드럽게 표현 가능

📌 예제 3: moving_avg로 3개월 이동 평균 계산

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "months": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      },
      "aggs": {
        "sum_psg": {
          "sum": {
            "field": "passangers"
          }
        },
        "moving_avg_psg": {
          "moving_avg": {
            "buckets_path": "sum_psg",
            "window": 3
          }
        }
      }
    }
  }
}

3개월 이동 평균을 계산하여 트렌드 파악
window: 3 → 3개월 이동 평균


6. 미분 (Derivative Aggregation)

변화율(증가율/감소율) 계산 가능
트래픽 증가율, 매출 성장률 분석에 활용

📌 예제 4: derivative로 승객 수 증가율 계산

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "months": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      },
      "aggs": {
        "sum_psg": {
          "sum": {
            "field": "passangers"
          }
        },
        "growth_rate_psg": {
          "derivative": {
            "buckets_path": "sum_psg"
          }
        }
      }
    }
  }
}

승객 수의 증가율(미분 값) 계산


7. 최대값이 있는 버킷 찾기 (Max Bucket Aggregation)

여러 버킷 중 최대값이 포함된 버킷을 찾음
가장 많은 승객이 있는 월 확인 가능

📌 예제 5: max_bucket으로 최대 승객 수를 기록한 월 찾기

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "months": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      },
      "aggs": {
        "sum_psg": {
          "sum": {
            "field": "passangers"
          }
        }
      }
    },
    "max_passangers_month": {
      "max_bucket": {
        "buckets_path": "months>sum_psg"
      }
    }
  }
}

가장 승객 수가 많았던 달을 찾는 예제
buckets_path: "months>sum_psg" → 부모 > 자식 관계로 접근


8. 정리

기능 설명 활용 예시
누적 합계 (cumulative_sum) 이전 값들의 합을 누적 총 방문자 수 분석
이동 평균 (moving_avg) 일정 구간의 평균 계산 3개월 이동 평균
미분 (derivative) 값의 증가율 계산 매출 성장률 분석
최대 버킷 (max_bucket) 최대값을 포함한 버킷 찾기 최대 방문자 수가 있는 날짜 찾기

9. 마무리

Pipeline Aggregations을 활용하면 복잡한 데이터 분석 가능
버킷을 기준으로 누적 합, 이동 평균, 증가율 등을 손쉽게 계산 가능
하지만 너무 깊은 Aggregations을 사용하면 성능 저하 가능

이제 Aggregations을 활용하여 더욱 강력한 데이터 분석을 진행할 수 있습니다! 🚀

Elasticsearch: Sub-Aggregations (하위 집계) 완벽 정리

Sub-Aggregations(하위 집계)는 버킷 집계(Bucket Aggregation) 안에서 또 다른 집계를 수행할 수 있도록 지원하는 기능입니다.
한 번의 쿼리로 그룹화된 데이터에 추가적인 분석을 수행 가능
Bucket Aggregation 안에 다시 Bucket 또는 Metrics Aggregation을 중첩하여 사용 가능
여러 계층의 집계를 수행할 수 있어 복잡한 데이터 분석에 적합

이번 글에서는 Sub-Aggregations의 개념, 주요 기능, 실전 예제까지 상세히 알아보겠습니다.


1. Sub-Aggregations 개요

     
개념 Bucket Aggregation 내에서 추가 집계 수행  
사용 목적 그룹화된 데이터 내에서 추가적인 통계 분석 수행  
주요 유형 버킷 안에 Metrics Aggregation 적용 버킷 안에 또 다른 버킷 생성  

2. 데이터 예제 (지하철 승객 수 데이터)

Sub-Aggregations을 테스트할 데이터를 준비합니다.

📌 예제 1: my_stations 인덱스 생성 및 데이터 입력

PUT my_stations/_bulk
{"index": {"_id": "1"}}
{"date": "2019-06-01", "line": "1호선", "station": "종각", "passangers": 2314}
{"index": {"_id": "2"}}
{"date": "2019-06-01", "line": "2호선", "station": "강남", "passangers": 5412}
{"index": {"_id": "3"}}
{"date": "2019-07-10", "line": "2호선", "station": "강남", "passangers": 6221}
{"index": {"_id": "4"}}
{"date": "2019-07-15", "line": "2호선", "station": "강남", "passangers": 6478}
{"index": {"_id": "5"}}
{"date": "2019-08-07", "line": "2호선", "station": "강남", "passangers": 5821}
{"index": {"_id": "6"}}
{"date": "2019-08-18", "line": "2호선", "station": "강남", "passangers": 5724}
{"index": {"_id": "7"}}
{"date": "2019-09-02", "line": "2호선", "station": "신촌", "passangers": 3912}
{"index": {"_id": "8"}}
{"date": "2019-09-11", "line": "3호선", "station": "양재", "passangers": 4121}
{"index": {"_id": "9"}}
{"date": "2019-09-20", "line": "3호선", "station": "홍제", "passangers": 1021}
{"index": {"_id": "10"}}
{"date": "2019-10-01", "line": "3호선", "station": "불광", "passangers": 971}

지하철 승객 수 데이터를 포함한 샘플 데이터 생성


3. Bucket 내부에서 Metrics Aggregation 수행

버킷 그룹별로 추가적인 통계(평균, 최대, 최소 등)를 계산 가능
terms(역 이름) 기준으로 그룹화 후, 각 역의 평균 승객 수 계산

📌 예제 2: station.keyword 기준으로 그룹화 후 평균 승객 수 계산

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "stations": {
      "terms": {
        "field": "station.keyword"
      },
      "aggs": {
        "avg_psg_per_st": {
          "avg": {
            "field": "passangers"
          }
        }
      }
    }
  }
}

각 역별 평균 승객 수(avg_psg_per_st) 계산 가능


4. Bucket 내부에서 또 다른 Bucket Aggregation 수행

하나의 Bucket 내에서 또 다른 기준으로 데이터를 그룹화 가능
지하철 노선(line.keyword) → 해당 노선의 역(station.keyword) 순으로 그룹화

📌 예제 3: 노선별(line.keyword)로 그룹화 후, 각 노선의 역(station.keyword) 그룹화

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "lines": {
      "terms": {
        "field": "line.keyword"
      },
      "aggs": {
        "stations_per_lines": {
          "terms": {
            "field": "station.keyword"
          }
        }
      }
    }
  }
}

노선별 → 해당 노선의 역을 그룹화하는 예제


5. Bucket 내부에서 Bucket + Metrics Aggregation 수행

버킷 안에 또 다른 버킷을 만들고, 그 내부에서 통계 연산 수행 가능
지하철 노선(line.keyword) → 역(station.keyword) → 평균 승객 수(avg_passangers) 순으로 계산

📌 예제 4: 노선별 → 역별 → 평균 승객 수 계산

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "lines": {
      "terms": {
        "field": "line.keyword"
      },
      "aggs": {
        "stations_per_lines": {
          "terms": {
            "field": "station.keyword"
          },
          "aggs": {
            "avg_passangers": {
              "avg": {
                "field": "passangers"
              }
            }
          }
        }
      }
    }
  }
}

노선별 그룹화 후, 각 역별 평균 승객 수까지 계산하는 예제


6. Sub-Aggregations 주의사항

     
하위 버킷이 많아지면 성능 저하 발생 너무 깊은 버킷 구조는 피할 것  
최대 2~3단계의 Sub-Aggregations을 권장 Elasticsearch 메모리 사용량 증가 가능  
데이터 양이 많다면 size 제한을 걸어야 함 기본 size 값은 10개  

7. 정리

     
버킷 내부에서 통계 연산 terms + avg 그룹화된 데이터 내에서 평균/최대/최소 등 계산
버킷 내부에서 또 다른 그룹화 terms + terms 하나의 그룹화된 데이터 내에서 추가 그룹화
버킷 + 하위 버킷 + 통계 연산 terms + terms + avg 2단계 이상의 그룹화 후 통계 연산 수행

8. 마무리

Sub-Aggregations을 활용하면 데이터를 더욱 정교하게 분석 가능
Bucket 내부에서 또 다른 Bucket 및 Metrics Aggregation 수행 가능
단, 너무 깊은 계층의 Sub-Aggregations은 성능 저하를 유발할 수 있음

다음 학습에서는 고급 Aggregations 기법 및 성능 최적화 방법을 다루겠습니다! 🚀

Elasticsearch: Bucket Aggregations (버킷 집계) 완벽 정리

Bucket Aggregations은 특정 기준으로 데이터를 그룹화하여 분석하는 강력한 기능을 제공합니다.
숫자, 날짜, 문자열 데이터를 기반으로 그룹을 나눌 수 있음
각 그룹(버킷)별로 포함된 문서 수(doc_count)를 계산
각 버킷에 추가적으로 Metrics Aggregation을 적용하여 통계 분석 가능

이번 글에서는 Bucket Aggregations 개념, 주요 기능, 실전 예제까지 상세히 알아보겠습니다.


1. Bucket Aggregations 개요

     
개념 데이터를 특정 기준에 따라 그룹화  
사용 목적 데이터 분석 및 요약 정보 제공  
주요 유형 range, histogram, date_range, date_histogram, terms  

2. 데이터 예제 (지하철 승객 수 데이터)

Bucket Aggregations을 테스트할 데이터를 준비합니다.

📌 예제 1: my_stations 인덱스 생성 및 데이터 입력

PUT my_stations/_bulk
{"index": {"_id": "1"}}
{"date": "2019-06-01", "line": "1호선", "station": "종각", "passangers": 2314}
{"index": {"_id": "2"}}
{"date": "2019-06-01", "line": "2호선", "station": "강남", "passangers": 5412}
{"index": {"_id": "3"}}
{"date": "2019-07-10", "line": "2호선", "station": "강남", "passangers": 6221}
{"index": {"_id": "4"}}
{"date": "2019-07-15", "line": "2호선", "station": "강남", "passangers": 6478}
{"index": {"_id": "5"}}
{"date": "2019-08-07", "line": "2호선", "station": "강남", "passangers": 5821}
{"index": {"_id": "6"}}
{"date": "2019-08-18", "line": "2호선", "station": "강남", "passangers": 5724}
{"index": {"_id": "7"}}
{"date": "2019-09-02", "line": "2호선", "station": "신촌", "passangers": 3912}
{"index": {"_id": "8"}}
{"date": "2019-09-11", "line": "3호선", "station": "양재", "passangers": 4121}
{"index": {"_id": "9"}}
{"date": "2019-09-20", "line": "3호선", "station": "홍제", "passangers": 1021}
{"index": {"_id": "10"}}
{"date": "2019-10-01", "line": "3호선", "station": "불광", "passangers": 971}

지하철 승객 수 데이터를 포함한 샘플 데이터 생성


3. Range Aggregation (범위별 버킷)

숫자 필드 값을 기준으로 특정 범위를 지정하여 그룹화
from(이상), to(미만)으로 범위를 정의

📌 예제 2: 승객 수(passangers)를 기준으로 그룹 나누기

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "passangers_range": {
      "range": {
        "field": "passangers",
        "ranges": [
          { "to": 1000 },
          { "from": 1000, "to": 4000 },
          { "from": 4000 }
        ]
      }
    }
  }
}

1000명 미만, 1000~4000명, 4000명 이상으로 그룹화


4. Histogram Aggregation (구간별 버킷)

특정 간격(interval)으로 숫자 필드를 그룹화
range와 달리 interval 값을 설정하여 자동 분할

📌 예제 3: 승객 수를 2000명 단위로 그룹화

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "passangers_his": {
      "histogram": {
        "field": "passangers",
        "interval": 2000
      }
    }
  }
}

2000 단위로 그룹을 생성하여 데이터 분포 확인


5. Date Histogram Aggregation (날짜별 버킷)

날짜 필드를 일정한 기간 간격으로 그룹화
interval 대신 fixed_interval 또는 calendar_interval 사용

📌 예제 4: 한 달 단위로 날짜 필드(date) 그룹화

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "date_his": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      }
    }
  }
}

1개월 단위로 데이터 그룹화하여 시계열 분석 가능


6. Terms Aggregation (카테고리별 버킷)

keyword 필드를 기준으로 데이터를 그룹화
가장 많이 등장하는 값 순으로 정렬됨
데이터 분석 시 특정 필드의 "빈도수"를 파악할 때 유용

📌 예제 5: 지하철 역(station) 기준으로 그룹화

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "stations": {
      "terms": {
        "field": "station.keyword"
      }
    }
  }
}

각 역(station)의 승객 수를 집계하여 가장 많이 등장하는 역을 파악 가능

📌 예제 6: 지하철 노선(line)별 그룹화 및 승객 수 평균 계산

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "lines": {
      "terms": {
        "field": "line.keyword"
      },
      "aggs": {
        "avg_passangers": {
          "avg": { "field": "passangers" }
        }
      }
    }
  }
}

노선별 평균 승객 수를 분석하는 예제


7. 정리

     
숫자 범위 range, histogram 특정 범위 또는 간격(interval)으로 그룹화
날짜 범위 date_range, date_histogram 특정 기간 간격으로 그룹화
카테고리별 그룹화 terms keyword 필드 기준으로 그룹화

8. 마무리

Bucket Aggregations을 사용하면 데이터를 원하는 기준으로 그룹화 가능
각 그룹별 개수(doc_count)와 추가 Metrics Aggregations을 조합하여 통계 분석 가능
시계열 데이터 분석, 숫자 범위 분석, 문자열(카테고리) 분석에 매우 유용

다음 학습에서는 고급 Aggregations 및 Nested Aggregations 활용법을 다루겠습니다! 🚀

Elasticsearch: Metrics Aggregations (메트릭 집계) 완벽 정리

Elasticsearch의 Metrics Aggregations을 활용하면 **숫자 필드의 연산(최소, 최대, 평균, 합계, 개수 등)**을 수행할 수 있습니다.
검색된 데이터에서 통계 정보를 추출
로그 분석, 사용자 접속 통계, 매출 분석 등에 활용 가능
백분위(Percentiles) 및 유니크 값(Cardinality) 분석 가능

이번 글에서는 Metrics Aggregations 개념, 주요 기능, 실전 예제까지 상세히 알아보겠습니다.


1. Metrics Aggregations 개요

     
개념 숫자 필드를 대상으로 다양한 통계 연산을 수행  
사용 목적 평균, 합계, 최소값, 최대값, 개수 등 통계 값 계산  
주요 유형 min, max, sum, avg, stats, cardinality, percentiles, percentile_ranks  

2. 데이터 예제 (지하철 승객 수 데이터)

Metrics Aggregations을 테스트할 데이터를 준비합니다.

📌 예제 1: my_stations 인덱스 생성 및 데이터 입력

PUT my_stations/_bulk
{"index": {"_id": "1"}}
{"date": "2019-06-01", "line": "1호선", "station": "종각", "passangers": 2314}
{"index": {"_id": "2"}}
{"date": "2019-06-01", "line": "2호선", "station": "강남", "passangers": 5412}
{"index": {"_id": "3"}}
{"date": "2019-07-10", "line": "2호선", "station": "강남", "passangers": 6221}
{"index": {"_id": "4"}}
{"date": "2019-07-15", "line": "2호선", "station": "강남", "passangers": 6478}
{"index": {"_id": "5"}}
{"date": "2019-08-07", "line": "2호선", "station": "강남", "passangers": 5821}
{"index": {"_id": "6"}}
{"date": "2019-08-18", "line": "2호선", "station": "강남", "passangers": 5724}
{"index": {"_id": "7"}}
{"date": "2019-09-02", "line": "2호선", "station": "신촌", "passangers": 3912}
{"index": {"_id": "8"}}
{"date": "2019-09-11", "line": "3호선", "station": "양재", "passangers": 4121}
{"index": {"_id": "9"}}
{"date": "2019-09-20", "line": "3호선", "station": "홍제", "passangers": 1021}
{"index": {"_id": "10"}}
{"date": "2019-10-01", "line": "3호선", "station": "불광", "passangers": 971}

지하철 승객 수 데이터를 포함한 샘플 데이터 생성


3. 기본 Metrics Aggregations

🔹 1) 최소, 최대, 합계, 평균값 계산

✔ **min, max, sum, avg**를 사용하여 숫자 필드의 통계를 계산 가능

📌 예제 2: 전체 승객 수의 평균, 합계, 최대, 최소값 구하기

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "min_passengers": {
      "min": { "field": "passangers" }
    },
    "max_passengers": {
      "max": { "field": "passangers" }
    },
    "sum_passengers": {
      "sum": { "field": "passangers" }
    },
    "avg_passengers": {
      "avg": { "field": "passangers" }
    }
  }
}

최소값, 최대값, 합계, 평균을 한 번에 계산 가능

📌 예제 3: 특정 역(강남)의 승객 합계 구하기

GET my_stations/_search
{
  "query": {
    "match": { "station": "강남" }
  },
  "size": 0,
  "aggs": {
    "gangnam_passengers": {
      "sum": { "field": "passangers" }
    }
  }
}

강남역의 전체 승객 수 합계를 구하는 예제


4. stats Aggregation

stats를 사용하면 min, max, sum, avg, count를 한 번에 계산 가능

📌 예제 4: 승객 수의 min, max, sum, avg, count 값 구하기

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "passenger_stats": {
      "stats": { "field": "passangers" }
    }
  }
}

한 번의 Aggregation으로 여러 값을 동시에 계산 가능


5. Cardinality Aggregation (고유 값 개수)

특정 필드에 대해 "고유한 값 개수"를 계산
예: line(지하철 노선)이 몇 개 있는지 확인

📌 예제 5: line 필드에서 고유한 노선 개수 구하기

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "uniq_lines": {
      "cardinality": { "field": "line.keyword" }
    }
  }
}

1호선, 2호선, 3호선 총 3개의 고유 값이 존재


6. Percentiles Aggregation (백분위 수 계산)

데이터의 특정 백분위 값을 확인 가능 (예: 승객 수의 90% 이상이 몇 명인지 분석)

📌 예제 6: 승객 수의 기본 백분위 계산

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "pass_percentiles": {
      "percentiles": { "field": "passangers" }
    }
  }
}

기본적으로 1%, 5%, 25%, 50%, 75%, 95%, 99% 백분위 값을 제공

📌 예제 7: 특정 백분위 값(20%, 60%, 80%)을 설정

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "pass_percentiles": {
      "percentiles": {
        "field": "passangers",
        "percents": [ 20, 60, 80 ]
      }
    }
  }
}

20%, 60%, 80% 백분위 값을 지정하여 확인 가능


7. Percentile Ranks Aggregation

특정 값이 전체 데이터에서 몇 %에 해당하는지 확인
예: 승객 수 1000명, 3000명, 6000명은 상위 몇 %인지 분석

📌 예제 8: 특정 값의 백분위 랭크 구하기

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "pass_percentile_ranks": {
      "percentile_ranks": {
        "field": "passangers",
        "values": [ 1000, 3000, 6000 ]
      }
    }
  }
}

각 값이 전체 데이터의 몇 % 수준인지 확인 가능 (예: 1000명은 하위 10% 수준)


8. 정리

     
기본 연산 min, max, sum, avg, stats  
고유 값 개수 cardinality  
백분위 수 분석 percentiles, percentile_ranks  

9. 마무리

Metrics Aggregations을 활용하면 데이터 분석이 가능
백분위 수, 고유 값 개수 등을 통해 인사이트 도출 가능
Elasticsearch를 통계 분석 플랫폼으로 활용 가능

다음 학습에서는 고급 Aggregations 및 성능 최적화 전략을 다루겠습니다! 🚀

Elasticsearch: 집계(Aggregations) 완벽 정리

Elasticsearch는 단순한 검색 기능뿐만 아니라 데이터 분석 및 통계 처리까지 가능합니다.
Aggregation(집계) 기능을 활용하면 다양한 연산 수행 가능
Kibana와 연동하여 데이터 시각화 가능
Metrics Aggregation & Bucket Aggregation으로 데이터 분석 가능

이번 글에서는 Aggregation 개념, 설정 방법, 주요 기능, 실전 예제까지 상세히 알아보겠습니다.


1. Aggregations 개요

     
개념 Elasticsearch에서 데이터를 그룹화하고 통계 처리하는 기능  
사용 목적 데이터 분석, 로그 처리, 검색 결과 요약, 통계 계산  
주요 유형 Metrics Aggregation (숫자 연산) Bucket Aggregation (데이터 그룹화)  

2. Aggregation 기본 구조

🔹 Aggregation 문법

✔ _search API에서 aggs(aggregations) 옵션을 사용
✔ 여러 개의 Aggregation을 동시에 수행 가능

📌 예제 1: Aggregation 기본 구조

GET my_index/_search
{
  "query": { ... },
  "aggs": {
    "aggregation_name_1": {
      "aggregation_type": {
        "field": "필드명"
      }
    },
    "aggregation_name_2": {
      "aggregation_type": {
        "field": "필드명"
      }
    }
  }
}

여러 개의 Aggregation을 한 번에 실행 가능


3. 데이터 예제 (지하철 승객 수 데이터)

이제 Aggregation을 테스트할 지하철 승객 수 데이터를 입력합니다.

📌 예제 2: my_stations 인덱스 생성 및 데이터 입력

PUT my_stations/_bulk
{"index": {"_id": "1"}}
{"date": "2019-06-01", "line": "1호선", "station": "종각", "passangers": 2314}
{"index": {"_id": "2"}}
{"date": "2019-06-01", "line": "2호선", "station": "강남", "passangers": 5412}
{"index": {"_id": "3"}}
{"date": "2019-07-10", "line": "2호선", "station": "강남", "passangers": 6221}
{"index": {"_id": "4"}}
{"date": "2019-07-15", "line": "2호선", "station": "강남", "passangers": 6478}
{"index": {"_id": "5"}}
{"date": "2019-08-07", "line": "2호선", "station": "강남", "passangers": 5821}
{"index": {"_id": "6"}}
{"date": "2019-08-18", "line": "2호선", "station": "강남", "passangers": 5724}
{"index": {"_id": "7"}}
{"date": "2019-09-02", "line": "2호선", "station": "신촌", "passangers": 3912}
{"index": {"_id": "8"}}
{"date": "2019-09-11", "line": "3호선", "station": "양재", "passangers": 4121}
{"index": {"_id": "9"}}
{"date": "2019-09-20", "line": "3호선", "station": "홍제", "passangers": 1021}
{"index": {"_id": "10"}}
{"date": "2019-10-01", "line": "3호선", "station": "불광", "passangers": 971}

지하철 노선, 역명, 날짜, 승객 수 데이터를 포함한 샘플 데이터 생성


4. Metrics Aggregations (숫자 계산)

숫자 필드(passangers)를 대상으로 평균, 최대, 최소, 합계를 계산

📌 예제 3: 승객 수의 평균, 합계, 최대, 최소값 구하기

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "avg_passengers": {
      "avg": {
        "field": "passangers"
      }
    },
    "sum_passengers": {
      "sum": {
        "field": "passangers"
      }
    },
    "max_passengers": {
      "max": {
        "field": "passangers"
      }
    },
    "min_passengers": {
      "min": {
        "field": "passangers"
      }
    }
  }
}

지하철 승객 수의 평균, 합계, 최대, 최소값을 계산


5. Bucket Aggregations (데이터 그룹화)

문자열 필드를 기준으로 그룹화하여 데이터 집계 가능
승객 수를 지하철 노선(line) 또는 역(station)별로 그룹화 가능

📌 예제 4: 지하철 노선(line)별 평균 승객 수 구하기

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "group_by_line": {
      "terms": {
        "field": "line.keyword"
      },
      "aggs": {
        "avg_passengers": {
          "avg": {
            "field": "passangers"
          }
        }
      }
    }
  }
}

각 지하철 노선별 평균 승객 수를 구하는 쿼리

📌 예제 5: 날짜(date)별 총 승객 수 구하기

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "group_by_date": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      },
      "aggs": {
        "sum_passengers": {
          "sum": {
            "field": "passangers"
          }
        }
      }
    }
  }
}

월별 승객 수를 계산하는 date_histogram을 사용


6. Nested Aggregations (중첩 집계)

하나의 집계 내부에서 또 다른 집계를 수행
예: 지하철 노선별 승객 수 합계를 계산하고, 그 안에서 최대값 구하기

📌 예제 6: 노선별 승객 수 합계 & 최대값 구하기

GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "group_by_line": {
      "terms": {
        "field": "line.keyword"
      },
      "aggs": {
        "sum_passengers": {
          "sum": {
            "field": "passangers"
          }
        },
        "max_passengers": {
          "max": {
            "field": "passangers"
          }
        }
      }
    }
  }
}

각 노선별로 승객 수 합계 및 최대값을 구하는 중첩 집계(Nested Aggregation)


7. 정리

     
Metrics Aggregations 숫자 필드 연산 avg, sum, max, min
Bucket Aggregations 특정 필드를 기준으로 그룹화 terms, date_histogram
Nested Aggregations 하나의 집계 내부에서 또 다른 집계 수행 terms + sum + max 조합

8. 학습 가이드

1️⃣ Aggregation의 기본 개념을 이해하고 직접 쿼리 실행
2️⃣ terms, avg, sum, date_histogram을 사용하여 데이터 분석 실습
3️⃣ 중첩 Aggregation을 활용하여 고급 데이터 분석 적용


9. 마무리

Elasticsearch의 집계(Aggregations) 기능을 활용하면
검색 결과를 통계적으로 분석 가능
다양한 유형의 데이터 그룹화 및 연산 수행 가능
Kibana와 연동하여 강력한 시각화 기능 제공

다음 학습에서는 Aggregation 성능 최적화 및 고급 활용법을 다루겠습니다! 🚀

Elasticsearch: 멀티 필드 (Multi Field) 완벽 정리

Elasticsearch에서는 하나의 필드에 여러 개의 분석 방식(Analyzer) 또는 타입을 적용할 수 있습니다.
하나의 필드 값을 여러 개의 역색인 방식으로 저장 가능
Text 필드에 Keyword 타입을 추가하여 검색 & 정렬 가능
다국어 문서 분석을 위해 여러 개의 애널라이저 적용 가능

이번 글에서는 멀티 필드(Multi Field)의 개념, 설정 방법, 활용 예제, 그리고 실전 적용 방법까지 상세히 알아보겠습니다.


1. 멀티 필드 개요

특징 설명 활용 사례
하나의 필드에 여러 타입 저장 text, keyword 타입을 함께 저장 가능 검색 & 정렬 모두 필요할 때
여러 개의 애널라이저 적용 가능 동일한 필드를 다른 방식으로 분석 가능 다국어 검색 최적화
동일한 데이터를 다양한 방법으로 색인 필드명 + . 을 추가하여 관리 message.english, message.nori

2. 멀티 필드 설정

🔹 멀티 필드 기본 개념

✔ fields 옵션을 사용하여 하나의 필드를 여러 개의 서브 필드로 확장
✔ text 타입은 검색용으로 사용하고, keyword 타입은 정렬/집계용으로 활용

📌 예제 1: text + keyword 타입의 멀티 필드 설정

PUT my_index
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

title 필드는 text 타입이지만 title.keyword는 keyword 타입으로 저장됨

📌 예제 2: 데이터 저장

PUT my_index/_doc/1
{
  "title": "Elasticsearch Multi Field Test"
}

이제 title 필드는 title.keyword 서브 필드와 함께 저장됨

📌 예제 3: title 필드 검색 (text 타입)

GET my_index/_search
{
  "query": {
    "match": {
      "title": "Elasticsearch"
    }
  }
}

text 타입이므로 형태소 분석 후 검색 가능

📌 예제 4: title.keyword 필드 검색 (keyword 타입)

GET my_index/_search
{
  "query": {
    "term": {
      "title.keyword": "Elasticsearch Multi Field Test"
    }
  }
}

keyword 타입이므로 정확한 문자열 검색만 가능

📌 예제 5: keyword 타입으로 정렬하기

GET my_index/_search
{
  "sort": [
    { "title.keyword": "asc" }
  ]
}

정확한 문자열 기준으로 정렬 가능


3. 멀티 필드에서 애널라이저(Analyzer) 적용

🔹 멀티 필드를 활용한 다국어 검색

✔ text 타입 필드에 여러 개의 애널라이저를 적용할 수 있음
한국어, 영어, 일본어 등 다국어 지원에 유용

📌 예제 6: english, nori(한국어) 애널라이저를 적용한 멀티 필드 설정

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "nori_analyzer": {
          "tokenizer": "nori_tokenizer"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "message": {
        "type": "text",
        "fields": {
          "english": {
            "type": "text",
            "analyzer": "english"
          },
          "nori": {
            "type": "text",
            "analyzer": "nori_analyzer"
          }
        }
      }
    }
  }
}

message.english → 영어 전용 애널라이저 적용
message.nori → 한국어 전용 애널라이저 적용

📌 예제 7: 데이터 저장

PUT my_index/_doc/1
{
  "message": "My favorite 슈퍼영웅 is Iron Man"
}

Elasticsearch는 message, message.english, message.nori 필드로 각각 색인

📌 예제 8: message 필드에서 "영웅" 검색 (text 타입)

GET my_index/_search
{
  "query": {
    "match": {
      "message": "영웅"
    }
  }
}

기본 message 필드에서는 검색되지 않음

📌 예제 9: message.nori 필드에서 "영웅" 검색 (한국어 애널라이저 적용)

GET my_index/_search
{
  "query": {
    "match": {
      "message.nori": "영웅"
    }
  }
}

한국어 애널라이저를 적용한 message.nori 필드에서는 정상적으로 검색됨


4. 정리

     
멀티 필드란? 하나의 필드를 여러 개의 타입/애널라이저로 저장하는 방식 fields 옵션 사용
주요 활용 예시 text + keyword 조합으로 검색 & 정렬 지원 title.keyword
다국어 검색 지원 같은 데이터를 여러 애널라이저로 색인 message.english, message.nori
정확한 검색 keyword 타입을 활용하여 정확한 문자열 검색 가능 "match": { "title.keyword": "..." }
검색 최적화 text 필드는 전체 검색, keyword 필드는 필터링 & 정렬 검색 속도 개선 가능

5. 학습 가이드

1️⃣ 멀티 필드를 활용하여 text + keyword 조합을 테스트
2️⃣ 여러 애널라이저(english, nori)를 적용하여 다국어 검색 실습
3️⃣ 정확한 검색(Keyword)과 유사 검색(Text)의 차이를 비교


6. 마무리

Elasticsearch의 멀티 필드(Multi Field) 기능을 활용하면
동일한 데이터를 여러 방식으로 색인할 수 있으며
검색 최적화(정렬 & 집계)다국어 분석에도 매우 유용합니다.

다음 학습에서는 멀티 필드를 활용한 고급 검색 최적화 및 성능 개선 전략을 다루겠습니다! 🚀

Elasticsearch: 기타 필드 타입 (IP, Range, Binary) 완벽 정리

Elasticsearch는 기본적인 문자열, 숫자, 날짜, 불리언, 위치 정보 외에도
IP 주소 저장 (ip 타입)
범위 데이터 저장 (range 타입)
바이너리 데이터 저장 (binary 타입)

을 지원합니다. 이번 글에서는 각 필드 타입의 특성, 매핑 설정, 검색 방식, 그리고 실전 활용 예제까지 상세히 알아보겠습니다.


1. 기타 필드 타입 개요

타입 특징 사용 예시
IP (ip) IPv4, IPv6 주소 저장 "192.168.1.1"
Range (range) 숫자, 날짜, IP 범위 저장 { "gte": 10, "lt": 20 }
Binary (binary) 바이너리 데이터 저장 (검색 불가능) "U29tZSBiaW5hcnkgZGF0YQ=="

2. IP (ip) 타입

🔹 IP 타입이란?

IPv4 및 IPv6 주소를 저장할 수 있는 데이터 타입
쿼리를 활용해 특정 IP 대역 검색 가능

📌 예제 1: IP 필드 매핑 설정

PUT my_ip_index
{
  "mappings": {
    "properties": {
      "client_ip": {
        "type": "ip"
      }
    }
  }
}

IPv4, IPv6 주소를 문자열처럼 저장 가능

📌 예제 2: IP 데이터 저장

PUT my_ip_index/_doc/1
{
  "client_ip": "192.168.1.1"
}
PUT my_ip_index/_doc/2
{
  "client_ip": "2001:db8::ff00:42:8329"
}

IPv4, IPv6 모두 저장 가능

📌 예제 3: 특정 IP 검색

GET my_ip_index/_search
{
  "query": {
    "term": {
      "client_ip": "192.168.1.1"
    }
  }
}

특정 IP 주소를 기준으로 검색 가능

📌 예제 4: 특정 IP 범위 검색 (range 쿼리)

GET my_ip_index/_search
{
  "query": {
    "range": {
      "client_ip": {
        "gte": "192.168.1.0",
        "lte": "192.168.1.255"
      }
    }
  }
}

지정된 IP 범위 내에 포함된 데이터 검색 가능


3. 범위 (range) 타입

🔹 Range 타입이란?

숫자, 날짜, IP 등의 범위를 저장할 수 있는 데이터 타입
쿼리를 활용해 특정 범위의 데이터를 검색 가능

📌 예제 5: Range 필드 매핑 설정

PUT my_range
{
  "mappings": {
    "properties": {
      "amount": {
        "type": "integer_range"
      },
      "days": {
        "type": "date_range"
      }
    }
  }
}

정수 범위(integer_range), 날짜 범위(date_range) 모두 저장 가능

📌 예제 6: Range 데이터 저장

PUT my_range/_doc/1
{
  "amount": {
    "gte": 19,
    "lt": 28
  },
  "days": {
    "gt": "2019-06-01T09:00:00",
    "lt": "2019-06-20"
  }
}

gte, gt, lte, lt 연산자를 사용하여 범위 지정 가능

📌 예제 7: 특정 범위 검색 (range 쿼리)

GET my_range/_search
{
  "query": {
    "range": {
      "amount": {
        "gte": 16,
        "lte": 25,
        "relation": "intersects"
      }
    }
  }
}

16~25 범위에 겹치는(intersects) 데이터를 검색 가능

📌 Range 쿼리의 relation 옵션

값 설명

   
within 도큐먼트의 범위가 쿼리 범위 안에 완전히 포함되는 경우
contains 쿼리 범위가 도큐먼트 범위 안에 완전히 포함되는 경우
intersects 도큐먼트 범위와 쿼리 범위가 겹치는 경우

📌 예제 8: 특정 날짜 범위 검색

GET my_range/_search
{
  "query": {
    "range": {
      "days": {
        "gte": "2019-06-05",
        "lte": "2019-06-15",
        "relation": "within"
      }
    }
  }
}

2019-06-05 ~ 2019-06-15 범위에 완전히 포함된 데이터 검색


4. 바이너리 (binary) 타입

🔹 Binary 타입이란?

파일, 이미지 등의 바이너리 데이터를 저장 가능
색인이 불가능하며, source에서만 조회 가능
보통 Elasticsearch에 직접 저장하기보다는 S3, HDFS 등 외부 저장소 활용 추천

📌 예제 9: Binary 필드 매핑 설정

PUT my_binary_index
{
  "mappings": {
    "properties": {
      "file_data": {
        "type": "binary"
      }
    }
  }
}

바이너리 데이터는 검색 및 집계 불가능 (색인 X)

📌 예제 10: 바이너리 데이터 저장

PUT my_binary_index/_doc/1
{
  "file_data": "U29tZSBiaW5hcnkgZGF0YQ=="
}

Base64 인코딩된 바이너리 데이터 저장 가능

📌 Binary 데이터는 가능하면 외부 저장소에 저장하고, Elasticsearch에는 URL 또는 키만 저장하는 것이 효율적


5. 정리

     
IP (ip) IPv4, IPv6 주소 저장 가능 "192.168.1.1"
IP 검색 (range) 특정 IP 범위 검색 가능 192.168.1.0 ~ 192.168.1.255
Range (range) 숫자, 날짜, IP 범위 저장 가능 { "gte": 10, "lt": 20 }
Range 검색 (relation) within, contains, intersects 옵션 활용 "relation": "intersects"
Binary (binary) 바이너리 데이터 저장 가능 (검색 불가) "U29tZSBiaW5hcnkgZGF0YQ=="

6. 학습 가이드

1️⃣ IP 주소(ip 타입) 데이터를 저장하고 특정 IP 범위 검색 실습
2️⃣ Range 데이터(range 타입)에서 within, contains, intersects 차이 이해
3️⃣ Binary 데이터(binary 타입)를 활용한 효율적인 데이터 저장 전략 고민


7. 마무리

Elasticsearch는 IP, 범위 데이터, 바이너리 데이터까지 다양한 데이터 타입을 지원하며
IP 데이터 검색 (특정 IP 및 범위 검색)
Range 데이터 활용 (숫자·날짜·IP 범위 저장 및 검색)
Binary 데이터 관리 (외부 저장소 연동 추천)

을 효과적으로 활용할 수 있습니다.

다음 학습에서는 Elasticsearch에서 필드 타입 최적화 및 성능 개선 방법을 다루겠습니다! 🚀

+ Recent posts