오랬동안 엘라스틱 서치를 활용해 진행했던 프로젝트를 끝내며 그간의 개발 과정을 돌이켜보았습니다.
여러 세그먼트의 조건을 만족하는 유저 Count를 노출. 간단하다.
예를 들어 A(모바일로 접속), B(방문 횟수 5이상), C(주문 회수 0) 라는 조건이 있다고 하면
A + B + C 조건을 모두 만족하는 유저 Count를 노출시키면 됩니다. 물론 조건값이 달라질 수 있고 다른 조건이 추가될 수도 있습니다.
세그먼트 조건을 쿼리로 변환하여 count를 계산하도록 만들었다.
A B C 를 만족하는 3에 해당하는 유저만 구하면 된다.
부하가 심한 쿼리를 기존 운영 DB에서 사용할 수는 없고 별도의 검색 엔진을 찾던중
방대한 양의 데이터를 신속하게 검색이 가능하다고 해서 엘라스틱서치로 결정.
이것저것 생각만 하기보다 일단 시작해보기로 했습니다.
RestHighLevelClient에서 제공하는 bulkInsert api와 delete api를 사용하여 삽입 및 삭제 실행.
String serviceKey = initTerminate.get().getServiceKey();
String date = LocalDateTime.now().format(Constants.DATE_TIME_FORMATTER_YYYYMMDD_WITH_DOT);
String indexName = USER_DATA + serviceKey + "-" + date;
ObjectMapper mapper = new ObjectMapper();
BulkRequest request = new BulkRequest();
request.timeout(TimeValue.timeValueMinutes(2));
for (ESUserData data : items) {
String jsonString = mapper.writeValueAsString(data);
request.add(new IndexRequest(indexName).source(jsonString, XContentType.JSON));
}
BulkResponse response = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
for (BulkItemResponse bulkItemResponse : response) {
if (bulkItemResponse.isFailed()) {
logger.info(bulkItemResponse.getFailure().getMessage());
break;
}
}
elasticsearch에서 제공하는 XcontentBuilder 를 사용하여 쿼리 생성. XcontentBuilder 클래스는 json hierarchy를 쉽게 만들어 낼 수 있도록 elasticsearch library에서 제공.
조회는 모듈에 대한 의존성이 더 낮고 API 의 body를 직접 제어할 수 있는 Low level REST Client 사용
Request request = new Request("GET", "//인덱스명" + "/_search");
request.setEntity(new NStringEntity(Strings.toString(xContentBuilder), ContentType.APPLICATION_JSON));
restClient.performRequestAsync(request, new ResponseListener() {
@Override
public void onSuccess(Response response) {
try {
String responseBody = EntityUtils.toString(response.getEntity());
JSONArray jsonArray = JsonPath.read(responseBody, "$.aggregations.userIds.buckets");
List<ESUserAggBucket> bucketList = new ObjectMapper().readValue(jsonArray.toJSONString(), new TypeReference<List<ESUserAggBucket>>() {});
latch.countDown();
} catch (Exception e) {
latch.countDown();
}
}
@Override
public void onFailure(Exception e) {
latch.countDown();
}
});