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에서 필드 타입 최적화 및 성능 개선 방법을 다루겠습니다! 🚀

Elasticsearch: 위치 정보 (Geo Point & Geo Shape) 완벽 정리

Elasticsearch는 위치 정보(Geo Data)를 저장하고 검색할 수 있도록
Geo Point (한 점의 위도·경도 좌표)
Geo Shape (점, 선, 다각형 등 복잡한 형태)
위치 기반 검색 (거리, 범위, 포함 관계)

을 지원합니다. 이번 글에서는 위치 정보의 저장 방식, 검색 방식, 그리고 실전 활용 예제까지 상세히 알아보겠습니다.


1. Elasticsearch에서 지원하는 위치 정보 타입

타입 특징 사용 예시
Geo Point 위도(latitude), 경도(longitude) 좌표를 저장 특정 좌표에서 가까운 위치 검색
Geo Shape 다각형, 선, 여러 개의 점 등 복잡한 형태 저장 가능 행정 구역, 도로망, 특정 지역 검색

2. Geo Point

🔹 Geo Point란?

✔ 하나의 점(위도·경도)을 저장하는 데이터 타입
다양한 형식으로 좌표 입력 가능

📌 예제 1: Geo Point 필드 매핑 설정

PUT my_locations
{
  "mappings": {
    "properties": {
      "location": {
        "type": "geo_point"
      }
    }
  }
}

Geo Point 필드는 반드시 사전 매핑 설정 필요!

📌 예제 2: 다양한 형식으로 좌표 입력하기

PUT my_locations/_doc/1
{
  "location": { "lat": 41.12, "lon": -71.34 }  // 객체 형식
}
PUT my_locations/_doc/2
{
  "location": "41.12,-71.34"  // 문자열 형식
}
PUT my_locations/_doc/3
{
  "location": [ -71.34, 41.12 ]  // 배열 형식 (경도, 위도 순서)
}
PUT my_locations/_doc/4
{
  "location": "drm3btev3e86"  // geohash 형식
}

객체, 문자열, 배열, geohash 등 다양한 형식 지원
배열 형식은 "경도(lon) → 위도(lat)" 순서 주의!


3. Geo Point 검색 (Bounding Box & Distance)

🔹 Bounding Box 쿼리 (네모 영역 검색)

위쪽 좌표(top_left)와 아래쪽 좌표(bottom_right)로 범위 지정
네모 범위 내에 포함된 모든 위치 검색

📌 예제 3: 특정 영역 내에 위치한 점 찾기

GET my_locations/_search
{
  "query": {
    "geo_bounding_box": {
      "location": {
        "top_left": { "lat": 37.5779, "lon": 126.9617 },
        "bottom_right": { "lat": 37.4899, "lon": 127.0388 }
      }
    }
  }
}

지정된 네모 영역 내에 위치한 좌표 검색 가능


🔹 Distance 쿼리 (반경 검색)

하나의 기준점에서 일정 거리 내에 있는 좌표 검색
"반경 5km 안에 있는 위치" 같은 검색에 사용

📌 예제 4: 반경 5km 내에 위치한 점 찾기

GET my_locations/_search
{
  "query": {
    "geo_distance": {
      "distance": "5km",
      "location": { "lat": 37.5358, "lon": 126.9559 }
    }
  }
}

반경 5km 안에 포함된 모든 위치 검색 가능
distance 값을 10km, 20km로 변경하여 범위 조절 가능


4. Geo Shape

 

 

🔹 Geo Shape이란?

다각형, 선, 직사각형 등 복잡한 위치 정보 저장 가능
행정 구역, 특정 지역 검색에 활용

📌 예제 5: Geo Shape 필드 매핑 설정

PUT my_shapes
{
  "mappings": {
    "properties": {
      "location": {
        "type": "geo_shape"
      }
    }
  }
}

Geo Shape은 점(Point)뿐만 아니라 선(Line), 다각형(Polygon)도 저장 가능

📌 예제 6: 다양한 Geo Shape 데이터 저장

