Chef.Yeon
Code Cook
Chef.Yeon
전체 방문자
오늘
어제
  • 분류 전체보기 (230)
    • 게임 개발 (1)
      • Unity (1)
    • Android (27)
      • Kotlin (19)
      • 우아한테크코스 5기 (4)
    • Language (11)
      • 파이썬 (3)
      • Java (7)
    • DB (2)
      • SQL (16)
    • Spring (25)
    • 코딩테스트 (56)
    • Git (1)
    • TIL (85)
    • DevOps (6)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • java
  • 우아한테크코스
  • til
  • rsocket
  • 코틀린 인 액션
  • grafana
  • 백준
  • Docker
  • MariaDB
  • Wil
  • elasticsearch
  • 코딩테스트
  • 레포지토리
  • 에라토스테네스의 체
  • Android
  • webflux
  • spring
  • 파이썬
  • 다이나믹 프로그래밍
  • 코틀린
  • 문자열
  • kotlin
  • kibana
  • 프로그래머스
  • SQL
  • 프리코스
  • enum
  • ec2
  • 안드로이드
  • 내림차순

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Chef.Yeon

Code Cook

[TIL-20240805] ElasticSearch + Spring Boot 연동 오류 해결
TIL

[TIL-20240805] ElasticSearch + Spring Boot 연동 오류 해결

2024. 8. 5. 07:04

 

💻문제점1: CreatedAt 필드 타입

post-mappings.json

{
  "properties": {
    "id": {
      "type": "long"
    },
    "title": {
      "type": "text",
      "analyzer": "korean"
    },
    "content": {
      "type": "text",
      "analyzer": "korean"
    },
    "createdAt": {
      "type": "date",
      "format": "yyyy-MM-dd'T'HH:mm:ss.SSSSSS||epoch_millis"
    },
    "imageUrl": {
      "type": "text"
    },
    "tags": {
      "type": "keyword"
    }
  }
}

 

 

PostDocument

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Document(indexName = "posts")
@Setting(settingPath = "elastic/post-setting.json")
@Mapping(mappingPath = "elastic/post-mapping.json")
public class PostDocument {
    @Id
    private Long id;
    private String title;
    private String content;
    private LocalDateTime createdAt;
    private String imageUrl;
    private List<String> tags;

    @Builder
    public PostDocument(
            Long id,
            String title,
            String content,
            LocalDateTime createdAt,
            String imageUrl,
            List<String> tags) {
        this.id = id;
        this.title = title;
        this.content = content;
        this.createdAt = createdAt;
        this.imageUrl = imageUrl;
        this.tags = tags;
    }
}

 

 

PostElasticRepository

@Repository
public interface PostElasticRepository extends ElasticsearchRepository<PostDocument, Long> {
    List<PostDocument> findByTitleContaining(String title);
}

 

Elasticsearch를 사용한 데이터 검색이 정상 동작하는지 확인하기 위해 간단히 검색 api를 만들어 테스트했다.

 

'http://localhost:8080/api/v1/posts/elastic?keyword=오늘'로 요청을 보냈을 때, 다음과 같은 오류가 발생했다.

 

No converter found capable of converting from type [java.lang.Long] to type [java.time.LocalDateTime]


🔍문제점1-해결

Kibana를 통해 생성된 posts 인덱스를 확인해보니, createdAt 필드 타입이 date 타입이 아닌 long 타입으로 생성되었다.

 

kibana > dev tools 를 통해 인덱스를 직접 생성해주었다.

