Post

02 ElasticSearch 기본 패턴

02 ElasticSearch 기본 패턴

1. Note

1. Note

  • 검색 방식은 RESTFUL API
    • 굳이 막 특정한 방식을 고집할 필요는 없고
    • 단순히 요청만 보내면됨.
    • 각기 URL + HttpMethod별로 방법을 학습해야함.
  • 스프링에서는 JPA와 굉장히 흡사!

2. ElasticSearch Docker

1. yaml 샘플

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
31
32
33
# Elasticsearch = 데이터 저장 + 검색 엔진
# Kibana = Elasticsearch를 웹 UI로 조회/관리하는 도구
# Volume = 데이터 안날아가게 저장소 유지

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.5.0 # Elasticsearch 8.5.0 이미지 사용
    container_name: elasticsearch # 컨테이너 이름 지정

    environment:
      - discovery.type=single-node # 단일 노드 모드 (클러스터 구성 X)
      - xpack.security.enabled=false # 보안 인증 비활성화 (ID/PW 없이 접근 가능)
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m" # JVM 힙 메모리 512MB 설정

    ports:
      - "9200:9200" # 호스트 9200 -> 컨테이너 9200 포트 연결

    volumes:
      - esdata:/usr/share/elasticsearch/data # 데이터 영속성(컨테이너 삭제돼도 데이터 유지)

  kibana:
    image: docker.elastic.co/kibana/kibana:8.5.0 # Kibana 8.5.0 이미지 사용
    container_name: kibana # 컨테이너 이름 지정

    ports:
      - "5601:5601" # 호스트 5601 -> 컨테이너 5601 포트 연결 (웹 UI)

    depends_on:
      - elasticsearch # Elasticsearch 먼저 시작 후 Kibana 실행

volumes:
  esdata:
    driver: local # 로컬 Docker Volume 사용

2. ElasticSearch 상태 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 상태 요청
# GET "http://localhost:9200/_cluster/health?pretty"

{
  "cluster_name": "docker-cluster", // 클러스터 이름 (기본 docker 환경 이름)
  "status": "green", // 클러스터 상태 (green = 완전 정상)
  "timed_out": false, // 상태 조회 요청 timeout 여부 (false = 정상 응답)
  "number_of_nodes": 1, // 전체 노드 수 (현재 1개 노드)
  "number_of_data_nodes": 1, // 데이터 저장 가능한 노드 수 (현재 1개)
  "active_primary_shards": 1, // 활성화된 Primary Shard 개수
  "active_shards": 1, // 활성화된 전체 Shard 수 (Primary + Replica)
  "relocating_shards": 0, // 다른 노드로 이동 중인 shard 수 (0 = 이동 없음)
  "initializing_shards": 0, // 초기화 중인 shard 수 (0 = 모두 준비 완료)
  "unassigned_shards": 0, // 할당 실패한 shard 수 (0 = 문제 없음)
  "delayed_unassigned_shards": 0, // 지연 상태인 미할당 shard 수
  "number_of_pending_tasks": 0, // 아직 처리되지 않은 내부 작업 수 (0 = 밀린 작업 없음)
  "number_of_in_flight_fetch": 0, // 현재 shard 정보 fetch 중인 작업 수
  "task_max_waiting_in_queue_millis": 0, // 대기열에서 가장 오래 기다린 작업 시간(ms)
  "active_shards_percent_as_number": 100.0 // shard 정상 활성화 비율 (100% = 완전 정상)
}

3. ElasticSearch 사용

1. HTTP METHOD

Method역할Elasticsearch 예시
POST생성(추가)POST /member/_doc
GET조회GET /member/_doc/1
PUT생성 or 수정PUT /member/_doc/1
DELETE삭제DELETE /member/_doc/1

2. URL

  • URL 구분
    1
    2
    3
    4
    5
    
    # ID 값을 자동 입력
    http://localhost:9200/{index}/{api}
      
    # ID 값을 직접 선택
    http://localhost:9200/{index}/{api}/{id}
    
  • 구성

    부분의미
    localhost:9200Elasticsearch 서버 주소
    {index}데이터를 넣을 공간(테이블 비슷)
    {api}어떤 작업할지 (_doc, _search)
    {id}특정 문서 ID (선택)
  • API 분류 / 작업 구분

    API역할예시용도
    _doc문서 CRUD/member/_doc데이터 저장, 단건 조회, 삭제
    _search검색/member/_search전체 조회, 조건 검색, 페이징, 정렬
    _mapping필드 구조 확인/member/_mapping필드 타입 확인 (text, keyword, date, long)
    _count개수 조회/member/_count데이터 총 개수 확인
    _bulk여러 건 한번에 처리/_bulk대량 insert/update/delete
    _update부분 수정/member/_update/1특정 필드만 수정
    _delete_by_query조건 삭제/member/_delete_by_query검색 조건 기반 삭제
    _cluster/health상태 확인/_cluster/healthElasticsearch 정상 상태 확인

3. Elasticsearch Spring

1. 셋팅

  • 의존성
    1
    2
    3
    
    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch'
    }
    
  • 프로퍼티스
    1
    2
    3
    4
    5
    6
    7
    
    spring:
      elasticsearch:
        uris: https://your-es-host:9200
        username: elastic
        password: your_password
        ssl:
          bundle: my-es-bundle
    

2. 스프링 내부로직

  • Entity
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    // JPA랑 비슷하고, Document 애노테이션 사용
    @Document(indexName = "products")
    public class Product {
      
        @Id
        private String id;
      
        @Field(type = FieldType.Text)
        private String name;
      
        @Field(type = FieldType.Integer)
        private int price;
    }
    
  • Repository
    1
    2
    3
    4
    
    // 확장을 ElasticsearchRepository
    public interface ProductRepository extends ElasticsearchRepository<Product, String> {
      List<Product> findByName(String name);
    }
    
  • Service
    1
    2
    3
    4
    
    // JPA랑 똑같음
    productRepository.save(new Product("1", "apple", 1000));
    
    List<Product> result = productRepository.findByName("apple");
    
This post is licensed under CC BY 4.0 by the author.