PUT my_shapes/_doc/1
{
  "location": {
    "type": "point",
    "coordinates": [127.027926, 37.497175]
  }
}
PUT my_shapes/_doc/2
{
  "location": {
    "type": "polygon",
    "coordinates": [
      [
        [127.027926, 37.497175],
        [126.991806, 37.571607],
        [126.924191, 37.521624],
        [127.027926, 37.497175]  // 시작점과 동일해야 함
      ]
    ]
  }
}

다각형은 반드시 첫 번째 좌표와 마지막 좌표가 동일해야 함


5. Geo Shape 검색 (Intersects, Within, Disjoint)

Geo Shape을 이용한 복잡한 위치 검색 가능
관계(Relation) 옵션을 사용하여 다양한 검색 가능

Relation 값 설명

   
intersects 쿼리 영역과 조금이라도 겹치는 도큐먼트 검색
within 쿼리 영역에 완전히 포함되는 도큐먼트 검색
disjoint 쿼리 영역과 겹치지 않는 도큐먼트 검색

📌 예제 7: 특정 영역과 겹치는 위치 찾기 (intersects)

GET my_shapes/_search
{
  "query": {
    "geo_shape": {
      "location": {
        "shape": {
          "type": "envelope",
          "coordinates": [
            [126.9687, 37.58], 
            [126.99, 37.5543]
          ]
        },
        "relation": "intersects"
      }
    }
  }
}

지정된 영역과 겹치는 도큐먼트 검색 가능


6. Object vs Geo Point vs Geo Shape 비교

     
Object JSON 객체 내부에 lat, lon 필드 저장 일반 텍스트 필드처럼 다룸
Geo Point 위도·경도를 한 점으로 저장 거리 기반 검색 가능 (geo_distance)
Geo Shape 다각형, 선, 다중 점 등 복잡한 형태 저장 특정 영역 검색 (geo_shape)

7. 정리

     
Geo Point 하나의 위도·경도를 저장 "서울역에서 반경 5km 내" 검색
Geo Shape 다각형, 선, 직사각형 등 복잡한 형태 저장 "강남구에 포함된 장소" 검색
Bounding Box Query 네모 영역 내 좌표 검색 "서울 시내에 포함된 역 찾기"
Distance Query 반경 내 좌표 검색 "5km 이내에 있는 카페 검색"
Geo Shape Query 특정 지역과 겹치는 도큐먼트 검색 "서울시 안에 완전히 포함된 도로 찾기"

8. 학습 가이드

1️⃣ Geo Point와 Geo Shape 데이터를 각각 저장하여 테스트
2️⃣ Bounding Box & Distance Query를 사용하여 위치 검색 실습
3️⃣ Geo Shape Query를 활용하여 특정 지역 검색 테스트


9. 마무리

Elasticsearch의 위치 정보(Geo Data) 기능을 활용하면
위치 기반 검색 (반경 내 검색, 특정 지역 검색 등)
복잡한 지도 데이터 처리 (도로망, 행정 구역 등)
다양한 위치 필터링 및 최적화된 공간 검색

을 쉽게 구현할 수 있습니다.

다음 학습에서는 Geo Query 성능 최적화 및 실전 활용법을 다루겠습니다! 🚀

Elasticsearch: Object vs Nested 타입 완벽 정리

Elasticsearch에서 Object와 Nested 타입JSON 객체(Object) 데이터를 저장하고 검색하는 방식을 결정하는 중요한 개념입니다.

Object 타입: 객체 내부의 필드들을 독립적으로 색인
Nested 타입: 객체 내부의 필드들을 하나의 단위로 유지하며 별도 저장

이번 글에서는 Object와 Nested 타입의 차이, 각 타입의 데이터 저장 방식, 검색 방식, 그리고 실전 예제까지 상세히 알아보겠습니다.


1. Object와 Nested의 차이점

타입 특징 검색 방식
Object JSON 객체를 필드별로 분리하여 색인 일반 Match Query 사용
Nested JSON 객체를 독립된 문서처럼 저장 Nested Query 사용 필요

2. Object 타입 이해하기

🔹 Object 타입이란?

  • JSON 객체 내부의 필드들을 독립적으로 색인
  • 하위 필드들을 분리하여 저장하기 때문에 부정확한 검색 결과 발생 가능

📌 예제 1: Object 타입 매핑 설정

