안녕하세요 진행중인 ShareMore 프로젝트에서 검색기능 구현이 필요해 ElasticSearch를 구현해보았습니다!
ElasticSearch는 분산형 RESTful 검색 및 분석 엔진입니다.
검색에 최적화된 엔진인 만큼 로깅 서치 등에 많이 활용되고 있습니다!
ElasticSearch와 RDB는 어떻게 다를까요?
RDB는 기본적으로 행 저장 형태입니다!
때문에 저장과 삭제가 용이하다는 장점이 있는데요
특정 조건으로 검색을 할 때는 모든 행을 다 탐색해야 한다는 단점또한 가지고 있습니다!
반면 ElasticSearch는 단어 기반 역인덱스 저장 방식입니다.
이와 같이 역 인덱스를 통해 단어기반으로 쉽게 검색할 수 있도록 하였고
검색에 특화 될 수 있습니다.
하지만 그만큼 삭제는 RDB에 비해 용이하지 않다는 단점도 있습니다.
먼저 docker-compose를 통해 여러 image들을 한꺼번에 실행 시켜줄겁니다!
version: '3.7'
services:
es:
container_name: es
environment:
- node.name=single-node
- cluster.name=backtony
- discovery.type=single-node
ports:
- 9200:9200
- 9300:9300
networks:
- es-bridge
kibana:
container_name: kibana
image: docker.elastic.co/kibana/kibana:7.15.2
environment:
SERVER_NAME: kibana
ELASTICSEARCH_HOSTS: http://es:9200
ports:
- 5601:5601
# Elasticsearch Start Dependency
depends_on:
- es
networks:
- es-bridge
networks:
es-bridge:
driver: bridge
간단하게 일래스틱서치용의 소스 이용이 가능한 데이터 시각화 대시보드 소프트웨어입니다.
자세한 정보는 추후 포스팅하겠습니다!
docker compose -f els.yml up -d
로 실행 시켜 줍니다!
잘실행되었고 http://localhost:5601 로 접속하면
kibana를 통한 시각화 화면이 나오게됩니다!
먼저 의존성 추가해줍니다!
implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch'
Spring Data Elasticsearch는 기존의 의존성을 추가하여 사용자로 하여금 쿼리를 편하게 해주는 라이브러리 등을 추가하여 지원해줍니다!
또한 ElasticSearch에 접근하여 Opration을 수행하기 위해 Configuration해줍니다!
@Configuration
@EnableElasticsearchRepositories(basePackages = "org.springframework.data.elasticsearch.repository")
public class ElasticSearchConfig extends ElasticsearchConfiguration {
@Override
public ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
}
}
@AllArgsConstructor
@NoArgsConstructor
@Getter
@ToString
@Builder
@Document(indexName = "item")
@Mapping(mappingPath = "static/elastic-mapping.json")
@Setting(settingPath = "static/elastic-token.json")
public class ItemDocument {
@Id
@Field(name = "id", type = FieldType.Keyword)
private String itemId;
@Field(type = FieldType.Keyword)
private String user;
@Field(type = FieldType.Text)
private String name;
@Field(type = FieldType.Text)
private String description;
@Field(type = FieldType.Text)
private String category;
@Field(type = FieldType.Integer)
private int price;
@Field(type = FieldType.Text)
private String itemImage;
}
- @Document를 통해 ElasticSearch의 "item" 인덱스에 매핑합니다.
-@Mapping, @Setting 를 통해 클래스에 해당하는 매핑/세팅 정보를 json파일에서 가져옵니다.
자세한 설정은 ElasticSearch 번역문서 에서 확인해주세요! 굉장히 잘 번역되어있습니다.
public interface ItemSearchRepository extends ElasticsearchRepository<ItemDocument, Long> {
List<ItemDocument> findByName(String keyword);
}
저는 이름으로 찾을 수 있도록 쿼리를 추가하였습니다.
@Service
@RequiredArgsConstructor
public class ItemSearchService {
private final ItemSearchRepository itemSearchRepository;
public ItemDocument createItem(ItemDocument itemDocument) {
return itemSearchRepository.save(itemDocument);
}
public List<ItemDocument> getItemByName(String keyword) {
List<ItemDocument> byName = itemSearchRepository.findByName(keyword);
return byName;
}
}
간단하게 생성과 조회만 해보도록할게요!
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/item/search")
public class ItemSearchController {
private final ItemSearchService itemSearchService;
@GetMapping
public ApiResponse<List<ItemDocument>> search(@RequestParam("keyword") String keyword) {
return ApiResponse.onSuccess(itemSearchService.getItemByName(keyword));
}
@PostMapping
public ApiResponse<ItemDocument> create(@RequestBody ItemDocument itemDocument) {
return ApiResponse.onSuccess(itemSearchService.createItem(itemDocument));
}
}
잘 조회되었습니다!🔫🔫
ElasticSearch를 통해 거의 실시간으로 검색 기능을 사용할 수 있었습니다.
다음에는 ELK같은 로깅 시스템에 적용해보도록하겠습니다!