몽고DB에 저장되어 있는 밀리세컨드(millisecond)값을 집계함수(aggregate)를 통해서 변환하는 방법 입니다.
* 기본적으로 몽고DB와 연동하는 라이브러리는 너무 낮지 않아야 합니다. : )
먼저 파싱 할 데이터를 살펴보겠습니다.
val이라는 키에 밀리세컨드값이 들어가 있습니다.
해당 값을 바꾸기 위해서 ConvertOperators 클래스를 활용하여 데이터를 변환하여 줍니다.
{
ToDate td = ConvertOperators.valueOf("val").convertToDate(); //ToDate라는 클래스가 반환 됩니다.
}
convertToDate메소드를 사용하면 ToDate라는 클래스 값을 받을 수 있습니다.
ToDate라는 클래스는 AbstractAggregationExpression 추상 클래스를 상속받고 있으며 해당 값은 몽고db의 질의를 위한 공통으로 사용되는 기능 입니다.
그러므로 해당 ToDate값은 몽고db에서의 project절에 사용을 할 수 있습니다.
이를 이제 한번 질의문에 적용하여 봅니다.
{
ToDate td = ConvertOperators.valueOf("val").convertToDate(); //ToDate라는 클래스가 반환 됩니다.
ProjectionOperation projection = Aggregation.project() //대상 매핑
.and("val").as("origin")
.and(td).as("parseToDate")
.and("1").as("1") ;
GroupOperation groupBy = Aggregation.group("1", "origin").first("parseToDate").as("parseToDate");
Aggregation agg = Aggregation.newAggregation( projection, groupBy );
}
val이라는 숫자 값을 날짜로 치환하여 parseToDate라는 이름으로 매핑하였습니다.
이를 실행하여 본 결과 입니다.
이를 조금만 응용하면 날짜값을 문자형태로("yyyy-mm-dd")도 쉽게 변환 할 수 있습니다.
처음 밀리세컨드 값을 변환하기 위해 ConvertOperators 클래스에서 valueOf 메소드를 통하여 이루어 졌다면, 날짜 값을 변환하기 위해서 Convert라는 이름을 Date로 바꾸어 DateOperators클래스를 활용하면 가능 합니다.
{
ToDate td = ConvertOperators.valueOf("val").convertToDate(); //ToDate라는 클래스가 반환 됩니다.
ProjectionOperation projection = Aggregation.project() //대상 매핑
.and("val").as("origin")
.and(td).as("parseToDate")
.and(DateOperators.DateToString.dateOf(td).toString("%Y-%m-%d")).as("parseToDateToString")
.and("1").as("1") ;
GroupOperation groupBy = Aggregation.group("1", "origin").first("parseToDate").as("parseToDate").first("parseToDateToString").as("parseToDateToString");
Aggregation agg = Aggregation.newAggregation( projection, groupBy );
}
이를 실행하여 보면 변환된 날짜값을 문자로 바꾸는 것을 볼 수 있습니다.
집계(aggregate)를 동작해야되는 필드가 이미 날짜형식의 데이터라면 간단하게 dateAsFormattedString 메소드를 활용하여 문자로 변환 할 수 있습니다.
하지만 여기서는 밀리세컨드에서 날짜로 변환된 데이터에 대해 다시 문자형식으로 변환을 하는 것 이므로 DateOperators를 활용하여 변환을 하여야 합니다.
아래 사진처럼 dateAsFormattedString 메소드를 바로 호출하여 조회해서는 안됩니다.
위 내용에 대한 최종 소스코드 입니다.
import java.util.List;
import org.bson.Document;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.ConvertOperators;
import org.springframework.data.mongodb.core.aggregation.ConvertOperators.ToDate;
import org.springframework.data.mongodb.core.aggregation.DateOperators;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.data.mongodb.core.aggregation.ProjectionOperation;
import com.mongodb.client.MongoClient;
public class MongoDBOperatorTest {
public static void test() {
ToDate td = ConvertOperators.valueOf("val").convertToDate(); //ToDate라는 클래스가 반환 됩니다.
ProjectionOperation projection = Aggregation.project() //대상 매핑
.and("val").as("origin")
.and(td).as("parseToDate")
.and(DateOperators.DateToString.dateOf(td).toString("%Y-%m-%d")).as("parseToDateToString")
.and("1").as("1") ;
GroupOperation groupBy = Aggregation.group("1", "origin").first("parseToDate").as("parseToDate").first("parseToDateToString").as("parseToDateToString");
AggregationOptions option = AggregationOptions.builder().allowDiskUse(true).build();
Aggregation agg = Aggregation.newAggregation( projection, groupBy ).withOptions(option);
AggregationResults<Document> results = template.aggregate(agg, "testCollection", Document.class);
List<Document> list = results.getMappedResults();
list.forEach(System.out::println);
}
}
물론 변환된 필드인 parseToDateToString값과 parseToDate값에 대해서도 group을 통해서 집계 할 수 있습니다.
위 내용 이외의 StringOperators, ArrayOperators 등등 다양한 쿼리 연산자 클래스를 통해서 데이터를 유용하게 다룰수가 있습니다.
* 추가 ------
밀리세컨드 값을 날짜 형식으로 변환하면 기본 설정인 UTC타입의 값으로 변환이 되어 버립니다. * TimeZone.none()
UTC형식으로 변환되어도 상관 없다면 문제되는 것은 없지만, 만약 한국시간대로(GMT) 변환을 해야되는 경우라면 시간차이가 9시간 나므로 값의 범위가 달라질 수 있습니다.
아래와 같은 예로,
2021년 7월 1일 데이터가 20개 나와야 하는데 그렇지 않고 7월 1일 10개, 6월 30일 10개 이런식으로 나올 수 있습니다.
그러므로 TimeZone 설정을 통하여 한국 시간과 맞게 나오도록 해야 합니다.
import org.springframework.data.mongodb.core.aggregation.ConvertOperators.ToDate;
import org.springframework.data.mongodb.core.aggregation.DateOperators;
import org.springframework.data.mongodb.core.aggregation.DateOperators.Timezone;
public class TestClass{
public void test{
//생략..
ToDate td = ConvertOperators.valueOf("대상날짜").convertToDate();
Timezone zone = DateOperators.Timezone.valueOf("Asia/Seoul");
ProjectionOperation projection = Aggregation.project() //대상 매핑
.and("대상날짜").as("origin")
.and(td).as("parseToDate")
.and(DateOperators.dateOf(td).withTimezone(zone).toString("%Y-%m")).as("parseToDateToString")
.and("1").as("1") ;
//생략..
}
}
DateOperators클래스에 withTimeZone 메소드를 호출한 다음에 필요한 값인 TimeZone 을 넣어주면 한국시간에 맞는 데이터로 변환되는 것을 볼 수 있습니다.
물론 해당 값을 바꾸면 원하는 국가별 시간대로 변경 가능 합니다.
아래 사이트는 Zone코드가 나온 사이트 입니다.
https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
이상으로 몽고db에서 밀리세컨드(milliseconds)값을 날짜 또는 문자형식으로 변환하는 집계(Aggregate)동작 방법에 대해서 살펴 보았습니다.
궁금한점 또는 틀린 부분은 언제든 연락주세요. 👻
'몽고DB > Java 몽고DB' 카테고리의 다른 글
Watch 함수를 통한 몽고DB 트리거 만들기(mongoDB watch trigger) (0) | 2022.01.28 |
---|---|
몽고DB Aggregate 를 병렬 동작 처럼(Mongodb aggregate facet) (0) | 2020.11.03 |
몽고 db에서의 특수문자 검색(Mongodb 특수문자)시 유의사항 (0) | 2020.07.29 |
Java 몽고DB 파일 업로드 (Java mongodb file, Java mongodb fs) (0) | 2020.07.03 |
MongoTemplate or연산자를 통한 질의문 만들기(MongoTemplate or query) (0) | 2020.06.18 |
댓글