PUT movie
{
  "mappings": {
    "properties": {
      "characters": {
        "properties": {
          "name": { "type": "text" },
          "age": { "type": "byte" },
          "side": { "type": "keyword" }
        }
      }
    }
  }
}

📌 예제 2: Object 데이터 저장

PUT movie/_doc/1
{
  "characters": {
    "name": "Iron Man",
    "age": 46,
    "side": "superhero"
  }
}

characters 객체 내부의 필드들이 각각 색인됨

📌 예제 3: Object 필드 검색

GET movie/_search
{
  "query": {
    "match": {
      "characters.name": "Iron Man"
    }
  }
}

Object 타입에서는 일반 Match Query 사용 가능


3. Object 타입의 문제점

Object 타입을 배열 형태로 저장할 때, 필드 간의 관계가 유지되지 않음

📌 예제 4: Object 타입을 배열로 저장

PUT movie/_doc/2
{
  "title": "The Avengers",
  "characters": [
    { "name": "Iron Man", "side": "superhero" },
    { "name": "Loki", "side": "villain" }
  ]
}

📌 예제 5: "Loki"이면서 "villain"인 문서 검색 (Object 타입)

GET movie/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "characters.name": "Loki" } },
        { "match": { "characters.side": "villain" } }
      ]
    }
  }
}

문제 발생: "Loki"가 "superhero"로 저장된 문서도 검색됨!

💡 이유:

  • Object 타입은 모든 필드를 개별적으로 저장
  • "characters.name": "Loki" 와 "characters.side": "villain"이 같은 객체인지 확인 불가능

4. Nested 타입으로 해결하기

🔹 Nested 타입이란?

  • JSON 객체 내부의 필드들을 하나의 단위로 저장
  • 각 객체를 별도 문서로 저장하여 관계 유지 가능
  • 검색 시 Nested Query를 사용해야 함

📌 예제 6: Nested 타입 매핑 설정

PUT movie
{
  "mappings": {
    "properties": {
      "characters": {
        "type": "nested",
        "properties": {
          "name": { "type": "text" },
          "side": { "type": "keyword" }
        }
      }
    }
  }
}

📌 예제 7: Nested 데이터 저장

PUT movie/_doc/3
{
  "title": "The Avengers",
  "characters": [
    { "name": "Iron Man", "side": "superhero" },
    { "name": "Loki", "side": "villain" }
  ]
}

📌 예제 8: "Loki"이면서 "villain"인 문서 검색 (Nested 타입)

GET movie/_search
{
  "query": {
    "nested": {
      "path": "characters",
      "query": {
        "bool": {
          "must": [
            { "match": { "characters.name": "Loki" } },
            { "match": { "characters.side": "villain" } }
          ]
        }
      }
    }
  }
}

정확한 문서만 검색됨!

💡 이유:

  • Nested 필드는 각 객체를 개별 문서처럼 저장
  • "characters.name": "Loki"와 "characters.side": "villain"이 같은 객체에 속하는지 확인 가능

5. Object vs Nested 비교

타입 특징 검색 방식
Object 객체 내부의 필드들이 개별적으로 색인됨 일반 Match Query 사용
Nested 객체 내부의 필드들이 한 단위로 유지됨 Nested Query 사용 필요
Object 필드 검색 문제 필드 간 관계가 유지되지 않아 부정확한 검색 결과 발생 가능 Loki가 superhero로 저장된 문서도 검색됨
Nested 필드 해결 객체 단위로 저장되어 정확한 검색 가능 Loki가 villain인 경우만 검색됨

6. 정리

Object 타입 JSON 객체의 필드를 독립적으로 저장 일반 Match Query 사용 가능
Nested 타입 JSON 객체 내부 필드 간 관계를 유지하여 저장 Nested Query 사용 필수
Object 타입 문제점 같은 필드 값이 포함된 다른 객체도 검색됨 잘못된 검색 결과 발생 가능
Nested 타입 해결책 각 객체를 별도 문서처럼 저장하여 관계 유지 정확한 검색 가능

7. 학습 가이드

1️⃣ Object 타입과 Nested 타입을 각각 사용하여 데이터를 저장하고 검색 실습
2️⃣ Object 타입에서 부정확한 검색 결과가 발생하는지 테스트
3️⃣ Nested Query를 사용하여 정확한 검색 결과 도출
4️⃣ Object 필드와 Nested 필드를 활용한 검색 최적화 연습