PUT /posts
{
  "settings": {
    "analysis": {
      "analyzer": {
        "english": {
          "type": "whitespace"
        },
        "korean": {
          "type": "nori"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "id": {
        "type": "long"
      },
      "title": {
        "type": "text",
        "analyzer": "korean"
      },
      "content": {
        "type": "text",
        "analyzer": "korean"
      },
      "createdAt": {
        "type": "date",
        "format": "yyyy-MM-dd'T'HH:mm:ss.SSS||epoch_millis"
      },
      "imageUrl": {
        "type": "text"
      },
      "tags": {
        "type": "keyword"
      }
    }
  }
}

💻문제점2: _class 필드 역직렬화

'http://localhost:8080/api/v1/posts/elastic?keyword=날씨' 로 요청을 보냈을 때, 다음과 같은 오류가 발생했다.

 

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "_class" (class com....post.domain.document.PostDocument), not marked as ignorable (6 known properties: "imageUrl", "title", "content", "id", "tags", "createdAt"])


🔍문제점2-해결

JSON 응답을 PostDocument로 역직렬화하는 과정에서 _class라는 인식되지 않은 필드가 존재하여 발생한 문제이다. Spring Data Elasticsearch는 기본적으로 엔터티 클래스의 _class 필드를 추가하여 인덱싱한다.

 

PostDocument

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Document(indexName = "posts", createIndex = false, writeTypeHint = WriteTypeHint.FALSE)
@Setting(settingPath = "elastic/post-setting.json")
@Mapping(mappingPath = "elastic/post-mapping.json")
public class PostDocument {
    @Id
    private Long id;
    private String title;
    private String content;
    private LocalDateTime createdAt;
    private String imageUrl;
    private List<String> tags;

    @Builder
    public PostDocument(
            Long id,
            String title,
            String content,
            LocalDateTime createdAt,
            String imageUrl,
            List<String> tags) {
        this.id = id;
        this.title = title;
        this.content = content;
        this.createdAt = createdAt;
        this.imageUrl = imageUrl;
        this.tags = tags;
    }
}

 

@Document 속성

  • indexName: ElasticSearch 인덱스 이름 지정
  • createIndex: 애플리케이션 시작 시 인덱스를 자동으로 생성할지 여부 지정
  • writeTypeHint: 도큐먼트에 타입 힌트를 쓸지 여부 지정
    • 도큐먼트에 _class 필드를 추가하지 않도록 한다.

💻문제점3: LocalDateTime 필드 매핑

'http://localhost:8080/api/v1/posts/elastic?keyword=날씨' 로 요청을 보냈을 때, 다음과 같은 오류가 발생했다

 

Type LocalDateTime of property PostDocument.createdAt is a TemporalAccessor class but has neither a @Field annotation defining the date type nor a registered converter for reading! It cannot be mapped from a complex object in Elasticsearch!


🔍문제점3-해결

LocalDateTime 필드를 Elasticsearch와 올바르게 매핑하기 위해 PostDocument의 createdAt 필드에 @Field 애노테이션을 추가했다.

    @Field(type = FieldType.Date, format = {}, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS||epoch_millis")
    private LocalDateTime createdAt;

 

기존 인덱스도 삭제하고 재생성해주었다.

DELETE /posts

 

post를 저장하고, 다음과 같이 kibana를 통해 확인할 수 있었다.

 

'http://localhost:8080/api/v1/posts/elastic?keyword=날씨' 로 요청을 보냈을 때 정상적으로 응답이 왔다.

 

 

Elasticsearch와 Spring Boot를 연동하여 데이터를 저장하고 검색하는 과정에서 다양한 문제가 발생했다.

요청 하나 보내기 정말 어렵다 😂

728x90

'TIL' 카테고리의 다른 글

[TIL-20240813-17] Elasticsearch 자동 완성 (2)  (0) 2024.08.13
[TIL - 20240810~12] ElasticSearch 자동 완성 (1)  (0) 2024.08.12
[TIL - 20240612] Swagger HTTPS 설정  (0) 2024.06.12
[TIL - 20240612] Swagger Failed to load remote configuration 해결  (0) 2024.06.12
[TIL-231219] 사용자 정의 애노테이션을 사용한 List 요소 검증  (0) 2024.03.20
    'TIL' 카테고리의 다른 글
    • [TIL-20240813-17] Elasticsearch 자동 완성 (2)
    • [TIL - 20240810~12] ElasticSearch 자동 완성 (1)
    • [TIL - 20240612] Swagger HTTPS 설정
    • [TIL - 20240612] Swagger Failed to load remote configuration 해결
    Chef.Yeon
    Chef.Yeon
    보기 좋고 깔끔한 코드를 요리하기 위해 노력하고 있습니다.

    티스토리툴바