8. 마무리

Elasticsearch에서 Object와 Nested 타입을 올바르게 선택하는 것은 데이터 검색의 정확성을 결정하는 중요한 요소입니다.
Object 타입검색이 간편하지만 필드 관계를 유지하지 못함
Nested 타입객체 단위의 관계를 유지하지만, Nested Query를 사용해야 함

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

Elasticsearch: Boolean(불리언) 타입 완벽 정리

Elasticsearch에서 Boolean(불리언) 타입true / false 값만을 저장할 수 있는 필드 타입입니다.
✔ true 또는 false 값 저장
✔ "true" 같은 문자열도 자동 변환됨
Term Query를 사용하여 검색

이번 글에서는 Boolean 타입의 기본 개념, 주요 옵션, 그리고 실전 적용 예제까지 상세히 알아보겠습니다.


1. Boolean 타입 개요

Boolean 타입은 논리적 참/거짓 값을 저장하는 데 사용됩니다.
✔ "true", "false", 1, 0 같은 값도 자동 변환되어 저장됩니다.

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

PUT my_index
{
  "mappings": {
    "properties": {
      "is_active": {
        "type": "boolean"
      }
    }
  }
}

✅ "true", "1" → true로 저장됨
✅ "false", "0" → false로 저장됨


2. Boolean 타입 필드의 주요 옵션

Boolean 타입은 문자열, 숫자 필드와 일부 동일한 옵션을 가집니다.

옵션 설명 기본값
index 색인 여부 (검색 가능 여부) true
doc_values 집계/정렬을 위한 최적화된 저장 방식 사용 여부 true
null_value 필드가 존재하지 않을 때 기본값 설정 없음

3. Boolean 데이터 저장 및 검색 예제

📌 예제 2: Boolean 데이터 저장

PUT my_index/_doc/1
{
  "is_active": true
}
PUT my_index/_doc/2
{
  "is_active": "false"
}
PUT my_index/_doc/3
{
  "is_active": 1
}
PUT my_index/_doc/4
{
  "is_active": "0"
}

문자열 "false"도 false로 변환됨
숫자 1, "0"도 true, false로 변환됨


📌 예제 3: Boolean 값 검색 (Term Query 사용)

GET my_index/_search
{
  "query": {
    "term": {
      "is_active": true
    }
  }
}

✅ "is_active": true 인 문서만 검색됨


4. Boolean 필드에서 null_value 옵션 활용

✔ Boolean 필드가 null이거나 존재하지 않을 경우 기본값을 설정할 수 있음

📌 예제 4: Boolean 필드에서 null_value 설정

PUT my_index
{
  "mappings": {
    "properties": {
      "is_active": {
        "type": "boolean",
        "null_value": false
      }
    }
  }
}

✅ null 값이 입력되면 자동으로 false 처리됨

📌 예제 5: null_value 옵션 테스트

PUT my_index/_doc/5
{
  "is_active": null
}

✅ "is_active": null → 실제로는 false로 저장됨


5. 정리

개념 설명 예제
Boolean 타입 true 또는 false 값만 저장 가능 "true", "false", 1, 0
자동 변환 문자열 "true"도 true로 저장됨 "false" → false
Term Query 사용 Boolean 값 검색 시 Term Query 활용 "is_active": true 검색
null_value 필드가 null일 경우 기본값 설정 가능 null_value: false

6. 학습 가이드

1️⃣ Boolean 필드에 다양한 값(true, "false", 1, 0)을 저장하고 변환 결과 확인
2️⃣ Term Query를 활용하여 Boolean 값 검색 테스트
3️⃣ null_value 옵션을 사용하여 기본값 설정 및 동작 방식 확인


7. 마무리

Elasticsearch의 Boolean(불리언) 타입단순한 참/거짓 값을 저장하는 데 최적화되어 있으며,
✔ true, false, "true", "0" 등 다양한 값이 자동 변환됩니다.
✔ null_value 옵션을 활용하면 null 값 처리 시 기본값을 설정할 수 있습니다.

다음 학습에서는 Boolean 필드와 Filter Query를 활용한 검색 최적화 방법을 다루겠습니다! 🚀

+ Recent posts